将datetime转换为unix时间戳

将datetime转换为unix时间戳

问题描述:

今天,我和一些同事正在尝试将日期时间正确地转换为非本地时区的时间戳。经过大量讨论,我们仍然不确定如何将日期时间正确地转换为时间戳,而仅部分确定如何针对我们的用例:America / New_York中的日期时间实例

Today me and some coworkers were trying to correctly convert a datetime into a timestamp that was in a non-local timezone. After much discussion, we still weren't sure about how to, in a general sense, correctly convert a datetime into a timestamp, and were only partially sure of how to do it for our use case: a datetime instance in the America/New_York timezone from pytz.

因此,我认为我会经历一些排列并尝试根据经验找出答案,因为阅读了文档并试图从逻辑上讲出了原因。

So, I figured I'd run through some permutations and try to empirically figure it out, since reading the docs and trying to logically reason it out wasn't getting me anywhere.

在输入数据中:

pst = pytz.timezone('America/Los_Angeles')
est = pytz.timezone('America/New_York')
utc = pytz.timezone('UTC')

epoch = int(time.time())
# local time for me is Pacific
local_naive = datetime.datetime.fromtimestamp(epoch)
local_aware = datetime.datetime.fromtimestamp(epoch, pst)
est_aware = datetime.datetime.fromtimestamp(epoch, est)
utc_naive = datetime.datetime.utcfromtimestamp(epoch)
utc_aware = datetime.datetime.fromtimestamp(epoch, utc)

结果的计算方法有四种:

And the result was computed in four ways:


  1. time.mktime(dt.timetuple())

  2. time.mktime(dt.utctimetuple())

  3. calendar.timegm(dt.timetuple())

  4. calendar.timegm(dt.utctimetuple())

  1. time.mktime(dt.timetuple())
  2. time.mktime(dt.utctimetuple())
  3. calendar.timegm(dt.timetuple())
  4. calendar.timegm(dt.utctimetuple())

我意识到其中一些本质上是荒谬的,但是我试图做到完整:)。

I realize some of those are inherently nonsensical, but I was trying to be complete :).

这是输出。 diff = 部分是为了帮助显示不正确的转换。

And here's the output. The diff= part is to help show the conversions that aren't correct.

now epoch                       : 1342671099
est   aware mktime(timetuple)   : 1342681899 diff=-10800
local aware mktime(timetuple)   : 1342671099 diff=0
local naive mktime(timetuple)   : 1342671099 diff=0
utc   aware mktime(timetuple)   : 1342699899 diff=-28800
utc   naive mktime(timetuple)   : 1342696299 diff=-25200
est   aware mktime(utctimetuple): 1342699899 diff=-28800
local aware mktime(utctimetuple): 1342699899 diff=-28800
local naive mktime(utctimetuple): 1342674699 diff=-3600
utc   aware mktime(utctimetuple): 1342699899 diff=-28800
utc   naive mktime(utctimetuple): 1342699899 diff=-28800
est   aware timegm(timetuple)   : 1342656699 diff=14400
local aware timegm(timetuple)   : 1342645899 diff=25200
local naive timegm(timetuple)   : 1342645899 diff=25200
utc   aware timegm(timetuple)   : 1342671099 diff=0
utc   naive timegm(timetuple)   : 1342671099 diff=0
est   aware timegm(utctimetuple): 1342671099 diff=0
local aware timegm(utctimetuple): 1342671099 diff=0
local naive timegm(utctimetuple): 1342645899 diff=25200
utc   aware timegm(utctimetuple): 1342671099 diff=0
utc   naive timegm(utctimetuple): 1342671099 diff=0

从此输出中可以看出,通常来说,调用calendar.timegm(dt.utctimetuple())通常是 正确的方法-除非是当地时间幼稚。好的,我可以解决...除了我看不到如何将本地原始时间与任何其他原始时间区分开来,这使得不可能将任意日期时间对象正确地转换成时间戳?

From what I can tell from this output, in general, calling calendar.timegm(dt.utctimetuple()) is usually the correct way -- unless its a naive local time. Ok, I can deal with that...except I don't see how you can disambiguate a local naive time from any other naive time, which makes it impossible to correctly convert an arbitrary datetime object into a timestamp? Is that really the case, or am I missing something?


我不知道怎么做吗?您可以将本地原始时间与其他任何原始时间区分开来。

I don't see how you can disambiguate a local naive time from any other naive time

完全正确。如您所知,朴素的意思是没有附加时区信息,因此 timegm 被强制推断出丢失的信息,并且您的结果表明它推断出朴素的日期时间为UTC。

Exactly. As you already know, naive means "no time zone information attached," so timegm is forced to infer the missing information, and your results show that it infers naive datetimes to be UTC.

如评论中所述,附加TZ的时间应被视为烫手山芋-您应该在输入后立即转换为UTC,并转换为在输出给用户之前本地。从长远来看,这将为您节省很多心痛。

As was said in the comments, times with TZ attached should be treated like a hot potato - you should convert to UTC as soon as you get input, and convert to local just before you output to the user. This will save you a lot of heartache in the long run.