Daniel Morales_

Maker - Data Scientist - Ruby on Rails Fullstack Developer

Twitter:
@daniel_moralesp

2020-12-18 18:02:21 UTC

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.

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

Creating the Whole Machine Learning Pipeline with PyCaret
This tutorial covers the entire ML process, from data ingestion, pre-processing, model training, hyper-parameter…towardsdatascience.com
Using Pandas Profiling to Accelerate Our Exploratory Analysis
Pandas Profiling is a library that generates reports from a pandas DataFrametowardsdatascience.com