Задача о сравнении двух дат

На одном из практических занятий Валерий Шахамболетович предложил интересную идею: исследовать последовательности "красивых" дат, например, состоящих из одинаковых двузначных чисел (это было навеяно последней двоичной датой в этом столетии – 11.11.11). В частности, он предложил написать программу, которая определяет, как часто бывают даты такого вида.
Но начав разработку данной идеи, я быстро осознал всю тривиальность задачи: в общем случае такую дату можно представить в виде xx.xx.aaxx (это не произведение, а десятичная запись), где xx – заданное двузначное число (01 <= xx <= 12), aa – параметр, изменение которого означает продвижение по столетиям. Это значит, что любая такая дата бывает раз в сто лет, и сей факт делает ее менее интересной для программирования.
После я решил немного расширить предметную область этой задачи, добавив требование найти следующую дату указанного вида. Однако в процессе решения этой задачи я сделал еще одного обобщение, окончательно дав возможность вычислить оставшееся время до любой даты относительно введенной даты (по умолчанию считается, что это сегодняшняя дата).
Итак, окончательная формулировка такова:
Даны две даты M и N (M < N), где M - сегодняшняя дата, в которых числа дней, месяцев и лет разделены пробелами. Вывести на экран сообщение о том, сколько лет, месяцев и дней должно пройти с M до N. Например, для входной последовательности 04 12 2011 01 08 2013 программа должна вывести ответ: "Этот день наступит через 1 год, 7 месяцев и 28 дней".
В процессе решения этой задачи я не учитывал дополнительные дни в високосные годы, так как они не влияют на окончательное разложение оставшегося времени на годы, месяцы и дни. Решение получилось достаточно громоздким, к тому же, оно содержит форматированный вывод для сохранения естественности выходного предложения с точки зрения русского языка.

  1. program DiffBetweenTwoDates;
  2.  
  3. const
  4.   Month: array[1..12] of byte = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
  5.  
  6. var
  7.   i, mm, dd1, mm1, dd2, mm2: byte;
  8.   yy, yy1, yy2, dd, days1, days2: word;
  9.  
  10. begin
  11.   mm := 0; // по умолчанию количество месяцев равно нулю
  12.   readln(dd1, mm1, yy1, dd2, mm2, yy2); // последовательно считываем обе даты
  13.   yy2 := yy2 - yy1; // вычисляем разницу в годах
  14.   for i := 1 to mm1 - 1 do days1 := days1 + month[i]; // рассчитываем, сколько дней прошло с начала года в нижней дате - прибавляем дни всех прошедших месяцев
  15.   days1 := days1 + dd1; // и прошедшие дни последнего незавершенного месяца
  16.   days2 := yy2 * 365; // разницу в годах между двумя датами умножаем на количество дней в году
  17.   for i := 1 to mm2 - 1 do days2 := days2 + month[i]; // а также аналогично прибавляем дни всех месяцев, которые должны пройти в год верхней даты
  18.   days2 := days2 + dd2; // и дни его последнего незавершенного месяца
  19.   dd := days2 - days1; // вычисляем различие в днях между двумя датами - мы нашли, сколько дней должно пройти с нижней даты
  20.   yy := dd div 365; // вычисляем количество полных лет
  21.   dd := dd mod 365; // и выбираем оставшиеся дни
  22.   while dd - month[mm1] > 0 do begin // теперь перебираем все месяцы нижней даты, начиная с первого, пока количество оставшихся дней не станет меньше дней в очередном месяце
  23.     dd := dd - month[mm1]; // отнимаем дни очередного полностью прошедшего месяца
  24.     inc(mm); // и увеличиваем счетчик месяцев, которые должны пройти
  25.     if mm1 = 12 then mm1 := 1 else inc(mm1) // если на каком-то шаге мы прибавили дни последнего месяца, следующий шаг начинаем с первого, иначе рассматриваем следующий месяц
  26.   end;
  27.   write('Этот день наступит через '); // вывод в соответствии с правилами употребления зависимых слов при количественных числительных
  28.   if yy > 0 then begin // если указано количество лет
  29.     write(yy);
  30.     case yy mod 100 of // смотрим последние две цифры
  31.       11, 12, 13, 14: write(' лет')
  32.     else // если последние две цифры не совпадают с указанными
  33.       case yy mod 10 of // смотрим последнюю цифру
  34.         1: write(' год');
  35.         2, 3, 4: write(' года')
  36.       else write( ' лет')
  37.       end
  38.     end;
  39.     if mm > 0 then // обработка случаев отсутствия некоторых компонентов вывода для сохранения пунктуационной правильности предложения
  40.       if dd > 0 then write(', ')
  41.       else write(' и ')
  42.     else
  43.       if dd > 0 then write(' и ')
  44.       else write('.')
  45.   end;
  46.   if mm > 0 then begin // если указано количество месяцев
  47.     write(mm);
  48.     case mm of // смотрим его значение
  49.       1: write(' месяц');
  50.       2, 3, 4: write(' месяца')
  51.     else write( ' месяцев')
  52.     end;
  53.     if dd > 0 then write(' и ') else write('.') // обработка случаев отсутствия некоторых компонентов вывода для сохранения пунктуационной правильности предложения
  54.   end;
  55.   if dd > 0 then begin // если указано количество дней
  56.     write(dd);
  57.     case dd of // смотрим его значение
  58.       11, 12, 13, 14: write(' дней.')
  59.     else // если оно не совпадает с указанными вариантами
  60.       case dd mod 10 of // смотрим последнюю цифру
  61.         1: write(' день.');
  62.         2, 3, 4: write(' дня.')
  63.       else write( ' дней.')
  64.       end
  65.     end
  66.   end
  67. end.

Валерий Шахамболетович!

Валерий Шахамболетович! Я очень надеюсь на Ваше внимание к этой задаче, так как оно демонстрирует методы алгоритмизации сразу в нескольких предметных областях, а также работу с числами в не встречавшейся в предыдущих задачах смешанной системе счисления (представление времени).