Практика программирования (Бейсик, Си, Паскаль)

       

Немного истории


Термин "календарь" обязан своим происхождением латинским словам calendae ("первый день месяца") и calendarium ("долговая книга"). В Древнем Риме на первое число каждого месяца приходилось время уплаты процентов по долгам.

Наиболее стабильным длительным промежутком времени с точки зрения ученых, ведущих астрономические наблюдения, является тропический год — интервал между моментами прохождения центра солнца через так называемую точку весеннего или осеннего равноденствия. Наблюдается это явление 21 марта и 23 сентября в обычный год и со смещением на один день — в високосный год. В этот момент лучи солнца падают на экватор отвесно и продолжительности ночи и дня совпадают. Длительность тропического года составляет 365 суток 5 часов 48 минут и примерно 46 секунд (365,2422 солнечных суток, длительность последних — 24 часа).

Древние календари, в большинстве своем, базировались на фазах Луны. Так, например, в Вавилоне год состоял из 12 лунных месяцев с чередующейся длительностью месяцев 29->30->29->30-> ... . Однако суммарная длительность такого года составляла 354 дня.

Один из первых солнечных календарей был принят в Египте примерно в IV в. до н. э. По египетскому календарю год состоял из 365 дней и включал 12 месяцев по 30 дней. В конце года 5 дней объявлялись праздничными и не входили ни в один из месяцев.

Наиболее близким к тропическому году стал римский календарь, принятый по указу императора Юлия Цезаря в 47 г. до н. э. Для ликвидации разницы с астрономическим годом длительность 46-го года была установлена в 432 дня. После этого вводились 3 обычных года по 365 дней, за которыми следовал 1 високосный год. Таким образом, средняя продолжительность римского года достигла 365,25 суток, что немного превышало длительность тропического года.

Тем не менее за 1500 лет набежало порядка 10 лишних суток. За очередное улучшение календаря принялся ватиканский ученый Луиджи Лилио. В 1582 году по указу папы Григория XIII был принят новый календарь, переход на который в разных странах растянулся на 200—300 лет. В России, например, новый календарь был введен декретом СНК РСФСР в январе 1918 года (после 31 января наступило 14 февраля, день недели при этом сохранился автоматически). Даты римского календаря стали называть "старым стилем", а даты григорианского календаря — "новым стилем". Суть ватиканской реформы заключалась в следующем. После четверга 4 октября 1582 года следующим днем объявлялась пятница 15 октября. Так устранялись набежавшие излишки. Второе новшество заключалось в том, что из круглых дат столетий исключались високосные годы, которые не делились нацело на 400. При этом средняя длительность года по григорианскому календарю оказалась больше тропического года всего на 26 с. Так что, разница в 1 сутки сможет набежать примерно к 4860 году.




Обратите внимание на специфику перехода от летоисчисления до новой эры. Первый год новой эры (эры Дионисия), последовавший после первого года до новой эры, отсчитывается от даты рождества Христова. С точки зрения математики, ему должен предшествовать нулевой год, которого не было. Поэтому в алгоритмах исчисления непрерывных календарных дат номера лет до новой эры следует считать отрицательными и увеличивать их на 1.

В конце того же XVI века астроном Джозеф Скалигер предложил новый способ отсчета времени. Начинался он от некоторого условного нуля (12 часов дня всемирного времени в понедельник 1 января 4713 года до новой эры, а с учетом приведенного выше замечания начальный год равен —4712) и представлялся в виде постоянно работающего таймера, отсчитывающего сутки и текущее время. Целая часть Юлианской даты JD (она была так названа в честь отца Скалигера) определяла количество суток, прошедших от начала отсчета, а дробная часть от 0,0 до 0,99999 соответствовала показанию суточных часов. Переход к следующей единице отсчета происходил в 12 часов очередного дня.

Например:

1 января 4712 г. до н.э. в 12 часов дня JD = 0.00000

2 января 4712 г. до н.э. в 12 часов дня JD = 1.00000

3 января 4712 г. до н.э. в 18 часов вечера JD = 2.25000

1 января 1900 г. в 12 часов дня JD = 2415021.0

22 июня 1941 г. в 4 часа утра JD = 2430167.66667

9 мая 1945 г. в 12 часов дня JD = 2431585.0

1 января 1999 г. в 12 часов дня JD = 2451180.0

1 января 2000 г. в 12 часов дня JD = 2451545.0

Следует заметить, что предложенная идея отсчета времени используется не только астрономами. В системах визуального программирования Borland C++ Builder и Delphi появился класс данных типа TDateTime, в объектах которого хранится обобщенное значение даты и времени в формате вещественного числа с двойной точностью (double). Его целая часть равна количеству дней, прошедших с полуночи 30 декабря 1899 года, а дробная часть соответствует времени дня. По сравнению с юлианской датой изменилась только точка начала отсчета.





Хранение даты и времени в формате юлианского дня представляется достаточно экономичным. Потребуется всего 8 байт для величины типа double, тогда как для запоминания символьной строки вида "YYYY/MM/DD HH:MM:SS" необходимо не менее 20 байт. Если нужно хранить только целую часть JD (тип long), то можно ограничиться 4 байтами. Конечно, для запоминания даты и времени в числовом машинном формате можно обойтись и 7 байтами (2 байта под год и по 1 байту под остальные компоненты). В некоторых системных программах MS-DOS попытки упаковать дату привели к еще более сжатым форматам. Вместо года Y хранится двоичное число, равное Y-1980 и принадлежащее интервалу [0,119], на номер месяца отведено 4 бита, а на все остальные компоненты — по 5 бит. Это позволило втиснуть дату и время в 32 двоичных разряда. Однако вместо полного номера года так можно представить только его младшие цифры, а вместо полного числа секунд — количество полусекунд. Для хранения дат создания файлов такой способ вполне пригоден, но для программ обработки календарных дат из более широкого временного интервала явно не годится.

Непрерывный таймер Дж. Скалигера удобен еще и тем, что позволяет очень просто вычислять различные временные интервалы как с точностью до суток, прошедших между двумя календарными датами, так и с точностью до секунд и даже долей секунды. В дальнейшем мы покажем, что по JD вычислить день недели можно всего за две операции.

Сложность заключается только в одном — надо перевести дату и время дня в показания юлианского хронометра. Первые алгоритмы такого перевода, которыми пользовались астрономы, базировались на таблицах юлианских дат, приходящихся на начало года. Дальше оставалось подсчитать порядковый день в году, соответствующий преобразуемой дате, и выполнить сложение. Однако для компьютерных программ табличный алгоритм неудобен, т. к. он связан с хранением довольно больших массивов, которые ежегодно приходилось пополнять.




Содержание раздела