Python Datetime and timezone Tutorial



Date and time are central to life and society and as a result, we can't avoid dealing with them while building our applications. But dealing with date and time can be challenging especially when it involves working with timezones. luckily, there are a number of python modules for dealing with this.


The Datetime Module

python provides us with a datetime module that we can use to carry out date and time related operations including timezones and daylight savings time.

The datetime module provides five main classes for working with date and time and they include:

  • date - is used to manipulate dates alone (year, month, day)
  • time - is used to carry out time related operations alone (hour, minute,second)
  • datetime - this is not the same as the datetime module. The datetime module just happens to have a class named datetime which allows us to carry out operations that combine date and time (year, month, day, hour, minute, second)
  • timedelta - is used to carry out time-duration based computations(this will become clearer as we proceed)
  • tzinfo - is used for making your datetime objects timezone aware (more on this later)


To create a datetime object, you simply import the datetime class from the datetime module. You can use the now() method to access the current date and time and this is based on the date and time settings of your computer.


from datetime import datetime

date_time_now = datetime.now()

print(date_time_now, type(date_time_now))

> 2020-07-07 00:32:33.147293 <class 'datetime.datetime'>


In case you have a different date and time in mind, you can supply your own arguments to datetime class in this format year, month, day, hour, minute, second, microsecond

from datetime import datetime

date_time = datetime(2020,2,2,1,50,37)

print(date_time, type(date_time))

> 2020-02-02 01:50:37 <class 'datetime.datetime'>

You should note however that it is not compulsory that you provide all the arguments as it all depends on how precise you want your datetime object to be.

You can also replace values in your newly created datetime object using the replace method


from datetime import datetime

date_time = datetime.now()

print(date_time)

>2020-07-07 00:45:43.590035

date_time = date_time.replace(year=2016,month=7,day=10,hour=10)

print(date_time)

>2016-07-10 10:45:43.590035



Accessing Date And Time Values Stored In The Datetime Object

Values stored in the datetime object can be accessed through the corresponding attributes. To illustrate:

from datetime import datetime

date_time = datetime.now()

year = date_time.year
month = date_time.month
day = date_time.day
weekday = date_time.weekday() // this is like monday to sunday represented with numbers
hour = date_time.hour
minute = date_time.minute
second = date_time.second
microsecond = date_time.microsecond

print(year)
> 2020
print(month)
> 7
print(day)
> 7
print(weekday)
> 1
print(hour)
> 16
print(minute)
> 45
print(second)
> 40
print(microsecond)
> 150455


Working With Unix Timestamp In Python

Sometimes we make the decision to store datetime as unix timestamp. Let's see how to convert unix timestamp to datetime objects and verse versa

from datetime import datetime

date_time = datetime.now()

time_stamp = datetime.timestamp()

print(date_time,type(date_time))
> 2020-07-07 16:45:40.150455 <class 'datetime.datetime'>
print(time_stamp,type(time_stamp))
> 1594136740.150455 <class 'float'>


to get datetime object from timestamp, we use the fromtimestamp method like so:

new_date_time = datetime.fromtimestamp(time_stamp)

print(new_date_time)
> 2020-07-07 16:45:40.150455 <class 'datetime.datetime'>


The Time Delta Class And Measuring Time Duration

A time delta object represents the difference between two datetime objects. It is a duration of time, like say 365 days while datetime objects are exact moments in time. Lets say today is 2016-08-01 and first day of next month is 2016-08-01. To get what five days from now will be, we can create a time delta object of 5 days and add it to today. lets see this in code:

from datetime import datetime, timedelta

today = datetime(2016,7,9)

print(today,type(today))
> 2016-07-09 00:00:00 <class 'datetime.datetime'>
five_days_duration = timedelta(days=5)

print(five_days_duration,type(five_days_duration))
> 5 days, 0:00:00 <class 'datetime.timedelta'>
next_five_days = today + five_days_duration

print(next_five_days,type(next_five_days))
> 2016-07-14 00:00:00 <class 'datetime.datetime'>


to show that the difference between two datetime objects is a timedelta object, lets see a code sample:

next_month = datetime(2016,8,1)
duration = next_month - today
print(duration,type(duration))

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


Do note that you can only add a datetime object to a timedelta object or can add or substract a timedelta object to and from a datetime object. Trying to subtract a datetime object (duration - today) doesn't make sense and will throw an error.


Converting Datetime Strings To Datetime Objects And Verse Versa

very often there is a need to convert datetime strings to datetime objects and verse versa. When we make an http request to an api and the response contains a datetime field, it is usually stored as string in the request and there needs to be a way to convert that string to datetime. datetime provides us with two main methods for dealing with this and they are strptime and strftime.

strptime is used to convert a datetime string to a datetime object. You need to know the exact way the datetime string is formatted (the pattern) before this would work. to see the available format codes, visit this link.

Enough with the talk, let us start coding:

from datetime import datetime

iso_format = datetime.now().isoformat() // iso format is an international standard for representing date and time as string
print(iso_format,type(iso_format))
> 2020-07-07T01:30:49.985542 <class 'str'>

another_datetime_string = "june 2, 2020"
print(another_datetime_string,type(another_datetime_string))
> june 2, 2020 <class 'str'>

from_iso_format = datetime.strptime(iso_format,"%Y-%m-%dT%H:%M:%S.%f")
print(from_iso_format,type(from_iso_format))
> 2020-07-07 01:30:49.985542 <class 'datetime.datetime'>

from_another = datetime.strptime(another_datetime_string,"%B %d, %Y")
print(from_another,type(from_another))
> 2020-06-02 00:00:00 <class 'datetime.datetime'>


strftime is used to convert datetime objects to any desired string format that is not iso format. To be clear, it can also be used to format datetime objects to iso formatted strings but this is prone to error. If you would like to have your datetime object in iso formatted string, use the .isoformat method.

Let is illustrate strftime with code

from datetime import datetime

now = datetime.now()
year_month_day = now.strftime("%Y-%m-%d")
hour_minute_second = now.strftime("%H:%M:%S")
date_time = now.strftime("%Y-%m-%d %H:%M:%S")
different_format = now.strftime("%d %B, %Y")
iso_format = now.isoformat()

print(year_month_day,type(year_month_day))
> 2020-07-07 <class 'str'>
print(hour_minute_second,type(hour_minute_second))
> 16:45:40 <class 'str'>
print(date_time,type(date_time))
> 2020-07-07 16:45:40 <class 'str'>
print(different_format,type(different_format))
> 7 june, 2020 <class 'str'>
print(iso_format,type(iso_format))
> 2020-07-07T16:45:40.150455 <class 'str'>


Again if you would like to learn more about the format codes available, check out this site


Timezones



As you may well know, datetime varies from location to location across the globe. When we say "2020-06-09 12:02:20", there is no way of knowing if we mean Asia/Kolkata time or if we mean West African Time. This might not be a problem if your app's users are only in one timezone, but it can be a huge pain when your application's users are located in different regions across the globe. Timezones are what allow us to deal with this kind of problem.

We have various timezones among which are "America/Los_Angeles", "US/Eastern","Asia/kolkata" and a reference timezone called Co-ordinated Universal Time (UTC). A timezone's offset is the difference in hours between the timezone and the Co-ordinated Universal Time (UTC)

Naive and Aware datetime objects

A naive datetime object is one that has no timezone information and an aware datetime object is one that contains timezone information. From the above definitions, you can already guess that we have only been dealing with naive datetime objects all along.
To perform timezone sensitive operations in python, we use the module pytz. pytz also handles daylight savings time for us.
Let us illustrate how to handle timezone conversions in python:

from datetime import datetime
from pytz import timezone, utc

now = datetime.now()

print(now,now.tzinfo)
> 2020-07-07 02:35:19.312722 None

american_timezone = timezone("America/Los_Angeles")
america_now = american_timezone.localize(now)

print(america_now, america_now.tzinfo)
> 2020-07-07 02:35:19.312722-07:00 America/Los_Angeles

asia_timezone = timezone("Asia/Kolkata")
asia_now = america_now.astimezone(asia_timezone)
print(asia_now,asia_now.tzinfo)
> 2020-07-07 15:05:19.312722+05:00 Asia/Kolkata


//convert to utc
utc_now = asia_now.astimezone(utc)
print(utc_now,utc_now.tzinfo)
> 2020-07-07 09:35:19.312722_00:00 UTC

Note that you can't combine naive and aware datetime objects in an operation. If you try to compare, add, subtract or find the difference between naive and aware datetime, you will get an error. To illustrate


from datetime import datetime
from pytz import utc

now = datetime.now()
utc_now = utc.localize(now)
now > utc_now

> TypeError:can't compare offset-naive and offset-aware datetimes

Conclusion

ok everyone, this is the end of this tutorial. of course there are many more methods in the datetime class and other classes in the datetime module, but with this tutorial, you now have a solid background to explore further when it is necessary or when you feel curious. If you enjoyed this tutorial, like and leave a comment below. Don't forget to checkout my other tutorials  on git and getting started contributing to open-source software



Recommended Read




Comments




-->