РАБОТА С КАЛЕНДАРЕМ ТРЕБУЕТ ОСОБОГО ВНИМАНИЯ

А. КОЛЕСОВ.

(Похоже, в алгоритме Microsoft есть ошибка)

В результате обсуждения компьютерной проблемы Y2K обнаружилось любопытное обстоятельство: большинство как пользователей, так и разработчиков ПО не знают правил определения високосного года. Оказалось, что известный с детства способ определения високосного года делением на четыре без остатка не совсем точен. Что касается программистов, то они вскоре облегченно вздохнули, узнав, что этот алгоритм вполне подходит еще для ближайших ста лет: 2000 год действительно високосный как исключение из ряда вековых лет, номера которых оканчиваются на два нуля.

В связи с этим возникает принципиальный вопрос: а как вообще нужно вести календарь? Что касается компьютерных программ, то тут нужно сделать ряд уточнений.

Многие современные программы так или иначе связаны с текущим временем, причем пользователь может об этом и не знать: текущая дата часто используется программами в служебных целях. Поэтому существует понятие "времени жизни" программы. Например, сегодняшний вариант наиболее популярных операционных систем семейства Microsoft Windows рассчитан на работу до 2099 года.

Совсем другой вопрос - с каким диапазоном дат (в качестве обрабатываемых ею данных) может работать прикладная программа. Допустим, сегодня вы захотели забронировать билет на самолет в 2010 году. Наверняка программа, которая используется для решения этой задачи, к тому времени уже "умрет" (будет заменена на новую версию), но сделку она должна обработать уже сегодня, то есть уметь работать с датами как минимум до 2010 года включительно. Другой пример - программа, определяющая день недели по заданной дате. Например, для историка может быть важным ответ: в какой день недели родился Александр Пушкин?

Многие современные программы для работы с датами используют механизм, реализованный в средствах программирования корпорации Microsoft. Его идея очень проста.

Дата хранится в виде числа. (Чтобы не усложнять пример, будем считать, что в формате целого. На самом деле там используется вещественное число, что позволяет учитывать и время с точностью до секунд.) Нулевая дата - 30 декабря 1899 года, суббота. Задав число суток от начала отсчета, вы получаете дату и день недели. И наоборот. Например, 31 декабря 2099 года будет четвергом, 73500-ым днем от 30.12.1899. А минус тысячный день (-1000) от той же точки отсчета - 4 апреля 1897 года, воскресенье. Этот алгоритм рассчитан на ведение календаря в диапазоне от 01.01.100 до 31.12.9999.

Казалось бы, все очень просто, и если вы имеете дело с бизнес-задачами - можете не волноваться: там, вроде бы, все в порядке. Но если вы историк и работаете с историческими датами - вам следует дочитать эту статью до конца.

Зададим себе вопрос: какой был день накануне пятницы 15 октября 1582 года? Скорее всего, каждый даст очевидный ответ (а программы Microsoft его дают однозначно): четверг 14 октября 1582 года. И будут неправы. Если считать по григорианскому календарю (новый стиль), то это действительно четверг, но 4 октября. Если же имеется в виду юлианский календарь (старый стиль), то 15 октября был понедельник, а накануне - 14 октября, воскресенье.

Напомним кратко историю календарей (подробнее см. "Наука и жизнь" № 1, 1999 г.). Основа современного календаря была заложена реформой Юлия Цезаря в 46 г. до н. э. После ряда уточнений спустя 50 лет календарь принял современный вид. За исключением порядка определения високосного года. В юлианском календаре средняя длина года была принята 365,25 суток, поэтому високосным считался каждый четвертый год. Исследования астрономов еще в средние века позволили определить, что в этой величине имеется погрешность (солнечный год меньше на 11 мин 14 сек), из-за чего за каждые 128 лет накапливалась ошибка в 1 сутки.

В результате получилось, что к концу 16 века дата весеннего равноденствия приходилась не на 21 марта (как это было в 325 году, когда христианская церковь приняла юлианский календарь в качестве официального), а на 11 марта. А день весеннего равноденствия издавна является ключевой точкой для счета времени в истории человечества.

Ошибка в календаре была исправлена папой римским Григорием XIII, который в 1582 году своей буллой передвинул счет дней на 10 дней вперед: день после четверга 4 октября предписывалось считать пятницей, но не 5, а 15 октября. Чтобы избежать накопления новой ошибки в будущем, был также изменен порядок вычисления високосных годов: из их числа исключаются вековые годы (с двумя нулями в конце), кроме тех, число сотен которых делится без остатка на четыре. Поэтому 2000 год - високосный, причем во всех календарях: и юлианском, и григорианском!

Вывод из этого можно сделать следующий: нельзя использовать алгоритм вычисления даты по григорианскому календарю по временной шкале вниз от 15 октября 1582 года. Но именно так делается в алгоритмах Microsoft.

Простой пример: в григорианском календаре просто нет дат с 6 по 14 октября 1582 года, и вся информация об исторических событиях в предыдущий период приводится по старому стилю. С сегодняшней точки зрения разница в несколько дней, казалось бы, является пустяком, но для историка вопрос, допустим, привязки даты к дню недели может быть принципиально важным (когда произошла Куликовская битва 08.09.1380 - до выходного дня или после?). Не говоря уже о том, что в истории человечества был, например, день 29 февраля 1500 года - недопустимая дата с точки зрения Visual Basic.

Еще внимательнее нужно относиться к датам с конца 16 до начала 20 века. Ведь переход разных стран со старого на новый стиль был не одновременным. Например, Франция, Италия и Испания перешли на григорианский календарь в 16 веке, Германия - в 17-м, Англия - в 18-м, Япония - в 19-м, Россия и Китай - в начале 20-го. Это привело к появлению огромного числа исторических мифов: о том, что граф Калиостро в один день мог побывать и в Петербурге, и в Берлине; что парусники с фантастической скоростью переплывали Атлантику, и прочих.

Вывод из сказанного таков. При работе с историческими датами после 4 октября 1582 года просто необходима возможность работы как в новом, так и в старом стиле. А использование алгоритма григорианского календаря в обратную сторону от даты его введения - скорее всего, ошибка. Например, пользуясь алгоритмом Microsoft, мы получим, что даты Рождества Христова (25 декабря), то есть собственно момент рождения, совпадают в юлианском и григорианском календарях только в третьем веке нашей эры, а не в первом, как это должно быть.

В реальной жизни данная проблема вряд ли затронет кого-либо всерьез. Однако вспомним: знаменитая эпопея с заменой микропроцессоров Pentium компанией Intel в 1994 году также начиналась с незначительной ошибки, обнаруженной в ходе весьма экзотических астрономических расчетов. При довольно редком сочетании исходных данных происходила ошибка округления при делении, касавшаяся седьмого знака мантиссы результата. Несмотря на то, что вероятность такой ошибки исчислялась миллионными долями, развернувшаяся общественная дискуссия в средствах массовой информации заставила корпорацию Intel принять решение о замене процессоров всем обратившимся с такой просьбой. Потеряв на этой операции около полумиллиарда долларов в течение шести месяцев, компания не только восстановила, но и повысила свой престиж в качестве лидера отрасли высоких технологий. Такова сегодня цена доверия клиентов.

См. в номере на ту же тему

А. КОЛЕСОВ - А вы готовы к 2000 компьютерному году?

А. ШИШЛОВА - Y2K и прочие "баги".

Проблема 2000 года и законы Мерфи

Другие статьи из рубрики «Человек и компьютер»

Портал журнала «Наука и жизнь» использует файлы cookie и рекомендательные технологии. Продолжая пользоваться порталом, вы соглашаетесь с хранением и использованием порталом и партнёрскими сайтами файлов cookie и рекомендательных технологий на вашем устройстве. Подробнее