Year 2038 Problem:修订间差异
重定向页面至协调世界时 |
创建页面,内容为“'''Year 2038 Problem'''(又称'''Y2038'''<ref name="enwiki">[https://en.wikipedia.org/wiki/Year_2038_problem Year 2038 Problem - Wikipedia]</ref>、'''Y2K38'''、'''Y2K38 superbug'''或'''Epochalypse'''<ref name=":0">[https://en.wikipedia.org/wiki/Year_2038_problem Year 2038 Problem - Wikipedia]</ref><ref name=":1">[https://graphsearch.epfl.ch/en/concept/300127 Year 2038 problem - EPFL]</ref>)是一个计算机系统中与时间表示相关的缺陷。该…” |
||
| 第1行: | 第1行: | ||
'''Year 2038 Problem'''(又称'''Y2038'''<ref name="en[[wiki]]">[https://en.wikipedia.org/wiki/Year_2038_problem Year 2038 Problem - Wikipedia]</ref>、'''Y2K38'''、'''Y2K38 superbug'''或'''Epochalypse'''<ref name=":0">[https://en.wikipedia.org/wiki/Year_2038_problem Year 2038 Problem - Wikipedia]</ref><ref name=":1">[https://graphsearch.epfl.ch/en/concept/300127 Year 2038 problem - EPFL]</ref>)是一个[[计算机]]系统中与时间表示相关的缺陷。该问题源于部分系统使用'''有符号32位整数'''(signed 32-bit integer)来[[存储]]'''[[Unix]]时间'''(即自协调世界时(UTC)1970年1月1日00:00:00起经过的秒数)<ref name=":0" /><ref name=":2">[https://zh.wikipedia.org/wiki/Y2K38 2038年问题 - 维基百科]</ref>。由于32位有符号整数的最大值是2,147,483,647,其可编码的最终时间为2038年1月19日(星期二)03:14:07 UTC<ref name=":0" /><ref name=":2" />。若时间增加至下一秒(03:14:08),整数将发生'''溢出'''(overflow),数值变为负数,系统可能将时间误解为1901年12月13日20:45:52<ref name=":0" /><ref name=":2" />,进而引发各类[[软件]]故障<ref name=":0" /><ref name=":2" />。此问题与'''2000年问题'''(Y2K)类似,但后者源于十进制数的存储缺陷,而2038年问题源于[[二进制]]数的存储限制<ref name=":0" />。 | |||
{{Infobox | |||
| 标题 = Year 2038 Problem | |||
| 内容 = | |||
{{!}}- | |||
! 中文名 | |||
{{!}} 2038年问题 | |||
{{!}}- | |||
! 英文名 | |||
{{!}} Year 2038 Problem | |||
{{!}}- | |||
! 别名 | |||
{{!}} Y2038, Y2K38, Y2K38 superbug, Epochalypse, Unix Y2K | |||
{{!}}- | |||
! 分类 | |||
{{!}} 计算机时间表示缺陷 | |||
{{!}}- | |||
! 发生时间 | |||
{{!}} 2038年1月19日 03:14:07 UTC | |||
{{!}}- | |||
! 影响范围 | |||
{{!}} 使用32位有符号整数存储Unix时间的系统 | |||
}} | |||
== 原因 == | |||
问题的根源在于'''Unix时间'''的存储方式。Unix时间定义为自[[UTC|协调世界时]](UTC)1970年1月1日00:00:00(即Unix纪元)起所经过的秒数(忽略闰秒)<ref name=":0" /><ref name=":2" />。在许多计算机系统中,尤其是基于[[C编程语言]]开发的系统,此时间值被存储在一个'''32位'''的'''有符号整数'''(`time_t`类型)中<ref name=":2" />。这种[[数据]]类型所能表示的最大值是2<sup>31</sup> - 1,即2,147,483,647<ref name=":0" /><ref name=":2" />。这个最大值对应的UTC时间恰恰是2038年1月19日03:14:07<ref name=":0" /><ref name=":2" />。当时间到达下一秒(03:14:08)时,整数值会增加到2,147,483,648,这超出了32位有符号整数的表示范围,从而引发'''整数溢出'''<ref name=":0" />。溢出后的数值会被解释为-2<sup>31</sup>,对应1901年12月13日20:45:52 UTC<ref name=":0" /><ref name=":1" />。系统因此无法识别正确的未来时间,可能导致程序运行异常或崩溃<ref name=":0" /><ref name=":2" />。 | |||
== 受影响系统 == | |||
所有使用32位有符号整数存储Unix时间的系统都可能受到2038年问题的影响<ref name=":0" /><ref name=":2" />。这主要包括: | |||
* '''类Unix[[操作系统]]''':如旧版的[[Linux]]、BSD、[[macOS]]等,以及它们之上的大量应用软件<ref name=":2" />。 | |||
* '''嵌入式系统''':这些系统通常更新频率低或从不更新,是风险最高的领域之一,可能涉及工业控制系统、医疗设备、汽车电子、网络设备等<ref name=":0" /><ref name=":1" />。 | |||
* '''使用C或[[C++]]等语言编写的、依赖系统时间进行日期计算或存储的旧版软件'''。 | |||
值得注意的是,部分系统在设计时使用了'''无符号32位整数'''(unsigned int32)来存储时间,这类系统的问题将推迟至'''2106年'''(即无符号32位整数溢出之年)才会显现<ref name=":0" /><ref name=":2" />。例如,[[比特币]]区块链的时间戳即采用此方法<ref name=":2" />。 | |||
== 解决方案 == | |||
解决2038年问题的最根本方法,是将存储Unix时间的数据类型从32位迁移至'''64位'''<ref name=":0" /><ref name=":2" />。一个64位有符号整数所能表示的时间范围极其广阔,其溢出将发生在约2920亿年后,远超宇宙的估计年龄<ref name=":0" /><ref name=":1" />。 | |||
然而,这一迁移过程并非易事: | |||
* '''软件兼容性''':简单地更改time_t的定义会破坏现有软件的二进制兼容性(ABI),所有依赖时间计算的库和应用程序都需要为此重新编译和测试<ref name=":2" />。 | |||
* '''数据迁移''':存储旧32位时间值的文件格式和[[数据库]]需要进行相应的升级和转换。 | |||
* '''硬件限制''':部分老旧或定制的32位嵌入式系统可能无法直接升级至64位,需要更复杂的改造或替换方案。 | |||
因此,目前并没有一个放之四海而皆准的简单解决方案<ref name=":2" />。对于关键系统和设备,需要提前进行普查、评估和逐步替换。 | |||
== 类似问题 == | |||
* '''2000年问题(Y2K)''':与本问题类似,但源于以两位十进制数表示年份所引发的世纪交替故障<ref name=":0" />。 | |||
* '''2106年问题''':影响使用无符号32位整数存储Unix时间的系统<ref name=":0" />。 | |||
* '''其他时间相关溢出问题''':例如,某些系统若使用不同的时间纪元(epoch)定义,其溢出时间点也会不同<ref name=":0" />。例如,使用CCSDS纪元(1958年)的系统可能在2026年即遭遇类似问题<ref name=":0" />。 | |||
== 参考文献 == | |||
<references /> | |||