Python: Dates, Times & TimeIt

This is part of my Python & Django Series which can be found here including information on how to download all the source code.

This article looks at dates and times along with functionality which will be useful when working with them.

Date

The date class provides a representation of a date. It is located within the datetime namespace.

Code:

from datetime import date

We can create an instance of the date class populated with today’s day, month and year with the today function.

Code:

from datetime import date

today = date.today()
print(today)

Output:

2015-06-09

A date instance responds to day, month and year.

Code:

print("{0}-{1}-{2}".format(today.day, today.month, today.year))

Output:

9-6-2015

We can create an instance of a date with the constructor which takes the year, month and day as integers.

Code:

print(date(1978, 10, 25))

Output:

1978-10-25

The date class is limited to a range of 0001-01-01 to 9999-12-31 with increments of 1 day. The min, max and resolution properties can be used to return this information.

Code:

print("Min = {0}, Max = {1}, Resolution = {2}".format(date.min, date.max, date.resolution))

Output:

Min = 0001-01-01, Max = 9999-12-31, Resolution = 1 day, 0:00:00

The date class is immutable but we can use the replace function to create a new instance replacing any of the year, month and day fields; all parameters are optional.

Code:

print(today.replace(1, 2, 3))

Output:

0001-02-03

We can determine the day of the week as an integer with the weekday and isoweekday functions. Weekday returns 0-6 for Monday to Sunday while isoweekday returns 1-7 for Monday to Sunday.

Code:

print(today.weekday())
print(today.isoweekday())

Output:

1
2

Date objects can support basic operators with the most useful being the minus operator, this allows us to determine the difference between two days. It returns a timedelta instance

Code:

print(today.replace(2016) - today )

Output:

366 days, 0:00:00

Date Time

The datetime class is similar to the date class but it also holds state for time. It is located within the datetime namespace.

Code:

from datetime import datetime

We can get an instance of datetime populated as the current date and time with the today, now and utcnow functions.

The functions today and now take the local time including daylight saving, the utcnow will be the local time without daylight saving.

Code:

print(datetime.today())
print(datetime.now())
print(datetime.utcnow())

Output:

2015-06-09 16:48:55.378254
2015-06-09 16:48:55.378304
2015-06-09 15:48:55.378328

Datetime can represent a date and time between the range of 0001-01-01 00:00:00, and 9999-12-31 23:59:59.999999. The minimal increment is 0.000001 seconds. This data can be retrieved with the min, max and resolution properties.

Code:

print("Min = {0}, Max = {1}, Resolution = {2}".format(datetime.min, datetime.max, datetime.resolution))

The datetime class has properties for the day, month, year as well as hour, minutes and seconds.

Code:

print("{0}-{1}-{2} {3}:{4}:{5}".format(now.day, now.month, now.year, now.hour, now.minute, now.second))

Output:

9-6-2015 16:48:55

We can create an instance of a datetime by passing in any of the required components of state into the constructor.

Code:

print(datetime(2001, 2, 3, 4, 5, 6))

Output:

2001-02-03 04:05:06

A datetime instance is immutable though we can use the replace function to create a new instance based on another while swapping over any of the state components; all parameters are optional.

Code:

# replace(year, month, day, hours, minutes, seconds)
print(datetime.today().replace(1, 2, 3, 4, 5, 6, 7))

Output:

0001-02-03 04:05:06.000007

We can use basic operators between two instances of datetime, the most useful being the minus operator. This can be used to determine the time period between two dates, it returns a timedelta.

Code:

print(datetime.now().replace(year=2016) - datetime.now())

Output:

365 days, 23:59:59.999989

##Formatting DateTime## {#FormattingDateTime}

Python provides the following templates which can be used with date, time and datetime where applicable when formatting them to strings.

Code Example Description
%a Mon Name of day short
%A Monday Name of day
%w 0 Day of week as integral. Sunday – Saturday = 0 – 6
%d 25 Day of the month
%b Jan Name of month short
%B January Name of month
%m 1 Month (0-12)
%y 79 Short year ( last two digits)
%Y 1978 Year ( as 4 digits)
%H 18 Hour as integral of 24 hour clock
%I 6 Hour as integral of 12 hour clock
%p AM AM/PM
%M 30 Minute as integral
%S 30 Second as integral
%f 989898 Microsecond as integral
%z UTC offset (form +HHMM or -HHMM)
%Z Time zone name
%j 213 Day of the year
%U 10 Week number of the year ( Sunday as the first day of the week)
%W 10 Week number of the year (Monday as the first day of the week)
%c 01/02/2014 12:30:55 Locale formatted date time
%x 01/02/2014 Locale formatted date
%X 12:30:55 Locale formatted time

We can use any number of these templates along with the strftime function.

Code:

print(date.today().strftime("%m-%d-%y"))
print(datetime.now().strftime("%d %b %Y %X"))

Output:

06-09-15
09 Jun 2015 17:01:34

We can also use the isoformat and ctime functions for predefined formatted representations.

Code:

print(datetime.today().isoformat())
print(date.today().isoformat())
print(datetime.today().ctime())
print(date.today().ctime())

Output:

2015-06-09T17:01:34.880119
2015-06-09
Tue Jun 9 17:01:34 2015
Tue Jun 9 00:00:00 2015

Time Delta

The timedelta class allows the representation of a time range. It is returned when subtracting or working out the difference between two dates or datetimes.

Code:

from datetime import timedelta

We can create an instance with the constructor, all parameter are optional.

Internally only days, seconds and microseconds are stored all other arguments are converted.

Code:

a_timedelta = timedelta(days=1, seconds=2, microseconds=3, milliseconds=0, minutes=0, hours=0, weeks=0)
print(a_timedelta)

Output:

1 day, 0:00:02.000003

We can access the days, seconds and microseconds by similarly named properties.

Code:

print(a_timedelta.days)
print(a_timedelta.seconds)
print(a_timedelta.microseconds)

Output:

1
2
3

A time period is made up of the microseconds, seconds and days all together. We can use the total_seconds function to get the entire time range within seconds.

Code:

print(a_timedelta.total_seconds()) # Seconds contained in days, second sand microseconds

Output:

86402.000003

A timedelta can hold data within a range from -999999999 days, 0:00:00 seconds to 999999999 days, 23:59:59.999999 seconds in increments of 0.000001 seconds. The min, max and resolution properties can be used to return this information.

Code:

print("Min = {0}, Max = {1}, Resolution = {2}".format(timedelta.min, timedelta.max, timedelta.resolution))

Output:

Min = -999999999 days, 0:00:00, Max = 999999999 days, 23:59:59.999999, Resolution = 0:00:00.000001

The print, str and repr functions can be used to report an instance into a string.

Code:

print(a_timedelta)
print(str(a_timedelta))
print(repr(a_timedelta))

Output:

1 day, 0:00:02.000003
1 day, 0:00:02.000003
datetime.timedelta(1, 2, 3)

We can use a timedelta to add or subtract a time period onto a date or datetime.

Code:

today = datetime.now()
yesterday = datetime.now() - timedelta(days=1)
print(today - yesterday)
print((today - yesterday).total_seconds())

Output:

23:59:59.999537
86399.999537

Time

The time class allows us to represent a time along with its date.

Code:

import time

We can grab the current time and date with the time function. It returns time in seconds or ticks since 12:00am, January 1, 1970.

Code:

print(time.time())

Output:

1433866491.5349488

We can convert this to something a little more human readable with the localtime function.

Code:

print(time.localtime(time.time()))

It returns a struct_time which is a named tuple.

Output:

time.struct_time(tm_year=2015, tm_mon=6, tm_mday=9, tm_hour=17, tm_min=14, tm_sec=51, tm_wday=1, tm_yday=160, tm_isdst=1)

The following defines the struc_time tuple.

Index Attribute Description Range
0 tm_year Year Any int
1 tm_mon Month 1 to 12
2 tm_mday Day of month 1 to 31
3 tm_hour Hour 0 to 23
4 tm_min Minutes 0 to 59
5 tm_sec Seconds 0 to 61 where 60/61 are leap-econds
6 tm_wday Day of week 0 to 6 where 0 is Monday
7 tm_yday Day of year 1 to 366 (Julian day)
8 tm_isdst Daylight saving 1=y, 0=n, -1=library determines DST

We can use the asctime function to format a time object into a string.

Code:

print(time.asctime(time.localtime(time.time())))

Output:

Tue Jun 9 17:14:51 2015

TimeIt

The timeit module provides stopwatch style functionality for timing the running of code.

Lets take a simple function which performs a loop and does some multiplication.

Code:

import timeit

def function_to_time(max_value):

    start = 0

    for count in range(max_value):
        start = start ** max_value

We can use the timer class in timit to run the function a set number of times and then return the time it required to run it.

In the following we run our function 100, 200 and then 300 times with a value of 100.

Code:

    t = timeit.Timer(lambda: function_to_time(100))

    for number in [100, 200, 300]:
        print("{0}: {1}".format(number, t.timeit(number=number)))

Output:

100: 0.004333864999352954
200: 0.009334164000392775
300: 0.013926845000241883

The example above used a lambda expression though timit allows the code to be run represented as a string. Below we loop through 0 to 100 and join all the numbers with a hyphen.

Code:

for number in [100, 200, 300]:
    print("{0}: {1}".format(number, timeit.timeit('"-".join(str(n) for n in range(100))', number=number)))

Output:

100: 0.0035422290002316004
200: 0.006914595000125701
300: 0.009374900999318925

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s