Why Pendulum?

Native datetime instances are enough for basic cases but when you face more complex use-cases they often show limitations and are not so intuitive to work with.

Pendulum provides a cleaner and easier to use API while still relying on the standard library. So it's still datetime but better.

Unlike other datetime libraries for Python, Pendulum is a drop-in replacement for the standard datetime class (it inherits from it), so, basically, you can replace all your datetime instances by DateTime instances in you code (exceptions exist for libraries that check the type of the objects by using the type function like sqlite3 or PyMySQL for instance).

It also removes the notion of naive datetimes: each DateTime instance is timezone-aware and by default in UTC for ease of use.

Pendulum also improves timedelta by providing more intuitive methods and properties. See the documentation for more information.

Why not Arrow?

Arrow is the most popular datetime library for Python right now, however its behavior and API can be erratic and unpredictable. The get() method can receive pretty much anything and it will try its best to return something while silently failing to handle some cases:

>>> arrow.get('2016-1-17')
<Arrow [2016-01-01T00:00:00+00:00]>

>>> pendulum.parse('2016-1-17')
DateTime(2016, 1, 17, 0, 0, 0, tz='UTC')

>>> arrow.get('20160413')
<Arrow [1970-08-22T08:06:53+00:00]>

>>> pendulum.parse('20160413')
DateTime(2016, 4, 13, 0, 0, 0, tz='UTC')

>>> arrow.get('2016-W07-5')
<Arrow [1970-08-22T08:06:53+00:00]>

>>> pendulum.parse('2016-W07-5')
DateTime(2016, 2, 19, 0, 0, 0, tz='UTC')

# Working with DST
>>> just_before = arrow.Arrow(2013, 3, 31, 1, 59, 59, 999999, 'Europe/Paris')
>>> just_after = just_before.replace(microseconds=1)
# Should be 2013-03-31T03:00:00+02:00

>>> (just_after.to('utc') - just_before.to('utc')).total_seconds()
# Should be 1e-06

>>> just_before = pendulum.create(2013, 3, 31, 1, 59, 59, 999999, 'Europe/Paris')
>>> just_after = just_before.add(microseconds=1)

>>> (just_after.in_timezone('utc') - just_before.in_timezone('utc')).total_seconds()

Those are examples showing that Arrow cannot always be trusted to have a consistent behavior with the data you are passing to it.

How are the Pendulum performances?

Here are multiple performance benchmarks. The other libraries used for these benchmarks are Arrow and Delorean

Objects creation

Creation of 10000 objects via the default constructor.

Time in seconds (less is better)
Create a "now" instance

Creation of 10000 objects representing the current time.

Time in seconds (less is better)
Change timezone

Changing the timezone 10000 times.

Time in seconds (less is better)
String casting

Casting an instance to string 10000 times.

Time in seconds (less is better)
String parsing

Creating an instance from a string 10000 times.

Time in seconds (less is better)
String formatting

Formatting an instance to a string 10000 times.

Time in seconds (less is better)
Creating from timestamp

Creating an instance from a timestamp 10000 times.

Time in seconds (less is better)