Python3 Tutorial: A Tutorial

Python, Date and Time

Introduction

Python, Date and Time

Python provides rich functionalities for dealing with date and time data. The standard libraries contains the modules

These modules supply classes for manipulating dates and times in both simple and complex ways.

Especially, the datetime class will be very important for the timeseries of Pandas.

Python Standard Modules for Time Data

The most important modules of Python dealing with time are the modules time, calendar and datetime.

The datetime module provides various classes, methods and functions to deal with dates, times, and time intervals.

The datetime module provides the following classes:

Let's start with a date object.

The Date Class

from datetime import date
x = date(1993, 12, 14)
print(x)
1993-12-14

We can instantiate dates in the range from January 1, 1 to December 31, 9999. This can be inquired from the attributes min and max:

from datetime import date
print(date.min)
print(date.max)
0001-01-01
9999-12-31

We can apply various methods to the date instance above. The method toordinal returns the proleptic Gregorian ordinal. The proleptic Gregorian calendar is produced by extending the Gregorian calendar backward to dates preceding its official introduction in 1582. January 1 of year 1 is day 1.

x.toordinal()
After having executed the Python code above we received the following:
727911

It is possible to calculate a date from a ordinal by using the class method "fromordinal":

date.fromordinal(727911)
The above code returned the following:
datetime.date(1993, 12, 14)

If you want to know the weekday of a certain date, you can calculate it by using the method weekday:

x.weekday()
This gets us the following output:
1
date.today()
The previous Python code returned the following result:
datetime.date(2017, 4, 12)

We can access the day, month and year with attributes:

print(x.day)
print(x.month)
print(x.year)
14
12
1993

The time Class

The time class is similarly organized than the date class.

from datetime import time
t = time(15, 6, 23)
print(t)
15:06:23

The possible times range between:

print(time.min)
print(time.max)
00:00:00
23:59:59.999999

Accessing 'hour', 'minute' and 'second':

t.hour, t.minute, t.second
The above code returned the following result:
(15, 6, 23)

Each component of a time instance can be changed by using 'replace':

t = t.replace(hour=11, minute=59)
t
The previous Python code returned the following result:
datetime.time(11, 59, 23)

We can render a date as a C-style like string, corresponding to the C ctime function:

x.ctime()
We received the following result:
'Tue Dec 14 00:00:00 1993'

The datetime Class

The datetime module provides us with functions and methods for manipulating dates and times. It supplies functionalities for date and time arithmetic, i.e. addition and subtraction. Another focus of the implementation is on attribute extraction for output manipulation and formatting.

There are two kinds of date and time objects:

If a time or date object is naive it doesn't contain information to compare or locate itself relative to other date or time objects. The semantics, if such a naive object belongs to a certain time zone, e.g. Coordinated Universal Time (UTC), local time, or some other timezone is contained in the logic of the program.

An aware object on the other hand possesses knowledge of the time zone it belongs to or the daylight saving time information. This way it can locate itself relative to other aware objects.

How can you tell if a datetime object t is aware?

t is aware if t.tzinfo is not None and t.tzinfo.utcoffset(t) is not None. Both conditions have to be fulfilled

On the other hand an object t is naive if t.tzinfo is None or t.tzinfo.utcoffset(t) is None

Let's create a datetime object:

from datetime import datetime
t = datetime(2017, 4, 19, 16, 31, 0)
t
The above code returned the following:
datetime.datetime(2017, 4, 19, 16, 31)

t is naive, because the following is True:

t.tzinfo == None
After having executed the Python code above we received the following output:
True

We will create an aware datetime object from the current date. For this purpose we need the module pytz. pytz is a module, which brings the Olson tz database into Python. The Olson timezones are nearly completely supported by this module.

from datetime import datetime
import pytz
t = datetime.now(pytz.utc)

We can see that both t.tzinfo and t.tzinfo.utcoffset(t) are different from None, so t is an aware object:

t.tzinfo, t.tzinfo.utcoffset(t)
We received the following output:
(<UTC>, datetime.timedelta(0))
from datetime import datetime, timedelta as delta
ndays = 15
start = datetime(1991, 4, 30)
dates = [start - delta(days=x) for x in range(0, ndays)]
dates
The above code returned the following output:
[datetime.datetime(1991, 4, 30, 0, 0),
 datetime.datetime(1991, 4, 29, 0, 0),
 datetime.datetime(1991, 4, 28, 0, 0),
 datetime.datetime(1991, 4, 27, 0, 0),
 datetime.datetime(1991, 4, 26, 0, 0),
 datetime.datetime(1991, 4, 25, 0, 0),
 datetime.datetime(1991, 4, 24, 0, 0),
 datetime.datetime(1991, 4, 23, 0, 0),
 datetime.datetime(1991, 4, 22, 0, 0),
 datetime.datetime(1991, 4, 21, 0, 0),
 datetime.datetime(1991, 4, 20, 0, 0),
 datetime.datetime(1991, 4, 19, 0, 0),
 datetime.datetime(1991, 4, 18, 0, 0),
 datetime.datetime(1991, 4, 17, 0, 0),
 datetime.datetime(1991, 4, 16, 0, 0)]

Differences between Times

Let's see what happens, if we subtract to datetime objects:

from datetime import datetime
delta = datetime(1993, 12, 14) - datetime(1991, 4, 30)
delta, type(delta)
The Python code above returned the following:
(datetime.timedelta(959), datetime.timedelta)

The result of the subtraction of the two datetime objects is a timedelta object, as we can see from the example above.

We can get information about the number of days elapsed by using the attribute 'days':

delta.days
The previous Python code returned the following:
959
t1 = datetime(2017, 1, 31, 14, 17)
t2 = datetime(2015, 12, 15, 16, 59)
delta = t1 - t2
delta.days, delta.seconds
After having executed the Python code above we received the following result:
(412, 76680)

It is possible to add or subtract a timedelta to a datetime object to calculate a new datetime object by adding or subtracting the delta in days:

from datetime import datetime, timedelta
d1 = datetime(1991, 4, 30)
d2 = d1 + timedelta(10)
print(d2)
print(d2 - d1)
d3 = d1 - timedelta(100)
print(d3)
d4 = d1 - 2 * timedelta(50)
print(d4)
1991-05-10 00:00:00
10 days, 0:00:00
1991-01-20 00:00:00
1991-01-20 00:00:00

It is also possible to add days and minutes to t datetime object:

from datetime import datetime, timedelta
d1 = datetime(1991, 4, 30)
d2 = d1 + timedelta(10,100)
print(d2)
print(d2 - d1)
1991-05-10 00:01:40
10 days, 0:01:40

Convert datetime Objects to Strings

The easiest way to convert a datetime object into a string consists in using str.

s = str(d1)
s
The previous code returned the following output:
'1991-04-30 00:00:00'

Conversion with strftime

The method call datetime.strftime(format) return a string representing the date and time, controlled by an explicit format string. A complete list of formatting directives can be found at strftime:

print(d1.strftime('%Y-%m-%d'))
print("weekday: " + d1.strftime('%a'))
print("weekday as a full name: " + d1.strftime('%A'))
# Weekday as a decimal number, where 0 is Sunday 
# and 6 is Saturday
print("weekday as a decimal number: " + d1.strftime('%w'))
1991-04-30
weekday: Tue
weekday as a full name: Tuesday
weekday as a decimal number: 2

Formatting months:

# Day of the month as a zero-padded decimal number. 
# 01, 02, ..., 31
print(d1.strftime('%d'))
# Month as locale’s abbreviated name. 
# Jan, Feb, ..., Dec (en_US); 
# Jan, Feb, ..., Dez (de_DE)
print(d1.strftime('%b'))
# Month as locale’s full name. 	
# January, February, ..., December (en_US);
# Januar, Februar, ..., Dezember (de_DE)
print(d1.strftime('%B'))
# Month as a zero-padded decimal number. 
# 01, 02, ..., 12
print(d1.strftime('%m'))
30
Apr
April
04

Creating datetime Objects from Strings

We can use strptime to create new datetime object by parsing a string containing a data and time. The arguments of strptime are the string to be parsed and a format specification.

from datetime import datetime
t = datetime.strptime("30 Nov 00", "%d %b %y")
print(t)
2000-11-30 00:00:00
dt = "2007-03-04T21:08:12"
datetime.strptime( dt, "%Y-%m-%dT%H:%M:%S" )
After having executed the Python code above we received the following:
datetime.datetime(2007, 3, 4, 21, 8, 12)
dt = '12/24/1957 4:03:29 AM'
dt = datetime.strptime(dt, '%m/%d/%Y %I:%M:%S %p')
dt
The above code returned the following:
datetime.datetime(1957, 12, 24, 4, 3, 29)

We can create an English date string on a Linux machine with the Shell command
LC_ALL=en_EN.utf8 date

dt = 'Wed Apr 12 20:29:53 CEST 2017'
dt = datetime.strptime(dt, '%a %b %d %H:%M:%S %Z %Y')
print(dt)
2017-04-12 20:29:53

Though datetime.strptime is an easy way to parse a date with a known format, it can be quote complicated and cumbersome to write every time a new specification string for new date formats.

Using the parse method from dateutil.parser:

from dateutil.parser import parse
parse('2011-01-03')
The previous Python code returned the following result:
datetime.datetime(2011, 1, 3, 0, 0)
parse('Wed Apr 12 20:29:53 CEST 2017')
We received the following result:
datetime.datetime(2017, 4, 12, 20, 29, 53, tzinfo=tzlocal())