datetime2 overview

The definition of a moment in history is independent from the way it is represented in different cultures. Indeed the same day is represented in different ways by different calendars. The datetime2 module detaches operations on date and time objects from their representation, and allows to add other representations at run time. The module does all this in an efficient and syntactically clear way.

We can create a date object by calling the relevant access attribute of the base class Date:

>>> d1 = Date.gregorian(1965, 3, 1)  # Gregorian: 1965-03-01
>>> d2 = Date.iso(2011, 23, 4)       # ISO: 2011-W23-4

Each of these date objects can be printed and has its own attributes and methods:

>>> print(d1.gregorian)
>>> print(d1.gregorian.month)
>>> print(d1.gregorian.weekday())
>>> print(d2.iso)
>>> print(d2.iso.week)
>>> print(d2.iso.day_of_year())

One of the strength of datetime2 is that we can mix these attributes, independently from how the date object is built:

>>> print(d1.iso)
>>> print(d1.iso.week)
>>> print(d1.iso.day_of_year())
>>> print(d2.gregorian)
>>> print(d2.gregorian.month)
>>> print(d2.gregorian.weekday())

The same strength is true also for time, where different representations can be mixed like in dates:

>>> t1 = Time.western(15, 47, 16, timezone=-6)
>>> t2 = Time.internet(895)
>>> print(t1.western)
>>> print(t1.internet)
>>> print(t2.western)
>>> print(t2.western.minute)

The relation between time objects can be either implicit, i.e. depending on implementation, or explicit, which means that the objects know how they relate to each other. Then standard way for the latter is with UTC. An object of the first kind is said to be naive, of the second kind is called aware (like in Aware and Naive Objects of the datetime2 module). For aware objects a second value is used in the constructor to indicate the distance from UTC.

Many representations of the time of day of this module are aware by definition, so in those cases the UTC offset must not be given. E.g., the Internet time representation is based on Basel time zone (UTC+1).

Internal representation

In order to be able to convert between the different calendars and between the different times of day, a generic and culturally independent way of internally representing them has been chosen. For calendars, the idea, inspired by the excellent book “Calendrical Calculations”[1], is to identify each day by simply counting the days starting with 1 for January 1st of year 1, 2 for January 2nd is day 2, and so on. Using the datetime2 module we write:

>>> d3 = Date(1)
>>> d4 = Date(737109)

These dates can then be handled like above:

>>> print(d3.gregorian)
>>> print(d3.iso)
>>> print(d4.gregorian)
>>> print(d4.iso)

Similarly, each Date object can be printed with the internal representation (even if it is of little use):

>>> print(d1)
R.D. 717396
>>> print(d2)
R.D. 734297

Where R.D. stands for Rata Die, the Latin for “fixed date”.

There are similar generic representations for all base classes of the datetime2 module:

  • Time: a moment of the day is represented as a fraction of the day, starting from midnight. Distance from UTC, if given is also given as a fraction of a day.
>>> print(t1)
14209/21600 of a day, -1/4 of a day from UTC
>>> print(t2)
179/200 of a day, 1/24 of a day from UTC
>>> t3 = Time(7, 10)
>>> t4 = Time(0.796875, utcoffset="1/4")
>>> print(t3.western)
>>> print(t4.western)
>>> print(t4.internet)
  • TimeDelta: a time interval is given in number of days, possibly fractional to account for parts of day.
>>> td1 = TimeDelta(8, 10)
>>> print(td1)
4/5 of a day
>>> print(td1.western)
19 hours, 12 minutes
>>> td2 = TimeDelta(118, 12)
>>> print(td2)
9 days and 5/6 of a day
>>> print(td2.western)
9 days and 20 hours
[1]“Calendrical Calculations: The Ultimate Edition”, E. M. Reingold, N. Dershowitz, Cambridge University Press, 2018

See also

Module datetime
Basic date and time types.
Module calendar
General calendar related functions.
Module time
Time access and conversions.