The datetime module provide essential tools for working with dates and times. The three most basic classes defined in the module are the date, time and datetime.

What are datetime objects?

The datetime class in the datetime module is used to create objects that store both date and time information.  The class provide an intuitive and structured approach in representing dates and time values broken down into various components.

from datetime import datetime

time_obj = datetime(year = 2023, month = 7, day = 13, hour = 11, minute = 45, second = 30, microsecond = 500)

print(time_obj)

#formatted time
print(time_obj.ctime())

Datetime objects  can be used to work with time intervals, perform calculations, format and parse dates and times, manipulate time zones, and handle other tasks related to date and time.

Get current time
import datetime

print(datetime.datetime.now())

Timezone naive datetime objects

By default datetime objects are timezone naive meaning that they do not contain any timezone information and are interpreted according to the local system's timezone. We can check this using the tzinfo attribute.

import datetime

now = datetime.datetime.now()

print(now.tzinfo)

Creating timezone aware datetime objects

Timezones are used to represent the time in different parts of the world.  Each time zone has an associated offset from UTC (Universal Coordinated Time), which is the global standard for time keeping. This allows people in different parts of the world to use the same clock time while keeping track of the difference in local time relative to the day and hour.

For example, the Eastern Standard Time Zone (EST) in the United States is five hours behind UTC. This means that when it is 12:00 UTC, EST is 7:00 AM. Similarly, the India Standard Time Zone (IST) is five and a half hours ahead of UTC. This means that when it is 12:00 UTC, IST is 5:30 PM.

The pytz module contain tools that  allow us to add  timezone information to datetime objects, effectively making them timezone-aware.

The pytz.localize() method takes a naive datetime object and localizes it into a given timezone.

import datetime
import pytz

now = datetime.datetime.now()
tz = pytz.timezone("Europe/Amsterdam")

tz_aware = tz.localize(now)

print(tz_aware.strftime('%Y-%m-%d %H:%M:%S'))

print(tz_aware.tzinfo)

2023-08-15 12:28:04 CES
Europe/Amsterdam

Converting between timezones

We can use the astimezone() method to convert a timezone-aware datetime object to a different timezone. This method takes a timezone as an argument and returns a new datetime object with the same date and time but the specified new timezone.

import datetime 
import pytz

date_string = '2023-09-13T10:45:00' 

# Parse the date_string 
date_object = datetime.datetime.strptime(date_string, "%Y-%m-%dT%H:%M:%S") 

# Convert the date object to a timezone aware datetime object 
tz = pytz.timezone('Europe/Amsterdam')
tz_date_object = tz.localize(date_object) 

print(tz_date_object, ',', tz_date_object.tzinfo)

# Convert the timezone aware datetime object to another timezone
new_timezone = pytz.timezone('Africa/Cairo') 

new_tz_date_object = tz_date_object.astimezone(new_timezone) 

print(new_tz_date_object ,', ', new_tz_date_object.tzinfo)

2023-09-13 10:45:00+02:00
Europe/Amsterdam

2023-09-13 11:45:00+03:00
Africa/Cairo

Formatting datetime objects with timezones included

The strftime() method of datetime objects is used to format the represented time into a given format.  We can use the %z and the %Z formatters to include timezone name and offset.

import datetime
import pytz

now = datetime.datetime.now()
tz = pytz.timezone("Asia/Kolkata")

tz_aware = tz.localize(now)

#use the %z formatter for the timezone offset
print(tz_aware.strftime('%Y-%m-%d %H:%M:%S %z'))

#use the %Z formatter for the timezone name
print(tz_aware.strftime('%Y-%m-%d %H:%M:%S%z %Z'), ', ', tz_aware.tzinfo)

2023-08-15 13:05:49+0530
2023-08-15 13:05:49+0530 IST,  Asia/Kolkata