utc时间、本地时间及时间戳转化

时间:2021-02-23 02:41:15

1、时间戳的概念

时间戳的定义请看百科unix时间戳,需要注意的时间戳为当前时刻减去UTC时间(1970.1.1)零点时刻的秒数差,与当前系统所处的时区无关,同一时刻不管在任何时区下得到的时间戳都是一样的。

最近因为存储数据库需要将时间转为时间戳的字节型来存储,用了python datetime模块,期间遇到一些问题,现在终于弄懂了时间戳、时间和UTC时间的正确转换关系,总结以下供大家参考。

2、python datatime模块实现时间戳和本地时间、UTC时间之间的互相转化

1) 获得unix timestamp

  dt=datetime.datetime.now()       #获取本地当前时间
  dt.timestamp()          #获取时间戳

注:

  • 此方式下now()函数中有个参数为tz,参数意思为时区信息,不设时为本地时间,当设置时,如tz=timezone.utc,则表示为当前的utc时间,无论是utc时间还是本地时间,获得的时间戳都是同一个值.
  • timestamp()内部会根据时区设置得到时间戳,当时区为utc时间时timestamp()函数直接减去EPOCH得到的秒数,当为其他时区的时间时通过标准C库函数mktime得到相差秒数,不管哪种方式,相差的秒数差是一样的,所以不同时区下的时间戳必定为同一个值

2) python datetime模块的小坑

    由1)的阐述得到python在不同时区下都能获得时间戳,我就采用了utc时间获得时间戳,datetime有两种方式获得utc时间:

    方式一:

   dt=datetime.datetime.now(timezone.utc)    #类型为aware datetime object,时区为utc
     dt.timestamp()                            #通过减去EPOCH得到时间戳

 方式二:

   dt=datetime.datetime.utcnow()          #类型为naive datetime object,不包含时区信息
   dt.timestamp()                 #通过mktime得到时间戳(得到的时间戳是错误的 
  • 在未理解naiveaware之前,以为两种方式获得时间戳都是一样的,未曾想第二种方式下再通过timestamp()获得的时间戳是错误的,为什么会发生这种情况,是因为naive是不含时区的类型,而aware是有时区类型。
  • 第二种虽然和方式一获得的值是相同的,但是第二种方式不包含时区信息,在方式二下执行dt.timestamp(),timestamp()默认tz=None,即为本地时区,这样就会按照mktime得到秒数差,但其实此时dt却是utc时间。而方式一有时区信息,执行dt.timestamp()是直接减去EPOCH时间。
  • 当时间值相同时,naive类型和aware类型时间下执行timestamp()结果是不一样的,一定要注意,不能踩了这个坑,除非是本地时间,如果想通过其他时区的时间通过timestamp()得到时间戳,一定要带有时区信息。

3) 通过timestamp得出datetimeutc datetime

  • timestamp转datetime

   datetime.datetime.fromtimestamp(timestamp)         #获得本地时间,类型naive datetime obiect
  •  timestamp转utc datetime

两种方式获得utc时间,但datetime object类型不一样。

方式一:

   datetime.datetime.utcfromtimestamp(timestamp)     #类型naive datetime object

方式二:

   datetime.datetime.fromtimestamp(timestamp,timezone.utc)    #类型aware datetime object。   

3、总结:

  • timestamp没有时区之分,不要认为不同时区有不同的时间戳。
  • datetime object有两种类型,naive是不含时区的类型,而aware是有时区类型,就算显示的值一样,不同类型的object也不能直接进行数学运算。