Python Datetime Tutorial: Manipulate Times, Dates, and Time Spans

python-datetime-tutorial

Dealing with dates and times in Python can be a hassle. Thankfully, there’s a built-in way of making it easier: the Python datetime module.

datetime helps us identify and process time-related elements like dates, hours, minutes, seconds, days of the week, months, years, etc. It offers various services like managing time zones and daylight savings time. It can work with timestamp data. It can extract the day of the week, day of the month, and other date and time formats from strings.

In short, it’s a really powerful way of handling anything date and time related in Python. So let’s get into it!

In this tutorial, we’ll learn about python datetime functions in detail, including:

  • Creating Date Objects
  • Getting year and month from the date
  • Getting month day and Weekday from date
  • Getting hour and minutes from the date
  • Getting Week number of the year from date
  • Converting date object into timestamp
  • Converting UNIX timestamp string to date object
  • Handling timedelta objects
  • Getting the difference between two dates and times
  • Formatting dates: strftime() and strptime()
  • Handling timezones
  • Working with Pandas datetime objects

    • Getting year, month, day, hour, and minute
    • Getting weekday and day of year
    • Converting date objects into a DataFrame index

As you work through this tutorial, we’d encourage you to run the code on your own machine. Alternatively, if you’d like to run code in your browser and learn in an interactive fashion with answer-checking to be sure you’re getting it right, our free Python intermediate course has a lesson on datetime in Python that we recommend. All it requires is signing up for a free user account.

Python datetime Classes

Before jumping into writing code, it’s worth looking at the five main object classes that are used in the datetime module. Depending on what we’re trying to do, we’ll likely need to make use of one or more of these distinct classes:

  • datetime – Allows us to manipulate times and dates together (month, day, year, hour, second, microsecond).

  • date – Allows us to manipulate dates independent of time (month, day, year).

  • time – Allows us to manipulate time independent of date (hour, minute, second, microsecond).

  • timedelta— A duration of time used for manipulating dates and measuring.

  • tzinfo— An abstract class for dealing with time zones.

If those distinctions don’t make sense yet, don’t worry! Let’s dive into datetime and start working with it to better understand how these are applied.

Creating Date Objects

First, let’s take a closer look at a datetime object. Since datetime is both a module and a class within that module, we’ll start by importing the datetime class from the datetime module.

Then, we’ll print the current date and time to take a closer look at what’s contained in a datetime object. We can do this using datetime‘s .now() function. We’ll print our datetime object, and then also print its type using type() so we can take a closer look.

# import datetime class from datetime module
from datetime import datetime

# get current date
datetime_object = datetime.now()
print(datetime_object)
print('Type :- ',type(datetime_object))

2019-10-25 10:24:01.521881
Type :-  <class 'datetime.datetime'>

We can see from the results above that datetime_object is indeed a datetime object of the datetime class. This includes the year, month, day, hour, minute, second, and microsecond.

Extract Year and Month from the Date

Now we’ve seen what makes up a datetime object, we can probably guess how date and time objects look, because we know that date objects are just like datetime without the time data, and time objects are just like datetime without the date data.

We can also antipate some problems. For example, in most data sets, date and time information is stored in string format! Also, we may not want all of this date and time data — if we’re doing something like a monthly sales analysis, breaking things down by microsecond isn’t going to be very useful.

So now, let’s start digging into a common task in data science: extracting only the elements that we actually want from a string using datetime.

To do this, we need to do a few things.

Handling Date and Time Strings with strptime() and strftime()

Thankfully, datetime includes two methods, strptime() and strftime(), for converting objects from strings to datetime objects and vice versa. strptime() can read strings with date and time information and convert them to datetime objects, and strftime() converts datetime objects back into strings.

Of course, strptime() isn’t magic — it can’t turn any string into a date and time, and it will need a little help from us to interpret what it’s seeing! But it’s capable of reading most conventional string formats for date and time data (see the documentation for more details). Let’s give it a date string in YYYY-MM-DD format and see what it can do!

my_string = '2019-10-31'

# Create date object in given time format yyyy-mm-dd
my_date = datetime.strptime(my_string, "%Y-%m-%d")

print(my_date)
print('Type: ',type(my_date))

2019-10-31 00:00:00
Type:  <class 'datetime.datetime'>

Note that strptime() took two arguments: the string (my_string) and "%Y-%m-%d", another string that tells strptime() how to interpret the input string my_string. %Y, for example, tells it to expect the first four characters of the string to be the year.

A full list of these patterns is available in the documentation, and we’ll go into these methods in more depth later in this tutorial.

You may also have noticed that a time of 00:00:00 has been added to the date. That’s because we created a datetime object, which must include a date and a time. 00:00:00 is the default time that will be assigned if no time is designated in the string we’re inputting.

Anyway, we were hoping to separate out specific elements of the date for our analysis. One way can do that using the built-in class attributes of a datetime object, like .month or .year:

print('Month: ', my_date.month) # To Get month from date
print('Year: ', my_date.year) # To Get month from year

Month:  10
Year:  2019

Getting Day of the Month and Day of the Week from a Date

Let’s do some more extraction, because that’s a really common task. This time, we’ll try to get the day of the month and the day of the week from my_date. Datetime will give us the day of the week as a number using its .weekday() function, but we can convert this to a text format (i.e. Monday, Tuesday, Wednesday…) using the calendar module and a method called day_name.

We’ll start by importing calendar, and then using .day and .weekday() on my_date. From there, we can get the day of the week in text format like so:

# import calendar module 
import calendar

print('Day of Month:', my_date.day)

# to get name of day(in number) from date
print('Day of Week (number): ', my_date.weekday())

# to get name of day from date
print('Day of Week (name): ', calendar.day_name[my_date.weekday()]) 

Day of Month: 31
Day of Week (number):  3
Day of Week (name):  Thursday

Wait a minute, that looks a bit odd! The third day of the week should be Wednesday, not Thursday, right?

Let’s take a closer look at that day_name variable using a for loop:

j = 0
for i in calendar.day_name:
    print(j,'-',i)
    j+=1

0 - Monday
1 - Tuesday
2 - Wednesday
3 - Thursday
4 - Friday
5 - Saturday
6 - Sunday

Now we can see that Python starts weeks on Monday and counts from the index 0 rather than starting at 1. So it makes sense that the number 3 is converted to “Thursday” as we saw above.

Getting Hours and Minutes From a Python Datetime Object

Now let’s dig into time and extract the hours and minutes from datetime object. Much like what we did above with month and year, we can use class attributes .hour and .minute to get the hours and minutes of the day.

Let’s set a new date and time using the .now() function. As of this writing, it’s October 25, 2019 at 10:25 AM. You’ll get different results depending on when you choose to run this code, of course!

from datetime import datetime
todays_date = datetime.now()

# to get hour from datetime
print('Hour: ', todays_date.hour) 

# to get minute from datetime
print('Minute: ', todays_date.minute) 

Hour:  10
Minute:  25

Getting Week of the Year from a Datetime Object

We can also do fancier things with datetime. For example, what if we want to know what week of the year it is?

We can get the year, week of the year, and day of the week from a datetime object with the .isocalendar() function.

Specifically, isocalendar() returns a tuple with ISO year, week number and weekday. The ISO calendar is a widely-used standard calendar based on the Gregorian calendar. You can read about it in more detail at that link, but for our purposes, all we need to know is that it works as a regular calendar, starting each week on Monday.

# Return a 3-tuple, (ISO year, ISO week number, ISO weekday).
todays_date.isocalendar() 

(2019, 43, 5)

Note that in the ISO calendar, the week starts counting from 1, so here 5 represents the correct day of the week: Friday.

We can see from the above that this is the 43rd week of the year, but if we wanted to isolate that number, we could do so with indexing just as we might for any other Python list or tuple:

todays_date.isocalendar()[1]

43

Converting a Date Object into Unix Timestamp and Vice Versa

In programming, it’s not uncommon to encounter time and date data that’s stored as a timestamp, or to want to store your own data in Unix timestamp format.

We can do that using datetime’s built-in timestamp() function, which takes a datetime object as an argument and returns that date and time in timestamp format:

#import datetime
from datetime import datetime

# get current date
now = datetime.now()

# convert current date into timestamp
timestamp = datetime.timestamp(now)

print("Date and Time :", now)
print("Timestamp:", timestamp)

Date and Time : 2019-10-25 10:36:32.827300
Timestamp: 1572014192.8273

Similarly, we can do the reverse conversion using fromtimestamp(). This is a datetime function that takes a timestamp (in float format) as an argument and returns a datetime object, as below:

#import datetime
from datetime import datetime

timestamp = 1572014192.8273

#convert timestamp to datetime object
dt_object = datetime.fromtimestamp(timestamp)

print("dt_object:", dt_object)
print("type(dt_object): ", type(dt_object))

dt_object: 2019-10-25 10:36:32.827300
type(dt_object):  <class 'datetime.datetime'>

python datetime tutorial - timedelta and time span

Measuring Time Span with Timedelta Objects

Often, we may want to measure a span of time, or a duration, using Python datetime. We can do this with its built-in timedelta class. A timedelta object represents the amount of time between two dates or times. We can use this to measure time spans, or manipulate dates or times by adding and subtracting from them, etc.

By default a timedelta object has all parameters set to zero. Let’s create a new timedelta object that’s two weeks long and see how that looks:

#import datetime
from datetime import timedelta

# create timedelta object with difference of 2 weeks
d = timedelta(weeks=2)

print(d)
print(type(d))
print(d.days)

14 days, 0:00:00
<class 'datetime.timedelta'>
14

Note that we can get our time duration in days by using the timedelta class attribute .days. As we can see in its documentation, we can also get this time duration in seconds or microseconds.

Let’s create another timedelta duration to get a bit more practice:

year = timedelta(days=365)
print(year)

365 days, 0:00:00

Now let’s start doing using timedelta objects together with datetime objects to do some math! Specifically, let’s add a few diffeent time durations to the current time and date to see what date it will be after 15 days, what date it was two weeks ago.

To do this, we can use the + or - operators to add or subtract the timedelta object to/from a datetime object. The result will be the datetime object plus or minus the duration of time specified in our timedelta object. Cool, right?

(Note: in the code below, it’s October 25 at 11:12 AM; your results will differ depending on when you run the code since we’re getting our datetime object using the .now() function).

#import datetime
from datetime import datetime, timedelta 
  
# get current time     
now = datetime.now() 
print ("Today's date: ", str(now))  

#add 15 days to current date
future_date_after_15days = now + timedelta(days = 15) 
print('Date after 15 days: ', future_date_after_15days) 

#subtract 2 weeks from current date
two_weeks_ago = now - timedelta(weeks = 2) 
print('Date two weeks ago: ', two_weeks_ago) 
print('two_weeks_ago object type: ', type(two_weeks_ago))

Today's date:  2019-10-25 11:12:24.863308
Date after 15 days:  2019-11-09 11:12:24.863308
Date two weeks ago:  2019-10-11 11:12:24.863308
two_weeks_ago object type:  <class 'datetime.datetime'>

Note that the output of these mathematical operations is still a datetime object.

Find the Difference Between Two Dates and Times

Similar to what we did above, we can also subtract one date from another date to find the timespan between them using datetime.

Because the result of this math is a duration, the object produced when we subtract one date from another will be a timedelta object.

Here, we’ll create two date objects (remeber, these work the same as datetime objects, they just don’t include time data) and subtract one from the other to find the duration:

# import datetime
from datetime import date

# Create two dates
date1 = date(2008, 8, 18)
date2 = date(2008, 8, 10)

# Difference between two dates
delta = date2 - date1

print("Difference: ", delta.days)
print('delta object type: ', type(delta))

Difference:  -8
delta object type:  <class 'datetime.timedelta'>

Above, we used only dates for the sake of clarity, but we can do the same thing with datetime objects to get a more precise measurement that includes hours, minutes, and seconds as well:

# import datetime
from datetime import datetime

# create two dates with year, month, day, hour, minute, and second 
date1 = datetime(2017, 6, 21, 18, 25, 30) 
date2 = datetime(2017, 5, 16, 8, 21, 10) 

# Difference between two dates
diff = date1-date2

print("Difference: ", diff) 

Difference:  36 days, 10:04:20

python datetime tutorial formatting dates strftime

Formatting Dates: More on strftime() and strptime()

We touched briefly on strftime() and strptime() earlier, but let’s take a closer look at these methods, as they’re often important for data analysis work in Python.

strptime() is the method we used before, and you’ll recall that it can turn a date and time that’s formatted as a text string into a datetime object, in the following format:

time.strptime(string, format)

Note that it takes two arguments:

  • string − the time in string format that we want to convert

  • format − the specific formatting of the time in the string, so that strptime() can parse it correctly

Let’s try converting a different kind of date string this time. This site is a really useful reference for finding the formatting codes needed to help strptime() interpret our string input.

# import datetime
from datetime import datetime

date_string = "1 August, 2019"

# format date
date_object = datetime.strptime(date_string, "%d %B, %Y")

print("date_object: ", date_object)

date_object:  2019-08-01 00:00:00

Now let’s do something a bit more advanced to practice everything we’ve learned so far! We’ll start with a date in string format, convert it to a datetime object, and look at a couple different ways of formatting it (dd/mm and mm/dd).

Then, sticking with the mm/dd formatting, we’ll convert it into a Unix timestamp. Then we’ll convert it back into a datetime object, and convert that back into strings using a few different strftime patterns to control the output:

# import datetime
from datetime import datetime

dt_string = "12/11/2018 09:15:32"
# Considering date is in dd/mm/yyyy format
dt_object1 = datetime.strptime(dt_string, "%d/%m/%Y %H:%M:%S")
print("dt_object1:", dt_object1)
# Considering date is in mm/dd/yyyy format
dt_object2 = datetime.strptime(dt_string, "%m/%d/%Y %H:%M:%S")
print("dt_object2:", dt_object2)

# Convert dt_object2 to Unix Timestamp
timestamp = datetime.timestamp(dt_object2)
print('Unix Timestamp: ', timestamp)

# Convert back into datetime
date_time = datetime.fromtimestamp(timestamp)
d = date_time.strftime("%c")
print("Output 1:", d)
d = date_time.strftime("%x")
print("Output 2:", d)
d = date_time.strftime("%X")
print("Output 3:", d)

dt_object1: 2018-11-12 09:15:32
dt_object2: 2018-12-11 09:15:32
Unix Timestamp:  1544537732.0
Output 1: Tue Dec 11 09:15:32 2018
Output 2: 12/11/18
Output 3: 09:15:32

Here’s an image you can save with a cheat sheet for common, useful strptime and strftime patterns:

Screenshot%20Capture%20-%202019-10-12%20-%2011-05-58.png

Let’s get a little more practice using these:

# current date and time
now = datetime.now() 

# get year from date
year = now.strftime("%Y")
print("Year:", year)

# get month from date
month = now.strftime("%m")
print("Month;", month)

# get day from date
day = now.strftime("%d")
print("Day:", day)

# format time in HH:MM:SS 
time = now.strftime("%H:%M:%S")
print("Time:", time)

# format date
date_time = now.strftime("%m/%d/%Y, %H:%M:%S")
print("Date and Time:",date_time)

Year: 2019
Month; 10
Day: 25
Time: 11:56:41
Date and Time: 10/25/2019, 11:56:41

Handling Timezones

Working with dates and times in Pythin can get even more complicated when timezones get involved. Thankfully, the pytz module exists to help us deal with cross-timezone conversions. It also handles the daylight savings time in locations that use that.

We can use the localize function to add a time zone location to a Python datetime object. Then we can use the function astimezone() to convert the existing local time zone into any other time zone we specify (it takes the time zone we want to convert into as an argument).

For example:

# import timezone from pytz module
from pytz import timezone

# Create timezone US/Eastern
east = timezone('US/Eastern')
# Localize date 
loc_dt = east.localize(datetime(2011, 11, 2, 7, 27, 0))
print(loc_dt) 

# Convert localized date into Asia/Kolkata timezone 
kolkata = timezone("Asia/Kolkata")
print(loc_dt.astimezone(kolkata)) 

# Convert localized date into Australia/Sydney timezone 
au_tz = timezone('Australia/Sydney')
print(loc_dt.astimezone(au_tz)) 

2011-11-02 07:27:00-04:00
2011-11-02 16:57:00+05:30
2011-11-02 22:27:00+11:00

This module can help make life simpler when working with data sets that include multiple different time zones.

Working with pandas Datetime Objects

Data scientists love pandas for many reasons. One of them is that it contains extensive capabilities and features for working with time series data. Much like datetime itself, pandas has both datetime and timedelta objects for specifying dates and times and durations, respectively.

We can convert date, time, and duration text strings into pandas Datetime objects using these functions:

  • to_datetime(): Converts string dates and times into Python datetime objects.
  • to_timedelta(): Finds differences in times in terms of days, hours, minutes, and seconds.

And as we’ll see, these functions are actually quite good at converting strings to Python datetime objects by detecting their format automatically, without needing us to define it using strftime patterns.

Let’s look at a quick example:

# import pandas module as pd
import pandas as pd

# create date object using to_datetime() function
date = pd.to_datetime("8th of sep, 2019")
print(date)

2019-09-08 00:00:00

Note that even though we gave it a string with some complicating factors like a “th” and “sep” rather than “Sep.” or “September”, pandas was able to correctly parse the string and return a formatted date.

We can also use pandas (and some of its affiliated numpy functionality) to create date ranges automatically as pandas Series. Below, for example, we create a series of twelve dates starting from the day we defined above. Then we create a different series of dates starting from a predefined date using pd.date_range():

# Create date series using numpy and to_timedelta() function
date_series = date + pd.to_timedelta(np.arange(12), 'D') 
print(date_series)

#  Create date series using date_range() function 
date_series = pd.date_range('08/10/2019', periods = 12, freq ='D') 
print(date_series)

DatetimeIndex(['2019-09-08', '2019-09-09', '2019-09-10', '2019-09-11',
               '2019-09-12', '2019-09-13', '2019-09-14', '2019-09-15',
               '2019-09-16', '2019-09-17', '2019-09-18', '2019-09-19'],
              dtype='datetime64[ns]', freq=None)
DatetimeIndex(['2019-08-10', '2019-08-11', '2019-08-12', '2019-08-13',
               '2019-08-14', '2019-08-15', '2019-08-16', '2019-08-17',
               '2019-08-18', '2019-08-19', '2019-08-20', '2019-08-21'],
              dtype='datetime64[ns]', freq='D')

Get Year, Month, Day, Hour, Minute in pandas

We can easily get year, month, day, hour, or minute from dates in a column of a pandas dataframe using dt attributes for all columns. For example, we can use df['date'].dt.year to extract only the year from a pandas column that includes the full date.

To explore this, let’s make a quick DataFrame using one of the Series we created above:

# Create a DataFrame with one column date
df = pd.DataFrame()
df['date'] = date_series
df.head()

date
0 2019-08-10
1 2019-08-11
2 2019-08-12
3 2019-08-13
4 2019-08-14

Now, let’s create separate columns for each element of the date by using the relevant Python datetime (accessed with dt) attributes:

# Extract year, month, day, hour, and minute. Assign all these date component to new column.
df['year'] = df['date'].dt.year 
df['month'] = df['date'].dt.month 
df['day'] = df['date'].dt.day 
df['hour'] = df['date'].dt.hour 
df['minute'] = df['date'].dt.minute 
df.head()

date year month day hour minute
0 2019-08-10 2019 8 10 0 0
1 2019-08-11 2019 8 11 0 0
2 2019-08-12 2019 8 12 0 0
3 2019-08-13 2019 8 13 0 0
4 2019-08-14 2019 8 14 0 0

Get Weekday and Day of Year

Pandas is also capable of getting other elements, like the day of the week and the day of the year, from its datetime objects. Again, we can use dt attributes to do this. Note that here, as in Python generally, the week starts on Monday at index 0, so day of the week 5 is Saturday.

# get Weekday and Day of Year. Assign all these date component to new column.
df['weekday'] = df['date'].dt.weekday 
df['day_name'] = df['date'].dt.weekday_name 
df['dayofyear'] = df['date'].dt.dayofyear 
df.head()

date year month day hour minute weekday day_name dayofyear
0 2019-08-10 2019 8 10 0 0 5 Saturday 222
1 2019-08-11 2019 8 11 0 0 6 Sunday 223
2 2019-08-12 2019 8 12 0 0 0 Monday 224
3 2019-08-13 2019 8 13 0 0 1 Tuesday 225
4 2019-08-14 2019 8 14 0 0 2 Wednesday 226

Convert Date Object into DataFrame Index

We can also use pandas to make a datetime column into the index of our DataFrame. This can be very helpful for tasks like exploratory data visualization, because matplotlib will recognize that the DataFrame index is a time series and plot the data accordingly.

To do this, all we have to do is redefine df.index:

# Assign date column to dataframe index
df.index = df.date
df.head()

date year month day hour minute weekday day_name dayofyear
date
2019-08-10 2019-08-10 2019 8 10 0 0 5 Saturday 222
2019-08-11 2019-08-11 2019 8 11 0 0 6 Sunday 223
2019-08-12 2019-08-12 2019 8 12 0 0 0 Monday 224
2019-08-13 2019-08-13 2019 8 13 0 0 1 Tuesday 225
2019-08-14 2019-08-14 2019 8 14 0 0 2 Wednesday 226

Conclusion

In this tutorial, we’ve taken a deep dive into Python datetime, and also done some work with pandas and the calendar module. We’ve covered a lot, but remember: the best way to learn something is by actually writing code yourself! If you’d like to practice writing datetime code with interactive answer-checking, check out our free Python intermediate course for a lesson on datetime in Python with interative answer-checking and in-browser code-running.