Working with Time and Time Zones in Python

Time conversions can be tedious, but Python offers some relief for the frustration. Here are some quick recipes which are quite useful when juggling with time.

Imagine you get logged timestamps in a certain format like 2017-05-30T23:51:03Z which is commonly referred as ISO 8601. You know that the time zone is Europe/Paris or Central European Time (UTC+01:00) and you want to normalize the timestamp to UTC. This can be done by using the pyhton datetime object as follows

import datetime import pytz timestring = "2017-05-30T23:51:03Z" # Create datetime object d = datetime . datetime . strptime ( timestring , "%Y-%m-%dT%H:%M:%SZ" ) print ( d . tzinfo ) # Return time zone info print ( d . strftime ( "%d.%m.%y %H:%M:%S" )) # Set the time zone to 'Europe/Paris' d = pytz . timezone ( 'Europe/Paris' ). localize ( d ) print ( d . tzinfo ) # Return time zone info # Transform the time to UTC d = d . astimezone ( pytz . utc ) print ( d . tzinfo ) # Return time zone info print ( d . strftime ( "%d.%m.%y %H:%M:%S" ))

with the result

None 30.05.17 23:51:03 Europe/Paris UTC 30.05.17 21:51:03

where strptime() translates the formated time string to a datetime object by using format codes and where strftime() translates the datetime object back to a String represented by a format string consisting of the same format codes. The pytz module is helpful for working with time zones. What is also important to mention is that due to Daylight Saving Time, the time zone Europe/Paris for this timestamp is Central European Summer Time (UTC+02:00), which can be seen in the time difference in the result. This Computerphile video illustrates how painful time zones can get.

Another convenient way to save timestamps is to use Unix timestamps, which are commonly in the UTC time zone. They measure the passed seconds since 1 January 1970, which will overflow for the 32-bit representation on the 19 January 2038. But we shouldn’t worry now about that problem.

import datetime timestamp = "1496181063" # Gives you the date and time in local time d = datetime . datetime . fromtimestamp ( int ( timestamp )) print ( d . strftime ( "%d.%m.%y %H:%M:%S" )) # Gives you the date and time in UTC d = datetime . datetime . utcfromtimestamp ( int ( timestamp )) print ( d . strftime ( "%d.%m.%y %H:%M:%S" ))

with the result

30.05.17 23:51:03 30.05.17 21:51:03

where the first timestamp is the local time (CEST) at that time transformed from UTC and the second timestamp is in UTC. I prefer to work directly in UTC to avoid confusion. In order to get the current timestamp you can use the time module as follows

import time import datetime # Returns unix timestamp for current time timestamp = time . time () # Get datetime object in local time d = datetime . datetime . fromtimestamp ( timestamp ) # Return unix timestamp from datetime object timestamp = d . timestamp ()

This is farely straight forward. Sometimes you need to get the time information of a certain file. In python you can access this information with the os.path module, where the following functions all return a unix timestamp.

import os import datetime filepath = "path/to/file" # Return the system’s ctime. # In Windows creation time and in Unix systems last metadata change timestamp = os . path . getctime ( filepath ) # Return the time of last modification of path timestamp = os . path . getmtime ( filepath ) # Return the time of last access of path timestamp = os . path . getatime ( filepath ) d = datetime . datetime . fromtimestamp ( timestamp )

Working with Time Differences

In order to perform arithmetic operations with time you can simply substract two datetime objects, which will return a datetime.timedelta object.

import datetime timestring = "2017-05-30T23:51:03Z" # Create datetime objects d0 = datetime . datetime . strptime ( timestring , "%Y-%m-%dT%H:%M:%SZ" ) d1 = datetime . datetime . now () # Current time # Calculate timedelta dt = d1 - d0 passed_days = dt . days passed_seconds = dt . days # remaining seconds passed_microseconds = dt . microseconds # remaining microseconds total_seconds = dt . total_seconds ()