How to use Time in Python

Peter Tribout
4 min readJan 3, 2021

What are the challenges we have to face ?

  1. Time is relative and needs to be referenced to a certain “Time Zone” like ‘Europe-London’ or ‘America/New_York’.
  2. We have to cope with ‘DST’ or Daylight Saving Time. This is the practice of turning the clock ahead in the spring and back in the fall so we can all enjoy an extra hour of sunshine. But this creates a day of 23h when introduced and a day of 25h at the end. So we need this DST info(True or False) when being confronted with timestamps at the transition period, like in the fall, in order to distinguish between 02h:01 and one hour later also 02h:01

Intro: What is Epoch time ?

Epoch, from Greek epochē, meaning “cessation” or “fixed point.”

In the context of computers:

Epoch time = number of seconds since 1 jan 1970

# In this example it is : 2021-01-02T17:22:09.820156+00:00Z
import time
my_time = time.time()
print(my_time)
1609608129.8201559

Ideal format for computers, timestamps in databases etc

Intro: What is Iso-8601 ?

Iso-8601 is the defacto time standard notation

format: YYYY-MM-DDThh:mm:ss+UTC offset or 'Z = Zulu time = +00:00'
- example: 2020-12-26T16:04:59+01:00

Ideal format for humans or log files

The concept of “Naive” and “Aware” objects

  • Naive = it has no clue or reference of a time zone
  • Aware = date/time referenced to a timezone

Examples:

- Naive = 2020–12–26 16:04:59

- Aware = 2020–12–26 16:04:59+01:00

In the above case of a Naive time, we don’t know what the exact time is. Is this 16h04 in London, New York or ..?

The Aware time gives us an exact time. Since New York is GMT -5 and the above reference is GMT+1, we now know it is 16h04 -6h=10h04 in New York.

What library should I choose “time” or “datetime”?

This is an essential choice but not so obvious ! This is because the time library is by default “Aware” and datetime is not. And this has some consequences!

Both can do the job. Datetime is much more powerful when it comes to dealing with date arithmetic, like date differences or x weeks from now etc but it comes at a cost. You additionally need an extra library, like pytz or dateutils, to create timezone objects and link this timezone to the datetime object to make it “Aware”. This can become very error prone if you are not an expert in both libraries!

The fact that there is a debate in the community about the choice of pytz versus dateutils indicates that this a complex matter. (see References)

When to choose what library?

  • time: ideal for unambiguous time stamping
  • datetime: for complex data manipulations and you fully master the concept.

Working with the time library

A nice and compact schema of the time library from wiki.python.org

https://wiki.python.org/moin/WorkingWithTime

Working with datetime and pytz

import pytz
from datetime import datetime
brussels=pytz.timezone('Europe/Brussels')
unaware = datetime(2020,12,26,16,4,59)
# In order to make a "Naive" or unaware time object "Aware" we have to link it to a timezone.
# To achieve this, we have 2 options.
# Method 1: with localize
aware1=brussels.localize(datetime(2020,12,26,16,4,59))
print(aware1)
# Method 2: with astimezone
aware2 = unaware.astimezone(brussels)
print(aware2)
# Both give result /> 2020-12-26 16:04:59+01:00

Working with datetime and dateutil

from dateutil import tz
from datetime import datetime
brugge =tz.gettz('Europe/Brussels')# Method 1: directly when creating the time (something that can NOT be done with pytz !!)
aware10 = datetime(2020,12,26,16,4,59,tzinfo=brugge)
print(aware10) # result /> 2020-12-26 16:04:59+01:00
# Method 2: with astimezone
unaware20= datetime.now()
aware21= unaware20.astimezone(tz=brugge)
aware22= datetime.now().astimezone(tz=tz.UTC)
print(unaware20) # result /> 2020-12-27 15:28:53.100971
print(aware21) # result /> 2020-12-27 15:28:53.100971+01:00
print(aware22) # result /> 2020-12-27 14:28:53.101049+00:00

Solving the DST challenge

from dateutils import tz
from datetime import datetime
brugge =tz.gettz('Europe/Brussels')
my_summerdate = datetime(2020,7,1,8,59,59,tzinfo=brugge)
# dst() indicates of Daylight Saving Time is active or not
print(my_summerdate.dst()) # result /> 1:00:00
# my_first_02H00 at DST change
unaware = datetime(2020,10,25,2,0,0)
my_first_02h00 = brussels.localize(unaware,is_dst=True)
my_second_02h00 =brussels.localize(unaware,is_dst=False)
print(my_first_02h00) # result /> 2020-10-25 02:00:00+02:00
print(my_first_02h00.timestamp()) # result /> 1603584000.0
print(my_second_02h00) # result /> 2020-10-25 02:00:00+01:00
print(my_second_02h00.timestamp()) # result /> 1603587600.0

More Examples:

See more examples and a Jupyter notebook to play with time. https://github.com/tribp/Getting-Started-Python-Date-and-Time-

References:

https://wiki.python.org/moin/WorkingWithTime

https://blog.ganssle.io/tag/dateutil.html

--

--