2038 年问题:修订间差异

跳转到导航 跳转到搜索
添加621字节 、​ 2025 年 11 月 7 日 (星期五)
无编辑摘要
无编辑摘要
无编辑摘要
第 2 行: 第 2 行:
2038 年问题是一种计算机日期范围问题。在计算机应用上,2038 年问题可能会导致某些软件在 2038 年 1 月 19 日 3 时 14 分 07 秒之后无法正常工作。所有使用 POSIX 时间表示时间的程序都会受到 2038 年问题的影响,这是因为这些程序是以自 1970 年 1 月 1 日开始经过的秒数(忽略闰秒)表示时间。这种时间表示法在类 Unix 操作系统之中是标准,影响使用 C 语言开发其他大部分操作系统使用的软件。
2038 年问题是一种计算机日期范围问题。在计算机应用上,2038 年问题可能会导致某些软件在 2038 年 1 月 19 日 3 时 14 分 07 秒之后无法正常工作。所有使用 POSIX 时间表示时间的程序都会受到 2038 年问题的影响,这是因为这些程序是以自 1970 年 1 月 1 日开始经过的秒数(忽略闰秒)表示时间。这种时间表示法在类 Unix 操作系统之中是标准,影响使用 C 语言开发其他大部分操作系统使用的软件。


在大部分的 32 位操作系统上,{{code|time_t}} 数据模式使用包括正负号在内的 32 位整数计算的秒数。这个数据是以 32 位存储的,第一位是符号位,其余的 31 位用来存储数字,而这 31 位数字可以存储的最大数字为 2147483647{{efn|在包括正负号在内的情况下,范围是 {{code|-2147483648}}~{{code|+2147483647}}}},记录子 1970 年 1 月 1 日 0 时 0 分 0 秒开始经历的秒数。依据此标准,在此格式下能够被表示的最晚时间是 2038 年 1 月 19 日 3 时 14 分 07 秒({{code|+2147483647}})。若超过这个范围,时间将会自动绕回,且在内部被表示为负数({{code|-2147483648}}),造成程序无法工作,原因在于这些程序无法将时间识别为 2038 年,可能会依照个别实现跳回到 1970 年或 1901 年(1901 年 12 月 13 日 20 时 45 分 52 秒,即 {{code|-2147483648}})。由于这种跳回,可能会产生错误的计算及动作,甚至会因此崩溃。
== 问题由来 ==
在大部分的 32 位操作系统上,{{code|time_t}} 数据模式使用包括正负号在内的 32 位整数计算的秒数。这个数据是以 32 位存储的,第一位是符号位,其余的 31 位用来存储数字,而这 31 位数字可以存储的最大数字为 2147483647{{efn|在包括正负号在内的情况下,32 位整数对应的十进制范围是 {{code|-2147483648}}~{{code|+2147483647}},绝对值可用值总数为 2 的 32 次方,即 4294967296(0 也单独计算为一个数,若不包括则为 4294967295,即 2 的 32 次方减 1)}},记录了自 1970 年 1 月 1 日 0 时 0 分 0 秒开始经历的秒数。依据此标准,在此格式下能够被表示的最晚时间是 2038 年 1 月 19 日 3 时 14 分 07 秒({{code|+2147483647}})。若超过这个范围,时间将会自动绕回,且在内部被表示为负数({{code|-2147483648}}),造成程序无法工作,原因在于这些程序无法将时间识别为 2038 年,可能会依照个别实现跳回到 1970 年(1970 年 1 月 1 日 0 时 0 分 0 秒,即 {{code|0}})或 1901 年(1901 年 12 月 13 日 20 时 45 分 52 秒,即 {{code|-2147483648}})。由于这种跳回,可能会产生错误的计算及动作,甚至会因此崩溃。


在少数情况下,在当制定规格时,特别规定以无正负号的 32 为整数存储 POSIX 时间{{efn|在无正负号在内的情况下,范围是 {{code|0}}~{{code|4294967295}}}},因此相同的错误会被延后到 2106 年 2 月 7 日 14 时 28 分 15 秒({{code|4294967295}})。例如比特币区块链中的区块时间戳,就是以这种方法存储。
在少数情况下,在当制定规格时,特别规定以无正负号的 32 位整数存储 POSIX 时间{{efn|在使用无正负号 32 位整数的情况下,对应十进制范围是 {{code|0}}~{{code|4294967295}},绝对值可用值总数为 4294967296(0 也单独计算为一个数)}},因此相同的错误会被延后到 2106 年 2 月 7 日 14 时 28 分 15 秒({{code|4294967295}})。例如比特币区块链中的区块时间戳,就是以这种方法存储。


== 修复方法 ==
截止到目前,并没有寻求到针对现有 CPU/操作系统搭配的简单解决方案。直接将 POSIX 时间更改为 64 位模式将会破坏对于软件、数据存储,以及所有与二进制表示时间相关的部分二进制兼容性。更改称无符号的 32 位整数则会影响许多与两种时间之差相关的程序。
截止到目前,并没有寻求到针对现有 CPU/操作系统搭配的简单解决方案。直接将 POSIX 时间更改为 64 位模式将会破坏对于软件、数据存储,以及所有与二进制表示时间相关的部分二进制兼容性。更改称无符号的 32 位整数则会影响许多与两种时间之差相关的程序。


第 12 行: 第 14 行:
2038 年问题不仅比 [[2000 年问题]]更隐蔽,而且比之前 2000 年问题更具有破坏力,这是因为 2000 年问题只会导致应用层的程序出现问题,比如信用卡支付系统,或者管理系统。而 2038 年问题将会影响系统最底层的时间控制的功能。
2038 年问题不仅比 [[2000 年问题]]更隐蔽,而且比之前 2000 年问题更具有破坏力,这是因为 2000 年问题只会导致应用层的程序出现问题,比如信用卡支付系统,或者管理系统。而 2038 年问题将会影响系统最底层的时间控制的功能。


要解决这个问题,最简单的方式是扩展 Unix 时间的长度,用 64 位数字来表示。64 位运算器使用 64 位二进制数记录,除去表示正负的符号位,它的实际可用位数是 63 位{{efn|在包括正负号在内的情况下,范围是 {{code|-9223372036854775808}}~{{code|+9223372036854775807}}}},最大表示到公历的协调世界时(UTC)时间 292277026596 年 12 月 4 日 15 时 30 分 08 秒({{code|+9223372036854775807}}),此时已经是大约 2922 亿年后了。当然,理想的情况是到 2038 年时,64 位系统已经成为主流,从而避免特意去修正这个问题所需要的大量开销。否则,人们就必须把新的 64 位时间拆分成两部分并分别保存在两个变量里,这是一个麻烦而且效率低下的选择。
要解决这个问题,最简单的方式是扩展 Unix 时间的长度,用 64 位数字来表示。64 位运算器使用 64 位二进制数记录,除去表示正负的符号位,它的实际可用位数是 63 位{{efn|在包括正负号在内的情况下,64 位整数的十进制范围是 {{code|-9223372036854775808}}~{{code|+9223372036854775807}},绝对值可用值总数为 2 的 64 次方,即 {{code|18446744073709551616}}({{code|0}} 也单独计算为一个数,若不包括则为 {{code|18446744073709551615}},即 2 的 64 次方减 1)}},最大表示到公历的协调世界时(UTC)时间 292277026596 年 12 月 4 日 15 时 30 分 08 秒({{code|+9223372036854775807}}),此时已经是大约 2922 亿年后了。当然,理想的情况是到 2038 年时,64 位系统已经成为主流,从而避免特意去修正这个问题所需要的大量开销。否则,人们就必须把新的 64 位时间拆分成两部分并分别保存在两个变量里,这是一个麻烦而且效率低下的选择。


== 注 ==
== 注 ==

导航菜单