时间戳,2038年计算机要面临的问题(代码演示)

        本章介绍时间戳,时间戳的定义、时间戳问题、危机详细分析、计算机2038年要面临的问题、代码模拟以及回顾2000年千年虫危机。

目录

1.  时间戳的定义

2.  时间戳危机

3.  详细分析

4.  代码演示

5.  解决办法

6.  前例-2000年千年虫

7.  结尾


1.  时间戳的定义

        时间戳,定义为从经度0°的英国格林尼治1970年1月1日0时0分0秒起算,到现在所经过的秒数。因为中国在东八区,比格林尼治早8个小时,当格林尼治0点时,中国已经是8点了,所以对于中国地区,时间戳就是从北京时间1970年1月1日8时0分0秒起算,到现在所经过的秒数。时间戳的定义解决了计算机无法计算时间的问题。

2.  时间戳危机

        在60年代,但是计算机存储器的成本很高,普遍采用了32位的存储器,许多设备和程序都使用32位存储器,至今,正是现在所说的电脑内核32位64位。随着1997年 “千年虫” 的的警钟拉起,人们逐渐意识到位数的不足导致的众多问题。

        时间戳是有 “耗尽” 的一天的,按照32位的时间戳存储结构,它能正确表示的秒数最大为2147483647(2的31次方,第一位是符号位),即到英国格林尼治时间 2038年1月19日03:14:07秒,也就是北京时间 2038年1月19日11:14:07秒。届时所有32位的设备和32位的程序都会受到严重的影响。

3.  详细分析

        这个问题的出现是由C语言引起的,而C语言为python的母语。在C语言中,用time_t (整数int型)来表示日期和时间,它以32位数据进行存储,其中最高位为符号位(0表示正数,1表示负数),剩余的31位用来存储数字,所以32位仅能表示2的31次方=2147483648秒,对于时间戳,一旦超过2147483648秒,即英国格林尼治时间 2038年1月19日03:14:07秒,计算机时间便出现问题。

整型溢出 变成负数
负数继续增加

        对于32位计算机,一旦超过01111111111111111111111111111111后,最高位进一,便变成负数。由于负数的表示为补码,就是用其正数进行取反(除最高位)再+1。反过来,知道一个负二进制数,求其十进制数如上图。

        当溢出后继续增加,该负数也会越来越大,如-2147483647继续加就变成-2147483646。得到此数后,我们在溢出界点对前后的变化进行分析:

在溢出边界的时间戳
“ 时光倒流 ”

        计算机时间存储溢出后,时间便 “倒流” 回中国1970年1月1日8时0分1秒的2147483648秒前,即1901/12/13 20:45:52。如果32位一直用下去,那么计算机里时间的历程为①→②→①→②反复循环。但是不可能一直用下去,因为其时间紊乱而得不到解决,注定退役。

 

4.  代码演示

        用代码模拟32位计算机面临的问题。由于datetime.datetime.fromtimestamp()不能传入负数,所以无法模拟 “时光倒流” 的情况,这里以该函数的报错来表示 “时光倒流”。

        把2147483648前后5个数转为二进制,发现2147483648前的为31为,因为最高位为0,所以不显示,把<2147483648最高位补回来:

        补回来后,可以观察到2147483648前的最高位(第32位)为0,而2147483648及后面的最高位(第32位)为1。最高位为0表示正数,1表示负数。

        把该二进制转回十进制,此时,小于2147483648的数为正数,而大于2147483648的数则为负数。把该数传到时间函数去模拟2038年32位计算机危机。最终代码为:

import datetime
for i in range(2147483648-5,2147483648+5):
    print(i)                     # 时间戳
    er = str(bin(i)).replace('0b','')         # 时间戳转为二进制,判断32位二进制最高是0还是1
    if len(er) == 31:
        er = f'0{er}'
        print(er)                # 如果二进制是31位,那给它还原最高位0
        wei_32 = int(er,2)
        print(wei_32)            # 长度是31证明最高位0,正数,直接把二进制转十进制
        ti = datetime.datetime.fromtimestamp(wei_32)           # 十进制的时间戳 输出时间
        print(ti)
        print('-'*50)
    else:
        print(er)                # 它长度为32,那最高位是1,那它(32位)表示的是负数
        wei_32 = -int(er,2)
        print(wei_32)
        ti = datetime.datetime.fromtimestamp(wei_32)       # 负数传该函数这会报错
        print(ti)
        print('-' * 50)

        当时间戳达到或者超过2147483648后,32位存储器表示的就是负数,结果正如我们所预料的,计算机开始出现危机。而表现在32位计算机的是 “时光倒流” ,所有关于时间的问题都会出现,如出租车计价,股票开盘,网上银行,铁路等系统。

        图中也可以看到,32位计算机的时间戳最大只能表示到北京时间2038年1月19日11时14分07秒,也就是格林尼治时间2038年1月19日03时14分07秒。

5.  解决办法

        及时对32位设备及程序进行退役,普及64位,用64位数字来表示它。64位的二进制数实际可用位数是63位,最大表示到公历的UTC时间292,277,026,596年12月4日15时30分08秒。如果那个时候人类还存在的话,公元纪年很可能已经因为太难用而被抛弃了。

        对于服务器和最新电脑,已经换成了64系统操作系统,2038年时间戳的问题将不复存在。而对于嵌入式设备来说,现在还有大量32位系统在全球各地运行,谁也无法保证这些系统在2038年之前就能光荣退役。另外对于64位操作系统,上面还会运行着32位的应用程序,它的2038年问题一样对人们造成威胁,不可小视。(来自百度百科-2038年问题

        现在我们的电脑基本都是64位了,但不排除上面还会运行着32位的应用程序。千年虫问题的解决只用了2年,我们面临2038年问题还有15年,相信科学家会找到完美过渡32位64位的方法,也希望2038年计算机危机能顺利渡过。

6.  前例-2000年千年虫

        千年虫,又称 “计算机2000年问题”,缩写 “Y2K”。某些60年代的存储器成本问题,计算机程序的智能系统的年份只使用两位十进制数来表示,因此系统涉及跨世纪的日期处理时,就回出现错误,引起各种系统功能紊乱、崩溃。千年虫可以认为是一种人为的bug,所使用的位数不足导致的,而非病毒。

        到1997年,信息界开始拉起了 “千年虫” 警钟。严重到各国政府出面,投入数以亿计的财政,全力解决 “千年虫” 问题。新年前一天,取得了令人可观的结果。但该来的还是会来,广州某公司电脑接二连三故障,向软件公司求助时发现已经100多家公司的数据库瘫痪;北京市计算机2000年问题办公室3天内接到十几个求助电话;在1999年12月31日23:59分打了3分钟的电话,电话局的账单却显示为(-100年+3分钟)......陆陆续续,2010年,2016年小规模再度现身,给经济造成巨大损失。(来自百度百科-千年虫-2000年计算机问题

7.  结尾

        感兴趣的朋友可以去查查自己的电脑操作系统是多少位吧!右击 “我的电脑” - “属性” ,查看 “系统类型” 。我的是 “64位操作系统,基于x64的处理器 ”。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值