Python – calendar.timegm() vs. time.mktime()

Question:

I seem to have a hard time getting my head around this.

What’s the difference between calendar.timegm() and time.mktime()?

Say I have a datetime.datetime with no tzinfo attached, shouldn’t the two give the same output? Don’t they both give the number of seconds between epoch and the date passed as a parameter? And since the date passed has no tzinfo, isn’t that number of seconds the same?

>>> import calendar
>>> import time
>>> import datetime
>>> d = datetime.datetime(2010, 10, 10)
>>> calendar.timegm(d.timetuple())
1286668800
>>> time.mktime(d.timetuple())
1286640000.0
>>> 
Asked By: ibz

||

Answers:

calendar.timegm converts from UTC timestamp, time.mktime converts from local time not UTC.

8 hours difference in their results corresponds exactly to timezone of your location.

Answered By: SilentGhost

time.mktime() assumes that the passed tuple is in local time, calendar.timegm() assumes it’s in GMT/UTC. Depending on the interpretation the tuple represents a different time, so the functions return different values (seconds since the epoch are UTC based).

The difference between the values should be equal to the time zone offset of your local time zone.

Answered By: sth

Let us consider below example,

>>> import datetime
>>> import time
>>> import calendar
>>> utc_time_now = datetime.datetime.utcnow()
>>> utc_time_now
datetime.datetime(2022, 5, 21, 6, 47, 33, 929433)
>>> time.mktime(utc_time_now.timetuple())
1653095853.0
>>> calendar.timegm(utc_time_now.timetuple())
1653115653
>>> time.tzname
('IST', 'IST')
>>> time.strftime("%z", time.gmtime())
'+0530'
>>> (1653115653-1653095853)
19800

Before we begin with an explanation, please note that ‘datetime.datetime.utcnow()’ returns a DateTime object which is ‘naive’ and has no information about your local timezone.

time.mktime()
Applying the above function to a DateTime object considers the ‘Timezone’.
So acc. to the example above, when you provide the time ‘2022-05-21 06:47:33’ to time.gmtime(), it assumes that this time is not actually in UTC but in your local timezone (‘IST’ in my case).

In my case, the timezone is ‘IST’, which is +05:30 (5 hr, 30 mins) ahead of the UTC timezone.
So to return the epoch in the UTC timezone, it subtracts +05:30 (19800 seconds) from the datetime object in its timestamp calculation.
Hence, it returns the timestamp (1653095853.0), which is 19800 seconds less than the original UTC epoch seconds (1653115653).

Note: If your timezone is negative (like -05:30), it will add 19800 seconds to the final epoch calculation. Hence you will see time.gmtime() timestamp is greater by 19800 seconds from the UTC epoch timestamp.

calendar.timegm()
It returns the corresponding Unix timestamp value, assuming an epoch of 1970-01-01. Hence no extra adjustment in the DateTime object is made.
Whatever DateTime object value it gets, it subtracts it from epoch time ‘1970-01-01’ and returns the total seconds() elapsed.

BONUS
Get timestamp epoch milliseconds from your UTC DateTime object.
1st Method:

>>> utc_time_now
datetime.datetime(2022, 5, 21, 7, 16, 34, 938547)
>>> int((calendar.timegm(utc_time_now.timetuple()) + (utc_time_now.microsecond/1e6))*1000.0)
1653117394938

2nd Method:

>>> utc_time_epoch = datetime.datetime.utcfromtimestamp(0)
>>> utc_time_epoch 
datetime.datetime(1970, 1, 1, 0, 0)
>>> utc_time_now = datetime.datetime.utcnow()
>>> utc_time_now 
datetime.datetime(2022, 5, 21, 7, 16, 34, 938547)
>>> elapsed_time = utc_time_now - utc_time_epoch
>>> elapsed_time
datetime.timedelta(19133, 26194, 938547)
>>> int(elapsed_time.total_seconds() * 1000.0)
1653117394938

Have a good time 🙂

Answered By: Sanjit
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.