Компьютерные ошибки апокалипсиса: баги с датами, которые чуть не разрушили цивилизацию
Готовим шапочки из фольги, запасаемся гречкой и готовимся к 2038 году.


Иллюстрация: Midjourney / Colowgee для Skillbox Media
31 декабря 1999 года миллионы людей по всему миру готовились встречать не только новое тысячелетие, но и потенциальный цифровой апокалипсис. Вместо традиционных мандаринов и горошка в супермаркетах раскупали консервы, воду и батарейки. На форумах обсуждали не подарки, а сценарии краха банковской системы, обнуления счетов и падения самолётов.
Виной всему была «Проблема 2000 года» — баг, связанный с тем, как компьютеры хранили даты. На первый взгляд, техническая мелочь, на деле — угроза глобального масштаба, от которой пришлось защищаться усилиями государств, корпораций и тысяч программистов.
Если кажется, что следующий такой кризис не скоро — плохие новости: до него осталось всего 13 лет. В 2038 году мир рискует столкнуться с новой системной уязвимостью — на этот раз в Unix-подобных системах.
В этой статье разбираемся с причинами «Проблемы 2000 года и выясняем, как человечество снова оказалось в ловушке собственного кода.
Содержание
- Что такое «Проблема 2000 года»
- Предпосылки: когда каждый байт был на вес золота
- Человек, который заметил баг за 40 лет до катастрофы
- «Судный день 2000»
- Первые звоночки Y2K
- Попытки предотвратить цифровой коллапс
- Последствия Y2K
- Проблема 2038 года
- Какие компьютерные сбои ещё ждут человечество
Что такое «Проблема 2000 года»
В конце 1999 года мир охватила паника в ожидании «апокалипсиса», но речь шла не о метеоритах, эпидемиях или глобальном потеплении. Поводом для тревоги стала компьютерная ошибка.
О надвигающемся кризисе говорили не только учёные и инженеры, но и президенты, политики, главы крупнейших корпораций. Темой потенциального коллапса IT-систем всерьёз занимались на международных конференциях, а миллионы долларов уходили на авральные работы по исправлению кода. Причина была до боли простой: неправильная работа с датами, вызванная экономией памяти. Ошибку назвали просто: в России — «Проблема 2000 года», на Западе — Y2K (Year 2000).
Суть проблемы скрывалась в одной маленькой детали: раньше в программах год хранили в виде двух цифр: например, 1999 год записывали как 99, а 1987 — как 87. Такую форму записи выбрали, чтобы сэкономить память ещё в середине XX века, однако решение оказалось бомбой замедленного действия. 1 января 2000 года в поле даты год отобразился бы в виде двух нулей, что компьютеры по всему миру интерпретировали как 1900 год.
В перспективе это могло нарушить работу банковских сервисов, заводов, аэропортов, больниц и даже систем запуска ядерных ракет.

Читайте также:
Предпосылки: когда каждый байт был на вес золота
Истоки «Проблемы 2000 года» уходят в 1960-е — время, когда компьютеры занимали целые комнаты и больше напоминали промышленные шкафы, чем современные устройства. Вычислительные ресурсы тогда были ограничены, особенно не хватало памяти.
Для понимания масштабов: один из самых продвинутых мейнфреймов того времени, IBM System/360, поставлялся с объёмом оперативной памяти всего 2 килобайта. В таких условиях разработчики были вынуждены оптимизировать всё: данные, инструкции, структуры. Каждый бит имел значение.

Фото: United States Census Bureau / Wikimedia Commons

Читайте также:
Один из способов экономии — хранение даты в формате DDMMYY, а не DDMMYYYY. Например, дата 15.12.1965 в двоичном коде занимает 24 бита. А если записать просто 151265, то всего 18. Урезание двух цифр года казалось безобидной оптимизацией.
С точки зрения современной архитектуры ПО хранить год в виде двух цифр — не лучшее решение. Ведь было очевидно, что в какой-то момент наступит 1 января 2000 года и машины интерпретируют дату 010100 как 1 января 1900 года. Последствия для вычислений, требующих корректной работы с датами, могли быть катастрофическими: ошибки в расчётах, сбои в логике программ, неверная сортировка данных и даже отказ систем.
Но в 1960-х об этом почти никто не думал. Тогда приоритет был один — жёсткая экономия ресурсов. Инженеры не проектировали код на века и не ожидали, что его будут использовать спустя десятилетия. Многие полагали, что вычислительная техника останется нишевой, а её развитие будет ограничено мейнфреймами в лабораториях и крупных корпорациях.
Человек, который заметил баг за 40 лет до катастрофы
Одним из первых, кто распознал потенциальную угрозу Y2K, стал Роберт Бемер — инженер, пионер программирования и один из создателей символа Esc в ASCII. В 1958 году, работая над системой для хранения генеалогических данных, он заметил, что его компьютер не различает 1900 и 2000 год. С этого момента Бемер начал активно убеждать коллег в том, что сокращённое представление даты может привести к логическим ошибкам.
В 1971 году он опубликовал статью, в которой представил конкретные расчёты и сценарии последствий. Реакция была почти нулевая. Тогда он начал отправлять письма в крупные IT-компании, правительственные ведомства США и Пентагон. Бемер писал, что компьютеры уже берут на себя управление промышленной автоматикой, авиадиспетчерскими службами и системами ядерного контроля. Сбой из-за Y2K, подчёркивал он, способен вывести такие комплексы из строя и даже спровоцировать ошибочный запуск ракет.
Письма Бемера не давали результата. Замеченным оказалось только обращение к Ричарду Никсону — президенту США. Он попросил Национальное бюро стандартов решить проблему, но специалисты просто рекомендовали разработчикам записывать даты полностью с четырьмя цифрами в поле года. Речи об исправлении бага в коде уже существующих программах не было.
Бемер продолжал борьбу вплоть до выхода на пенсию в 1982 году. Эстафету по предупреждению человечества принял специалист по компьютерной безопасности Питер де Ягер.
«Судный день 2000»
В 1993 году статья Питера де Ягера Doomsday 2000 (в русском переводе — «Судный день — 2000») донесла масштаб проблемы до широкой аудитории. В отличие от прежних публикаций, наполненных теорией и абстрактными расчётами, Де Ягер говорил на языке, который могли понять все, а не только инженеры. Посыл статьи был простым: до массового коллапса в 2000 году осталось 2308 дней, человечество к этому не готово.

Изображение: Peter de Jager // Computerworld. 1993. Vol. 27. № 36. P. 105.
Также де Ягер впервые назвал, сколько надо времени и денег, чтобы исправить проблему с обработкой дат в корпоративных и государственных системах. По его подсчётам, для этого требовалось 50 миллиардов долларов и около 1,2 миллиона человеко-лет труда инженеров.

Питер де Ягер
Программист, который первым привлёк внимание широкой общественности к проблеме 2000 года
Вы когда-нибудь бывали в автомобильной аварии? Время будто замедляется, когда вы понимаете, что врежетесь в машину впереди. Слишком поздно, чтобы предотвратить это, — вы вот-вот разобьетесь. И всё, что вы можете сделать сейчас, — просто смотреть, как это происходит. Компьютерное сообщество движется к событию более разрушительному, чем автомобильная авария. Мы приближаемся к 2000 году. Мы приближаемся к падению нашего стандартного формата даты: мм/дд/гг.
Эффект был мгновенным. На Y2K обратили внимание правительства — в первую очередь США, а затем и других развитых стран. Крупные корпорации начали формировать специальные отделы по рефакторингу старого кода. Выяснилось, что первые проявления ошибки замечали уже в 1980-х, но случаи были единичными, поэтому их просто игнорировали.
Первые звоночки Y2K
Одним из ранних проявлениев «Проблемы 2000 года» был инцидент в британском супермаркете. В систему поступила партия консервов с датой годности 01.01.2000, но программа посчитала, что продукт просрочен уже почти сто лет, и отправила его на списание.
Похожая история произошла в 1997 году в Италии: 104-летняя женщина получила уведомление о зачислении в детский сад. Причина — ошибка в алгоритме, рассчитывающем возраст по дате рождения.
Проблемы возникали и в финансовом секторе. Ряд банкоматов отказывался принимать карты со сроком действия, истекающим в 2000 году, — ПО считало их уже просроченными, так как 00 воспринималось как 1900.
Ситуация вышла на новый уровень, когда в США два федеральных министерства сообщили о сбоях в своих IT-системах, связанных с переходом на новый век. Ошибки в расчётах мешали планировать бюджет, вести учёт и прогнозировать события.
Попытки предотвратить цифровой коллапс
В 1998 году президент США Билл Клинтон подписал указ о создании комитета по решению «Проблемы 2000 года». Страны-участницы G8 согласились, что проблема есть, и тоже создали комитеты и советы. В России проблемой глобального компьютерного сбоя занимались Государственный комитет по связи и информатизации и специальная правительственная комиссия, созданная при поддержке Совета безопасности.
Корпорации тоже начали помогать исправить ошибку. Их подход был прост: дать денег — и как можно больше. Например, телекоммуникационная компания AT&T в конце 1990-х тратила на борьбу с багом 500 миллионов долларов в год. Генеральный директор AT&T в шутку жаловался, что у программистов получалось выйти за рамки практически безграничного бюджета.
По разным оценкам, мировые расходы на решение «Проблемы 2000 года» варьировались от 300 до 600 миллиардов долларов. Средства уходили на аудит систем, переписывание кода, обновление оборудования, тестирование и наём консультантов.
Пока политики созывали комиссии, а консультанты выступали на форумах, реальную работу делали программисты. Их задача была предельно проста по формулировке: найти и исправить все участки кода, где годы хранились в форме двух цифр. Но на практике это означало анализ миллионов строк, написанных десятилетия назад, часто без документации и стандартизации.
Решений было немного — и ни одно из них не было идеальным.
Решение 1
Добавить столетие
Один из очевидных способов — просто добавить два дополнительных разряда для хранения века. Например, структура даты в COBOL могла выглядеть так:
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.
В ней:
- EMP-HIRE-DATE — имя переменной, представляющей дату целиком.
- EMP-HIRE-DATE-YR — вложенная структура для записи года.
- EMP-HIRE-DATE-CC — век, например 19 для 1999-го или 20 для 2023-го.
- EMP-HIRE-DATE-YY — последние две цифры года, например 99 для 1999 или 23 для 2023.
- EMP-HIRE-DATE-MM — месяц (01–12).
- EMP-HIRE-DATE-DD — день (01–31).
Такой подход был надёжен: дата становилась четырёхзначной и проблема откладывалась как минимум до 9999 года. Но был и минус: во многих системах, особенно написанных на старом COBOL, приходилось переделывать логику хранения, вывода и сравнения дат, что означало рефакторинг почти всех бизнес-процессов.

Читайте также:
Решение 2
Условная интерпретация года
Другой подход — условная интерпретация года. Программа просто проверяла, к какому веку относится дата. Например:
IF EMP-HIRE-DATE-YY > 50
MOVE 19 TO PRINT-HIRE-DATE-CC
ELSE
MOVE 20 TO PRINT-HIRE-DATE-CC
Этот метод был быстрым и дешёвым, поэтому его активно использовали в 1990-х. Однако решение было только временным, так как программа могла запутаться в интерпретации даты. Например, число 20 в коде могло быть как 1920-м, так и 2020 годом.
Решение 3
Компромиссное хранение
В некоторых системах дата хранилась в 3 байтах, упакованных в 4-битные сегменты. Это позволяло разработчикам добавить в формат даты дополнительный байт под столетие без кардинальной перестройки. Этот способ позволял отсрочить коллапс до 2100 или 2900 года — в зависимости от схемы кодирования.
Последствия Y2K
В роковую ночь с 31 декабря 1999 года на 1 января 2000 года Питер де Ягер был в самолёте. Он хотел на личном примере показать всему миру, что проблема решена и никаких кризисов не будет: самолёты не упадут, электростанции не взорвутся.
Масштабных сбоев в 2000 году не было, но появились локальные ошибки в системах, которые работали на устаревшем ПО:
- В Японии и Австралии были сбои в работе автобусов, в Китае в полночь вышли из строя таксометры.
- В Гонконге, на радость людям, у полиции перестали работать алкотестеры.
- В Греции около 10% кассовых аппаратов выдали чеки за 1900 год.
- В Дании компьютер решил, что первому ребёнку, родившемуся в 2000 году, уже 100 лет.
- Салоны видеопроката в США и Южной Корее выписали клиентам штрафы за то, что те не вернули видеокассеты вовремя. Вернуть их надо было 100 лет назад.
- В итальянской судебной системе из-за сбоя некоторым заключённым увеличили срок на 100 лет, а других программа, наоборот, порекомендовала выпустить на свободу.
- В итальянской судебной системе из-за сбоя некоторым заключённым увеличили срок на 100 лет, а других программа, наоборот, порекомендовала выпустить на свободу.
В Германии банк случайно перевёл клиенту 12 миллионов марок, оформив транзакцию на 30 декабря 1899 года.
В некоторых регионах заметили и более серьёзные последствия. Например, в больницах Египта, Швеции и Южной Корее перестали работать аппараты для гемодиализа и ЭКГ. В Великобритании возраст некоторых беременных женщин неправильно отобразился в программе для оценки риска синдрома Дауна. Из-за этого пострадали 154 пациентки.
Не ошиблись аналитики и насчёт атомных электростанций: в Японии на АЭС «Сика» вышло из строя оборудование радиационного контроля. К счастью, сбой быстро устранили и аварий не произошло.
В целом же последствия и ущерб от Y2K признали незначительными. Мир вздохнул спокойно. Правда, некоторые журналисты попытались разоблачить Роберта Бемера, Питера де Ягера и других жадных компьютерщиков, которые «нажились на выдуманной проблеме».
Проблема 2038 года
После Y2K казалось, что человечество извлекло урок. Но на горизонте уже маячит новый временной баг — и снова связанный с тем, как машины представляют даты. Речь о проблеме 2038 года (Y2038), актуальной для систем, работающих на 32-битных Unix-подобных ОС.
Суть проблемы
Отсчёт времени в Unix-системах ведётся от «эпохи Unix» — нуля, зафиксированного в 00:00:00 UTC 1 января 1970 года. Время хранится как количество секунд, прошедших с этого момента, и кодируется целым знаковым числом (signed int) в 32 бита.
Максимальное значение, которое можно представить в таком формате, — 2 147 483 647 секунд. Это соответствует дате: 03:14:07 UTC 19 января 2038 года. После этой отметки счётчик переполнится и начнёт отсчёт с −2 147 483 648, что может быть интерпретировано системой как 13 декабря 1901 года.
Последствия бага зависят от того, как конкретная программа использует время. Например, часы на некоторых компьютерах просто перестанут работать или уйдут в прошлое на почти 137 лет. В худшем случае ошибка может спровоцировать появление в программах вечных циклов, которые вызовут аварийное завершение работы.
Но в зону риска бага Y2038 попадают:
- файловые системы, использующие 32 бита для представления времени;
- базы данных с 32-битными полями времени;
- программы на SQL, которые используют команды типа UNIX_TIMESTAMP();
- любые 32-разрядные устройства, например, смартфоны, компьютеры, авиационные бортовые журналы, GPS-приёмники и банкоматы.
Если строить фантастические картины в духе паники прошлого столетия, то 19 января 2038 года самолёты начнут сбиваться с курса, на дорогах выстроятся многокилометровые пробки, банкоматы перестанут выдавать наличные, телефоны превратятся в бесполезные кирпичи и весь мир останется без интернета. Всё это звучит пугающе, но на самом деле инженеры уже начали решать проблему Y2038.
Превентивные решения
Чтобы избежать «Проблемы 2038 года», разработчики предлагают несколько решений. Одно из наиболее очевидных — заменить 32-битное знаковое целое число (int32_t) на 64-битное (int64_t) и хранить не секунды, а, например, миллисекунды или микросекунды с начала эпохи Unix. Это увеличивает диапазон возможных дат на 292 тысячи лет.
Многие современные системы уже перешли на новые форматы представления времени:
- Ruby, начиная с версии 1.9.2, использует 64-битное представление времени.
- NetBSD 6.0, OpenBSD, FreeBSD перешли на 64-битный time_t в своих ядрах и пользовательских библиотеках.
- Linux исторически ориентировался на 64-битные архитектуры.
- PostgreSQL с 2002 года хранит тип timestamp как 64-битное значение, что делает его устойчивым к Y2038.
Главная проблема остаётся с языком C, в котором тип time_t до сих пор реализован как 32-битный signed int. Любая попытка изменить его размер влияет на бинарную совместимость с существующими библиотеками и приложениями. Программисты пока не придумали эффективного решения проблемы. Основная ставка делается на естественное вымирание 32-битных систем к 2038 году
Какие компьютерные сбои ещё ждут человечество
Увы, невозможно точно предсказать, какие ошибки ждут нас в ближайшем будущем. Как показывает история, глобальные баги чаще всего находят случайно. Например, как в случае с решением проблемы Y2K, когда наименее затратное решение просто отодвинуло проблему до 2020 года.
Можно с высокой долей уверенности сказать: решения, которые сегодня кажутся надёжными и оптимальными, через 50 лет станут поводом для паники будущих программистов, политиков и журналистов.

Больше интересного про код — в нашем телеграм-канале. Подписывайтесь!