Python datetimes made easy
instance()
now supports all native types (date, time and datetime)Before this release, only a datetime could be given to the instance()
helper to get an equivalent DateTime
instance.
Now you can give to instance a date or time as well:
import pendulum
from datetime import date, time
pendulum.instance(date(2023, 12, 15))
pendulum.instance(time(12, 34, 56))
This release now provides improved testing helpers that rely internally on time-machine.
These helpers are optional and for them to work, you need to opt-in the test
extra when installing Pendulum.
poetry add "pendulum[test]"
# Or directly via pip
pip install "pendulum[test]"
You can travel in time relatively to the current time
>>> import pendulum
>>> now = pendulum.now()
>>> pendulum.travel(minutes=5)
>>> pendulum.now().diff_for_humans(now)
"5 minutes after"
Note that once you've travelled in time the clock keeps ticking. If you prefer to stop the time completely
you can use the freeze
parameter:
>>> import pendulum
>>> now = pendulum.now()
>>> pendulum.travel(minutes=5, freeze=True)
>>> pendulum.now().diff_for_humans(now)
"5 minutes after" # This will stay like this indefinitely
Sometimes, you may want to place yourself at a specific point in time.
This is possible by using the travel_to()
helper. This helper accepts a DateTime
instance
that represents the point in time where you want to travel to.
>>> import pendulum
>>> pendulum.travel_to(pendulum.yesterday())
Similarly to travel
, it's important to remember that, by default, the time keeps ticking so, if you prefer
stopping the time, use the freeze
parameter:
>>> import pendulum
>>> pendulum.travel_to(pendulum.yesterday(), freeze=True)
Using any of the travel helpers will keep you in the past, or future, until you decide
to travel back to the present time. To do so, you may use the travel_back()
helper.
>>> import pendulum
>>> now = pendulum.now()
>>> pendulum.travel(minutes=5, freeze=True)
>>> pendulum.now().diff_for_humans(now)
"5 minutes after"
>>> pendulum.travel_back()
>>> pendulum.now().diff_for_humans(now)
"a few seconds after"
However, it might be cumbersome to remember to travel back so, instead, you can use any of the helpers as a context manager:
>>> import pendulum
>>> now = pendulum.now()
>>> with pendulum.travel(minutes=5, freeze=True):
>>> pendulum.now().diff_for_humans(now)
"5 minutes after"
>>> pendulum.now().diff_for_humans(now)
"a few seconds after"
Some parts of Pendulum were historically written in C for improved performances. These are now written in Rust for cleaner, more maintainable code. Performances are also better with this rewrite.
This is the first step towards a more extensive rewrite in Rust of the library. Note that Pendulum will still provide a pure Python version of the library.
Timezone
class now relies on the native zoneinfo.ZoneInfo
class. #569
Period
class to Interval
. #676
period
helper to interval
. #676
test()
and set_test_now()
. #626
week_of_month
property for edge cases in January and December. #774
fold
attribute when deep-copying a DateTime
instance. #776
start_of()/end_of()
methods. #713
Timezone
class now relies on the native zoneinfo.ZoneInfo
class. #569
Period
class to Interval
. #676
period
helper to interval
. #676
test()
and set_test_now()
. #626
from_format()
(#374).fold
attribute was overridden when using replace()
(#414).now()
was not returning the correct result on DST transitions (#483).parse()
function (#452).pl
locale (#459).is_anniversary()
method as an alias of is_birthday()
(#298).is_utc()
will now return True
for any datetime with an offset of 0, similar to the behavior in the 1.*
versions (#295)Duration.in_words()
will now return 0 milliseconds
for empty durations.nth_of("month")
(#357).from_format()
(#372).DateTime
with a fixed timezone (#431).Period
instances were not properly compared to other classes, especially timedelta
instances (#427).test()
helper would not unset the test instance when an exception was raised (#445).week_of_month
attribute was not returning the correct value (#446).Z
ISO-8601 UTC designator was not parsed as UTC (#448).nl
locale.it
locale.id
locale.nb
locale.nn
locale.from_format()
not recognizing input strings when the specified pattern had escaped elements.x
token for string formatting.from_format()
from_format()
trying to parse escaped tokens.z
token timezone parsing in from_format()
to allow underscores.age
calculation for future dates.weeks
property for negative Period
instances.start_of()
methods not setting microseconds to 0.strftime
format.