datetime2 - New date and time types

The heart of the datetime2 module is made of four base classes, each having a very simple definition. All base classes implement operations for date and time independently of the way they are created.

datetime2 class names use the CapitalizedWords convention required by PEP 8, so they differ from the names of their similar counterparts in datetime module.

Date objects

A Date object represents a specific date. To do so it uses an idealized calendar, in which it counts the days elapsed from Gregorian Dec 31st of year 0, i.e. January 1st of year 1 is day number 1, January 2nd of year 1 is day number 2, and so on. This calendar ideally extends indefinitely in both directions.

There are two ways of creating a Date instance:

class datetime2.Date(day_count)

Return an object that represent a date which is day_count days after December 31st of year 0 in an ideal Gregorian calendar that has no limit. The argument day_count is required and it must be an integer, otherwise a TypeError exception is raised. There is no restriction on its numeric value.

classmethod Date.today()

Return a Date object that represents the current local date.

Date instances have one attribute:

Date.day_count

An integer that represents the number of days between the given date and January 1st, year 1. This attribute is read-only: an AttributeError exception is raised when trying to change it.

Date instances are immutable, so they can be used as dictionary keys. When two aware instances indicate the same time, even if they have different UTC offsets, the have the same hash. The hash function takes into consideration also that They can also be pickled and unpickled. In boolean contexts, all Date instances are considered to be true.

Date has one instance method:

Date.__str__()

Return R.D. followed by the day count. R.D. stands for Rata Die, the Latin for “fixed date”.

Available calendars

Currently (version 0.9.4) the calendars listed below are available.

Calendar Access attribute Calendar class Module
Gregorian gregorian GregorianCalendar datetime2.western
ISO iso IsoCalendar datetime2.modern

Supported operations

Operation Result
date2 = date1 + timedelta date2 is timedelta days after date1. Reverse addition (timedelta + date1) is allowed. (1) (2)
date2 = date1 - timedelta date2 is timedelta days before date1. (1) (3)
timedelta = date1 - date2 A TimeDelta object is returned representing the number of days between date1 and date2. (4)
date1 < date2 date1 is less than date2 when it represents a day earlier that that of date2. (5) (6)

Notes:

  1. A ValueError exception is raised if timedelta is not an integral number of days. timedelta object with non-integral number of days must be added or subtracted from DateTime instances.
  2. If timedelta is negative, date2 will be before date1.
  3. If timedelta is negative, date2 will be after date1.
  4. The timedelta instance created when subtracting Date instances will always have an integral number of days, positive if date1 is later than date2, negative otherwise.
  5. In other words, date1 < date2 if and only if date1.day_count < date2.day_count. All other comparison operators (<=, >, >=, == and !=) behave similarly.
  6. When comparing a Date object and an object of another class, if the latter has a day_count attribute, NotImplemented is returned. This allows a Date-like instance to perform reflected comparison if it is the second operator. When the second object doesn’t have a day_count attribute, if the operator is equality (==) or inequality (!=), the value returned is always False and True respectively. If the operator is one of the other four (<=, >, >= or ==), a TypeError exception is raised.

Time objects

An indication of time, independent of any particular day, expressed as a fraction of day. There might be an indication of time difference from UTC, e.g. due to time zone or daylight saving time. This time difference is expressed as fraction of a day and represents the time to be added to local time to get UTC. If there is this indication, the Time object is said to be “aware” and it is used to represent a precise moment (regardless of the day). An object without indication is said to be “naive”, and its interpretation is left to the program that uses it.

There are five Time constructors:

class datetime2.Time(day_frac, *, utcoffset=None)
class datetime2.Time(numerator, denominator, *, utcoffset=None)

Return an object that represents a moment in a day as a fraction of the whole day, given in the day_frac argument. If needed, it is possible to assign to the instance an indication of the time offset from UTC, for whatever political, algorithmic or geographic need (e.g. time zone), using the utcoffset argument, which must be explicitly named.

The day_frac and utcoffset arguments can be anything that can be passed to the fractions.Fraction constructor, i.e. an integer, a float, another Fraction, a Decimal number or a string representing an integer, a float or a fraction. The day_frac argument only can also be passed with two values that represent numerator and denominator of the fraction. A TypeError exception is raised if the type of any argument is not one of the accepted types. A ZeroDivisionError exception is raised if the denominator is 0.

The value for day_frac must be equal or greater than 0 and less than 1. The value for utcoffset in aware objects must be equal or greater than -1 and less or equal to 1. A ValueError exception is raised if values are outside these ranges.

classmethod Time.now(utcoffset=None)

Return an aware Time object that represents the current time. Without argument, the time represented in day_frac will be local standard time and utcoffset will be set to the difference between local standard time and UTC.

If utcoffset is given, the returned object will be the current time at the given time difference from UTC. utcoffset follows the same requirements of the default constructor.

classmethod Time.localnow()

Return a naive Time object that represents the current local standard time.

classmethod Time.utcnow()

Return a naive Time object that represents the current standard UTC.

Two read-only attributes store the day_frac and utcoffset arguments. The former is always a Fraction object, the latter is either a Fraction object or None, for naive time. An attempt to directly set the values of these two attributes will raise an AttributeError exception.

Time objects support comparison, where time1 is considered less than time2 when the former represents a moment earlier than the latter. UTC offset in aware instances is always taken into account. When both objects are Time instances they must have the same naivety, otherwise TypeError is raised if an order comparison is attempted, while for equality comparisons, naive instances are never equal to aware instances.

When comparing a Time object and an object of another class, if the latter has the day_frac and utcoffset attributes, NotImplemented is returned. This allows a Time-like instance to perform reflected comparison if it is the second operator. In this case, the second object is responsible for checking naivety.

Time instances are immutable, so they can be used as dictionary keys. They can also be pickled and unpickled. In boolean contexts, all Time instances are considered to be true.

Instance method:

Time.__str__()

Return the string <fraction> of a day, where fraction is the value of the day_frac attribute. UTC offset, if present, is represented as well:

>>> print(Time(4, 12))
1/3 of a day
>>> print(Time(3, 24, utcoffset="-4/24"))
1/8 of a day, -1/6 of a day from UTC

Available time representations

Currently (version 0.9.4) the time of day listed below are available.

Representation Attribute Time representation class Module
Western western WesternTime datetime2.western
Internet internet InternetTime datetime2.modern

Supported operations

Operation Result
time2 = time1 + timedelta time2 is timedelta time after time1. Reverse addition (timedelta + time1) is allowed. (1) (2)
time2 = time1 - timedelta time2 is timedelta time before time1. (1) (3)
timedelta = time1 - time2 A TimeDelta object is returned representing the day fraction between time1 and time2. (4)
time1 < time2 time1 is less than time2 when the former represents a moment earlier than the latter. UTC offset, if present, is taken into consideration. (5) (6) (7)

Notes:

  1. The result of this operation will always be a valid Time instance. If overflow or underflow occur, the full day part will be truncated so that only the fractional part will remain. Naivety is preserved: if time1 has a UTC offset, this will be copied to time2.
  2. If timedelta is negative, time2 will be before time1.
  3. If timedelta is negative, time2 will be after time1.
  4. The timedelta object created when subtracting two Time instances will always represent a fractional part of a day, with the days attribute value greater than -0.5 and less or equal to 0.5. time1 and time2 must have the same naivety; if they don’t, a ValueError exception is raised. If they are aware, UTC offset of both instances will be taken into account to generate the result.
  5. All other comparison operators (<=, >, >=, == and !=) behave similarly.
  6. If both objects to be compared are Time instances, they must have the same naivety; if they don’t, a ValueError exception is raised.
  7. When comparing a Time object and an object of another class, if the latter has a day_frac attribute, NotImplemented is returned. This allows a Time-like instance to perform reflected comparison if it is the second operator. In this case, the second object is responsible for checking naivety. If the second object doesn’t have a day_frac attribute, if the operator is equality (==) or inequality (!=), the value returned is always False and True respectively. If the operator is one of the other four (<=, >, >= or ==), a TypeError exception is raised.

Note

Given the rules above it, if time1 and time2 are aware instances, time1 + (time2 - time1) compares equal to time2, but it will have the same day_frac value only if the UTC offsets of time1 and time2 are equal.

TimeDelta objects

An interval of time, expressed in fractional days.

There are two TimeDelta constructors:

class datetime2.TimeDelta(fractional_days)
class datetime2.TimeDelta(numerator, denominator)

Return an object that represents a time interval in fractional days, given in the fractional_days argument. This value will be greater than 1 to indicate an interval longer than 1 day.

The fractional_days argument can be anything that can be passed to the fractions.Fraction constructor, i.e. an integer, a float, another Fraction, a Decimal number or a string representing an integer, a float or a fraction. The argument can also be passed with two values that represent numerator and denominator of the fraction. A TypeError exception is raised if the type of any argument is not one of the accepted types. A ZeroDivisionError exception is raised if the denominator is 0. There are no limits on the value of fractional_days.

The read-only attribute fractional_days stores the value, always as a Python Fraction object. An attempt to directly set the values of this attribute will raise an AttributeError exception. It is also possible to access the integral and fractional parts of fractional_days with two calculated attributes: int_part and frac_part. If the time interval is negative, both int_part and frac_part are negative. Given any TimeDelta instance td, it is always: td.fractional_days == td.int_part() + td.frac_part()

>>> td1 = Timedelta(16, 3)
>>> td1.int_part
5
>>> td1.frac_part
Fraction(1, 3)
>>> td2 = TimeDelta(-7.625)
>>> td2.int_part
-7
>>> td2.frac_part
Fraction(-5, 8)

TimeDelta objects support comparison, where timedelta1 is considered greater than timedelta2 when the former represents a time interval longer than the latter. When comparing a TimeDelta object and an object of another class, if the latter has the fractional_days attribute, NotImplemented is returned. This allows a TimeDelta-like instance to perform reflected comparison if it is the second operator.

TimeDelta instances are immutable, so they can be used as dictionary keys. They can also be pickled and unpickled.

In boolean contexts, a TimeDelta instance is considered to be true if and only if it isn’t equal to TimeDelta(0).

Instance methods:

TimeDelta.int()
TimeDelta.frac()

The first method return the same instance with only the integer part. The last method returns the same instance with only the fractional part. All methods return a negative value if the time interval is negative. In this way, given any TimeDelta instance td, it is always: td == td.int() + td.frac()

>>> td1 = Timedelta(16, 3)
>>> td1.int()
TimeDelta(Fraction(5, 1))
>>> td1.frac()
TimeDelta(Fraction(1, 3))
>>> td2 = TimeDelta(-7.625)
>>> int(td2)
TimeDelta(Fraction(-7, 1))
>>> td2.frac()
TimeDelta(Fraction(-5, 8))
TimeDelta.is_integer()

Returns True if the time interval is made of an integer number of days.

>>> Timedelta("3/4").is_integer()
False
>>> TimeDelta(-1).is_integer()
True
TimeDelta.__str__()

Returns a string indicating the number of days and the remaining fraction of a day. Note that whilst in datetime.timedelta the fractional part is always positive, in TimeDelta the fractional part has the same sign of the integer part.

>>> td1 = Timedelta("1/12")
>>> print(td1)
1/12 of a day
>>> td2 = TimeDelta(3)
>>> print(td2)
3 days
>>> td3 = TimeDelta(11, -7)
>>> print(td3)
-1 day and -4/7 of a day

Available time interval representations

The following table lists the available time representations interval and the attributes by which they are reachable:

Representation Attribute Time representation class Module
Western western WesternTimeDelta datetime2.western

Note

Not available in version 0.9.0.

Supported operations

Operation Result
timedelta1 = timedelta2 + timedelta3 Sum of two time intervals.
timedelta1 = timedelta2 - timedelta3 Difference of two time intervals.
timedelta1 = timedelta2 * number or timedelta1 = number * timedelta2 Multiplication of a time interval by a number. (1)
timedelta1 = timedelta2 / number Division of a time interval by a number. (1)
number = timedelta1 / timedelta2 Returns a fraction which is the ratio between the two time intervals.
timedelta1 = timedelta2 // number Floor division. Returns a time interval with an integer number of days. If dividend and divisor are of different sign, the result is negative and, if not integer, it is more negative than the true result.
number = timedelta1 // timedelta2 Integer number of times timedelta2 is contained in timedelta1. If dividend and divisor are of different sign, the result is negative and, if not integer, it is more negative than the true result.
timedelta1 = timedelta2 % divisor Remainder of the division. This result always has the same sign of the divisor.
divmod(timedelta, divisor) Return a tuple made of the integral quotient and remainder of timedelta divided by dividend. (2)
timedelta1 < timedelta2 timedelta1 is less than timedelta2 when the former represents an interval shorter than the latter. (3)

The table above does not include mixed type operations between TimeDelta and Date, Time or DateTime. For more information, see the Supported operations chapter of each of these classes.

Class TimeDelta also upports unary arithmetic operators +, - and abs().

Notes:

  1. The number is first converted to a fraction, then multiplication or division takes place. As such, if number is a float, float to Fraction conversion error may happen, and result may not be exact.
  2. If dividend is a number, see note (1).
  3. All other comparison operators (<=, >, >=, == and !=) behave similarly.