Ошибка 2038 года

Как вы хорошо знаете, в Unix-системах мы измеряем время как количество секунд, прошедших с «эпохи»: 00:00:00 UTC 1 января 1970 года. Немало людей сильно разозли...

Как вы хорошо знаете, в Unix-системах мы измеряем время как количество секунд, прошедших с «эпохи»: 00:00:00 UTC 1 января 1970 года. Немало людей сильно разозлилось из-за этого, да и вообще, общественное мнение сочло это ошибкой.

Во-первых, это определение основано не на чём-то разумном, например, на объективной частоте колебаний атома цезия-133, а на удобной доле времени полного оборота одного большого камня вокруг собственной оси.

Во времени Unix каждый день гарантированно состоит из 86400 секунд и мы притворяемся, что это число равномерно увеличивается. Когда оказывается, что вышеупомянутый камень на самом деле вращался дольше, чем удобно для нас, и нам нужно добавить секунду координации, то мы просто притворяемся, что этого не было, а механизм меток времени не идентифицирует уникальный момент времени.

Ещё один аспект, который продолжает вызывать проблемы, когда мы пытаемся считать секунды, заключается в том, что мы сталкиваемся с проблемами хранения и описания данных, потому что, как оказалось, компьютеры не так уж хорошо справляются с числами. Не говоря уж об «эпохальном сбое».

Как же мы к этому пришли? Всё началось в 1971 году, когда в в первом издании руководства для программиста Unix было дано определение времени Unix как «времени с 00:00:00 1 января 1971 года, измеряемого в шестидесятых долях секунды«:

Именно так, изначально эпохой Unix было 1971-01-01T00:00:00. Вы спросите, какого часового пояса? Ну, это точно не был «UTC», потому что он заменит GMT в качестве стандартного времени только в 1972 году. Во-вторых, обратите внимание, что время измерялось в 1/60 секунды, а не в секундах. Зачем же так сделали?

Вспомним, что в то время Unix разрабатывался в США на PDP-11. Эти системы имели часы линейного времени (Line-Time Clock, LTC), использующие частоту питания переменного тока для генерации прерывания для процессора. Тогда это прерывание использовалось для обновления системных часов.

Забавно здесь то, что эта частота прерываний зависит от частоты в сети источника питания. В основной части Азии и Европы эта частота равна 50 Гц, однако в США Westinghouse Electric Corporation (конкурент Томаса Эдисона и General Electric; любопытный факт: позже Westinghouse приобрела CBS, а затем была куплена Viacom) заметила, что использовавшиеся тогда дуговые лампы с угольным электродом меньше мерцают при 60 Гц, а поэтому стандартизировала эту частоту.

(Странный побочный эффект этого различия между США и Европой заключается в том, что в Японии используются обе частоты: на западе, где первые генераторы были куплены у немецкой AEG и установлены в Токио, частота в сети равна 50 Гц; на востоке, в Осаке, были установлены генераторы G.E., и используются 60 Гц. В результате этого в стране теперь работает множество высоковольтных линий постоянного тока для преобразования электричества между двумя регионами!)

Электросеть Японии

Итак, в первом издании UNIX измерял время на этих 60 Гц с хранением в 32-битных integer, таким образом имея возможность учитывать только 2^32 / 60 тактов/с * 60 с/мин * 60 мин/ч * 24 ч/д * 365 д/г = 2,3 лет, как и написано в руководстве. Несколько позже в том же 1971 году измерению времени было дано другое определение, оно учитывалось в секундах и могло описывать до 136 лет. Датой же эпохи Unix был достаточно произвольно выбран 1970 год (вопреки распространённому заблуждению о том, что она обозначает дату рождения Unix):

«В то время у нас не было плёночных накопителей, работала пара файловых систем, и мы постоянно меняли начало отсчёта времени. Поэтому в конце концов мы сказали: давайте выберем что-то одно, что достаточно долго не будет переполняться. Нас вполне устроил 1970 год», — сказал он.

Дэннис Ритчи, Wired

(Истинная дата рождения Unix приходится примерно на 1969 год, когда Кен Томпсон портировал «Space Travel» на PDP-7, поэтому легко понять, почему эпоха Unix кажется обозначением рождения Unix.)

Секунды координации

Итак, теперь у нас есть 32-битный счётчик секунд от эпохи, который равномерно увеличивает значение с частотой 1 Гц и гарантирует нам, что будет насчитывать ровно 86400 секунд в любой 24-часовой период. Однако наш космический булыжник отсчёта замедляется в своём вращении, поэтому время от времени это число нужно изменять.

Для этого Международная служба вращения земли (IERS) отправляет всем Повелителям Времени электронные письма, сообщающие, должна или нет добавляться секунда координации:

Сегодня мы не можем винить время эпохи Unix за то, что оно изначально не учитывало секунды координации, потому что их не существовало до 1972 года. С тех пор (на 2022 год) произошло уже 27 положительных секунд координации, последняя из которых была введена в конце 2016 года. Каждый раз, когда происходит секунда координации, время эпохи Unix просто притворяется, что этого не было, из-за чего две даты соответствуют одной метке времени эпохи (epoch-time.c):

From epoch to time, via gmtime(3) to strftime(3):
1483228798 2016-12-31T23:59:58
1483228799 2016-12-31T23:59:59
//здесь отсутствующая секунда координации
1483228800 2017-01-01T00:00:00

From time to epoch, via strptime(3) to mktime(3):
2016-12-31T23:59:58 is 1483228798
2016-12-31T23:59:59 is 1483228799
2016-12-31T23:59:60 is 1483228800
2017-01-01T00:00:00 is 1483228800 //здесь дублирующаяся метка времени

(И давайте не забывать обо всех отрицательных секундах координации и тот факт, что некоторые системы Unix определяют диапазон tm_sec как [0-61], учитывая мифическую «двойную секунду координации», которой на самом деле никогда не существовало.)

Хорошо в этом то, что всё это соответствует требованиям POSIX:

4.16 Секунды после эпохи

Значение, которое аппроксимирует количество секунд, прошедшее после эпохи.

Соотношение между истинным временем суток и текущим значением секунд после эпохи точно не установлено.

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

Проблема 2038 года

Даже при равномерном отсчёте и игнорировании секунд координации используемый для измерения секунд после эпохи тип данных time_t неизбежно придёт к переполнению. Хорошо, что есть стандарты, которые спасут нас в этой ситуации! Пусть POSIX не решает проблемы, но хорошо в стандартах то, что их много и можно выбрать подходящий, не так ли? Ох, постойте, в чём же дело? Давайте разберёмся.

Плохие новости: стандарты нас не спасут. Например, стандарт C гласит:

Диапазон и степень точности времени, представленного в clock_t и time_t, зависят от реализации.

Что ж, ладно. Имея 32-битный time_t, мы можем рассчитывать начиная с 1970 года примерно на 136 лет. Однако time_t является знаковым 32-битным integer, то есть у нас есть всего 68 лет в обоих направлениях, из-за чего возникает так называемая «Проблема 2038 года».

Она состоит в том, что самая большая дата, которую можно записать как time_t при помощи знакового 32-битного integer — это 2^31 - 1 = 2147483647 эпохи, или 2038-01-19T03:14:07Z:

Это легко исправить, правда? Мы «просто» изменяем тип данных time_t на знаковый 64-битный integer, что даёт нам теоретический максимум даты эпохи 2^63-1 = 9223372036854775807 после 1 января 1970 года. Как любят говорить люди, это значение задаёт дату примерно на 292 миллиарда лет в будущем, или примерно в 22 раз больше приблизительного возраста Вселенной, поэтому официально может считаться Чьей-то Чужой Проблемой.

Но — всегда есть «но», не правда ли? — действительно ли это произойдёт? Почему бы не попробовать и не проверить, как разные системы поведут себя, если мы передадим им для обработки не совсем логичные значения времени?

Оборот mktime(3)

Хотя время представлено в виде time_t, используется и другой популярный формат для записи разбитого на части времени — struct tm, из которого можно получить time_t, вызвав mktime(3). В POSIX зафиксированы следующие элементы struct tm:

int    tm_sec   Seconds [0,60]. 
int    tm_min   Minutes [0,59]. 
int    tm_hour  Hour [0,23]. 
int    tm_mday  Day of month [1,31]. 
int    tm_mon   Month of year [0,11]. 
int    tm_year  Years since 1900. 
int    tm_wday  Day of week [0,6] (Sunday =0). 
int    tm_yday  Day of year [0,365]. 
int    tm_isdst Daylight Savings flag.

Забавно в описанных здесь диапазонах то, что они в лучшем случае являются… рекомендательными. В POSIX конкретно написано:

… исходные значения […] компонентов не должны быть ограничены диапазонами, описанными в <time.h>.

Так что же произойдёт, если передать mktime(2) тип struct tm со значениями вне этих диапазонов? Рассмотрим следующую программу:

int main() {
        struct tm t;
        time_t epoch;

	/* 2022-12-31 */
        t.tm_year = 122; t.tm_mon = 11; t.tm_mday = 31;

	/* 22:57 */
        t.tm_hour = 22; t.tm_min = 57;

        t.tm_sec = 3785;

        if ((epoch = mktime(&t)) == -1) {
                err(EXIT_FAILURE, "mktime");
        }

        (void)printf("%s", ctime(&epoch));

	return 0;
}
$ cc -Wall -Werror -Wextra t.c
$ ./a.out
Sun Jan  1 00:00:05 2023
$ 

Здесь перед присвоением tm_sec значения наш struct tm задавал дату December 31st, 22:57:00, 2022. Но потом мы присвоили tm_sec значение 3785, то есть 1 час, 3 минуты и 5 секунд. Это приводит к тому, что выполняется инкремент tm_min на 3 минуты, что приводит к увеличению tm_hour на единицу. Затем мы ещё раз выполняем инкремент tm_hour (из оставшихся от tm_sec 3600 секунд), что приводит к оборачиванию этого значения на 00 и необходимости инкремента tm_mday. Теперь tm_mday оборачивается до 01 с инкрементом tm_year, и в результате мы получаем дату 2023-01-01T00:00:05.

Такая нормализация меток времени становится ещё более запутанной, когда мы добавляем отрицательные значения (например, tm_mday = -1 означает предыдущий день tm_mon - 1) или (снова) при участии секунд координации, что может стать причиной головной боли. Лучше избегать такой ситуации.

Забавная date(1)

Давайте рассмотрим даты эпохи в момент или рядом с эпохой. Проигнорируем тот факт, что время эпохи до 1972 года определено не очень чётко, поскольку время эпохи по определению считается в UTC, но (см. выше) UTC стандартизировали только в 1972 году. Ну, мы поступим точно так же, как Unix поступает с секундами координации, и притворимся, что это нас не волнует.

Отобразить произвольную дату при помощи команды date(1) довольно легко. Достаточно просто передать дату в формате CCyymmddHHMM.SS. Если только вы не работаете в Linux, где date(1) GNU хочет использовать, наверное, самый выбешивающий формат (MMDDhhmmCCYY.ss). Зачем вставлять год между минутами и секундами?

Однако использование любого из этих форматов всё равно бесполезно для наших целей, потому что в определённый момент нам нужно будет выйти за пределы годов из четырёх цифр, поэтому давайте укажем непосредственно секунды после эпохи («-r <seconds>» для date(1) в BSD, «--date @<seconds>» для date(1) в GNU).

Отобразить даты в момент эпохи или рядом с ней довольно просто:

NetBSD / FreeBSD / macOS:
$ date -r 0
Thu Jan  1 00:00:00 UTC 1970
$ date -r -1
Wed Dec 31 23:59:59 UTC 1969
$ date -r 1 
Thu Jan  1 00:00:01 UTC 1970

Linux:
$ date --date @0
Thu Jan  1 12:00:00 AM UTC 1970
$ date --date @-1
Wed Dec 31 11:59:59 PM UTC 1969
$ date --date @1
Thu Jan  1 12:00:01 AM UTC 1970

OmniOS (с использованием даты GNU)
$ date -r 0
January  1, 1970 at 12:00:00 AM UTC
$ date -r -1
December 31, 1969 at 11:59:59 PM UTC
$ date -r 1
January  1, 1970 at 12:00:01 AM UTC

(date(1) GNU, использующая AM/PM вместо 24 часов, раздражает, ну да ладно.)

Давайте посмотрим, что произойдёт, если мы попробуем проверить 32-битный time_t. Как говорилось выше, проблема 2038 года возникнет в 2147483648 / -2147483649 эпохи:

netbsd$ date -r 2147483647
Tue Jan 19 03:14:07 UTC 2038
netbsd$ date -r 2147483648
Tue Jan 19 03:14:08 UTC 2038
netbsd$ date -r -2147483648
Fri Dec 13 20:45:52 UTC 1901
netbsd$ date -r -2147483649
Fri Dec 13 20:45:51 UTC 1901

linux$ date --date @2147483647
Tue Jan 19 03:14:07 AM UTC 2038
linux$ date --date @2147483648
Tue Jan 19 03:14:08 AM UTC 2038
linux$ date --date @-2147483648
Fri Dec 13 08:45:52 PM UTC 1901
linux$ date --date @-2147483649
Fri Dec 13 08:45:51 PM UTC 1901

omnios$ date -r -2147483648
December 13, 1901 at 08:45:52 PM UTC
omnios$ date -r -2147483649
date: failed to parse -r argument: -2147483649
omnios$ date -r 2147483647
January 19, 2038 at 03:14:07 AM UTC
omnios$ date -r 2147483648
date: failed to parse -r argument: 2147483648

О, постойте-ка. Похоже, у OmniOS возникают проблемы с датами эпохи после 2^31. Интересно, что произойдёт, если мы не только отобразим дату, но и установим её? Давайте в цикле установим дату и выведем её:

omnios$ for s in 5 6 7 8; do sudo date -u 011903142038.0$s; date; done
January 19, 2038 at 03:14:05 AM UTC
January 19, 2038 at 03:14:05 AM UTC
January 19, 2038 at 03:14:06 AM UTC
January 19, 2038 at 03:14:06 AM UTC
January 19, 2038 at 03:14:07 AM UTC
December 13, 1901 at 08:45:52 PM UTC //!!!
ld.so.1: date: fatal: /lib/libc.so.1: Value too large for defined data type
Killed
omnios$ date
ld.so.1: date: fatal: /lib/libc.so.1: Value too large for defined data type
Killed
omnios$ ls
ld.so.1: ls: fatal: /lib/libc.so.1: Value too large for defined data type
Killed
omnios$ sudo reboot
sudo: unknown uid 100
sudo: error initializing audit plugin sudoers_audit
omnios$

Замечательно. Обратите внимание, что дата на самом деле оборачивается, но ОС сходит с ума. Но ведь у других систем не должно быть никаких проблем с установкой даты, правильно?

netbsd# date 197001010000; date +%s
Thu Jan  1 00:00:00 UTC 1970
0
netbsd# date 196912312359
date: settimeofday: Invalid argument
netbsd$

linux$ sudo date -s @0
date: cannot set date: Invalid argument
Thu Jan  1 12:00:00 AM UTC 1970
linux$ uptime; sudo date -s @7080
 03:34:27 up  1:57,  1 user,  load average: 0.04
Thu Jan  1 01:58:00 AM UTC 1970

Вот так, в NetBSD мы не можем установить дату до эпохи, а в Linux (с версии ядра 4.3) мы не можем установить дату до текущего аптайма. settimeofday(2) вернёт EINVAL из-за гарантий, даваемых его «CLOCK_MONOTONIC«, который, согласно POSIX, «представляет количество времени после неуказанной точки в прошлом«:

Все варианты CLOCK_MONOTONIC гарантируют, что время, возвращаемое последовательными вызовами, не будет идти вспять, однако последовательные вызовы могут (в зависимости от архитектуры) возвращать идентичные (неувеличившиеся) значения времени.

С учётом всего этого, похоже, OmniOS вычисляет аптайм на основе времени запуска относительно системной даты, а, например, NetBSD и Linux хранят отдельные счётчики:

omnios$ sudo date -u 010100001970.00
January  1, 1970 at 12:00:00 AM GMT
omnios$ uptime
00:01:46    up -49 min(s),  1 user,  load average: 0.00, 0.00, 0.02
omnios$ sudo date -u 011803142038.00
January 18, 2038 at 03:14:00 AM GMT
omnios$ uptime
03:14:11    up 5567 day(s), 7 min(s),  1 user,  load average: 0.24, 0.16, 0.07

Попытка установить дату до эпохи тоже приводит к разным результатам. В NetBSD и Linux это сделать просто не удастся, а в OmniOS будет установлен месяц, день, час, минута и секунда, однако год будет ограничен значением 1970:

omnios$ sudo date -u 020100001969.00
February  1, 1970 at 12:00:00 AM GMT
omnios$ date
February  1, 1970 at 12:00:01 AM UTC
omnios$ sudo date -u 121308451901.52
December 13, 1970 at 08:45:52 AM GMT
omnios$ date
December 13, 1970 at 08:45:54 AM UTC

Но какую максимальную дату мы можем установить в системах, использующих 64-битный time_t? Как говорилось выше, можно ожидать, что доступно время до 2^63 - 1 = 9223372036854775807 эпохи. Давайте сначала отобразим дату, а затем попытаемся её установить:

netbsd$ date -r 9223372036854775807
date: 9223372036854775807: localtime: Value too large to be stored in data type
netbsd$ date -r 67768036191676799
Wed Dec 31 23:59:59 UTC 2147485547
netbsd$ date -r 67768036191676800
date: 67768036191676800: localtime: Value too large to be stored in data type

linux$ date --date @9223372036854775807
date: time ‘9223372036854775807’ is out of range
linux$ date --date @67768036191676799
Wed Dec 31 11:59:59 PM UTC 2147485547
linux$ date --date @67768036191676800
date: time ‘67768036191676800’ is out of range
linux$

freebsd$ date -r 9223372036854775807
date: invalid time
freebsd$ date -r 67768036191676799
date: invalid time
freebsd$ date -r 67767976233532799
Tue Dec 31 23:59:59 UTC 2147483647
freebsd$ date -r 67767976233532800
date: invalid time

Это интересно. Несмотря на то, что нам обещали 64-битный time_t, мы не можем установить время на 9223372036854775807. Похоже, максимальное значение равно 67768036191676799 в 2147485547 году. Хотя поначалу это значение кажется произвольным, можно заметить, что 2147485547 — это 2^31 - 1, и внезапно всё обретает смысл: даже несмотря на то, что time_t является 64-битным, tm_year структуры struct tm всё равно остаётся 32-битным, а потому максимальным значением, которое он может задать, является последняя секунда 2147485547 года.

А как дела в FreeBSD? Почему в ней время 67768036191676799 эпохи является недопустимым, а 67767976233532799 эпохи соответствует тому, что на других платформах является 67768036191676799? Если провести вычисления, то можно заметить, что разница между этими двумя моментами времени эпохи равна 1900 годам, то есть, очевидно, FreeBSD основывает свой tm_year не на 1900 годе (как заявляется struct tm в <time.h>), а на 0 годе? Так как я не смог с этим разобраться, то отправил баг-репорт.

Если мы попытаемся установить дату, то поначалу заметим, что при использовании date(1) NetBSD невозможно установить дату выше 9999 года (ещё один баг-репорт), но забавно, что на самом деле это не важно, поскольку мы всё равно не можем добраться выше 4147 года:

netbsd# date 414708200732.17
date: settimeofday: Invalid argument
netbsd# date 414708200732.16; date +%s
Sun Aug 20 07:32:16 UTC 4147
68719476736

Так получилось потому, что в NetBSD есть жёстко прописанное ограничение в 2^36 = 68719476736 для значения tv_sec, которое принимается при установке времени, потому что бОльшие значения вызывают недовольство KUBSAN (код):

        /*
         * Установка завышенного значения времени
         * приводит к недопустимому поведению системы.
         */
        if (ts->tv_sec < 0 || ts->tv_sec > (1LL << 36))
                return EINVAL;

В Linux используется другой практический максимум даты, установленный на 2232 год:

linux$ sudo date -s @8277292036
date: cannot set date: Invalid argument
Wed Apr 18 11:47:16 PM UTC 2232
linux$ sudo date -s '@8277292035'
Wed Apr 18 11:47:15 PM UTC 2232
linux$ sleep 10; date +%s
8277292045
linux$ sudo date -s @$(date +%s)
date: cannot set date: Invalid argument
Wed Apr 18 11:47:25 PM UTC 2232

Причина этого ограничения, найденная в исходном коде, заключается в том, что оно может использовать 30-летний аптайм до оборачивания счётчика:

#define NSEC_PER_SEC    1000000000L
#define KTIME_MAX       ((s64)~((u64)1 << 63))
#define KTIME_SEC_MAX   (KTIME_MAX / NSEC_PER_SEC)

/*
 * Ограничения settimeofday():
 *
 * Чтобы предотвратить установку времени близко к точке оборачивания,
 * устанавливаемое время ограничено так, чтобы можно было использовать разумный аптайм.
 * Достаточно будет аптайма в 30 лет,
 * то есть точкой отсечки является 2232. На этом этапе эта отсечка
 * является просто небольшой частью более серьёзной проблемы *
 */
#define TIME_UPTIME_SEC_MAX    (30LL * 365 * 24 *3600)
#define TIME_SETTOD_SEC_MAX    (KTIME_SEC_MAX - TIME_UPTIME_SEC_MAX)

Это означает, что в Linux знаковое 64-битное максимальное значение времени (2^63 - 1 = 9223372036854775807) не обозначает секунды после эпохи, а подсчитывает наносекунды после эпохи, поэтому теоретическая максимальная дата Linux (KTIME_SEC_MAX) снижается до всего лишь 9223372036 секунд эпохи, или даты 2262-04-23T11:47:16, что очень далеко от «22 приблизительных возрастов Вселенной», и ближе к тому, чтобы стать реальной проблемой.

Проверяя, какое значение FreeBSD позволяет установить для часов, я выяснил, что в двух последних релизах это значение различается, но оба релиза имели неприятную проблему, приводящую к спонтанной перезагрузке системы:

freebsd# date -u -f "%s" 49282253052249598
Fri Dec 31 23:59:58 UTC 1561694399
49282253052249598
freebsd# sleep 1; date; date +%s
Fri Dec 31 23:59:59 UTC 1561694399
49282253052249599
freebsd# sleep 1; date; date +%s
Sat Jan  1 00:00:00 UTC 1561694400
49282253052249600
[ system reboots ]

Примечание: изначально я могу установить дате значение больше 49282253052249598, но спустя примерно три секунды система перезагружается. Если задать дату на одну секунду меньше, то есть 49282253052249597, то система не перезагружается, даже когда системное время уходит дальше следующего значения. Разве компьютеры — это не чудесно?

О, и ещё кое-что…

Всем нам нравится, что macOS — это UNIX; она является одной из всего шести зарегистрированных на данный момент систем (остальные — это AIX, EulerOS (коммерческий дистрибутив Linux, созданный Huawei), HP-UX, Xinuos (ранее UnixWare, создан старыми AT&T Unix System Laboratories + Novell, SCO,
Caldera и UnXis) и z/OS). Однако фреймворк Core Foundation компании Apple не использует эпоху Unix как основу своего времени. В качестве его даты отсчёта используется 2001-01-01T00:00:00 GMT:

Все варианты CLOCK_MONOTONIC гарантируют, что время, возвращаемое Core
Foundation, измеряет время в секундах. В качестве базового типа данных используется CFTimeInterval, измеряющий разность в секундах между двумя моментами времени. Фиксированные моменты времени, или даты определяются типом данных CFAbsoluteTime, измеряющим интервал времени между конкретной датой и абсолютной датой отсчёта Jan 1 2001 00:00:00 GMT.

То есть если вы захотите преобразовать эти метки времени в эпоху Unix, нужно будет прибавить 978307200.


Как я и сказал, время — иллюзия, а время Unix — иллюзия вдвойне. И хотя вас может и не беспокоить проблема 2038 года (наверно, только если вы не пользуетесь OmniOS), возможно, мне удалось показать, что внутри может таиться множество других сюрпризов. А ведь мы ещё не касались безумия, творящегося с часовыми поясами и летним временем…

Что подарить любимым? Топ идей в Каталоге Onlíner!

Более 20 лет назад весь мир стоял на ушах в преддверии 2000 года. Наступали новый век и очередное тысячелетие — события из ряда вон выходящие сами по себе, символизирующие начало другой эпохи. Ощущения были необычные, хотя для истории и течения времени нет никакого значения, что там за цифры на выдуманных человеком календарях.

Millennium bug

В новостях тогда активно обсуждали новый феномен, не характерный для прошлого, — проблему 2000 года. В интернете, на телевидении и даже в газетах пугали грядущим цифровым апокалипсисом: все компьютеры после наступления нового года превратятся в тыкву. А заодно — и электроника, которая хоть как-то умеет считать время. Странно, но все было завязано на то, как компьютеры записывают дату — или, вернее, год. Для его обозначения использовалось всего две цифры: например, 97, 98, 99 и, наконец, 00. Это позволяло сократить объем хранимых данных, да и смысла в четырех символах не было.

Но для компьютера два нуля вовсе не означало 2000 год: он мог «подумать», что наступает 1900-й или просто 0-й. Так могли появиться очень «старые» дети, которым сразу после рождения стукнуло 100 лет, банки путались бы в платежах, а самолеты летели бы в непонятном направлении — опасались этого и всего чего угодно еще.

На решение проблемы, которую обрисовали задолго до ее наступления, якобы направили сотни миллиардов долларов (точной цифры никто не знает). Гипотетический (отчасти, потому что сбои все же наблюдались) баг смогли обойти, и никакого апокалипсиса не настало. Одни говорили, что все было потрачено не зря и что в противном случае мир перестал бы существовать. Другие указывали на то, что огромное количество электроники не было затронуто мероприятиями по обеспечению «поддержки 2000 года», но на ее работе это никак не сказалось.

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

На заре современного компьютеростроения речь шла о 16-битных системах, способных хранить в своей памяти всего 65 536 значений. Это теперь компьютеры управляют практически всеми аспектами нашей жизни, а тогда они не были тесно интегрированы в нее. Позже распространение получили 32-битные системы, которые остались всерьез и надолго, однако не навсегда.

Время пойдет вспять после отметки 03:14:08.

Если говорить о подсчете времени, в распоряжении условного 32-битного «Скайнета» находится лишь 2 147 483 647 секунд, еще столько же — со знаком минус, но ими обычно нельзя воспользоваться. И вот эти секунды «закончатся» в 2038 году, так как отсчет ведется с 1970-го (со временем отсчета — «эпохами» — есть нюансы, так как «обычные» ПК, например, часто отсчитывают время с 1980 года; есть и другие исключения, продлевающие или укорачивающие время «жизни»). То есть 2 147 483 647 — максимальное число, которое умещается в 32-разрядной системе без «твиков».

Помните, в 2012 году отовсюду звучала песня Gangnam Style южнокорейского артиста PSY? Спустя пару лет композиция стала первой набравшей на YouTube более 2 млрд просмотров. И тогда проявился баг, напомнивший об ограниченных возможностях существующих систем (когда видеосервис только стартовал, казалось, что 32-битного поля более чем достаточно для счетчика просмотров).

В конце 2014 года оказалось, что счетчика не хватает. В начале декабря СМИ пестрели заголовками: «Хит Gangnam Style сломал YouTube». На самом деле все было не так, однако небольшой лаг в подсчетах все же случился — какие-то 5 млн просмотров. Само собой, в YouTube прогнозировали события, поэтому начали модернизировать систему заранее, переведя ее на платформу с поддержкой 64-битных типов данных. Над этим команда инженеров начала работать еще осенью 2014 года, увеличив максимально возможное количество просмотров до 9,22 квинтильона.

История с Gangnam Style — наглядный пример того, чем грозит 2038 год, если не предпринимать хотя бы минимальных усилий. 64-битные процессоры и соответствующее программное обеспечение для него стали мейнстримом давно: даже Windows XP успела перейти на 64 бита, а с 2011 года аналогичным путем двинулась Apple с ее настольной ОС. Однако в строю остается немало систем, не отвечающих новым требованиям, да и наверняка к тому времени останется кучка пользователей «древней» электроники.

Какие конкретно есть угрозы

GPS

Чаще всего вспоминают системы GPS, которые полностью завязаны на время и транслируют его. Существует миф, что спутники и управляющие системы в 2038 году могут выйти из строя, потянув за собой все остальное. Да, отсчет времени для GPS ведется как раз с 1980 года, однако он происходит по неделям и секундам в каждой из них. Более того, каждые 19,7 года (или 1024 недели) наступает событие GPS week number rollover, когда отсчет начинается заново: 10-битного значения достаточно для хранения информации только о 1023 неделях. Следующий сброс запланирован как раз на 2038 год (а прошлый состоялся в 2019-м).

Более того, современные устройства перешли на более совершенную систему, которая использует для хранения информации о неделях 13 бит, что позволяет считать недели без каких-либо проблем до 2137 года. Что касается конечного оборудования, здесь все кроется в своевременном обновлении ПО, а это зависит от его поставщиков и производителей. Ранее из-за запоздавшей реакции пострадали некоторые аэропорты, научное оборудование, системы слежения за погодой, бытовые GPS-навигаторы и даже старые iPhone и iPad. То есть основная проблема кроется в неправильной обработке данных о времени на конечном устройстве.

Для ГЛОНАСС эта проблема вовсе не характерна, а у других спутниковых систем «запас» времени иссякнет нескоро — лет через 50.

Компьютеры, смартфоны, базы данных и ПО

Сейчас сложнее найти новое устройство, которое работало бы на 32-битных платформах: все давно переходят на 64-битные, не остаются в стороне и мобильные девайсы.

Однако проблема не столько кроется в железе и операционных системах (отдельные 32-битные, которые могут использовать 64-битный тип данных для хранения времени, либо беззнаковые 32-битные, где это возможно), сколько касается прикладного ПО, встраиваемых систем, коммуникационных протоколов (NTP, например), баз данных, файловых систем, драйверов и остального. На условном 64-битном компьютере можно запускать 32-битное приложение, не совместимое с проблемой 2038 года, да и 64-битная программа может быть собрана «криво».

Теперь популярна и концепция интернета вещей, которая может стать одним из слабых звеньев цепи, если разработчики не предусмотрят все нюансы. Не исключено, что их пока будут частично игнорировать из-за желания сэкономить, снизив затраты на разработку и комплектующие. Так что в 2038-м «кое-какие» проблемы все же будут.

Для обхода может использоваться адаптация «несовместимого» кода. Это касается, например, баз данных, в которых возможно записывать даты в «правильном» формате — просто потребуется немного работы инженеров и больше дискового пространства (в четыре раза больше, если быть точнее). В прошлом это было серьезным ограничением, однако ныне это уже менее актуально.

ПО можно перекомпилировать (если, конечно, не утеряны исходники оригинального кода), остается и вопрос внутренней совместимости. Доступен переход на новые решения, но в некоторых случаях потребуется время. Представьте, как компания с 10 тыс. сотрудников запускает новый почтовый сервер с новым клиентом: надо все перенести, «отформатировать», как полагается, и объяснить, как с этим работать. Или системы видеонаблюдения с десятками тысяч камер и гигабайтами логов…

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

Часть профессионального сообщества считает Y2K bug более серьезным, нежели грядущий в 2038-м — потому что тогда решение не было столь очевидным. В то же время через 17 лет компьютеры будут распространены куда шире, чем 21 год назад, и их будет в разы больше. Поэтому другая часть ждет восстания машин.

Читайте также:

  • Кто кого? Ноутбук MagicBook View 14 против MacBook на M1
  • Омикрон создали биохакеры, «непонятные» лаборатории и мыши? Что сейчас известно о новом штамме коронавируса

Наш канал в Telegram. Присоединяйтесь!

Есть о чем рассказать? Пишите в наш телеграм-бот. Это анонимно и быстро

Перепечатка текста и фотографий Onlíner без разрешения редакции запрещена. ng@onliner.by

В полночь первого января 1970 года началась «Эпоха Unix». В Unix и других POSIX-совместимых ОС приняли систему описания моментов времени. Но одновременно с новой эпохой у инженеров и разработчиков возникли новые проблемы. Одна из них — «Проблема 2038 года». Рассказываем, что это такое и ждёт ли нас «Апокалипсис» через 18 лет.

Минутка истории

Ошибка Y2K заключалась в следующем. В 1950-х и 60-х годах, когда создавался софт для первых компьютеров, разработчики отображали год в дате двумя последними цифрами. Для экономии ресурсов. Поэтому они переживали, что 1 января 2000 года компьютеры, отображающие новую дату «00», ошибочно решат, что это 1900 год.

Это звучало правдоподобно, и многие люди сделали бизнес на консультациях по этому вопросу. Вырос спрос на COBOL-разработчиков — им приходилось исправлять старые приложения. По мере приближения Миллениума люди готовились к глупым коммунальным платежам, гаснущим фонарям и падающим самолётам

В конце концов, появились Y2K-совместимые системы, и 2000 год начался почти без шума. Но «проблема 2038 года» немного сложнее.

Время Unix — это количество секунд, начиная с полуночи 1 января 1970 года. Отсчёт начался с 0, и любое значение времени или даты выражается числом секунд, следующих за 0. Так, значение 919642718 равно 919 642 718 секундам после 00:00:00 часов 1 января 1970 года. То есть воскресенью 16:18:38 21 февраля 1999 года.

Это удобный формат, потому что если вы вычтете любые два значения, то получите количество секунд — то есть разницу во времени — между ними. Так можно определить, сколько минут, часов, дней, месяцев или лет прошло между двумя любыми датами.

Старые 32-разрядные процессоры способны считать только до 2 147 483 647. Таким образом, 19 января 2038 года в 03:14:07 по Всемирному времени (UTC) они достигнут максимальной мощности.

Проблема 2038 года приведёт к тому, что часы на некоторых устройствах перестанут работать. По одной из теорий, время обернётся назад к «началу» и будет храниться в виде отрицательных чисел. И из-за того, как написан код, компьютеры будут интерпретировать это время как происходящее 13 декабря 1901 года, а не 19 января.

Всё не так плохо

Большинство компьютеров и смартфонов, сделанных в последнее время, 64-разрядные и могут содержать числа размером 9 223 372 036 854 775 807. То есть будут отсчитывать время до 292 277 026 596 года. Так что их основная часть (за исключением действительно старых) не пострадает.

Что касается банкоматов, медицинской и военной техники и прочего, то к 2038 году, вполне вероятно, большинство (если не все) 32-битных устройств не будут использовать. Им на замену придут более современные системы, которые не нужно исправлять. Главной головной болью может стать модернизация оборудования. Но инженеров есть ещё 18 лет, чтобы с ней справиться.

Проблема 2038 года

Проблема 2038 года, ее еще называют Unix Millennium bug или Y2K38. Что это такое и почему она возникнет?

Смотрите видео, посвященное проблеме 2038 года

19 января 2038 года или на кануне этой даты могут произойти сбои в различном программном обеспечении.

Почему

Время и дату в компьютерных программах можно хранить по разному. Один из способов хранения даты — это использование стандарта POSIX (UNIX timestamp, Unix epoch).

В стандарте POSIX время записывается как количество секунд, прошедших с 0 часов 0 минут 0 секунд 1 января 1970 года по Всемирному времени (UTC). Для Unix-подобных операционных систем — это стандарт представления времени.

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

Например:
Для 01.01.1970 00:00:05 это число +5 (сек).
Для 31.08.1970 12:10:33 это число +20952633 (сек).
Для 19.01.2038 00:00:00 это число +2147472000 (сек).
Для 19.01.2038 03:14:07 это число +2147483647 (сек).

В старых программах (а иногда даже в новых) дата часто хранится в целочисленном 32-х битном знаковом формате — signed int. Это означает, что под число выделяется 32 бита:
00000000 00000000 00000000 00000000 

  • Первый бит (выделен красным), служит для определения знака числа. Значение 0 соответствует +, а значение 1 соответствует ).
  • 31 бит (выделены синим) для хранения значения самого числа.

Максимальное число, которое можно сохранить, используя 31 бит, это число 2147483647. В 32-х битном знаковом целочисленном формате записывается оно следующим образом:
01111111 11111111 11111111 11111111 
В POSIX это число соответствует дате 19.01.2038 03:14:07. Как видим, это и есть «роковое» 19 января 2038 года.

Представление числа в знаковом 32 битном формате

Что произойдет 19 января 2038

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

Что будет внутри программ

Рассмотрим, что именно произойдет внутри программ. Числа больше 2147483647 не влезают в 31-бит.

Например, для числа 2147483647+1= 2147483648 нужно уже 32 бита. Это число записывается в двоичной системе, как единица в старшем разряде и 31 ноль:
10000000 00000000 00000000 00000000 
Для 32-х битного типа signed integer — это число соответствует числу: −2147483648. Как было сказано выше, 1 в первом разряде обозначает отрицательное число.

Получается, что числа больше 2147483647 уже нельзя записать в 31 бит, но так как у нас есть еще один бит для хранения знака, программа запишет эти числа в память, но в программе они будут трактоваться как отрицательные числа.

Происходит как бы зацикливание числа. Если говорить о количестве секунд, увеличивающихся на 1, то они достигают значения 2147483647, а потом переходят в отрицательную область: −2147483648, −2147483647, −2147483646 и т.д. В программах такие числа будут трактоваться как 1970-й или 1901-й год (зависит от реализации).

Как это повлияет на работу программ

Все зависит от того, насколько дата и время важны в конкретной программе. Если работа программы зависит от времени, то скорее всего могут произойти сбои в работе программы или потери данных.

Например, если в табличных данных используется сортировка по времени, а для новых данных оно будет трактоваться, как отрицательное число, то эти данные будут трактоваться как старые данные, и сортировка будет нарушена.

Или, например, если программа очищает, какие-нибудь данные спустя определенное время, то при неверной трактовки времени, могут быть удалены еще актуальные данные.

Получается, что, чем больше работа программа зависит от времени, хранимого 32-х битном типе signed integer, то тем серьезнее могут быть последствия.

Так ли все серьезно

И да и нет. На самом деле — да!

Современные 64-х разрядные системы не подвержены данное проблеме, поэтому на них она никак не повлияет.

Для существующих 32-разрядных программ и систем уже выпущено множество патчей для исправления данной проблемы. Например, Microsoft, как он утверждает, уже обнаружил и исправил проблемы в 32-х разрядных версиях Windows.

Но все программы не исправить, поэтому многие из них остаются в зоне риска. Более того, даже сейчас выпускается множество 32-х битных систем, особенно встраиваемых.

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

Проблема 2038

Поэтому, если не предпринимать никаких действий, то последствия проблемы 2038 года могут от смешных до катастрофических.

Конечно, до 2038 года еще много времени и многие из них будут заменены на новые. Но все мы знаем, как быстро идет время, поэтому расслабляться не стоит. Более того, есть программы, которые уже сейчас могут использовать даты в будущем. Проблемы в таких программах могут начаться намного раньше.

Unix Millennium bug

Прочитал тут пост блогера STRRAVAGANZA про ПРИВЕТ С ТОГО СВЕТА (кстати, клевая идейка то было) и узнал, что существует проблема 2038 года. Помните, была проблема 2000 года, ее вроде удачно пережили.

А теперь вот это. Как оно пройдет ? Опять все надуманно и раздувают на пустом месте ? Вот вам про проблему подробнее …

Проблема 2038 года в вычислительной технике — ожидаемые сбои в программном обеспечении 19 января 2038 года. Данная проблема затрагивает программы и системы, в которых используется представление времени по стандарту POSIX (UNIX-время), которое представляет собой количество секунд, прошедшее с 1 января 1970 года. Такое представление времени — это стандарт для Unix-подобных операционных систем (из-за повсеместного использования языка Си).

В старых 32-битных системах (до середины 90-х) используется тип данных time_t для хранения секунд в виде signed int (32-битного целого со знаком). Самая поздняя дата, которая может быть представлена таким форматом в стандарте POSIX — это 03:14:07, вторник, 19 января 2038 года по Всемирному времени (UTC).

Более позднее время заставит такое поле данных стать отрицательным, как бы закольцевав таким образом время (поскольку отрицательное число может быть воспринято программами как время в 1970 или 1901 году, в зависимости от реализации). В результате могут быть произведены ошибочные вычисления или результаты.

Для проблемы 2038 года не существует простого решения для существующих комбинаций процессоров и операционных систем.

Изменение определения типа time_t на 64 бита нарушит бинарную совместимость программ, существующих хранимых данных и всего другого, использующего представление времени в бинарном виде. А приведение time_t в целое без знака может нарушить работу программ, которые вычисляют разницу во времени.

В большинстве операционных систем для 64-битных архитектур уже используется 64-битное представление целого в time_t. Переход на такие архитектуры уже происходит, и некоторые ожидают, что он будет завершён к 2038 году.

Тем не менее, сотни тысяч 32-битных систем всё ещё вводились в строй в 2010 году, в том числе и во встраиваемых системах. Вызывает сомнение, что они все будут заменены к 2038 году. Несмотря на то, что современные компьютерные системы могут модернизироваться раз в 18—24 месяцев (по «Закону Мура»), встроенные компьютеры могут действовать без модернизации весь срок, который работают системы, ими управляемые. Например, компьютеры управления процессами модели IBM 1800, выпуск которых был начат в 1965 году, всё ещё использовались на одной из атомных станций в Канаде в 2006 году.

В дополнение к этому, 32-битный формат time_t также включён в спецификации форматов файлов, таких как повсеместно распространённый архивный формат ZIP. Формат файла может существовать в течение времени, за которое сменятся многие поколения компьютеров, а это означает, что Проблема 2038 останется актуальной.

Введение 64-битного формата вносит новую дату «закольцовывания» — оно произойдёт примерно через 290 миллиардов лет (4 декабря 292 277 026 596 года в 15:30:08

Кстати, возвращаясь к теме поста про «привет из склепа» как то думал про то, что вот скоро начнет умирать активно поколение социальных сетей и интернет будет заполняться страницами людей, которые давно умерли. Т.е вот так через несколько поколений люди будут заходить к давно умершим в гости и смотреть какой фигней они страдали там в сетях. Самострели, приколы, фотки еды … Правнуки будут бродить по страницам прабабушек и прадедушек, а то и дальше ?

Есть вариант конечно, что по сроку давности страницы будут удаляться. Почему не сделать услугу с предоплатой, чтобы страница жила в интернете вечно.

А жаль если удалят … я бы свои оставил. А вы  ?

Оригинал статьи находится на сайте ИнфоГлаз.рф Ссылка на статью, с которой сделана эта копия — http://infoglaz.ru/?p=83688

Проблема 2038 года занимает умы многих пользователей — реальна ли она и насколько вероятна угроза?…

Проблема 2038 года заключается в ожидаемых сбоях, которые могут затронуть компьютеры использующие стандарт POSIX.

Интересно, что в ожидании миллениума многие эксперты говорили о проблеме 2000, которая должна была затронуть всю вычислительную технику — проблему 2038 можно отнести к этой же категории.

[adace-ad id=»5173″]

Сбой может произойти 19 января 2038 года в 3 часа ночи — в этот момент возможен коллапс компьютерных систем, которые используют POSIX-время. POSIX использует в качестве точки отсчета сумму всех секунд, начиная с нуля часов 1 января 1970 год. POSIX-время используется во всех языках семейства С.

До девяностых годов прошлого века повсеместно использовались исключительно 32-битные системы. Временной тип данных time_t и сегодня активно используется — в нём секунды хранятся в виде целого тридцати двух битного числа со знаком (один бит при этом отводится под знак)

Крайняя дата, которую можно представить в современном стандарте POSIX — 19 января 2038 года (3 часа 14 минут 7 секунд). После этой даты значение времени в POSIX становится отрицательным и кольцо времени замкнется. Время с «минусом» в POSIX будет трактоваться компьютером как дата 20 века.

Таким образом, начиная с 19 января 2038 года, возможен сбой любых программ, которые используют систему времени POSIX. Сбой также может привести к некорректным вычислениям в самих программах и стать причиной потери данных.

Моментального решения проблемы 2038 года на сегодняшний день не существует. Безусловно, решения для массовых операционных систем, платформ и программ сегодня существуют — выпускаются патчи, которые устраняют проблемы POSIX-времени, но предусмотреть все сценарии развития событий невозможно.

Увеличение стандарта time_t с 32 на 64 бита может привести к нарушению совместимости программ, а превращение данного типа в целое число без знака может и вовсе разрушить алгоритм работы различных программ и систем, которые высчитывают временную разницу

В основе современных 64-битных платформ представление о целом во временном типе заложено изначально. Планируется, что полный переход на подобные архитектуры должен быть завершен к 2040 году. Несмотря на это до сих пор продолжается выпуск 32-битных платформ и программ.

Согласно закону Мура все современные компьютеры могут подвергаться усовершенствованию только один раз в течение полутора-двух лет, а встроенные в оборудование компьютерные системы и вовсе могут обходиться без доработки весь срок эксплуатации. К примеру, на одной из канадских АЭС до 2010 года все еще работала вычислительная машина IBM 1800 — удивительно, но она была выпущена ещё в 1965 году

Временной тип данных time_t предназначался именно для 32-битных архитектур, кроме этого сегодня time_t используется в файловых форматах. Здесь всё несколько сложнее, отметим лишь, что временной тип данных задействован во всех файловых расширениях, например — в файловых форматах .zip. Именно поэтому разговоры о том, что проблема может изжить себя сама собой некорректны — файловые форматы использующие time_t живут минимум несколько десятилетий. Данное обстоятельство выдвигает проблему 2038 года на новый уровень и делает её более острой.

Повсеместный переход на 64-битные платформы способен решить проблему — тогда прогнозируемая проблема будет отодвинута на 300 миллиардов лет вперед. Если быть точным новый сбой случиться в 292277026596 году 4 декабря — в 15 часов 30 минут и 8 секунд.

Кого затронет проблема 2038

Для 32-битных платформ Windows проблема 2038 года стоит особенно остро — большая часть современных операционных систем и их программных надстроек написаны на языках группы С.

Microsoft до сих пор не даёт гарантий, что сторонние программы будут работать после января 2038 года. Тем не менее разработчик сделал всё возможное и попытался исправить все проблемные места в коде, но как поведёт себя программное обеспечение сторонних разработчиков не знает никто

Определенно можно сказать одно — конфликты программ и операционных систем после 2038 года неизбежны.

MySQL

Система управления базами данных SQL Server, а также MySQL, имеют ограничение по временным значениями — доступный диапазон включает в себя период с 01 января 1970 года 00:00:00 по 19 января 2038 года 03:14:07.

В чём причины проблемы 2038

Глобальные сбои вычислительной техники ожидаются не только в 2038 году, но и за несколько лет до этой даты.

Дело в том, что в программном обеспечении параметр время/дата реализуются в различных форматах. Самым распространенным видом хранения и представлением этих величин является стандарт POSIX. Здесь всё просто: время отражается как общее значение — в нашем случае как общее количество секунд (важно, что отсчёт происходит именно с 1 января 1970 года)

Стоит отметить, что для систем семейства POSIX/UNIX дата является уже, непосредственно, целым числом — здесь она реализована в качестве суммарного числа, которое указывает количество секунд.

[adace-ad id=»5168″]

Отталкиваясь от 1970 года число времени (а проще говоря — секунд) постоянно увеличивается — с каждым годом все большее значение накапливается внутри программ:

Таким образом, проблема 2038 была рассчитана математически и сомневаться в её реалистичности не приходиться.

Последствия проблемы 2038

Ответить что будет в 2038 году с основной массой вычислительной техники довольно сложно — в силу большого разнообразия конфигураций подобных систем и архитектур.

Ожидаются следующие сбои:

  • Утрата данных;
  • Различные ошибки ПО и операционных систем;
  • Нарушение функционирования промышленного и медицинского оборудования.

Почему же сбои произойдут именно в 2038 году и как удалось рассчитать точную дату? Дело в том, что число секунд от 1 января 1970 года до 19 января 2038 года равняется 2147483647 — данное число никаким образом не может уместиться в тридцать одном бите, но если к нему всё же прибавить 1, то получится 2147483648 и потребуется уже 32 бита.

Указанное значение должно уложиться в двоичную систему — выглядит оно как единица с тридцатью одним нулём. Единица на месте первого разряда означает минус — число станет отрицательным и будет означать уже — 2147483648

Таким образом, вместить в тридцать один бит число больше 2147483647 невозможно. Кстати, один бит зарезервирован под знак данного числа, и программа может записать такое число в виде его отрицательного значения. Происходит так называемое числовое зацикливание — если и далее секунды будут увеличиваться на единицу, то итоговое число все время будет находиться в отрицательной области и уменьшать свое значение:

  • 2147483647 +1 секунда = − 2147483648;
  • + 1 секунда = − 2147483647;
  • + 1 секунда = − 2147483646.

Проблема 2038 года заключается в том, что программы и операционные системы считывают отрицательные числа некорректно, а точнее как 1970-й год, либо — как 1901-й. Такая разница в трактовке вызвана различиями при реализации time_t.

Вышеуказанные изменения приведут к некорректным расчетам внутри самих программ и данные могут трактоваться операционной системой как устаревшие — они периодически удаляются.

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

Для 64-разрядных версий Windows потенциальная проблема 2038 года стоит не так остро, но всё равно является потенциально опасной. Для 32-разрядных систем уже разработано большое количество патчей, которые в теории могут защитить данные от удаления, но избежать конфликтов программного обеспечения данные патчи не помогут

Microsoft подтверждает, что все дыры в 32-разрядных системах Windows практически исправлены, но остается множество программ, которые писались именно под 32-разрядные архитектуры — исправить их уже невозможно. Именно поэтому проблема 2038 года не может быть устранена полностью.

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

Конечно, мнения о том, что «остановятся» электронные платежи, заводы и предприятия, атомные станций и прочие потенциально опасные объекты сегодня звучат не совсем реалистично.

Мы отлично помним о том, что накануне миллениума звучали похожие мнения, самые пессимистичные из которых гласили, что упадут самолёты и мир впадёт в глобальный блэкаут — к счатью, ничего подобного так и не случилось…

Question book-4.svg

В этой статье не хватает ссылок на источники информации.

Информация должна быть проверяема, иначе она может быть поставлена под сомнение и удалена.
Вы можете отредактировать эту статью, добавив ссылки на авторитетные источники.
Эта отметка установлена 21 ноября 2011.

Пример, показывающий сброс даты (в 03:14:08 UTC 19 января 2038 года).

Проблема 2038 года в вычислительной технике — ожидаемые сбои в программном обеспечении 19 января 2038 года. Данная проблема затрагивает программы и системы, в которых используется представление времени по стандарту POSIX (UNIX-время), которое представляет собой количество секунд, прошедшее с 1 января 1970 года. Такое представление времени — это стандарт для Unix-подобных операционных систем (из-за повсеместного использования языка Си).

На большинстве 32-битных систем используется тип данных time_t для хранения секунд в виде signed int (32-битного целого со знаком). Самая поздняя дата, которая может быть представлена таким форматом в стандарте POSIX — это 03:14:07, вторник, 19 января 2038 года по Всемирному времени (UTC).

Более позднее время заставит такое поле данных стать отрицательным, как бы закольцевав таким образом время (поскольку отрицательное число может быть воспринято программами как время в 1970 или 1901 году, в зависимости от реализации). В результате могут быть произведены ошибочные вычисления или результаты.

Для проблемы 2038 года не существует простого решения для существующих комбинаций процессоров и операционных систем.

Изменение определения типа time_t на 64 бита нарушит бинарную совместимость программ, существующих хранимых данных и всего другого, использующего представление времени в бинарном виде. А приведение time_t в целое без знака может нарушить работу программ, которые вычисляют разницу во времени.

В большинстве операционных систем для 64-битных архитектур уже используется 64-битное представление целого в time_t. Переход на такие архитектуры уже происходит, и некоторые ожидают, что он будет завершён к 2038 году.

Тем не менее, сотни тысяч 32-битных систем всё ещё вводятся в строй в 2010 году, в том числе и во встраиваемых системах. Вызывает сомнение, что они все будут заменены к 2038 году. Несмотря на то, что современные компьютерные системы могут модернизироваться раз в 18-24 месяцев (по «Закону Мура»), встроенные компьютеры могут действовать без модернизации весь срок, который работают системы, ими управляемые. Например, компьютеры управления процессами модели IBM 1800, выпуск которых был начат в 1965 году, всё ещё использовались на одной из атомных станций в Канаде в 2006 году.

В дополнение к этому, 32-битный формат time_t также включён в спецификации форматов файлов, таких как повсеместно распространённый архивный формат ZIP. Формат файла может существовать в течение времени, за которое сменятся многие поколения компьютеров, а это означает, что Проблема 2038 останется актуальной.

Введение 64-битного формата вносит новую дату «закольцевания» через примерно 290 миллиардов лет.

Windows

Проблема 2038 года актуальна и для 32-разрядных версий Windows, так как значительная часть самой ОС и большое число программ для неё написано на C/C++. Разработчики Windows говорят[1], что исправили большинство багов, связанных с этой проблемой, однако, они не могут дать никаких гарантий по поводу стороннего ПО.

Примечания

  1. Year 2038 problem — GES on Windows 7 — Site Home — MSDN Blogs
 Просмотр этого шаблона Проблемы дат в программировании
Программирование
По годам Проблема 100 года • Проблема 2000 года • Проблема 2038 года • Проблема 10000 года
См. также 0 год
Разработка программного обеспечения

Понравилась статья? Поделить с друзьями:
  • Ошибка 2037 fanuc
  • Ошибка 2035 авв частотник
  • Ошибка 2034 эпик геймс
  • Ошибка 2034 роблокс при донате
  • Ошибка 2034 при оплате картой роблокс