I have some trouble understanding time conversions in python. I have two identical time_struct
objects
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)
When I feed it to the time.mktime
function on one machine
time.mktime(local_dt.timetuple())
it returns 946681200.0
On a second machine I get a different answer
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
The machines have different timezones, though:
In [44]: time.tzname
Out[44]: ('Europe', 'Europe')
In [45]: time.tzname
Out[45]: ('CET', 'CEST')
The documentation on the time module says:
Use the following functions to convert between time representations: struct_time in local time seconds since the epoch mktime()
As I understand my local time is "America/Los_Angeles" so seconds since epoch should be exactly the same and not be depending on the system configuration.
What am I misunderstanding? How do I have to calculate the timestamp correctly then?
time.mktime()
interprets the timetuple
based on the local machine's timezone. Notice how your timetuple
object doesn't contain any timezone info, so the timestamp created will always vary based on timezone set on the local machine. Thus it's entirely understandable why the same time.mktime(local_dt.timetuple())
returns different value on those two machines.
You can use 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 Cmktime()
function to perform the conversion.
... But since you're creating the timestamp
directly from the non-naive datetime
object, it still retains the timezone info and can shift the time accordingly:
For aware
datetime
instances, the return value is computed as:
(dt - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds()
Observe:
>>> 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
The last time.mktime()
processed utc.timetuple()
as a local time since the timezone info was not passed. You can notice it's offset by 18000 ( time.timezone
for EST, my time zone).
As you said : "The machines have different timezones, though:" and doc said: "in local time".
Your "local time" is not the same on both machine : one is Europe/europe (probably GMT, so UTC+0), the other one is CEST (UTC +1).
see 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.
I think you want to convert your datetime into "UTC+0 datetime"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.