Pendulum 0.6.0 is now out. It brings a new option to control transition normalization behavior, a new formatter and several fixes.

For the full list of changes, see the Change Log

New Features

An option to control the transition normalization behavior.

In previous versions, pendulum would automatically normalize datetimes:

import pendulum

pendulum.create(2013, 3, 31, 2, 30, 0, 0, 'Europe/Paris')
# 2:30 for the 31th of March 2013 does not exist
# so pendulum will return the actual time which is 3:30+02:00
'2013-03-31T03:30:00+02:00'

pendulum.create(2013, 10, 27, 2, 30, 0, 0, 'Europe/Paris')
# Here, 2:30 exists twice in the day so pendulum will
# assume that the transition already occurred
'2013-10-27T02:30:00+01:00'

Now, the behavior can be controlled by a global option:

import pendulum

pendulum.set_transition_rule(pendulum.PRE_TRANSITION)

pendulum.create(2013, 3, 31, 2, 30, 0, 0, 'Europe/Paris')
'2013-03-31T02:30:00+01:00'
pendulum.create(2013, 10, 27, 2, 30, 0, 0, 'Europe/Paris')
'2013-10-27T02:30:00+02:00'

pendulum.set_transition_rule(pendulum.TRANSITION_ERROR)

pendulum.create(2013, 3, 31, 2, 30, 0, 0, 'Europe/Paris')
# NonExistingTime: The datetime 2013-03-31 02:30:00 does not exist
pendulum.create(2013, 10, 27, 2, 30, 0, 0, 'Europe/Paris')
# AmbiguousTime: The datetime 2013-10-27 02:30:00 is ambiguous.

A new alternative formatter

Pendulum now supports an alternative format when using the format() method. This format is more intuitive to use than the default one and supports more directives. You can use this format either locally when calling the format() method or globally by using pendulum.set_formatter().

import pendulum

dt = pendulum.Pendulum(1975, 12, 25, 14, 15, 16)
dt.format('YYYY-MM-DD HH:mm:ss', formatter='alternative')
'1975-12-25 14:15:16'

pendulum.set_formatter('alternative')
dt.format('YYYY-MM-DD HH:mm:ss')
'1975-12-25 14:15:16'

# Reset to default formatter
pendulum.set_formatter()

For the list of available tokens, refer to the documentation.

To escape characters in format strings, you can wrap the characters in square brackets.

import pendulum

pendulum.now().format('[today] dddd', formatter='alternative')
'today Sunday'

New intersect() method on Period class

You can get the intersection of the current Period instance with others by using the intersect() method.

import pendulum


monday = pendulum.create(2016, 9, 12)
wednesday = monday.next(pendulum.WEDNESDAY)
friday = monday.next(pendulum.FRIDAY)
saturday = monday.next(pendulum.SATURDAY)

period = pendulum.period(monday, friday)

period.intersect(pendulum.period(wednesday, saturday))
# <Period [2016-09-14T00:00:00+00:00 -> 2016-09-16T00:00:00+00:00]>

You can also pass multiple periods to intersect().

import pendulum


monday = pendulum.create(2016, 9, 12)
wednesday = monday.next(pendulum.WEDNESDAY)
thursday = monday.next(pendulum.THURSDAY)
friday = monday.next(pendulum.FRIDAY)
saturday = monday.next(pendulum.SATURDAY)
sunday = monday.next(pendulum.SUNDAY)

period = pendulum.period(monday, friday)
wednesday_to_saturday = pendulum.period(wednesday, saturday)
thursday_to_sunday = pendulum.period(thursday, sunday)

period.intersect(
    wednesday_to_saturday,
    thursday_to_sunday
)
# <Period [2016-09-15T00:00:00+00:00 -> 2016-09-16T00:00:00+00:00]>

If no intersection exists, intersect() will return None:

period.intersect(pendulum.period(saturday, sunday))
None

Interval.in_words() supports a custom separator

You can now pass a separator keyword to the in_words() method.

import pendulum

it = pendulum.interval(days=1177, seconds=7284, microseconds=1234)

it.in_words()
'168 weeks 1 day 2 hours 1 minute 24 seconds'

it.in_words(separator=', ')
'168 weeks, 1 day, 2 hours, 1 minute, 24 seconds'

Changes

  • Improved meridians formatting by supporting minutes.
  • Changed behavior of create*() methods (time now defaults to 00:00:00)

Fixes

  • Fixed setters and modifiers (start_of/end_of) to properly apply transitions.
  • Fixed issue when compiling on 32 bit systems. (Thanks to guyzmo)
  • Fixed NameError Exception on Python 3.2. (Thanks to guyzmo)
  • Fixed absolute intervals.