Yet Another Python datetime Replacement: Pendulum

I stumbled across another new library that purports that it is better than Python’s datetime module. It is called Pendulum. Pendulum is heavily influenced by Carbon for PHP according to its documentation.

These libraries are always interesting, although I am not sure what makes this one better than Arrow or Delorean. There were some comments on Reddit between the creator of Pendulum where he stated that he found Arrow to behave strangely in certain circumstances.

Regardless, this article isn’t about comparing these competing libraries. It’s just to take a look at how Pendulum itself works. One of the primary purposes for these various libraries is to create a datetime module with a more “Pythonic” API and one that is timezone aware.

Let’s get it installed so we can check it out:

pip install pendulum

If you don’t like installing it directly to your main Python installation, feel free to install it in a virtualenv instead. Regardless of where you install it, you will see it install a couple of dependencies of its own such as tzlocal, python-translate, codegen, and polib.

Now that it is installed, let’s open up Python’s interpreter and give it a try:

>>> import pendulum
>>> pendulum.now('Japan')
<Pendulum [2016-07-13T10:39:22.788807+09:00]>
>>> pendulum.now()
<Pendulum [2016-07-12T20:39:27.250320-05:00]>

Here we grab the current time for my location and then we ask for the current time in Japan. You will note that Pendulum automatically detects your time zone. As you might expect, you can also create a datetime-like object from a date:

>>> from pendulum import Pendulum
>>> Pendulum.create_from_date(2016, 7, 8, 'US/Eastern')
<Pendulum [2016-07-08T21:39:59.837012-04:00]>
>>> Pendulum.create_from_date(2016, 7, 8, 'US/Central')
<Pendulum [2016-07-08T20:40:13.680983-05:00]>
>>> Pendulum.create_from_date(2016, 7, 8, 'US/Mountain')
<Pendulum [2016-07-08T19:40:20.687576-06:00]>

This example demonstrates how you can get various datetime-like objects by specifying different time zones. However, one of the things I like about Pendulum is how it calculates dates based on periods of time:

>>> today = pendulum.now()
>>> today
<Pendulum [2016-07-15T15:31:04.658325-05:00]>
>>> tomorrow = pendulum.now().add(days=1)
>>> tomorrow
<Pendulum [2016-07-16T15:31:17.754182-05:00]>
>>> last_week = pendulum.now().subtract(weeks=1)
>>> last_week
<Pendulum [2016-07-08T15:31:46.298015-05:00]>

I found the way that it adds and subtracts periods of time to be quite intuitive. Pendulum also has an interesting concept of intervals:

>>> interval = pendulum.interval(days=365)
>>> interval.weeks
52
>>> interval.years
1
>>> interval.days
365
>>> interval.for_humans
<bound method PendulumInterval.for_humans of 52 weeks 1 day>
>>> interval.for_humans()
'52 weeks 1 day'

Here we create an interval of 365 days. We can than ask it various pieces of information about that interval of time, such as how many days, weeks, and years it contains. Another fun thing you can do is create a datetime and then ask it for other dates related to the created date:

>>> dt = pendulum.create(2012, 1, 31, 12, 0, 0)
>>> dt.start_of('decade')
<Pendulum [2010-01-01T00:00:00+00:00]>
>>> dt.start_of('century')
<Pendulum [2001-01-01T00:00:00+00:00]>
>>> dt
<Pendulum [2012-01-31T12:00:00+00:00]>
>>> dt.end_of('month')
<Pendulum [2012-01-31T23:59:59.999999+00:00]>
>>> dt
<Pendulum [2012-01-31T12:00:00+00:00]>

In an earlier version of Pendulum, these calls would actually change the dt object in place. This would mean that instead of 2012-1-31, my dt object would change to the start of the decade, then the century and finally end up at the end of the month, which would have been 2001-01-30. This has been fixed at the time of writing to match what you see above.

Wrapping Up

Pendulum is a really interesting library. There has been a lot of updates to it in the last week or so as the author is changing the API based on feedback from people using it. I’ve found functions that I was trying to use while I was writing this article that had already changed by the time I was getting ready to publish. I do think this library is worth a look, but we will see if it survives when there are already at least two other worthy contenders that have been around a while. Be sure and check out the documentation as it is changing a lot and this article may be out of date sooner rather than later.

Related Projects

Related Articles

Print Friendly, PDF & Email
  • Anonymus

    When I try “tomorrow = pendulum.now().add_day()”, I don’t understand why I get the error: “AttributeError: ‘Pendulum’ object has no attribute ‘add_day'”…

  • The reason is that the API changed while I was working on the article. It is now add(days=1). I went ahead and updated the article to reflect the change. Since this project is pretty alpha, I am guessing they don’t deprecate methods before removing them.

  • Anonymus

    Thank you. I should have seen that by myself.