Pendulum: Probably The Best Python DateTime Library | by Christopher Tao | Towards Data Science

The datetime module is one of the most important build-in modules in Python. It is very flexible and powerful by providing many out-of-the-box solutions to real programming problems. For example, the timedelta is one of my favourite tools.
However, I have to say that there are also some limitations of the datetime module. For example, when we deal with timezones, it usually reveals the shortage. Sometimes, we have to introduce some 3rd party libraries as supplements. Also, some aspects in the datetime module are not very intuitive or commonly used in other programming languages.
In this article, I’ll introduce a 3rd party library called Pendulum which will resolve all of the issues of the build-in datetime module.
It is not uncommon to use some 3rd party libraries such as pytz to solve some issues that Python datetime is not good at. However, we still need to import the datetime module and use it as essential, because we need to use it to instantiate datetime objects.
Let me show you why Pendulum is a drop-in replacement. Firstly, we need to install it using pip.
pip install pendulum
The library's name is a bit long, so I would recommend importing it with an alias.
import pendulum as pdl
Although pd is a shorter abbreviation, but I would reserve it for Pandas. Don’t want to create any confusion.
Let’s create a datetime object using Pendulum, and have a look at its object type.
from datetime import datetimedt = pdl.datetime(2021, 11, 6)isinstance(dt, datetime)
There is no magic. It is only because Pendulum inherits the Python datetime object. So, we don’t need to worry about using some original features from the datetime module. Literally, a Pendulum datetime object is a Python datetime object.
The most impressive feature of the Pendulum library will be the timezones. This is also one of the critical issues of the built-in datetime module. Before Python 3.9, we have to involve pytz if we want to use the IANA timezones.
With the Pendulum library, we can create a datetime object with a timezone as easy as such.
dt_melbourne = pdl.datetime(2021, 11, 6, tz='Australia/Melbourne')dt_brisbane = pdl.datetime(2021, 11, 6, tz='Australia/Queensland')print(dt_melbourne)print(dt_brisbane)
In the above example, we have created two objects for the same time. However, the timezones are different. Pendulum also allows us to compare the times easily.
dt_melbourne.diff(dt_brisbane).in_hours()
How easy it is! Comparing two datetime objects with different timezones and getting the exact result!
If we need to define multiple datetime objects and want to re-use the timezone string, we can create a timezone object and pass it to the datetime constructor.
my_timezone = pdl.timezone('Australia/Melbourne')dt_melbourne = pdl.datetime(2021, 11, 6, tz=my_timezone)print(dt_melbourne)print(dt_melbourne.timezone.name)
One more cool feature is to return the time to a different time zone. For example, it is midnight in Melbourne, then what’s the time in Brisbane?
Parsing a datetime is probably the most common use case in programming. Python datetime module does that very well. However, compared to most other programming languages, Python uses a different format %Y%m%d.
Pendulum allows us to use the common format codes as follows.
pdl.from_format('2021-11-06 22:00:00', 'YYYY-MM-DD HH:mm:ss')
Also, it fully supports the RFC 3339 and ISO 8601 formats, as well as some other common formats. That means we don’t have to specify the format codes to parse a string into datetime.
pdl.parse('2021-11-01 22:00:00')
Pendulum also integrates many common datetime extensions such as dateutil. If we want the library to fall back on the dateutil parser, we can pass the flag strict=False.
pdl.parse('21-11-06', strict=False)
Apart from these, Pendulum supports much more formats on the fly. For example, the datetime with numbers only.
pdl.parse('20211106')
And this one is very interesting, specifying the year, the week number and the day of that week, Pendulum gives you the correct datetime.
pdl.parse('2021-W44-6')
If we want to have a date object or a time object particularly, just specify exact=True, which is much easier than the Python datetime module.
pdl.parse('20211106', exact=True)pdl.parse('22:00:00', exact=True)
After parsing strings into datetime objects, the next important thing will be to output the datetime into strings with formats.
First of all, let’s have a datetime object. Since Pendulum inherits Python datetime, we can use all the methods such as now().
dt = pdl.now()
Then, let me pick up several examples of “to string” methods from Pendulum to see how easy it is to output datetime with formats out-of-the-box.
dt.to_date_string()  # with date onlydt.to_time_string()  # with time onlydt.to_formatted_date_string()  # month_abbr date, yeardt.to_day_datetime_string() # day, month_abbr date, year hh:mm am/pmdt.to_iso8601_string()  # to ISO 9601 standarddt.to_atom_string()  # to Atom formatdt.to_cookie_string()  # to cookie style format
Of course, we can use the format code to customise the output string, and the format code is more intuitive.
dt.format('DD MMMM, YYYY dddd HH:mm:ss A')
Another cool stuff is that we can easily add some irrelevant strings into the format string and have them escape from the format.
dt.format('[Hi! Today is] DD MMMM, YYYY dddd HH:mm:ss A')
In the built-in Python datetime module, the timedelta tool does the comparing jobs very well. However, Pendulum can even improve it by providing some more human-friendly output when comparing two datetime objects.
For example, the method diff_for_humans() will compare a datetime object with the current time and return a very human-friendly output.
dt1 = pdl.datetime(2021, 1, 1)dt1.diff_for_humans()dt2 = pdl.datetime(2021, 11, 7, 1)dt2.diff_for_humans()
One of the aspects that the built-in Python datetime could improve is finding the relative datetime based on a given one. For example, when we want to find the last day of the current month, we have to use relativedelta from the datetutil module.
from dateutil.relativedelta import relativedeltadatetime.datetime(2013, 2, 21) + relativedelta(day=31)
Also, the code is not quite readable because we are using day=31 as the argument, although it does the tricks when the month has less than 31 days.
While in Pendulum, it can’t be easier.
pdl.now().start_of('day')  # find the start time of the daypdl.now().start_of('month')pdl.now().end_of('day')pdl.now().end_of('month')
Another inconvenience of the built-in datetime module is to find a day of a week. For example, if we want to find the date of next Monday, this is probably the easiest way to do so.
from datetime import datetime, timedeltadatetime.now() + timedelta(days=(0-datetime.now().weekday()+7)%7)
It does the job, but with poor readability. A developer will need to spend some time to understand what is the logic for this line of code.
With Pendulum, it is as easy as such.
pdl.now().next(pdl.MONDAY)
We are even not bothered with thinking about whether it should be 0 or 1 to indicate Monday because Pendulum uses enumeration for that.
Similarly, we can use previous() method to find the previous Tuesday as follows. Also, we can keep the time part by setting the argument keep_time=True.
pdl.now().previous(pdl.TUESDAY)pdl.now().previous(pdl.TUESDAY, keep_time=True)
There are more “sugars” that are hidden in this library. Just a few more examples, such as getting yesterday or tomorrow.
print(pdl.yesterday())print(pdl.today())print(pdl.tomorrow())
It is also very easy to output the datetime with locale for different cultures and languages.
pdl.now().format('dddd DD MMMM YYYY', locale='zh')
One more example. If a person was born on Jan 1st, 1988, what’s the age of this person?
pdl.datetime(1988, 1, 1).age
There is more interesting stuff that can be found in the official documentation.
pendulum.eustace.io
In this article, I have introduced the 3rd party Python library Pendulum. It is a drop-in replacement for the built-in datetime module of Python. By using this library, many issues that the datetime module can solve, such as finding relative dates, can be solved easily now. More importantly, Pendulum provided neat and clean APIs to improve the readability of our code and these solutions are more intuitive.
medium.com
If you feel my articles are helpful, please consider joining Medium Membership to support me and thousands of other writers! (Click the link above)