Handling Date and Time in Python

Time & Date features are found abundantly in most datasets, and time indicative components are consequential in data analysis and should be handled with care. Temporal attributes are crucial since they help clarify the cyclic trends in data, mark events of grave importance, and keep the data in an ordered and meaningful series. However, such features in their raw form are sometimes complex to understand due to their inconsistent representations and lack of understanding.

As data scientists, we should know how to handle the date-time data and the standard set of date-time operations we can apply to transform the raw data. Fortunately, we have date-time manipulation libraries specifically for this purpose. The 'datetime' is an inbuilt date-time manipulation python module widely used by data scientists. In this article, we will go through all basic date-time manipulation techniques, explore different date-time formats, transform the raw timestamps into a usable form, and finally, we will see some miscellaneous applications.

Working with Date class of Datetime Module

As the name suggests, the Date class in the Datetime module deals with date manipulations and follows the Gregorian Calendar. Let's generate a date using the Datetime module:

from datetime import date

current_date = datetime.now(2022,6,1)
print(current_date)


# Output
# 2022-06-01

We can separately extract different elements of the date. Let's say we want to dismantle the current date into the day, month, and year. We can easily extract it using the day, month, and year attributes. Let's extract them: 

# Extracts day from date
print('Day :',current_date.day)

# Extracts month from date
print('Month :',current_date.month)

# Extracts year from date
print('Year :',current_date.year)


# Output 
'''
Day : 12
Month : 6
Year : 2022
'''

If you're wondering about the class of the variable' current_date,' it's an object of the datetime class. We can confirm the same using the type() function. As we know, in Python, everything is an object. The Date time objects are categorized into Naive and Aware objects depending on whether they include timezone information. Let's learn about these two objects in detail.

print(type(current_date))

# Output
<class 'datetime.date'>

Naive Object

A naive object does not include enough information to locate itself for some other date-time object. It is similar to a program that doesn't explicitly indicate if the distance measured is in meters, miles, or feet. Similarly, we don't know if the date-time calculated follows the UTC, local time, or another timezone. It is purely up to the program to decide. The Naive Objects are easy to interpret at the cost of skipping some elements of reality. The example above is a Naive Object.

Aware Object

An aware object can find itself comparative to other aware objects. It represents a particular point in time that is not open to interpretation. It is relatively explainable and follows standards, unlike Naive Object.

Timezone naive: 2022-06-29 13:22:02.256978
Timezone Aware: 2022-06-29 07:52:02.256978+00:00

Let's continue with checking the time class of the datetime module. The time class offers similar functions as that of the date class. Let's see:

Working with Time class of Datetime Module

Time is another shared class of the datetime module. It requires arguments till the micro-seconds and yields a date-time object which can either be naive or aware. Let's generate some "time" using the time class of the Datetime module:

from datetime import time

current_time = time(1,32,13,30)
print(current_time)

# Output
# 01:32:13.000030

Even in time class, we can extract different features like an hour, minute, second, and micro-second. 

# hour
print('Hour :', current_time.hour)

# minute
print('Minute :', current_time.minute)

# second
print('Second :', current_time.second)

# microsecond
print('Microsecond :', current_time.microsecond)

# Output
'''
Hour : 1
Minute : 32
Second : 13
Microsecond : 30
'''

Let's move on to the datetime class, known for its state-of-the-art date-time manipulation functions.

Datetime class of Datetime Module

Datetime class combines the information on both date and time within a single object, datetime. Datetime is a class as well as an object in the datetime module. Arguments of datetime object are a combination of date and time particulars which starts with year and ends with microsecond precision. Let's view the syntax of datetime class datetime object:

Constructor Syntax:

class datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)

Information on year, month, and day is necessary for constructing a datetime object. Defining a timezone (tzinfo) is not required; however, to keep the datetime object aware, it is recommended to keep a meaningful timezone. The range of arguments is as follows:

  • Hours range between [0, 24], all integers
  • Minutesranges between [0, 60], all integers 
  • Seconds range between [0, 60], and all integers
  • Microsecond range between [0, 1000000], all integers
  • Fold in [0, 1], all integers

Let's create a datetime object using the datetime class:

from datetime import datetime
current_date_time = datetime(2022,6,13,3,30,30,4540)
print(current_date_time)

# Output
# 2022-06-13 03:30:30.004540

We can also find the weekday on some specific date; what week is it, or if a year is a leap year or not? Etc. Let's see how we can find it using the date-time module:

import calendar
from datetime import datetime

current_date_time = datetime(2022,6,12,6,25,40,4000)

# Prints Weekday given date-timestamp
print(current_date_time.weekday())

# Prints the week of the year
print('Week :', current_date_time.isocalendar()[1])

# Prints if a year is a leap year or not
print(calendar.isleap(current_date_time.year))

# Output
# 6 - It's Sunday
# Week : 23 
# False - It's not a Leap Year

Date Time Formating

The datetime module allows us to modify the date-time formats between a few available options. Strptime and Strftime are two functions that help us to accomplish the same. 'Strptime' function constructs a datetime object from strings and depicts the date and time. The 'Strptime' function takes two arguments: the date and the desired format string.

Let's understand this with an example:

from datetime import datetime
date = '12 June, 2022 06:45:24'

converted_date = datetime.strptime(date,'%d %B, %Y %H:%M:%S')
print(converted_date)

# Output
# 2022-06-12 06:45:24

The 'strptime' function returns a date-time object. Further, the format in which the date needs to be changed is defined using the formating code or formatting string. We can learn about these formatting strings through this.

Conversely, we have another function, 'strftime.' which converts the date-time objects to strings defining the date and time. Let's see an example:

from datetime import datetime

current_date_time = datetime.now()
print('Datetime object :',current_date_time)

formated_date = current_date_time.strftime('%d/%m/%Y %H:%M:%S')


print('Formatted date :',formated_date)
print('Data Type of Formated Date:' ,type(formated_date))



# Output
# Datetime object : 2022-06-14 00:17:41.835617
# Formatted date : 14/06/2022 00:17:41
# Data-type of Formated Date: <class 'str'>

We can use the same function to extract the Weekday, Week number, and Month name. Let's see how: 

from datetime import datetime
current_date_time = datetime.now()

print('Weekday Name:', current_date_time.strftime('%A'))
print('Month Name:', current_date_time.strftime('%B'))
print('Week number:', current_date_time.strftime('%W'))


# Output
# Weekday Name: Tuesday
# Month Name: June
# Week number: 24

Another widely used function of the date-time class is the 'timedelta' function. Let's see what 'timedelta' functions in action.  

Timedelta

We have now covered how to create a date-time object and its formating, but we will introduce the concept of time differencing that will allow us to find the duration between two dates. This is extremely helpful in feature creation from temporal features. Also, the duration is returned as a 'timedelta' object.

Let's find the duration elapsed between two dates:

from datetime import datetime

first_date = datetime(2022,6,11,1,2,13)
second_date = datetime(2022,6,12,1,2,13)

duration = second_date - first_date

print("The time elapsed between the two dates is: ", duration)
print(type(duration))

# Output
# The time elapsed between the two dates is:  1 day, 0:00:00
# <class 'datetime.timedelta'>

The first and second dates differ by 1 Day, and we precisely obtained the same duration by taking the difference between them, and it's a time-delta object. We can further change the duration formats. Suppose we want the duration in hours or minutes only. Even this is achievable using the timedelta function: 

from datetime import timedelta

print('Time Elapsed in hours :',duration/timedelta(hours=1))
print('Time Elapsed in minutes :',duration/timedelta(minutes=1))
print('Time Elapsed in seconds :',duration/timedelta(seconds=1))

# Output
# Time Elapsed in hours : 24.0
# Time Elapsed in minutes : 1440.0
# Time Elapsed in seconds : 86400.0

What if we need to add a few days sequentially to generate a date-time range feature? Well, it's feasible using the timedelta function:

date = datetime.now()

for day in range(0,6):
    date = date + timedelta(days=1)
    print("{} Day :".format(day+1), date)
    

# Output
# 1 Day : 2022-06-20 01:25:56.311360
# 2 Day : 2022-06-21 01:25:56.311360
# 3 Day : 2022-06-22 01:25:56.311360
# 4 Day : 2022-06-23 01:25:56.311360
# 5 Day : 2022-06-24 01:25:56.311360
# 6 Day : 2022-06-25 01:25:56.311360

Not just days; we can add seconds, minutes, hours, months, years, etc., as per the requirement. This feature is convenient for simulating dates in a fixed or incremental order.

Handling Date Time in Pandas

Pandas is a well-known library for manipulating data, and it comes with no wonder that it can also easily handle datetime objects. Pandas support great functions for handling datetime like 'todatetime.' and 'totimedelta.' Let's see them in action:

import pandas as pd

date = pd.to_datetime('21 June, 2022')

print(date)
print(type(date))

# Output
# 2022-06-21 00:00:00
# <class 'pandas._libs.tslibs.timestamps.Timestamp'>

We converted the string into a date, but the returned object is not a date-time object. Instead, it is a timestamp equivalent to a datetime object in Python.

We have already seen the timedelta function in the Datetime module, and Python's 'to_timedelta' is no different. Let's see its implementation:

import pandas as pd
from datetime import datetime

date = datetime.now()

for itr in range(0,6):
    date = date + pd.to_timedelta(1, unit='D')
    print("{} Day :".format(itr+1), date)
    
# Output
# 1 Day : 2022-06-22 00:53:09.046590
# 2 Day : 2022-06-23 00:53:09.046590
# 3 Day : 2022-06-24 00:53:09.046590
# 4 Day : 2022-06-25 00:53:09.046590
# 5 Day : 2022-06-26 00:53:09.046590
# 6 Day : 2022-06-27 00:53:09.046590

There's a slight difference in syntax that you might have noticed. Here the unit determines the unit of time-delta. In our case, the unit is 'D' stands for day, and we are adding only 1 Day to our current date; hence, it is set to 1. 

Date Range in Pandas

A sequence of dates with a specified interval can also be obtained using the date_range function. It is a more convenient way of creating a sequence of dates with a fixed interval. Let's see its implementation:

import pandas as pd
pd.date_range(start='6/1/2022', end='6/18/2022', freq='D')


# Output
#DatetimeIndex(['2022-06-01','2022-06-02','2022-06-03','2022-06-04',
#               '2022-06-05','2022-06-06','2022-06-07','2022-06-08',
#               '2022-06-09','2022-06-10','2022-06-11','2022-06-12',
#               '2022-06-13','2022-06-14','2022-06-15','2022-06-16',
#               '2022-06-17','2022-06-18'],
#               dtype='datetime64[ns]', freq='D')

In the above method, we provide the start date, end date, and the frequency to which we want to create the dates. However, there's one more method that doesn't require an end date; Instead, it requires a period that indicates the number of instances we want to create. Let's implement that as well:

import pandas as pd
from datetime import datetime

start_date = datetime.now()

dates_start = pd.date_range(start=start_date, periods=6, freq='T')
print(dates_start)

# Output
# DatetimeIndex(['2022-06-21 01:16:18.3','2022-06-21 01:17:18.3',
#               '2022-06-21 01:18:18.3', '2022-06-21 01:19:18.3',
#               '2022-06-21 01:20:18.3', '2022-06-21 01:21:18.3'],
#               dtype='datetime64[ns]', freq='T')

We can also extract date-time features from a date data frame using the Pandas dt attribute. Let's try extracting the date-specific features: 

Dates = pd.DataFrame(dates_start, columns=["Dates"])

Dates["Seconds"] = Dates["Dates"].dt.second
Dates["Minutes"] = Dates["Dates"].dt.minute
Dates["Hours"] = Dates["Dates"].dt.hour

Dates["Day"] = Dates["Dates"].dt.day
Dates["Month"] = Dates["Dates"].dt.month
Dates["Year"] = Dates["Dates"].dt.year

print(Dates)

Output of the above program

Conclusion 

We started with the essential introduction to the date-time module. We discussed the basic operations like generating date-time objects using the date, time, and datetime classes of the datetime module. We learned date-time format conversion and extraction of specific time-related parameters using the datetime class. Further, we witnessed the time-delta function, which is convenient for estimating the time differences. Finally, we saw that time-based manipulations could also be done using the pandas library. We hope you enjoyed it.

Enjoy Learning!

More from EnjoyAlgorithms

Self-paced Courses and Blogs