Dates and time

Python has three standard modules for working with dates and times:

  • The calendar module

  • The time module

  • The datetime module

While each module has a particular area of focus, there is a lot of crossover functionality. The most useful module for working with data — and the module we'll learn about in this lesson — is the datetime module.

The datetime module contains a number of classes, including the following:

  • datetime.datetime: for working with date and time data

  • datetime.time: for working with time data only

  • datetime.timedelta: for representing time periods

You may have noticed that the first class, datetime, has the same name as the module.

Import whole module by alias

  • Pro: there is no ambiguity between dt (alias for the module) and dt.datetime (the class).

  • Con: the dt alias isn't a common convention, which would confuse other people reading our code

In the end, even though using an alias for the datetime module (the third option) is less common, it's a nice compromise between avoiding module versus class confusion, and it keeps our code easy to read.

The datetime.datetime class is the most commonly used class from the datetime module, and it has attributes and methods that work with data containing both the date and the time. The signature of the class is below (with some less-common parameters omitted):

The signature indicates that the year, month, and day arguments are necessary, and the time arguments are optional and set to the equivalent of midnight if omitted. The hour parameter is in 24 hour time, so 11 is 11 a.m., 12 is 12 p.m., 13 is 1 p.m., etc.

Because we didn't pass any time arguments, the object created represents midnight on the 1st of January, 2000. Let's instantiate a second object, this time with both a date and a time:

Using Strptime to Parse Strings as Dates

This date value indicates clearly that the format is month/day/year, and it confirms that the time is in 24-hour format.

Using what we know so far, we could convert these values into datetime objects by manually splitting the string, converting the variables to numeric types, and then instantiating a datetime object using the resultant values:

Luckily, there is an easier way — using a special constructor. The special __init__() method is also a constructor. Classes can also have additional constructors, so we can define objects in multiple ways. The datetime class has one of these that we can use to parse dates directly from strings.

The datetime.strptime() constructor returns a datetime object defined using a special syntax system to describe date and time formats called strftime. (Note that the syntax system is strftime with an "f" versus the constructor which is strptime with a "p." We'll find out more about this later.) The syntax was originally developed in the 1980s as part of the C programming language, and it has become a de facto standard in many modern languages, including Python, R, and C++.

The strftime syntax uses a series of format codes consisting of a % character followed by a single character that specifies a date or time part in a particular format. Let's look at an example for parsing the date in the string "24/12/1984":

The first argument of the datetime.strptime() constructor is the string we want to parse, and the second argument is a string that specifies the format.

The %d, %m, and %Y format codes specify a two-digit day, two-digit month, and four-digit year, and the forward slashes between them specify the forward slashes in the original string. Let's use this example in code:

We can see that the constructor returns a datetime object. Let's look at another example — "12-24-1984" – the same date, but in our string, a dash separates the date parts instead of a slash, and the day/month are in reverse order:

Strftime Code
Meaning
Examples

%d

Day of the month as a zero-padded number1

04

%A

Day of the week as a word2

Monday

%m

Month as a zero-padded number1

09

%Y

Year as a four-digit number

1901

%y

Year as a two-digit number with zero-padding1, 3

01 (2001) 88 (1988)

%B

Month as a word2

September

%H

Hour in 24 hour time as zero-padded number1

05 (5 a.m.) 15 (3 p.m.)

%p

a.m. or p.m.2

AM

%I

Hour in 12 hour time as zero-padded number1

05 (5 a.m., or 5 p.m. if AM/PM indicates otherwise)

%M

Minute as a zero-padded number1

07

1. The strptime parser will parse non-zero padded numbers without raising an error. 2. Date parts containing words will be interpreted using the locale settings on your computer, so strptime won't be able to parse "febrero" ("February" in Spanish) if your locale is set to an English language locale. 3. Year values from 00-68 will be interpreted as 2000-2068, with values 69-99 interpreted as 1969-1999.

Datetime from list example

Using Strftime to Format Dates

The datetime class has a number of attributes that simplify retrieving the various parts that make up the date stored within the object:

  • datetime.day: the day of the month

  • datetime.month: the month of the year

  • datetime.year: the year

  • datetime.hour: the hour of the day

  • datetime.minute: the minute of the hour

If we wanted to create string representation of a datetime object representing the date like December 24th, 1984 in the form day/month/year, we could use those attributes to extract the values and then insert them into a string:

This is a lot of code for a simple task, and our code would need to be even more complex if we wanted to represent the date using words, like Monday, December 24, 1984.

Luckily, the datetime class has a datetime.strftime() method that will return a string representation of the date using the strftime syntax we learned on the previous screen. It's easy to confuse strptime and strftime. Here is an easy way to remember which is which:

  • strptime >> str-p-time >> string parse time

  • strftime >> str-f-time >> string format time

With the strftime() method, we can use %d, %m, and %Y to represent the day, month, and year.

And we can use %A, %I, %M, and %p to represent the day of the week, the hour of the day, the minute of the hour, and a.m./p.m.:

The Time Class

atetime class can hold values for dates and times, the time class holds only time data: hours, minutes, seconds, and microseconds.

The syntax to instantiate a time object is as follows:

As the signature indicates, we can instantiate a time object without arguments and it will represent the time "0:00:00" (midnight). Otherwise, we can pass arguments for any or all of the hour, minute, second, and microsecond parameters. Let's look at an example for the time 2:30 p.m.:

Notice that we provided the hours in 24-hour time — the hour argument requires an integer between 0 and 23. Let's look at an example instantiating a time object for five seconds after 8 a.m.:

We can also create a time object from a datetime object, using the datetime.datetime.time() method. This method returns a time object representing the time data from the datetime object.

The time class doesn't have a strptime() constructor, but if we need to parse times in string form, we can use datetime.strptime() and then convert directly to a time object:

Apart from having no strptime constructor, time objects behave similarly to datetime objects:

  • They have attributes like time.hour and time.second that you can use to access individual time components.

  • They have a time.strftime() method, which you can use to create a formatted string representation of the object.

Comparing Time Objects

A useful feature of time objects is that they support comparisons. We can test if one time is greater — or later — than another:

Because these comparison operations are supported, we can also use Python built-in functions like min() and max():

Calculations with Dates and Times

Just like time objects, datetime objects support comparison operators like > and <. Let's experiment with mathematical operators like - and + to see if they work too, starting with +:

If we try to add two date objects using the + operator, we get a TypeError that tells us the operator is not valid.

Let's try the - operator:

When we use the - operator with two date objects, the result is the time difference between the two datetime objects. Let's look at the type of the resulting object:

The resulting object is a datetime.timedelta object. The timedelta type represents a period of time, compared to the other classes we've seen which represent a specific moment in time.

We observed that we can create an object of the timedelta class using the - operator, but we can also instantiate a timedelta class directly. Let's look at the syntax to do this:

You might notice that the ordering of the parameters doesn't follow the order you might expect, and for this reason, it can be clearer to use keyword arguments when instantiating objects if we are using anything other than days:

We can also use timedelta objects to add or subtract time from datetime objects. Let's look at the example below, where we look to find the date one week from a date object:

Operation
Explanation
Resultant Type

datetime - datetime

Calculate the time between two specific dates/times

timedelta

datetime - timedelta

Subtract a time period from a date or time.

datetime

datetime + timedelta

Add a time period to a date or time.

datetime

timedelta + timedelta

Add two periods of time together

timedelta

timedelta - timedelta

Calculate the difference between two time periods.

timedelta

Note: In the table above, we can substitute any datetime object with a time object

Last updated