How to Use Python Datetimes Correctly
By: Daniel Morales
Tags: Machine Learning, Data Science, Python Programming, Python, Python3

How to Use Python Datetimes Correctly

Datetime is basically a python object that represents a point in time, like years, days, seconds, milliseconds. This is very useful to create our programs.

Image by petradr

The datetime module provides classes to manipulate dates and times in a simple and complex way. While date and time arithmetic is supported, the application focuses on the efficient extraction of attributes for formatting and manipulating output

You can download a jupyter notebook with all these steps here.

Let’s import the Python module

In [1]:

from datetime import datetime

Creating a date using year, month, and day as arguments.

datetime(year, month, day hour, minute, seconds)

In [2]:

birthday = datetime(1994, 2, 15, 4, 25, 12)

Now once we’ve created the object and assigned to the variable called birthday , we can access to each date format just like this

In [3]:

birthday

Out[3]:

datetime.datetime(1994, 2, 15, 4, 25, 12)

In [4]:

birthday.year

Out[4]:

1994

In [5]:

birthday.month

Out[5]:

2

In [6]:

birthday.day

Out[6]:

15

As you can see, it’s very easy to create a date using this module. Now we can do other interesting things, like:

In [7]:

birthday.weekday()

Out[7]:

1

This means that the birthday was a Monday, because days are in this format (0-6) , or what is the same indexed as a list (beginning with zero).

But what if I want to know what is the current datetime ? In that case, we can use datetime.now() , Go ahead and write down this into next cell

In [8]:

datetime.now()

Out[8]:

datetime.datetime(2020, 11, 17, 11, 32, 11, 992169)

Ok, that’s interesting. What if you run that command again? Go ahead and see the difference

In [9]:

datetime.now()

Out[9]:

datetime.datetime(2020, 11, 17, 11, 33, 36, 433919)

As you can see the output is now different, because time changed. Great! Now you can ask, how do I calculate the time from one date to another? That’s called time tracking, let’s see how it works

In [10]:

# time tracking operation

datetime(2018, 1, 1) - datetime(2017, 1, 1)

Out[10]:

datetime.timedelta(365)

In [11]:

datetime(2018, 1, 1) - datetime(2017, 1, 12)

Out[11]:

datetime.timedelta(354)

You can see, how easy it is, we can run arithmetic operations between dates, which is great! But what if now you want to know how much time has passed from a given date to today, at this very moment? How do you think that can be done? Think about it for a moment!

In [12]:

datetime.now() - datetime(2020, 1, 1)

Out[12]:

datetime.timedelta(321, 41994, 571469)

Excellent now we use the .now() method and subtract the date we want to calculate. Easy!

Using strptime

This method will help us to transform dates that are given in strings to a datetime format, which is quite useful!

Let’s see it in action:

In [13]:

parsed_date = datetime.strptime('Nov 15, 2020', '%b %d, %Y')

In [14]:

parsed_date

Out[14]:

datetime.datetime(2020, 11, 15, 0, 0)

In [15]:

type(parsed_date)

Out[15]:

datetime.datetime

As we see, we have passed two parameters to the strptime method, the first has been the string of the date, and the second the "directive" in which we want to make the conversion. To see all the available "directives", go to the following link:

Image by python

Image by python

We already have parsed our date in the parsed_date variable, now let's start making calls to the methods it contains.

In [16]:

parsed_date.month

Out[16]:

11

In [28]:

parsed_date.year

Out[28]:

2020

Using strftime

All right, now let’s do the opposite operation, passing a datetime type as a parameter to the strftime function and converting it to a string. We do it like this:

In [37]:

date_string = datetime.strftime(datetime.now(), '%b %d, %Y')

In [38]:

date_string

Out[38]:

'Nov 17, 2020'

As you can see, we pass datetime.now() as the first argument and then the directives of the formats in which we want the output. Really simple!

Time object

A time object represents a time of day (local), independent of any particular day, and subject to adjustment through a tzinfo object.

All arguments are optional. tzinfo can be None , or an instance of a tzinfo subclass. The rest of the arguments can be integers, in the following ranges:

Image by Author

If an argument is given outside these ranges, the Value-Error is raised.

All default values are 0 except tzinfo , which defaults to None . Time to play with this object!

In [40]:

from datetime import time

In [42]:

my_time = time(hour=12, minute=34, second=56, microsecond=123456)

In [43]:

my_time

Out[43]:

datetime.time(12, 34, 56, 123456)

As we can see it will give us a time object as a result. However, it has a not very “friendly” format. With the time object we can use the isoformat

In [44]:

my_time.isoformat(timespec='minutes')

Out[44]:

'12:34'

In [45]:

my_time.isoformat(timespec='microseconds')

Out[45]:

'12:34:56.123456'

In [46]:

my_time.isoformat(timespec='auto')

Out[46]:

'12:34:56.123456'

In [47]:

my_time.isoformat()

Out[47]:

'12:34:56.123456'

We can see that there are several iso formats to display the time. We use different formats, and the default one is auto , which we can use without passing a parameter explicitly. These are the possible fromatos to use

Image by Author

timedelta object

A timedelta object represents a duration, the difference between two dates or times, which is quite useful! Let's look how it works. First we need to importa timedelta and then we need to call the different built-in functions

In [48]:

from datetime import timedelta

In [49]:

year = timedelta(days=365)

In [50]:

year

Out[50]:

datetime.timedelta(365)

In [51]:

year.total_seconds()

Out[51]:

31536000.0

In [56]:

ten_years = 10 * year

In [58]:

ten_years.total_seconds()

Out[58]:

315360000.0

We’ve passed the parameter days = 365 to timedelta and then called two functions. One of them returns the total seconds that 365 days have.An the other one creates 10 years.

Let’s make another calculations

In [59]:

another_year = timedelta(weeks=40, days=84, hours=23,

minutes=50, seconds=600) # adds up to 365 days

In [60]:

another_year

Out[60]:

datetime.timedelta(365)

In [61]:

year == another_year

Out[61]:

True

We have now done a boolean operation, where we ask if one timedelta is the same as another. For which we get a True .

Naive & Aware methods

There are two types of date and time objects: “naive” & “aware”.

An “aware” object has sufficient knowledge of the applicable algorithmic and political time settings, such as time zone and daylight savings information, to be able to position itself in relation to other “aware” objects.

An “aware” object is used to represent a specific moment in time that is not open to interpretation. Ignore Relativity

A “naïve” object does not contain enough information to place itself unambiguously in relation to other date/time objects

Whether a “ship” object represents Coordinated Universal Time (UTC), local time or the time of some other time zone depends purely on the program, just as it depends on the program whether a given number represents meters, miles or mass

The “naive” objects are easy to understand and work with, at the cost of ignoring some aspects of reality.

This finally serves us to work time zones, and time changes (depending on summer-winter) and American zones as for example EST or EDT

Supporting time zones at deeper levels of detail depends on the application.

The rules for time adjustment worldwide are more political than rational, change frequently, and there is no standard suitable for every application other than UTC

Objects of this type are immutable.

Objects of the date type are always naive.

I hope you enjoyed this reading! you can follow me on twitter or linkedin

Read these other posts I have written for Towards Data Science