Chapter 22 - Working with Dates and Time

Python gives the developer several tools for working with dates and time. In this chapter, we will be looking at the datetime and time modules. We will study how they work and some common uses for them. Let’s start with the datetime module!

The datetime Module

We will be learning about the following classes from the datetime module:

  • datetime.date
  • datetime.timedelta
  • datetime.datetime

These will cover the majority of instances where you’ll need to use date and datetime object in Python. There is also a tzinfo class for working with time zones that we won’t be covering. Feel free to take a look at the Python documentation for more information on that class.

datetime.date

Python can represent dates several different ways. We’re going to look at the datetime.date format first as it happens to be one of the simpler date objects.

>>> datetime.date(2012, 13, 14)
Traceback (most recent call last):
  File "<string>", line 1, in <fragment>
builtins.ValueError: month must be in 1..12
>>> datetime.date(2012, 12, 14)
datetime.date(2012, 12, 14)

This code shows how to create a simple date object. The date class accepts three arguments: the year, the month and the day. If you pass it an invalid value, you will see a ValueError, like the one above. Otherwise you will see a datetime.date object returned. Let’s take a look at another example:

>>> import datetime
>>> d = datetime.date(2012, 12, 14)
>>> d.year
2012
>>> d.day
14
>>> d.month
12

Here we assign the date object to the variable d. Now we can access the various date components by name, such as d.year or d.month. Now let’s find out what day it is:

>>> datetime.date.today()
datetime.date(2014, 3, 5)

This can be helpful whenever you need to record what day it is. Or perhaps you need to do a date-based calculation based on today. It’s a handy little convenience method though.

datetime.datetime

A datetime.datetime object contains all the information from a datetime.date plus a datetime.time object. Let’s create a couple of examples so we can better understand the difference between this object and the datetime.date object.

>>> datetime.datetime(2014, 3, 5)
datetime.datetime(2014, 3, 5, 0, 0)
>>> datetime.datetime(2014, 3, 5, 12, 30, 10)
datetime.datetime(2014, 3, 5, 12, 30, 10)
>>> d = datetime.datetime(2014, 3, 5, 12, 30, 10)
>>> d.year
2014
>>> d.second
10
>>> d.hour
12

Here we can see that datetime.datetime accepts several additional arguments: year, month, day, hour, minute and second. It also allows you to specify microsecond and timezone information too. When you work with databases, you will find yourself using these types of objects a lot. Most of the time, you will need to convert from the Python date or datetime format to the SQL datetime or timestamp format. You can find out what today is with datetime.datetime using two different methods:

>>> datetime.datetime.today()
datetime.datetime(2014, 3, 5, 17, 56, 10, 737000)
>>> datetime.datetime.now()
datetime.datetime(2014, 3, 5, 17, 56, 15, 418000)

The datetime module has another method that you should be aware of called strftime. This method allows the developer to create a string that represents the time in a more human readable format. There’s an entire table of formatting options that you should go read in the Python documentation, section 8.1.7. We’re going to look at a couple of examples to show you the power of this method:

>>> datetime.datetime.today().strftime("%Y%m%d")
'20140305'
>>> today = datetime.datetime.today()
>>> today.strftime("%m/%d/%Y")
'03/05/2014'
>>> today.strftime("%Y-%m-%d-%H.%M.%S")
'2014-03-05-17.59.53'

The first example is kind of a hack. It shows how to convert today’s datetime object into a string that follows the YYYYMMDD (year, month, day) format. The second example is better. Here we assign today’s datetime object to a variable called today and then try out two different string formatting operations. The first one adds forward slashes between the datetime elements and also rearranges it so that it becomes month, day, year. The last example creates a timestamp of sorts that follows a fairly typical format: YYYY-MM-DD.HH.MM.SS. If you want to go to a two-digit year, you can swap out the %Y for %y.

datetime.timedelta

The datetime.timedelta object represents a time duration. In other words, it is the difference between two dates or times. Let’s take a look at a simple example:

>>> now = datetime.datetime.now()
>>> now
datetime.datetime(2014, 3, 5, 18, 13, 51, 230000)
>>> then = datetime.datetime(2014, 2, 26)
>>> delta = now - then
>>> type(delta)
<type 'datetime.timedelta'>
>>> delta.days
7
>>> delta.seconds
65631

We create two datetime objects here. One for today and one for a week ago. Then we take the difference between them. This returns a timedelta object which we can then use to find out the number of days or seconds between the two dates. If you need to know the number of hours or minutes between the two, you’ll have to use some math to figure it out. Here’s one way to do it:

>>> seconds = delta.total_seconds()
>>> hours = seconds // 3600
>>> hours
186.0
>>> minutes = (seconds % 3600) // 60
>>> minutes
13.0

What this tells us is that there are 186 hours and 13 minutes in a week. Note that we are using a double-forward slash as our division operator. This is known as floor division.

Now we’re ready to move on and learn a bit about the time module!

The time Module

The time module provides the Python developer access to various time-related functions. The time module is based around what it known as an epoch, the point when time starts. For Unix systems, the epoch was in 1970. To find out what the epoch is on your system, try running the following:

>>> import time
>>> time.gmtime(0)
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0,
                 tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)

I ran this on Windows 7 and it too seems to think that time began in 1970. Anyway, in this section, we will be studying the following time-related functions:

  • time.ctime
  • time.sleep
  • time.strftime
  • time.time

Let’s get started!

time.ctime

The time.ctime function will convert a time in seconds since the epoch to a string representing local time. If you don’t pass it anything, then the current time is returned. Let’s try out a couple of examples:

>>> import time
>>> time.ctime()
'Thu Mar 06 07:28:48 2014'
>>> time.ctime(1384112639)
'Sun Nov 10 13:43:59 2013'

Here we show the results of calling ctime with nothing at all and with a fairly random number of seconds since the epoch. I have seen sort of thing used when someone saves the date as seconds since the epoch and then they want to convert it to something a human can understand. It’s a bit simpler to save a big integer (or long) to a database then to mess with formatting it from a datetime object to whatever date object the database accepts. Of course, that also has the drawback that you do need to convert the integer or float value back into a string.

time.sleep

The time.sleep function gives the developer the ability to suspend execution of your script a given number of seconds. It’s like adding a pause to your program. I have found this personally useful when I need to wait a second for a file to finish closing or a database commit to finish committing. Let’s take a look at an example. Open a new window in IDLE and save the following code:

import time

for x in range(5):
    time.sleep(2)
    print("Slept for 2 seconds")

Now run the code in IDLE. You can do that by going to the Run menu and then choose the Run module menu item. When you do so, you will see it print out the phrase Slept for 2 seconds five times with a two second pause between each print. It’s really that easy to use!

time.strftime

The time module has a strftime function that works in pretty much the same manner as the datetime version. The difference is mainly in what it accepts for input: a tuple or a struct_time object, like those that are returned when you call time.gmtime() or time.localtime(). Here’s a little example:

>>> time.strftime("%Y-%m-%d-%H.%M.%S",
                  time.localtime())
'2014-03-06-20.35.56'

This code is quite similar to the timestamp code we created in the datetime portion of this chapter. I think the datetime method is a little more intuitive in that you just create a datetime.datetime object and then call its strftime method with the format you want. With the time module, you have to pass the format plus a time tuple. It’s really up to you to decide which one makes the most sense to you.

time.time

The time.time function will return the time in seconds since the epoch as a floating point number. Let’s take a look:

>>> time.time()
1394199262.318

That was pretty simple. You could use this when you want to save the current time to a database but you didn’t want to bother converting it to the database’s datetime method. You might also recall that the ctime method accepts the time in seconds, so we could use time.time to get the number of seconds to pass to ctime, like this:

>>> time.ctime(time.time())
'Fri Mar 07 07:36:38 2014'

If you do some digging in the documentation for the time module or if you just experiment with it a bit, you will likely find a few other uses for this function.

Wrapping Up

At this point you should know how to work with dates and time using Python’s standard modules. Python gives you a lot of power when it comes to working with dates. You will find these modules helpful if you ever need to create an application that keeps track of appointments or that needs to run on particular days. They are also useful when working with databases.