好吧,我承认这篇文章有点标题党,本文内容与霍金同学同名书无任何相关,而是一篇不折不扣的关于时间和计算机程序的“时间简史”。时间是什么?数学家说时间是第四维度,不过显然计算机不这么看, 在计算机的世界里,硬件层面看,时间就是RTC时钟和计时器、计数器、晶振等。而从软件层面看,时间就是一个数据结构,用来存放能表达时间的内容,当然还有一些相应的读写函数。
汇编时代
和现在的高级编程语言不同,汇编语言基本没有工业级的函数库,然而汇编程序也绝非任何功能都要一字一句敲打出来,远古时代的汇编语言大都依赖系统调用的方式进行输入输出的处理,包括BIOS调用、DOS调用、linux系统调用等,实现诸如获取输入,在屏幕上显示字符,显示图形等功能。记得当年一代码神求伯君领着小弟雷军还写过一本《深入DOS编程》就是讲DOS系统调用的,诸君有兴趣不妨一观。言归正传,汇编时代下时间如何获取和表示呢,我们以DOS系统为例,使用int21号系统调用,功能码0x2a获取系统日期,0x2C获取系统时间,数据结构没有现成的,只能自己定义了。系统调用之后的结果通常存放在寄存器中,再从寄存器mov到自己的数据字段中即可。
Basic时代
Basic算是一门中古世纪的语言,内置相关函数,访问日期用DATE$,访问时间用TIME$,相当简单和方便。
C时代
从C时代开始,我们的时间小朋友终于不再裸奔了,穿上了两件小衣服。一件是小背心time_t,这是一个整数,代表从1970年1月1日0时开始的秒数。还有件看起来不错的外套tm结构体,里面设立了年月日时分秒夏令时等字段)。此外还提供了不少库函数帮我们完成时间获取、时间格式化的工作。
数据结构/函数 | what |
- time_t | 从1970年1月1日00:00:00开始的秒数 |
- tm | 多元素结构体 |
- time() | 获取当前秒数 |
- asctime() | "Wed Jun 30 21:49:08 1993” |
- ctime() | "Wed Jun 30 21:49:08 1993” |
- gmtime() | 得到UTC时间 |
- localtime() | 得到当地时间 |
- mktime() | (contrast to gmtime) |
Mysql数据库
这个时候,数据库作为一方诸侯也邀请时间小朋友入住了,以著名的mysql为例,为时间主要准备了以下数据类型
DATETIME(8) | 1000-01-01 00:00:00 to 9999-12-31 23:59:59 |
TIMESTAMP(4) | 1970-01-01 00:00:00 to 2038-1-19 03:14:07 |
显然,TIMESTAMP对应的就是32位平台C语言的time_t,而我们储备数据还是尽可能选用DATETIME吧,毕竟2038年也不是那么遥远的事情。
Cpp时代
C孤单了很久,终于有一天找了个对象,于是成了家的C亲切的被大家叫做面向对象的Cpp。继而工业级别的函数库、模块不断出现,如stl,boost等等。那么时间也多了几个小弟像chrono、 date、 systemclock,主要实现来更好的跨平台特性和时间差计算功能。
Java时代
Java的库都是以包的形式提供的,在代码中只需要import即可,比起c系列来说确实方便不少。它提供了java.util包,里面有Date类和SimpleDateFormat类可以完成上面提到的时间获取,时间格式化等操作,真的是蛮方便的。
Python时代
接下来就是当下十分火爆的python语言了,它提供了两个模块(package)来做和时间相关的活,一个是time,一个是datetime。time 模块
- timestamp:时间戳,从1970年1月1日00:00:00开始的秒数
- struct_time:9元素touple(年月日时分秒,wday,yday,isdst)
- strftime("%Y-%m-%d %X") 格式化时间
- strptime('2011-05-05 16:37:06', '%Y-%m-%d %X') 解析时间字符串
可以看出,time模块基本等价于C的time实现,比较底层,此外提供了格式化和解析时间字符串的功能。
datetime模块
- 包括date、time、datatime、timedelta、tzinfo
- time被限制在24小时以内
- timedelta可以方便的计算时间差
- 提供和time模块基本相同的函数可以格式化和解析时间
以上就是关于时间和计算机的“时间简史”,在汇编->C语言->C++->Java->Python的演化中究其本源,它其实只进化了1次,就是从32位进化到64位。目前来看,很长一段时间内它应该不会再进化了,毕竟64位的秒数表示够我们用到天荒地老了。