Об ошибке 2000 года в общественном сознании быстро забыли. Её обсуждали месяцами в профильных изданиях, но уже в первые дни наступившего года интерес угас. Произошедшее не привело к катастрофам, которые так пугали.
За кулисами ситуация была гораздо серьёзнее, чем представляли неспециалисты. Опасность компьютерных сбоев действительно существовала, и над устранением проблемы Y2K работали целые отделы программистов.
В повседневной жизни мы не записываем первые два символа года, они почти всегда одинаковые, поэтому и на компьютерах их можно отбросить. Это экономит место на накопителях.
Но без контекста невозможно установить, прожил ли человек полноценную жизнь или внезапно умер после родов. Также компьютер не отличит 2000 год от 1900. Это и есть ошибка Y2K.
Срок действия на банковской карте указывается в виде MM/YY, и некоторые алгоритмы платёжных систем проверяли просроченность арифметическим сравнением чисел YYMM. В 1999 году такой алгоритм назовёт недействительной карту со сроком действия 12/01, до декабря 2001 года.
Часто говорят, что источник проблем — наследие первых компьютеров и языков программирования. Это лишь отчасти так: заря компьютерной эпохи заложила традиции разработки, которые живут до сих пор.
Здесь YY — две цифры года, MM — номер месяца, DD — день.
01 EMP-HIRE-DATE.
03 EMP-HIRE-DATE-YY PIC 99.
03 EMP-HIRE-DATE-MM PIC 99.
03 EMP-HIRE-DATE-DD PIC 99.
Здесь дата представлена в виде 3 байтов, по 4 бита на каждую из цифр. Кобол настолько древний, что даже числа в нём десятичные (если не указано обратное, USAGE IS COMPUTATIONAL).
Стандартизированного поля даты в Коболе нет, но самописные реализации всё же чем-то руководствовались. Код ACCEPT todays-date FROM DATE возвращает текущую дату системы в виде 6-значного числа формата YYMMDD. Если его сравнить с числом из представления выше, то легко понять, наступил этот день или нет. Функция CENTURY-DATE, которая возвращала дату в виде 8-значного числа YYYYMMDD с указанием века, появится в более поздних стандартах языка.
По дате формата YYMMDD удобно сортировать: сравнение, что случилось раньше, сводится к арифметической операции.
С наступлением нового века сортировка сломается: год 00 должен быть позднее 99, а не наоборот. Число 000101 окажется меньше, чем 991231, то есть 1 января 2000 года программа скажет, что 31 декабря 1999 ещё не наступило. Попытка вычислить срок между этими датами вернёт почти 100 лет, а не 1 сутки.
Даже при обновлении старых систем формат даты не меняли, чтобы сохранить совместимость с существующими базами данных и другими компонентами. Программист не задумывался, что его софтом будут пользоваться через 20—30 лет. Для него «ошибка 2000 года» звучит ещё более отдалённо, чем для нас «переполнение 32-битного Unix-времени». Последнее случится уже в 2038 году и исправлено в Linux для 32-битных систем только с версии ядра 5.6. Но почему-то мы не торопимся обновлять старые маршрутизаторы.
Часть «вины» лежит на распространении двоично-десятичного кода (BCD), в котором каждый разряд десятичного числа записан 4 битами. В BCD невозможна ситуация, когда при сложении 0,1 и 0,2 получится 0,30000000000000004, как в двоичном коде с плавающей запятой. Это нервирует бухгалтеров и финансистов. Поэтому процессоры для бизнес-применений поддерживали нативную обработку BCD, и переводить числа между формами записи приходилось меньше.
Дата из 6 цифр уместится в 3 байта. Но перевод её в двоичное целое число потребует сложных математических действий. Это дольше, чем перевод BCD в десятичный код. Двоично-десятичный код добавляет лишние байты в запись даты, но избавляет от ассемблерных инструкций и упрощает код.
В восьмидесятые программисты переходили на настольные персональные компьютеры. Их встречала знакомая аппаратная поддержка BCD. Наконец, часть проблем касалась календаря. Если 2000 год високосный, то 1900 — нет. В 2000 году есть 29 февраля. Если компьютер посчитает, что на дворе 1900 год, то после 28 февраля наступит сразу 1 марта.
Канадский программист Питер де Ягер привлёк внимание общественности к проблеме смены веков. В 1978 году он обнаружил, что компьютер может принять два нуля за 1900 год. Руководство IBM отнеслось к его жалобе с пренебрежением, утверждая, что проблему решат к 2000 году.
В 1989 году де Ягер ради эксперимента сдвинул время на своём компьютере на несколько минут назад до полуночи 31 декабря 1999 года, и через десять минут дата сменилась на 1984 год. Это подтвердило его опасения.
В 1993 году де Ягер написал статью в журнал Computerworld, которая привлекла всеобщее внимание к проблеме Y2K. Его красочные описания грядущей беды не воспринимались всерьёз, но по мере приближения 2000 года его репутация эксперта в области цифрового армагеддона росла. С тех пор де Ягер занимался исключительно проблемой дат.
В индустрии давно замечают странности обработки дат. Британский продуктовый магазин получил партию консервов с указанным сроком годности 01/00. Система учета приняла это за январь 1900 года и потребовала утилизировать продукцию.
В середине 1997 года компания «Крайслер» для тестирования перевела часы завода в Стерлинг-Хайтсе на 31 декабря 1999 года. В результате сотрудники не могли войти и выйти из помещений.
В конце 90-х в компаниях появились специальные команды инженеров, которые занимались исправлением бага Y2K. На саммите «Большой восьмёрки» в 1998 году все участники признали опасность бага. В России этим вопросом занимались Госкомсвязи и специальная правительственная комиссия.
Паника была повсеместной. Журналисты и писатели начали рисовать картину цифрового Апокалипсиса. Даже крупные и уважаемые издания рекомендовали запасаться водой и продовольствием.
Добавление двух цифр решает проблему на 8000 лет.
01 EMP-HIRE-DATE.
03 EMP-HIRE-DATE-YR.
05 EMP-HIRE-DATE-CC PIC 99.
05 EMP-HIRE-DATE-YY PIC 99.
03 EMP-HIRE-DATE-MM PIC 99.
03 EMP-HIRE-DATE-DD PIC 99.
Но длина записи в Коболе ограничена. Если нужно вставить два байта по центру, придётся переписать весь файл с нуля в новый и заменить оригинал исправленной копией. Код приложения, которое обрабатывает этот файл, тоже придётся скорректировать. Процесс сулит долгое тестирование и отключения. Не всегда базу данных получается вот так тормознуть.
Относительно небольшое обновление кода программы не так изящно и добавляет лишь несколько десятилетий жизни, но менее затратно по времени. Пусть если год меньше 50, то это уже новый XXI век.
IF EMP-HIRE-DATE-YY > 50
MOVE 19 TO PRINT-HIRE-DATE-CC
ELSE
MOVE 20 TO PRINT-HIRE-DATE-CC.
Не все данные позволяют быть уверенными в невозможности дат до 1950 и после 2050 года. В некоторых случаях «костыли» продлевали жизнь на 20 лет. В январе выяснили, что счета приходили из 1920 года, а ПО не работало.
Y2K исправляли не всегда до 10 000 года. Если 3 байта даты хранились в 4-битном знаковом числе, а в полбайта влезет одна цифра для подписи века, то программы могут быть подвержены проблеме 2100 или 2900 года.
Дату можно представить как число дней, прошедших от точки отсчета в прошлом. Так можно представить 16 384 различных лет.
Иногда запись года вовсе не исправляли. Формат TLE (для описания объектов на орбите Земли) до сих пор указывает лишь 2 последних символа года, хотя на ситуацию могут повлиять компании спутникового Интернета, которым потребуются десятки тысяч аппаратов на орбите.
Детали патчей военного оборудования держатся в секрете. Чаще всего в СМИ публиковали сообщения об успешной проверке на готовность к Y2K с помощью симуляторов и тестовой среды. Иногда проходили полноценные боевые испытания.
В 1999 году только 7% американцев беспокоились об ошибке 2000 года. 31 декабря Питер де Ягер провёл в полёте, чтобы показать безопасность патчей. Утро 1 января не принесло никаких сбоев. Но критика имела основания: комиссии и эксперты перестарались и обещали несбыточное.
Мир не пал из-за микросхем, где год представлен двумя знаками. Они слишком распространены, чтобы их все заменить. На деле же перевода и сравнения дат на этих микросхемах просто не происходит.
Пугающий сценарий предполагал развитие каскада отказов, но на деле если одна подсистема ошибочно выдаст год 1900, то другая его либо передаст дальше, либо выдаст ошибку, либо пометит год неверным.
Готовая к Y2K уязвимая к багу 2000 года система из-за неучтённого високосного дня 29 февраля может получить разрешение на посадку на одну и ту же полосу. Но веб-приложение не начнёт передавать по всей системе неправильную запись в базе данных.
Обыватель не ощутил ни подготовку к багу, ни бессонную ночь на рубеже веков для команд технической поддержки, ни последствия непропатченных систем. Очевидцы и руководители команд устранения Y2K вспоминают незначительные сбои.
В одном из регионов Англии из-за бага Y2K после наступления 2000 года было слишком много детей, рождённых с синдромом Дауна.
Программа оценки неправильно посчитала возраст 154 беременных женщин и некорректно выставила группу риска. В итоге у матерей с неправильно определённой низкой группой риска появились четыре ребёнка с синдромом Дауна. А из-за неверной оценки высокого риска два аборта были проведены по ошибке.
Исправление ошибки 2000 года стоило сотни миллиардов долларов. Специалисты оправдывались: проблема была и исправлена. Кто-то радовался общественному вниманию к вопросам критической инфраструктуры и апгрейдам.
События, когда заканчиваются знаки, случались и будут случаться. Переход с IPv4 на IPv6 призван решить проблему дефицита интернет-адресов. К телефонным номерам добавят еще одну цифру. В 19 января 2038 году для непропатченных систем Unix наступит либо 1970 год, либо, из-за использования знаковой переменной, 1901 год.
У любого информационного проекта есть ограничения, но это не страшно. Если система выходит за эти рамки, это свидетельствует о ее популярности.