难以理解时间转换

trouble understanding time conversions

我无法理解 python 中的时间转换。 我有两个相同的 time_struct 对象

In [22]: local_dt
Out[22]: datetime.datetime(2000, 1, 1, 0, 0, tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>)
In [23]: local_dt.timetuple()                                                                                                                             
Out[24]: time.struct_time(tm_year=2000, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=1, tm_isdst=0)

当我将它提供给一台机器上的 time.mktime 函数时

time.mktime(local_dt.timetuple())

它returns946681200.0

在第二台机器上我得到了不同的答案

In [31]: local_dt.timetuple()                                                                                                                             
Out[31]: time.struct_time(tm_year=2000, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=1, tm_isdst=0)

In [32]: time.mktime(local_dt.timetuple())                                                                                                                
Out[32]: 946684800.0

虽然这些机器有不同的时区:

In [44]: time.tzname                                                                                                                                      
Out[44]: ('Europe', 'Europe')

In [45]: time.tzname
Out[45]: ('CET', 'CEST')

时间模块的文档说:

Use the following functions to convert between time representations: struct_time in local time seconds since the epoch mktime()

据我所知,我的当地时间是 "America/Los_Angeles",所以自纪元以​​来的秒数应该完全相同,而不取决于系统配置。

我误会了什么?那么我该如何正确计算时间戳?

正如你所说:"The machines have different timezones, though:" 和医生说:"in local time".

你的"local time"在两台机器上都不一样:一个是Europe/europe(可能是GMT,所以UTC+0),另一个是CEST(UTC+1)。

https://www.timeanddate.com/time/zones/eu

Central European Time (CET) is 1 hour ahead of Coordinated Universal Time (UTC). This time zone is in use during standard time in: Europe, Africa.

我认为您想将日期时间转换为 "UTC+0 datetime"

time.mktime() 根据本地计算机的时区解释 timetuple。请注意您的 timetuple 对象如何不包含任何时区信息,因此创建的时间戳将始终根据本地计算机上设置的时区而有所不同。因此完全可以理解为什么在这两台机器上相同的 time.mktime(local_dt.timetuple()) returns 不同的值。

您可以使用 local_dt.timestamp() instead, while both are essentially the same...

Naive datetime instances are assumed to represent local time and this method relies on the platform C mktime() function to perform the conversion.

...但是由于您是直接从非天真的 datetime 对象创建 timestamp ,它仍然保留时区信息并可以相应地改变时间:

For aware datetime instances, the return value is computed as:

(dt - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds()

观察:

>>> est = datetime.datetime(1999, 12, 31, 19, 0).astimezone(pytz.timezone('EST'))
>>> utc = est.astimezone(pytz.timezone('UTC'))
>>> est
datetime.datetime(1999, 12, 31, 19, 0, tzinfo=<StaticTzInfo 'EST'>)
>>> utc
datetime.datetime(2000, 1, 1, 0, 0, tzinfo=<UTC>)
>>> est.timestamp()
946684800.0           
>>> utc.timestamp()
946684800.0           # same as est
>>> time.mktime(est.timetuple())
946684800.0
>>> time.mktime(utc.timetuple())
946702800.0           # different than est

由于未传递时区信息,最后 time.mktime() 处理 utc.timetuple() 为当地时间。您会注意到它偏移了 18000(time.timezone 对于 EST,我的时区)。