Image from Metropolitan Museum of Art

Working with Time and Time Zones in Python

Table of Contents

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.

Parse Timestamps to UTC

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 (CET) (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 (DST), the time zone Europe/Paris for this timestamp is Central European Summer Time (CEST) (UTC+02:00), which can be seen in the time difference in the result. This Computerphile video illustrates how painful time zones can get.

Working with Unix Timestamps

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()

Getting Timestamps from Files

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()

where dt can be used as a offset for another datetime object, by using one of the various timedelta operations.

Resources