Skip to content

time

python中常用的时间相关的标准库有三个。

  • time
  • datetime
  • calender

我们一网打尽。

time

time是用C编写的,为python提供时间处理功能的标准库。

时间是什么?

时间是人为定义出来的,什么是一秒钟,今天是哪天都是人为定义的(无意冒犯基督)。

并且这个定义随着人类技术水平的发展还在不断修正。

秒是国际单位制中时间的基本单位,符号是s。秒在英文里的原始词义是计算小时的六十分之一(分钟)后,再计算六十分之一。

  • 在西元1000至1960年之间,秒的定义是平均太阳日的1/86,400(在一些天文及法律的定义中仍然适用)。
  • 在1960至1967年之间,定义为1960年地球自转一周时间的1/86,400。
  • 现在则是用原子的特性来定义。秒也可以用机械钟、电子钟或原子钟来计时。

有了一秒钟的定义,我们就可以定义某一刻的时间了。

高中的地理课上大家都学习过时区的概念,听说过格林尼治天文台本初子午线这些名词。实际上这就是GMT(Greenwich Mean Time):把格林尼治天文台所在地的地方平太阳时被定义为全世界的时间标准,然后各地按照时区做加减法。

但是这个定义有些问题:太阳时不是那么精准。19世纪,依赖原子钟技术的UTC(Coodinated Universal Time)出现了,取代GMT成为了新的时间标准。

UTC

1963年,CCIR在其发布的第374号建议案中给出了首个对协调世界时作出定义的国际规范,国际时间局则在1965年开始以当时的原子时A3(国际原子时的前身)来计量UTC。

但由于UTC与原子时存在的频偏问题以及其时间单位与国际单位制下的秒长的不一致性,其后几年UTC经历了多次的调整。直到1970年,CCIR发布了第460号建议案,对上述两个问题进行了修正,且要求加入跳秒机制使UTC与原有世界时的偏移被控制在1秒以内,UTC的定义才得以稳定下来。这一新的UTC系统自1972年的1月1日零时开始使用,并沿用至今。

比较有意思的是这个跳秒机制(leap second,也叫闰秒)。

闰秒

闰秒是偶尔运用于协调世界时(UTC)的调整,经由增加或减少一秒,以消弥精确的时间(使用原子钟测量)和不精确的观测太阳时 (称为UT1),之间的差异。这会由于地球自转的不规则和长期项的地球自转减慢而有所不同。UTC标准时间广泛用于国际计时,并在大多数国家用作民用时的参考,它使用精确的原子时,因此,除非根据需要将其重置为UT1,否则将超前运行在观测到的太阳时。闰秒的存在就是为了提供这样的调整。

OK,故事讲到这里你就可以理解为什么时间戳(timestamp)是从1972年1月1日零时开始计算至今经过的秒数了。这个零点其实就是UTC时间标准启用的时间。

时间的各种表示法

在python里,大概有这样几种:

  • 1682676590.8083282
  • 'Fri Apr 28 18:10:07 2023'
  • time.struct_time(tm_year=2023, tm_mon=4, tm_mday=28, tm_hour=10, tm_min=10, tm_sec=40, tm_wday=4, tm_yday=118, tm_isdst=0)

第一种是时间戳(浮点数),第二种是文本类型的表示法(字符串),第三种是结构化数据(元组)。

python中获取当前时间的方法
>>> import time
>>> time.time() # 获取当前时间戳
1682676590.8083282
>>> time.strftime('%c') # 获取格式化的字符串时间
'Fri Apr 28 18:10:07 2023'
>>> time.gmtime() # 获取结构化的时间
time.struct_time(
    tm_year=2023, tm_mon=4, tm_mday=28, 
    tm_hour=10, tm_min=10, tm_sec=40, 
    tm_wday=4, tm_yday=118, tm_isdst=0
)
>>> time.gmtime()[0] # 可以通过指标来获取指定位置的数值
2023
>>> time.gmtime().tm_mday # 也可以通过属性名来获取
28

各种时间类型的转化

python中的time.struct_time是比较理想的结构化数据(tuple),所以我们做时间类型转化可以用它作为中介。

时间戳转化成元组

gmtime([seconds]) -> (tm_year, tm_mon, tm_mday, tm_hour, tm_min,
                       tm_sec, tm_wday, tm_yday, tm_isdst)

元组转化成时间戳

mktime(tuple) -> floating point number

元组转化成字符串

strftime(format[, tuple]) -> string

字符串转化成元组

strptime(string, format) -> struct_time

注意到涉及到字符串的转化时需要指定字符串时间的格式(format),诸如:

  • "2023-01-01 10:21 AM"
  • 'Thu, 28 Jun 2001 14:17:15 +0000'
  • "2023年10月20日 21时30分"

他们的格式参数分别是:

  • %Y-%m-%d %H:%M %p
  • %a, %d %b %Y %H:%M:%S +0000
  • %Y年%m月%d日 %H时%M分

其中用%开头的是转义字符,他们的含义如下: |指令|含意| |--|--| |%a|本地化的缩写星期中每日的名称。| |%A|本地化的星期中每日的完整名称。| |%b|本地化的月缩写名称。| |%B|本地化的月完整名称。| |%c|本地化的适当日期和时间表示。| |%d|十进制数 [01,31] 表示的月中日。| |%H|十进制数 [00,23] 表示的小时(24小时制)。| |%I|十进制数 [01,12] 表示的小时(12小时制)。| |%j|十进制数 [001,366] 表示的年中日。| |%m|十进制数 [01,12] 表示的月。| |%M|十进制数 [00,59] 表示的分钟。| |%p|本地化的 AM 或 PM 。| |%S|十进制数 [00,61] 表示的秒。| |%U|十进制数 [00,53] 表示的一年中的周数(星期日作为一周的第一天)。 在第一个星期日之前的新年中的所有日子都被认为是在第 0 周。| |%w|十进制数 [0(星期日),6] 表示的周中日。| |%W|十进制数 [00,53] 表示的一年中的周数(星期一作为一周的第一天)。 在第一个星期一之前的新年中的所有日子被认为是在第 0 周。| |%x|本地化的适当日期表示。| |%X|本地化的适当时间表示。| |%y|十进制数 [00,99] 表示的没有世纪的年份。| |%Y|十进制数表示的带世纪的年份。| |%z|时区偏移以格式 +HHMM 或 -HHMM 形式的 UTC/GMT 的正或负时差指示,其中H表示十进制小时数字,M表示小数分钟数字 [-23:59, +23:59] 。| |%Z|时区名称(如果不存在时区,则不包含字符)。| |%%|字面的 '%' 字符。|

datetime