From 708078967a6902536584b577311ddb705d510074 Mon Sep 17 00:00:00 2001 From: Lorenzo Cappelletti Date: Sun, 26 Sep 2021 21:59:50 +0200 Subject: [PATCH 1/6] docs/library: Add new module `datetime`. Signed-off-by: Lorenzo Cappelletti --- docs/library/datetime.rst | 696 ++++++++++++++++++++++++++++++++++++++ docs/library/index.rst | 1 + 2 files changed, 697 insertions(+) create mode 100644 docs/library/datetime.rst diff --git a/docs/library/datetime.rst b/docs/library/datetime.rst new file mode 100644 index 0000000000000..a69acd05d3863 --- /dev/null +++ b/docs/library/datetime.rst @@ -0,0 +1,696 @@ +:mod:`datetime` -- basic date and time types +============================================ + +.. module:: datetime + :synopsis: basic date and time types + +|see_cpython_module| :mod:`python:datetime`. + +This module supplies classes for manipulating dates, times, and deltas. + +:class:`datetime` objects may be categorized as “aware” or “naive” +depending on whether or not they include timezone information. +An aware object can locate itself relative to other aware objects. An +*aware* object represents a specific moment in time that is not open to +interpretation. + +A *naive* object does not contain enough information to unambiguously +locate itself relative to other :class:`datetime` objects. Whether a naive +object represents Coordinated Universal Time (UTC), local time, or time +in some other timezone is purely up to the program, just like it is up +to the program whether a particular number represents metres, miles, or +mass. Naive objects are easy to understand and to work with, at the cost +of ignoring some aspects of reality. + +For applications requiring aware objects, :class:`datetime` objects have +an optional time zone information attribute, *tzinfo*, that can be set to +an instance of a :class:`timezone` class. These objects capture +information about the offset from UTC time and the time zone name. + +The following classes are provided: + +* :class:`timedelta` +* :class:`timezone` +* :class:`datetime` + +Python's classes `date() +`_ and `time() +`_ +are mimicked with a class :class:`datetime` set to midnight, and a class +:class:`timedelta` in the range [0-24h). + + +:class:`timedelta` Objects +-------------------------- + +A :class:`timedelta` object represents a duration, the difference between two +dates or times. With respect to the Python module +`datetime `_, +this implementation is constrained as follows: + + * Minimum resolution is *1 second*, instead of *1 microsecond*. + * Masimum delta spans over ±24855 days (±2\ :sup:`31` seconds or ±68 years) + instead of ±999999999 days. + + +Class attributes +^^^^^^^^^^^^^^^^ + +.. attribute:: timedelta.MINYEAR + + The year of :attr:`timedelta.min`, i.e. + ``timedelta.min.tuple()[1] // (365*24*60*60) == -68``. + + +.. attribute:: timedelta.MAXYEAR + + The year of :attr:`timedelta.max`, i.e. + ``timedelta.max.tuple()[1] // (365*24*60*60) == 68``. + + +.. attribute:: timedelta.min + + The most negative :class:`timedelta` object, ``timedelta(-2**31)``. + + +.. attribute:: timedelta.max + + The most positive :class:`timedelta` object, ``timedelta(2**31 - 1)``. + + +.. attribute:: timedelta.resolution + + The smallest possible difference between non-equal :class:`timedelta` + objects, ``timedelta(seconds=1)``. + + +Class methods +^^^^^^^^^^^^^ + +.. class:: timedelta(hours=0, minutes=0, seconds=0, days=0, weeks=0) + +All arguments are optional and default to ``0``. Arguments may be integers +or floats, and may be positive or negative. Only seconds are stored +internally. Arguments are converted to those units: + + * A minute is converted to 60 seconds. + * An hour is converted to 3600 seconds. + * A week is converted to 7 days. + +If no argument is a float, the conversion and normalization processes are +exact (no information is lost). + + +.. method:: timedelta.total_seconds() + + Return the total number of seconds contained in the duration. + + +.. method:: timedelta.__add__(other) + + Return a :class:`timedelta` which represents the sum of two durations. + + +.. method:: timedelta.__sub__(other) + + Return a :class:`timedelta` which represents the difference between + two durations. + + +.. method:: timedelta.__mul__(other) + + Return a delta multiplied by an integer or float. The result is rounded to + the nearest second using round-half-to-even. + + +.. method:: timedelta.__truediv__(other) + + When *other* is a float or an integer, returns a delta divided by *other*. + The result is rounded to the nearest multiple of timedelta.resolution + using round-half-to-even. + + When *other* is a delta, division of overall duration by interval unit + *other*. Returns a float object. + + +.. method:: timedelta.__floordiv__(other) + + The floor is computed and the remainder (if any) is thrown away. When + *other* is a delta, an integer is returned. + + +.. method:: timedelta.__mod__(other) + + The remainder is computed as a :class:`timedelta` object. + + +.. method:: timedelta.__divmod__(other) + + Computes the quotient and the remainder: ``q = td1.__floordiv__(td2)`` and + ``r = td1.__mod__(td2)``. ``q`` is an integer and ``r`` is a :class:`timedelta` + object. + + +.. method:: timedelta.__neg__() + + Equivalent to ``td1.__mul__(-1)``. + + +.. method:: timedelta.__eq__(other) + + Equivalent to ``td1.total_seconds() == td2.total_seconds()``. + + +.. method:: timedelta.__le__(other) + + Equivalent to ``td1.total_seconds() <= td2.total_seconds()``. + + +.. method:: timedelta.__lt__(other) + + Equivalent to ``td1.total_seconds() < td2.total_seconds()``. + + +.. method:: timedelta.__ge__(other) + + Equivalent to ``td1.total_seconds() >= td2.total_seconds()``. + + +.. method:: timedelta.__gt__(other) + + Equivalent to ``td1.total_seconds() > td2.total_seconds()``. + + +.. method:: timedelta.__bool__() + + Return ``False`` when duration is ``0``. + + +.. method:: timedelta.__abs__() + + Return a positive delta. + + +.. method:: timedelta.isoformat() + + This method mimics Python's `isoformat() + `_ + for *time* objects by returning a string in the format ``HH:MM:SS``, where + ``HH``, ``MM``, and ``SS`` are two digits of the time delta's hours, + minutes and seconds, respectively, since midnight. This is only if value + is within the range [0-24h). + + For other values, it returns the format ``±Dd HH:MM:SS``, where ``±`` is + the sign of the delta and ``D`` its number of days. This is *not* ISO + compliant, but provides a complete representation. + + +.. method:: timedelta.tuple(sign_pos='') + + Return the tuple ``(sign, days, hours, minutes, seconds)``, where ``sign`` is + ``-`` if delta is negative, *sign_pos* otherwise. + + +Examples of usage +^^^^^^^^^^^^^^^^^ + +An example of normalization:: + + import datetime.timedelta + + # Components of another_year add up to exactly 365 days + year = timedelta(days=365) + another_year = timedelta(weeks=40, days=84, hours=23, minutes=50, seconds=600) + print(year == another_year) # True + print(year.total_seconds()) # 31536000 + + +Examples of timedelta arithmetic:: + + import datetime.timedelta + + year = timedelta(days=365) + ten_years = year * 10 + print(ten_years) # 3650d 00:00:00 + nine_years = ten_years - year + print(nine_years) # 3285d 00:00:00 + three_years = nine_years // 3 + print(three_years) # 1095d 00:00:00 + + +:class:`timezone` Objects +------------------------- + +The :class:`timezone` class represents a timezone defined by a fixed +offset from UTC. Define a subclass of :class:`timezone` to capture +information about a particular time zone. + +An instance of :class:`timezone` can be passed to the constructors for +:class:`datetime`. The latter objects view their attributes as being in +local time, and the :class:`timezone` object supports methods revealing +offset of local time from UTC, the name of the time zone, and DST offset, +all relative to a date-time object passed to them. + + +Methods to customize +^^^^^^^^^^^^^^^^^^^^ + +A subclass of :class:`timezone` may need to override the following methods. +Exactly which methods are needed depends on the uses made of aware +:class:`datetime` objects. If in doubt, simply implement all of them. + + +.. method:: timezone.utcoffset(dt) + + Return offset of local time from UTC, as a :class:`timedelta` object + that is positive east of UTC. If local time is west of UTC, this should + be negative. + + This represents the *total* offset from UTC; for example, if a + :class:`timezone` object represents both time zone and DST adjustments, + :meth:`timezone.utcoffset` should return their sum. If the UTC offset + isn’t known, return ``None``. Else the value returned must be a + :class:`timedelta` object strictly between ``timedelta(hours=-24)`` and + ``timedelta(hours=24)`` (the magnitude of the offset must be less than one + day). Most implementations of :meth:`timezone.utcoffset` will probably + look like one of these two: + + return CONSTANT # fixed-offset class + return CONSTANT + self.dst(dt) # daylight-aware class + + If :meth:`timezone.utcoffset` does not return ``None``, :meth:`timezone.dst` + should not return None either. + + The default implementation of :meth:`timezone.utcoffset` returns the sum + of time zone and DST adjustments, if available. + +.. method:: timezone.dst(dt) + + Return the daylight saving time (DST) adjustment, as a :class:`timedelta` + object or ``None`` if DST information isn’t known. + + Return ``timedelta(0)`` if DST is not in effect. If DST is in effect, return + the offset as a :class:`timedelta` object (see :meth:`timezone.utcoffset` + for details). Note that DST offset, if applicable, has already been added + to the UTC offset returned by :meth:`timezone.utcoffset`, so there’s no + need to consult :meth:`timezone.dst` unless you’re interested in obtaining + DST info separately. + + Most implementations of :meth:`timezone.dst` will probably look like one + of these two:: + + def dst(self, dt): + # a fixed-offset class: doesn't account for DST + return timedelta(0) + + or:: + + def dst(self, dt): + # Code to set dston and dstoff to the time zone's DST + # transition times based on the input *dt*'s year, and + # expressed in standard local time. + + dt_ = dt.replace(tzinfo=None) + if dt_ >= dston and dt_ < dstoff: + return timedelta(hours=1) + else: + return timedelta(0) + + The default implementation of :meth:`timezone.dst` returns ``None``. + + +.. method:: timezone.tzname(dt) + + Return the time zone name corresponding to the :class:`datetime` object + *dt*, as a string. Nothing about string names is defined by the + :class:`datetime` module, and there’s no requirement that it mean anything + in particular. For example, “GMT”, “UTC”, “-500”, “-5:00”, “EDT”, + “US/Eastern”, “America/New York” are all valid replies. Return ``None`` if + a string name isn’t known. Note that this is a method rather than a fixed + string primarily because some :class:`timezone` subclasses will wish to + return different names depending on the specific value of *dt* passed, + especially if the :class:`timezone` class is accounting for daylight time. + + The default implementation of :meth:`timezone.tzname` returns the fixed + value specified when the :class:`timezone` instance is constructed. + If *name* is not provided in the constructor, the name returned by + ``tzname()`` is generated from the value of the ``offset`` as follows. + If *offset* is ``timedelta(0)``, the name is “UTC”, otherwise it returns + the string provided by :meth:`timezone.isoformat` method. + +These methods are called by a :class:`datetime` object, in response to their +methods of the same names. A :class:`datetime` object passes *self* as *dt* +argument. + + +Class attributes +^^^^^^^^^^^^^^^^ + +.. attribute:: timezone.utc + + The UTC timezone, ``timezone(timedelta(0))``. + + +Class methods +^^^^^^^^^^^^^ + +.. class:: timezone(offset, name=None) + + The *offset* argument must be specified as a :class:`timedelta` + object representing the difference between the local time and UTC. + It must be strictly between ``timedelta(hours=-24)`` and + ``timedelta(hours=24)``, otherwise :exc:`ValueError` is raised. + + The *name* argument is optional. If specified it must be a string + that will be used as the value returned by the :meth:`datetime.tzname` + method. + + +.. method:: timezone.isoformat(dt) + + Return a string in the format ``UTC±HH:MM``, where ``±`` is the sign of + *offset* from UTC, ``HH`` and ``MM`` are two digits of offset's hours and + offset's minutes respectively. If *offset* is ``timedelta(0)``, “UTC” + is returned. + + If *utc* is ``False``, this method always returns ``±HH:MM``. + + *dt* is needed in determining the right offset; it can be ``None``. + + +Examples of usage +^^^^^^^^^^^^^^^^^ + +`Central European Time `_ +(CET), used in most parts of Europe and a few North African countries, is a +standard time which is 1 hour ahead of Coordinated Universal Time (UTC). +As of 2011, all member states of the European Union observe summer time; +those that during the winter use CET use Central European Summer Time (CEST) +(or: UTC+02:00, daylight saving time) in summer (from last Sunday of March +to last Sunday of October). :: + + import datetime + + class Cet(datetime.timezone): + def __init__(self): + super().__init__(datetime.timedelta(hours=1), "CET") + + def dst(self, dt): + return datetime.timedelta(hours=1) if self.isdst(dt) else datetime.timedelta(0) + + def tzname(self, dt): + return 'CEST' if self.isdst(dt) else 'CET' + + def isdst(self, dt): + if dt is None: + return False + year, month, day, hour, minute, second, tz = dt.tuple() + if not 2000 <= year < 2100: + raise ValueError + if 3 < month < 10: + return True + if month == 3: + beg = 31 - (5*year//4 + 4) % 7 # last Sunday of March + if day < beg: return False + if day > beg: return True + return hour >= 3 + if month == 10: + end = 31 - (5*year//4 + 1) % 7 # last Sunday of October + if day < end: return True + if day > end: return False + return hour < 3 + return False + + tz = Cet() + print(tz.isoformat(datetime(2011, 1, 1))) # UTC+01:00 + print(tz.tzname (datetime(2011, 1, 1))) # CET + print(tz.isoformat(datetime(2011, 8, 1))) # UTC+02:00 + print(tz.tzname (datetime(2011, 8, 1))) # CEST + +The two formulas above are a simplification of the general +`Gauss's algorithm (disparate variation) +`_ +for calculating the week day of any given date:: + + def week_day (year, month, day, verbose=False): + if month <= 2: + raise ValueError + + Y = year + y = Y%100 + c = Y//100 + m = month - 2 + d = day + W = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat') + + k1 = d + int(2.6*m - 0.2) - 507*c//4 + k = k1 % 7 + w = (5*year//4 + k) % 7 + print(f'w(year) = (5*year//4 + {k}) % 7 # {100*c} <= year < {(c+1)*100}') + + if verbose: + print() + print(f'year = {year}, month = {month}, day = {day}') + print( 'w(y) = (d + int(2.6*m - 0.2) + y + y//4 + c//4 - 2*c) % 7') + print( 'w(y) = (d + int(2.6*m - 0.2) + 5*y//4 - 7*c//4) % 7') + print() + print( 'w(year) = (d + int(2.6*m - 0.2) + 5*year//4 - 5*c*100//4 - 7*c//4) % 7') + print( 'w(year) = (d + int(2.6*m - 0.2) + 5*year//4 - 507*c//4) % 7') + print(f'w(year) = ({d} + int(2.6*{m} - 0.2) + 5*year//4 - 507*{c}//4) % 7') + print(f'w(year) = (5*year//4 + ({k1}) % 7) % 7') + print(f'w(year) = (5*year//4 + {k}) % 7') + print(f'w({year}) = {w} ({W[w]})') + +which produces the following output for March and October:: + + >>> week_day(2000, 3, 31) + w(year) = (5*year//4 + 4) % 7 # 2000 <= year < 2100 + >>> week_day(2000, 10, 31) + w(year) = (5*year//4 + 1) % 7 # 2000 <= year < 2100 + + +:class:`datetime` Objects +------------------------- + +A :class:`datetime` object is a single object containing all the information +for specifying an absolute date and time point. + +:class:`datetime` assumes the current Gregorian calendar extended in both +directions, past and future. January 1 of year 1 is called day number 1, +January 2 of year 1 is called day number 2, and so on. + +:class:`datetime` assumes there are exactly 3600*24 seconds in every day and +subject to adjustment via a :class:`timezone` object. + + +Constructors +^^^^^^^^^^^^ + +.. class:: datetime(self, year, month, day, hour=0, minute=0, second=0, tzinfo=None) + + The *year*, *month* and *day* arguments are required. *tzinfo* may be + ``None``, or an instance of a :class:`timezone` class. The remaining + arguments must be integers in the following ranges: + + * ``MINYEAR <= year <= MAXYEAR``, + * ``1 <= month <= 12``, + * ``1 <= day <= number of days in the given month and year``, + * ``0 <= hour < 24``, + * ``0 <= minute < 60``, + * ``0 <= second < 60``, + + If an argument outside those ranges is given, :exc:`ValueError` is raised. + + +.. function:: fromisoformat(date_string) + + Return a :class:`datetime` corresponding to a *date_string* in the format + emitted by :meth:`datetime.isoformat`. + + Specifically, this function supports strings in the format:: + + YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]] + + where ``*`` can match any single character. + + +.. function:: fromordinal(n) + + Return the :class:`datetime` corresponding to the proleptic Gregorian + ordinal, where January 1 of year 1 has ordinal 1. :exc:`ValueError` is + raised unless ``1 <= ordinal <= datetime.max.toordinal()``. The hour, + minute and second of the result are all 0, and *tzinfo* is ``None``. + + +.. function:: combine(date, time, tzinfo) + + Return a new :class:`datetime` object whose date components are equal to + the given *date* object’s (see :meth:`datetime.date`), and whose time + components are equal to the given *time* object’s (see + :meth:`datetime.time`). If the *tzinfo* argument is provided, its value + is used to set the *tzinfo* attribute of the result, otherwise the + *tzinfo* attribute of the *date* argument is used. + + +Class attributes +^^^^^^^^^^^^^^^^ + +.. attribute:: datetime.MINYEAR + + The smallest year number allowed in a :class:`datetime` object. + :attr:`datetime.MINYEAR` is ``1``. + + +.. attribute:: datetime.MAXYEAR + + The largest year number allowed in a :class:`datetime` object. + :attr:`datetime.MAXYEAR` is ``9999``. + + +.. attribute:: datetime.timezone + + The object passed as the *tzinfo* argument to the :class:`datetime` + constructor, or ``None`` if none was passed. + + +Class methods +^^^^^^^^^^^^^ + +.. method:: datetime.__add__(other) + + In the expression ``datetime2 = datetime1.__add__(timedelta)``, ``datetime2`` + is a duration of ``timedelta`` removed from ``datetime1``, moving forward + in time if ``timedelta > 0``, or backward if ``timedelta < 0``. The result + has the same :class:`timezone` attribute as the input ``datetime1``, and + ``datetime2 - datetime1 == timedelta`` after. + + Note that no time zone adjustments are done even if the input is an aware + object. + + +.. method:: datetime.__sub__(other) + + If *other* is an instance of :class:`timedelta`, the expression + ``datetime2 = datetime1.__sub__(timedelta)`` computes the ``datetime2`` such + that ``datetime2 + timedelta == datetime1``. As for addition, the result has + the same :class:`timezone` attribute as the input ``datetime1``, and no time + zone adjustments are done even if the input is aware. + + If *other* is an instance of :class:`datetime`, subtraction + ``timedelta = datetime2.__sub__(datetime1)`` is defined only if both operands + are naive, or if both are aware. If one is aware and the other is naive, + :exc:`TypeError` is raised. + + If both are naive, or both are aware and have the same :class:`timezone` + attribute, the :class:`timezone` attributes are ignored, and the result + is a :class:`timedelta` object *t* such that ``datetime2 + t == datetime1``. + No time zone adjustments are done in this case. + + If both are aware and have different :class:`timezone` attributes, ``a-b`` + acts as if *a* and *b* were first converted to naive UTC datetimes first. + + +.. method:: datetime.__lt__(other) + + Equivalent to ``dt1.toordinal() < dt2.toordinal()``. + + +.. method:: datetime.__le__(other) + + Equivalent to ``dt1.toordinal() <= dt2.toordinal()``. + + +.. method:: datetime.__eq__(other) + + Equivalent to ``dt1.toordinal() == dt2.toordinal()``. + + +.. method:: datetime.__ge__(other) + + Equivalent to ``dt1.toordinal() >= dt2.toordinal()``. + + +.. method:: datetime.__gt__(other) + + Equivalent to ``dt1.toordinal() > dt2.toordinal()``. + + +.. method:: datetime.utcoffset() + + If *tzinfo* is ``None``, returns ``None``, else returns a + :class:`timedelta` object with magnitude less than one day. + + +.. method:: datetime.replace(year=None, month=None, day=None, hour=None, minute=None, second=None, tzinfo=True) + + Return a :class:`datetime` with the same attributes, except for those + attributes given new values by whichever keyword arguments are specified. + Note that ``tzinfo=None`` can be specified to create a naive + :class:`datetime` from an aware :class:`datetime` with no conversion of + date and time data. + + +.. method:: datetime.astimezone(tz) + + Return a :class:`datetime` object with new *tzinfo* attribute + *tz*, adjusting the date and time data so the result is the same UTC time + as *self*, but in *tz*’s local time. *self* must be aware. + + If you merely want to attach a :class:`timezone` object *tz* to a + :class:`datetime` *dt* without adjustment of date and time data, use + ``dt.replace(tzinfo=tz)``. If you merely want to remove the :class:`timezone` + object from an aware :class:`datetime` *dt* without conversion of date and + time data, use ``dt.replace(tzinfo=None)``. + + +.. method:: datetime.isoformat(sep='T') + + Return a string representing the date and time in ISO 8601 format + ``YYYY-MM-DDTHH:MM:SS``. If :meth:`datetime.utcoffset` does not return + ``None``, a string is appended, giving the UTC offset: + ``YYYY-MM-DDTHH:MM:SS+HH:MM``. + + +.. method:: datetime.date() + + Return a :class:`datetime` instance whose date and time zone components + are equal to the input object and time is set to midnight. + + +.. method:: datetime.time() + + Return a :class:`timedelta` instance whose time components are equal to + the input object. + + +.. method:: datetime.toordinal() + + Return the proleptic Gregorian ordinal of the date. + + +.. method:: datetime.isoweekday() + + Return the day of the week as an integer, where Monday is 1 and Sunday + is 7. For example, ``date(2002, 12, 4).isoweekday() == 3``, a Wednesday. + + +.. method:: datetime.tuple() + + Return the tuple ``(year, month, day, hour, minute, second, tzinfo)``. + + +Examples of usage +^^^^^^^^^^^^^^^^^ + +Examples of working with :class:`datetime` objects:: + + from datetime import timedelta, timezone, datetime, fromisoformat + + print(datetime(2005, 7, 14, 12, 30)) # 2005-07-14 12:30:00 + dt = fromisoformat('2006-11-21 16:30+01:00') + print(dt.add(timedelta(hours=23))) # 2006-11-22 15:30:00+01:00 + tz1 = timezone(timedelta(hours=4, minutes=30)) + print(tz1) # UTC+04:30 + dt = datetime(1900, 11, 21, 3, 30, tzinfo=tz1) + print(dt) # 1900-11-21 03:30:00+04:30 + print(dt.astimezone(timezone.utc)) # 1900-11-20 23:00:00+00:00 diff --git a/docs/library/index.rst b/docs/library/index.rst index 2b1d6b9651343..3134a7ff0a925 100644 --- a/docs/library/index.rst +++ b/docs/library/index.rst @@ -57,6 +57,7 @@ library. builtins.rst cmath.rst collections.rst + datetime.rst errno.rst gc.rst hashlib.rst From 309fd5bce6f7ba734abde962de7ffccd11fb9be3 Mon Sep 17 00:00:00 2001 From: Lorenzo Cappelletti Date: Tue, 26 Oct 2021 22:42:36 +0200 Subject: [PATCH 2/6] docs/library/datetime.rst: Add EPOCH. Signed-off-by: Lorenzo Cappelletti --- docs/library/datetime.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/library/datetime.rst b/docs/library/datetime.rst index a69acd05d3863..41f5485ff479e 100644 --- a/docs/library/datetime.rst +++ b/docs/library/datetime.rst @@ -547,6 +547,12 @@ Class attributes :attr:`datetime.MAXYEAR` is ``9999``. +.. attribute:: datetime.EPOCH + + :class:`datetime` object representing the time epoch of 2000-01-01 00:00:00 + UTC (same as :mod:`time`'s epoch). + + .. attribute:: datetime.timezone The object passed as the *tzinfo* argument to the :class:`datetime` From 00278196a28fb2af6ac8fb175dcadbf17c9d7448 Mon Sep 17 00:00:00 2001 From: Lorenzo Cappelletti Date: Tue, 2 Nov 2021 21:21:57 +0100 Subject: [PATCH 3/6] docs/library/datetime.rst: Nanosecond resolution. Signed-off-by: Lorenzo Cappelletti --- docs/library/datetime.rst | 50 +++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/docs/library/datetime.rst b/docs/library/datetime.rst index 41f5485ff479e..eae3f6d70af8a 100644 --- a/docs/library/datetime.rst +++ b/docs/library/datetime.rst @@ -48,9 +48,9 @@ dates or times. With respect to the Python module `datetime `_, this implementation is constrained as follows: - * Minimum resolution is *1 second*, instead of *1 microsecond*. - * Masimum delta spans over ±24855 days (±2\ :sup:`31` seconds or ±68 years) - instead of ±999999999 days. + * Minimum resolution is *1 nanosecond*, instead of *1 microsecond*. + * Masimum delta spans over ±106751 days (±2\ :sup:`63` nanoseconds or + ±292 years) instead of ±999999999 days. Class attributes @@ -59,40 +59,50 @@ Class attributes .. attribute:: timedelta.MINYEAR The year of :attr:`timedelta.min`, i.e. - ``timedelta.min.tuple()[1] // (365*24*60*60) == -68``. + ``timedelta.min.tuple()[1] // (365 * 24 * 60 * 60 * 10**9) == -292``. .. attribute:: timedelta.MAXYEAR The year of :attr:`timedelta.max`, i.e. - ``timedelta.max.tuple()[1] // (365*24*60*60) == 68``. + ``timedelta.max.tuple()[1] // (365 * 24 * 60 * 60 * 10**9) == 292``. .. attribute:: timedelta.min - The most negative :class:`timedelta` object, ``timedelta(-2**31)``. + The most negative :class:`timedelta` object, + ``timedelta(nanoseconds=-2**63)``. .. attribute:: timedelta.max - The most positive :class:`timedelta` object, ``timedelta(2**31 - 1)``. + The most positive :class:`timedelta` object, + ``timedelta(nanoseconds=2**63 - 1)``. .. attribute:: timedelta.resolution The smallest possible difference between non-equal :class:`timedelta` - objects, ``timedelta(seconds=1)``. + objects, ``timedelta(nanoseconds=1)``. + + +.. attribute:: timedelta.nanoseconds + + The internal time delta representation as 64-bit integer. Class methods ^^^^^^^^^^^^^ -.. class:: timedelta(hours=0, minutes=0, seconds=0, days=0, weeks=0) +.. class:: timedelta(hours=0, minutes=0, seconds=0, days=0, weeks=0, + milliseconds=0, microseconds=0, nanoseconds=0) All arguments are optional and default to ``0``. Arguments may be integers -or floats, and may be positive or negative. Only seconds are stored +or floats, and may be positive or negative. Only nanoseconds are stored internally. Arguments are converted to those units: + * A microsecond is converted to 1000 nanoseconds. + * A millisecond is converted to 10\ :sup:`6` nanoseconds. * A minute is converted to 60 seconds. * An hour is converted to 3600 seconds. * A week is converted to 7 days. @@ -103,7 +113,7 @@ exact (no information is lost). .. method:: timedelta.total_seconds() - Return the total number of seconds contained in the duration. + Return a float representing the total number of seconds contained in the duration. .. method:: timedelta.__add__(other) @@ -120,7 +130,7 @@ exact (no information is lost). .. method:: timedelta.__mul__(other) Return a delta multiplied by an integer or float. The result is rounded to - the nearest second using round-half-to-even. + the nearest nanosecond using round-half-to-even. .. method:: timedelta.__truediv__(other) @@ -204,11 +214,14 @@ exact (no information is lost). the sign of the delta and ``D`` its number of days. This is *not* ISO compliant, but provides a complete representation. + If the fractional part of :meth:`timedelta.total_seconds()` is not 0, + ``.ffffff`` is appended. + .. method:: timedelta.tuple(sign_pos='') - Return the tuple ``(sign, days, hours, minutes, seconds)``, where ``sign`` is - ``-`` if delta is negative, *sign_pos* otherwise. + Return the tuple ``(sign, days, hours, minutes, seconds, nanoseconds)``, + where ``sign`` is ``-`` if delta is negative, *sign_pos* otherwise. Examples of usage @@ -222,7 +235,7 @@ An example of normalization:: year = timedelta(days=365) another_year = timedelta(weeks=40, days=84, hours=23, minutes=50, seconds=600) print(year == another_year) # True - print(year.total_seconds()) # 31536000 + print(year.total_seconds()) # 31536000.0 Examples of timedelta arithmetic:: @@ -486,7 +499,7 @@ subject to adjustment via a :class:`timezone` object. Constructors ^^^^^^^^^^^^ -.. class:: datetime(self, year, month, day, hour=0, minute=0, second=0, tzinfo=None) +.. class:: datetime(self, year, month, day, hour=0, minute=0, second=0, nanosecond=0, tzinfo=None) The *year*, *month* and *day* arguments are required. *tzinfo* may be ``None``, or an instance of a :class:`timezone` class. The remaining @@ -498,6 +511,7 @@ Constructors * ``0 <= hour < 24``, * ``0 <= minute < 60``, * ``0 <= second < 60``, + * ``0 <= nanosecond < 999_999_999``, If an argument outside those ranges is given, :exc:`ValueError` is raised. @@ -627,7 +641,7 @@ Class methods :class:`timedelta` object with magnitude less than one day. -.. method:: datetime.replace(year=None, month=None, day=None, hour=None, minute=None, second=None, tzinfo=True) +.. method:: datetime.replace(year=None, month=None, day=None, hour=None, minute=None, second=None, nanosecond=None, tzinfo=True) Return a :class:`datetime` with the same attributes, except for those attributes given new values by whichever keyword arguments are specified. @@ -682,7 +696,7 @@ Class methods .. method:: datetime.tuple() - Return the tuple ``(year, month, day, hour, minute, second, tzinfo)``. + Return the tuple ``(year, month, day, hour, minute, second, nanosecond, tzinfo)``. Examples of usage From 418c9a6f82c1352a14939ea0b02f0094112f2389 Mon Sep 17 00:00:00 2001 From: Lorenzo Cappelletti Date: Fri, 12 Nov 2021 14:45:12 +0100 Subject: [PATCH 4/6] docs/library/datetime.rst: Microsecond resolution. --- docs/library/datetime.rst | 49 ++++++++++++--------------------------- 1 file changed, 15 insertions(+), 34 deletions(-) diff --git a/docs/library/datetime.rst b/docs/library/datetime.rst index eae3f6d70af8a..0f6008f59f2c2 100644 --- a/docs/library/datetime.rst +++ b/docs/library/datetime.rst @@ -44,65 +44,46 @@ are mimicked with a class :class:`datetime` set to midnight, and a class -------------------------- A :class:`timedelta` object represents a duration, the difference between two -dates or times. With respect to the Python module -`datetime `_, -this implementation is constrained as follows: - - * Minimum resolution is *1 nanosecond*, instead of *1 microsecond*. - * Masimum delta spans over ±106751 days (±2\ :sup:`63` nanoseconds or - ±292 years) instead of ±999999999 days. +dates or times. Class attributes ^^^^^^^^^^^^^^^^ -.. attribute:: timedelta.MINYEAR - - The year of :attr:`timedelta.min`, i.e. - ``timedelta.min.tuple()[1] // (365 * 24 * 60 * 60 * 10**9) == -292``. - - -.. attribute:: timedelta.MAXYEAR - - The year of :attr:`timedelta.max`, i.e. - ``timedelta.max.tuple()[1] // (365 * 24 * 60 * 60 * 10**9) == 292``. - - .. attribute:: timedelta.min The most negative :class:`timedelta` object, - ``timedelta(nanoseconds=-2**63)``. + ``timedelta(days=-999_999_999)``. .. attribute:: timedelta.max The most positive :class:`timedelta` object, - ``timedelta(nanoseconds=2**63 - 1)``. + ``timedelta(days=999_999_999, hours=23, minutes=59, seconds=59, microseconds=999_999)``. .. attribute:: timedelta.resolution The smallest possible difference between non-equal :class:`timedelta` - objects, ``timedelta(nanoseconds=1)``. + objects, ``timedelta(microseconds=1)``. -.. attribute:: timedelta.nanoseconds +.. attribute:: timedelta.microseconds - The internal time delta representation as 64-bit integer. + The internal time delta representation as an integral number of microseconds. Class methods ^^^^^^^^^^^^^ .. class:: timedelta(hours=0, minutes=0, seconds=0, days=0, weeks=0, - milliseconds=0, microseconds=0, nanoseconds=0) + milliseconds=0, microseconds=0) All arguments are optional and default to ``0``. Arguments may be integers -or floats, and may be positive or negative. Only nanoseconds are stored +or floats, and may be positive or negative. Only microseconds are stored internally. Arguments are converted to those units: - * A microsecond is converted to 1000 nanoseconds. - * A millisecond is converted to 10\ :sup:`6` nanoseconds. + * A millisecond is converted to 1000 microseconds. * A minute is converted to 60 seconds. * An hour is converted to 3600 seconds. * A week is converted to 7 days. @@ -130,7 +111,7 @@ exact (no information is lost). .. method:: timedelta.__mul__(other) Return a delta multiplied by an integer or float. The result is rounded to - the nearest nanosecond using round-half-to-even. + the nearest microsecond using round-half-to-even. .. method:: timedelta.__truediv__(other) @@ -220,7 +201,7 @@ exact (no information is lost). .. method:: timedelta.tuple(sign_pos='') - Return the tuple ``(sign, days, hours, minutes, seconds, nanoseconds)``, + Return the tuple ``(sign, days, hours, minutes, seconds, microseconds)``, where ``sign`` is ``-`` if delta is negative, *sign_pos* otherwise. @@ -499,7 +480,7 @@ subject to adjustment via a :class:`timezone` object. Constructors ^^^^^^^^^^^^ -.. class:: datetime(self, year, month, day, hour=0, minute=0, second=0, nanosecond=0, tzinfo=None) +.. class:: datetime(self, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None) The *year*, *month* and *day* arguments are required. *tzinfo* may be ``None``, or an instance of a :class:`timezone` class. The remaining @@ -511,7 +492,7 @@ Constructors * ``0 <= hour < 24``, * ``0 <= minute < 60``, * ``0 <= second < 60``, - * ``0 <= nanosecond < 999_999_999``, + * ``0 <= microsecond < 999_999``, If an argument outside those ranges is given, :exc:`ValueError` is raised. @@ -641,7 +622,7 @@ Class methods :class:`timedelta` object with magnitude less than one day. -.. method:: datetime.replace(year=None, month=None, day=None, hour=None, minute=None, second=None, nanosecond=None, tzinfo=True) +.. method:: datetime.replace(year=None, month=None, day=None, hour=None, minute=None, second=None, microsecond=None, tzinfo=True) Return a :class:`datetime` with the same attributes, except for those attributes given new values by whichever keyword arguments are specified. @@ -696,7 +677,7 @@ Class methods .. method:: datetime.tuple() - Return the tuple ``(year, month, day, hour, minute, second, nanosecond, tzinfo)``. + Return the tuple ``(year, month, day, hour, minute, second, microsecond, tzinfo)``. Examples of usage From cf0c5ef06f5a4d287161cda0498f02d9344d67bc Mon Sep 17 00:00:00 2001 From: Lorenzo Cappelletti Date: Thu, 23 Dec 2021 06:18:00 +0100 Subject: [PATCH 5/6] docs/library/datetime.rst: Full update for new implementation. --- docs/library/datetime.rst | 1443 ++++++++++++++++++++++++++++--------- 1 file changed, 1090 insertions(+), 353 deletions(-) diff --git a/docs/library/datetime.rst b/docs/library/datetime.rst index 0f6008f59f2c2..f39dc3d079750 100644 --- a/docs/library/datetime.rst +++ b/docs/library/datetime.rst @@ -27,159 +27,203 @@ an optional time zone information attribute, *tzinfo*, that can be set to an instance of a :class:`timezone` class. These objects capture information about the offset from UTC time and the time zone name. -The following classes are provided: - -* :class:`timedelta` -* :class:`timezone` -* :class:`datetime` - -Python's classes `date() -`_ and `time() -`_ -are mimicked with a class :class:`datetime` set to midnight, and a class -:class:`timedelta` in the range [0-24h). +Constants +--------- -:class:`timedelta` Objects --------------------------- +The datetime module exports the following constants: -A :class:`timedelta` object represents a duration, the difference between two -dates or times. +.. data:: MINYEAR + The smallest year number allowed in a :class:`date` or :class:`datetime` + object. :const:`MINYEAR` is 1. -Class attributes -^^^^^^^^^^^^^^^^ -.. attribute:: timedelta.min +.. data:: MAXYEAR - The most negative :class:`timedelta` object, - ``timedelta(days=-999_999_999)``. + The largest year number allowed in a :class:`date` or :class:`datetime` + object. :const:`MAXYEAR` is 9 999. -.. attribute:: timedelta.max +Available Types +--------------- - The most positive :class:`timedelta` object, - ``timedelta(days=999_999_999, hours=23, minutes=59, seconds=59, microseconds=999_999)``. +The following classes are provided: +* :class:`timedelta`: a duration expressing the difference between two date, + time, or datetime instances to microsecond resolution. +* :class:`tzinfo`: an abstract base class for time zone information objects. + These are used by the :class:`!datetime` and :class:`!time` classes to + provide a customizable notion of time adjustment (for example, to account for + time zone and/or daylight saving time). +* :class:`timezone`: a class that implements the tzinfo abstract base class as + a fixed offset from the UTC. +* :class:`date`: an idealized naive date, assuming the current Gregorian + calendar always was, and always will be, in effect. +* :class:`time`: an idealized time, independent of any particular day, assuming + that every day has exactly 24*60*60 seconds. (There is no notion of “leap + seconds” here.) +* :class:`datetime`: a combination of a date and a time. + +Objects of these types are immutable. They are also *hashable*, meaning that +they can be used as dictionary keys. -.. attribute:: timedelta.resolution - - The smallest possible difference between non-equal :class:`timedelta` - objects, ``timedelta(microseconds=1)``. +:class:`timedelta` Objects +----------------------------------------------------------------------------- -.. attribute:: timedelta.microseconds +A :class:`!timedelta` object represents a duration, the difference between two +dates or times. With respect to the Python module `datetime +`_, this implementation +differs in: - The internal time delta representation as an integral number of microseconds. + * ``__repr__()`` produces a different, yet compatible, output. + * Delta is stored as a signed bignum integer of microseconds. -Class methods -^^^^^^^^^^^^^ +Constructors +^^^^^^^^^^^^ -.. class:: timedelta(hours=0, minutes=0, seconds=0, days=0, weeks=0, - milliseconds=0, microseconds=0) +.. class:: timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0) -All arguments are optional and default to ``0``. Arguments may be integers -or floats, and may be positive or negative. Only microseconds are stored -internally. Arguments are converted to those units: +All arguments are optional and default to ``0``. Arguments may be integers or +floats, and may be positive or negative. Arguments are "merged" and normalized +into microseconds according to the following conversions: - * A millisecond is converted to 1000 microseconds. - * A minute is converted to 60 seconds. - * An hour is converted to 3600 seconds. * A week is converted to 7 days. + * A day is converted to 24 hours. + * An hour is converted to 60 minutes. + * A minute is converted to 60 seconds. + * A second is converted to 1000 milliseconds. + * A millisecond is converted to 1000 microseconds. If no argument is a float, the conversion and normalization processes are exact (no information is lost). +Note that normalization of negative values may be surprising at first. For +example:: -.. method:: timedelta.total_seconds() - - Return a float representing the total number of seconds contained in the duration. - - -.. method:: timedelta.__add__(other) - - Return a :class:`timedelta` which represents the sum of two durations. - - -.. method:: timedelta.__sub__(other) - - Return a :class:`timedelta` which represents the difference between - two durations. - - -.. method:: timedelta.__mul__(other) - - Return a delta multiplied by an integer or float. The result is rounded to - the nearest microsecond using round-half-to-even. - - -.. method:: timedelta.__truediv__(other) - - When *other* is a float or an integer, returns a delta divided by *other*. - The result is rounded to the nearest multiple of timedelta.resolution - using round-half-to-even. - - When *other* is a delta, division of overall duration by interval unit - *other*. Returns a float object. - - -.. method:: timedelta.__floordiv__(other) - - The floor is computed and the remainder (if any) is thrown away. When - *other* is a delta, an integer is returned. - - -.. method:: timedelta.__mod__(other) - - The remainder is computed as a :class:`timedelta` object. + >>> from datetime import timedelta + >>> td = timedelta(hours=-1) + >>> days, hours, minutes, seconds, microseconds = td.tuple() + >>> days, hours, minutes, seconds, microseconds + (-1, 23, 0, 0, 0) -.. method:: timedelta.__divmod__(other) - - Computes the quotient and the remainder: ``q = td1.__floordiv__(td2)`` and - ``r = td1.__mod__(td2)``. ``q`` is an integer and ``r`` is a :class:`timedelta` - object. - - -.. method:: timedelta.__neg__() - - Equivalent to ``td1.__mul__(-1)``. - - -.. method:: timedelta.__eq__(other) - - Equivalent to ``td1.total_seconds() == td2.total_seconds()``. - - -.. method:: timedelta.__le__(other) - - Equivalent to ``td1.total_seconds() <= td2.total_seconds()``. +Class attributes +^^^^^^^^^^^^^^^^ +.. attribute:: timedelta.min -.. method:: timedelta.__lt__(other) + The most negative :class:`timedelta` object, ``timedelta(-999999999)``. - Equivalent to ``td1.total_seconds() < td2.total_seconds()``. +.. attribute:: timedelta.max -.. method:: timedelta.__ge__(other) + The most positive :class:`timedelta` object, ``timedelta(days=999_999_999, + hours=23, minutes=59, seconds=59, microseconds=999_999)``. - Equivalent to ``td1.total_seconds() >= td2.total_seconds()``. +.. attribute:: timedelta.resolution -.. method:: timedelta.__gt__(other) + The smallest possible difference between non-equal :class:`timedelta` + objects, ``timedelta(microseconds=1)``. - Equivalent to ``td1.total_seconds() > td2.total_seconds()``. +.. attribute:: timedelta.days +.. attribute:: timedelta.seconds +.. attribute:: timedelta.microseconds -.. method:: timedelta.__bool__() + Days (between -999 999 999 and 999 999 999 inclusive), seconds (between 0 + and 86 399 inclusive) and microseconds (between 0 and 999 999 inclusive) + representing the time delta. If you need two or more of them, consider using + :meth:`~timedelta.tuple` instead. + + +Operations +^^^^^^^^^^ + +The class support a number of operators. + + +Comparison operators +"""""""""""""""""""" + ++-------------------------------+---------------------------------------------------------------------------------------+ +| Operation | Result | ++===============================+=======================================================================================+ +| ``td`` | True when *td.microseconds* is not 0. | ++-------------------------------+---------------------------------------------------------------------------------------+ +| ``td1 < td2`` | True when *td1.microseconds* is less than, less or equal to, equal to, not equal to, | ++-------------------------------+ greater or equal to, greater than *td2.microseconds*. False otherwise. | +| ``td1 <= td2`` | | ++-------------------------------+ | +| ``td1 == td2`` | | ++-------------------------------+ | +| ``td1 != td2`` | | ++-------------------------------+ | +| ``td1 >= td2`` | | ++-------------------------------+ | +| ``td1 > td2`` | | ++-------------------------------+---------------------------------------------------------------------------------------+ + + +Arithmetic operators +"""""""""""""""""""" + ++-------------------------------+---------------------------------------------------------------------------------------+ +| Operation | Result | ++===============================+=======================================================================================+ +| ``+td1`` | A :class:`timedelta` with the same value. | ++-------------------------------+---------------------------------------------------------------------------------------+ +| ``-td1`` | A :class:`timedelta` equivalent to *-1 * td1*. | ++-------------------------------+---------------------------------------------------------------------------------------+ +| ``td3 = td1 + td2`` | A :class:`timedelta`, sum of *t1* and *t2*. Afterwards, *td1 == td3 - td2*. | ++-------------------------------+---------------------------------------------------------------------------------------+ +| ``td3 = td1 - td2`` | A :class:`timedelta`, difference of *t1* and *t2*. Same as *td1 + (-td2)*. | ++-------------------------------+---------------------------------------------------------------------------------------+ +| | ``td2 = i * td1`` | A :class:`timedelta`, *i* times greater than *td1*. Afterwards, *td1 // i == td2*. | +| | ``td2 = td1 * i`` | | ++-------------------------------+---------------------------------------------------------------------------------------+ +| ``td2 = f * td1`` | A :class:`timedelta` rounded to the nearest microsecond using round-half-to-even. | ++-------------------------------+---------------------------------------------------------------------------------------+ +| ``f = td2 / td1`` | A :class:`float`, division of overall duration *td2* by interval unit *td1*. | ++-------------------------------+---------------------------------------------------------------------------------------+ +| | ``td2 = td1 / i`` | A :class:`timedelta`, division of a float or an int. The result is rounded to the | +| | ``td2 = td1 / f`` | nearest microsecond using round-half-to-even. | ++-------------------------------+---------------------------------------------------------------------------------------+ +| ``td2 = td1 // i`` | A :class:`timedelta`, floor of the integer division (remainder is discarded). | ++-------------------------------+---------------------------------------------------------------------------------------+ +| ``td3 = td2 // td1`` | An integer, floor of the integer division (remainder is discarded). | ++-------------------------------+---------------------------------------------------------------------------------------+ +| ``td3 = td2 % td1`` | A :class:`timedelta`, remainder of the integer division. | ++-------------------------------+---------------------------------------------------------------------------------------+ +| ``q, r = divmod(td1, td2)`` | Computes the quotient and the remainder: ``q = t1 // t2`` and ``r = t1 % t2``. | ++-------------------------------+---------------------------------------------------------------------------------------+ +| ``abs(td)`` | A :class:`timedelta` equivalent to *+td* when ``td.days >= 0`` and to *-td* otherwise.| ++-------------------------------+---------------------------------------------------------------------------------------+ + + +Other operators +""""""""""""""" + ++-------------------------------+---------------------------------------------------------------------------------------+ +| Operation | Result | ++===============================+=======================================================================================+ +| ``str(td)`` | A string in the form ``[[-]D day[s], ][H]H:MM:SS[.UUUUUU]``. | ++-------------------------------+---------------------------------------------------------------------------------------+ +| ``repr(td)`` | A string representation of a constructor call with canonical attribute values. | ++-------------------------------+---------------------------------------------------------------------------------------+ +| ``hash(td)`` | The hash number for dictionary keys. | ++-------------------------------+---------------------------------------------------------------------------------------+ - Return ``False`` when duration is ``0``. +Class methods +^^^^^^^^^^^^^ -.. method:: timedelta.__abs__() +.. method:: timedelta.total_seconds() - Return a positive delta. + Return a float representing the total number of seconds contained in the duration. .. method:: timedelta.isoformat() @@ -195,7 +239,7 @@ exact (no information is lost). the sign of the delta and ``D`` its number of days. This is *not* ISO compliant, but provides a complete representation. - If the fractional part of :meth:`timedelta.total_seconds()` is not 0, + If the fractional part of :meth:`~timedelta.total_seconds()` is not 0, ``.ffffff`` is appended. @@ -210,7 +254,7 @@ Examples of usage An example of normalization:: - import datetime.timedelta + from datetime import timedelta # Components of another_year add up to exactly 365 days year = timedelta(days=365) @@ -221,7 +265,7 @@ An example of normalization:: Examples of timedelta arithmetic:: - import datetime.timedelta + from datetime import timedelta year = timedelta(days=365) ten_years = year * 10 @@ -232,148 +276,141 @@ Examples of timedelta arithmetic:: print(three_years) # 1095d 00:00:00 -:class:`timezone` Objects -------------------------- +:class:`tzinfo` Objects +----------------------------------------------------------------------------- -The :class:`timezone` class represents a timezone defined by a fixed -offset from UTC. Define a subclass of :class:`timezone` to capture +This is an abstract base class, meaning that this class should not be +instantiated directly. Define a subclass of :class:`!tzinfo` to capture information about a particular time zone. -An instance of :class:`timezone` can be passed to the constructors for -:class:`datetime`. The latter objects view their attributes as being in -local time, and the :class:`timezone` object supports methods revealing -offset of local time from UTC, the name of the time zone, and DST offset, -all relative to a date-time object passed to them. +An instance of (a concrete subclass of) :class:`!tzinfo` can be passed to the +constructors for :class:`datetime` and :class:`time` objects. The latter +objects view their attributes as being in local time, and the :class:`!tzinfo` +object supports methods revealing offset of local time from UTC, the name of +the time zone, and DST offset, all relative to a date or time object passed to +them. +The :mod:`datetime` module provides :class:`timezone`, a simple concrete +subclass of :class:`!tzinfo` which can represent timezones with fixed offset +from UTC such as UTC. -Methods to customize -^^^^^^^^^^^^^^^^^^^^ +A concrete subclass of :class:`!tzinfo` may need to implement the following +methods. Exactly which methods are needed depends on the uses made of aware +:mod:`datetime` objects. If in doubt, simply implement all of them. -A subclass of :class:`timezone` may need to override the following methods. -Exactly which methods are needed depends on the uses made of aware -:class:`datetime` objects. If in doubt, simply implement all of them. +.. method:: tzinfo.tzname(dt) -.. method:: timezone.utcoffset(dt) - - Return offset of local time from UTC, as a :class:`timedelta` object - that is positive east of UTC. If local time is west of UTC, this should - be negative. + Return the time zone name corresponding to the :class:`datetime` object + *dt*, as a string. Return ``None`` if a string name isn't known. - This represents the *total* offset from UTC; for example, if a - :class:`timezone` object represents both time zone and DST adjustments, - :meth:`timezone.utcoffset` should return their sum. If the UTC offset - isn’t known, return ``None``. Else the value returned must be a - :class:`timedelta` object strictly between ``timedelta(hours=-24)`` and - ``timedelta(hours=24)`` (the magnitude of the offset must be less than one - day). Most implementations of :meth:`timezone.utcoffset` will probably - look like one of these two: + If the :class:`tzinfo` class is accounting for daylight time, this method + will likely return different names depending on the specific value of *dt* + passed. - return CONSTANT # fixed-offset class - return CONSTANT + self.dst(dt) # daylight-aware class + The default implementation raises :exc:`NotImplementedError`. - If :meth:`timezone.utcoffset` does not return ``None``, :meth:`timezone.dst` - should not return None either. - The default implementation of :meth:`timezone.utcoffset` returns the sum - of time zone and DST adjustments, if available. +.. method:: tzinfo.utcoffset(dt) -.. method:: timezone.dst(dt) + Return offset of local time from UTC, as a :class:`timedelta` object that is + positive east of UTC. If local time is west of UTC, this should be negative. - Return the daylight saving time (DST) adjustment, as a :class:`timedelta` - object or ``None`` if DST information isn’t known. + This represents the *total* offset from UTC; for example, if a + :class:`tzinfo` object represents both time zone and DST adjustments, + :meth:`utcoffset` should return their sum. If the UTC offset isn't known, + return ``None``. Else the value returned must be a :class:`timedelta` object + strictly between ``timedelta(hours=-24)`` and ``timedelta(hours=24)``. Most + implementations of :meth:`utcoffset` will probably look like one of these + two:: - Return ``timedelta(0)`` if DST is not in effect. If DST is in effect, return - the offset as a :class:`timedelta` object (see :meth:`timezone.utcoffset` - for details). Note that DST offset, if applicable, has already been added - to the UTC offset returned by :meth:`timezone.utcoffset`, so there’s no - need to consult :meth:`timezone.dst` unless you’re interested in obtaining - DST info separately. + return CONSTANT # fixed-offset class + return CONSTANT + self.dst(dt) # daylight-aware class - Most implementations of :meth:`timezone.dst` will probably look like one - of these two:: + If :meth:`utcoffset` does not return ``None``, :meth:`dst` should not return + ``None`` either. - def dst(self, dt): - # a fixed-offset class: doesn't account for DST - return timedelta(0) + The default implementation raises :exc:`NotImplementedError`. - or:: - def dst(self, dt): - # Code to set dston and dstoff to the time zone's DST - # transition times based on the input *dt*'s year, and - # expressed in standard local time. +.. method:: tzinfo.dst(dt) - dt_ = dt.replace(tzinfo=None) - if dt_ >= dston and dt_ < dstoff: - return timedelta(hours=1) - else: - return timedelta(0) - - The default implementation of :meth:`timezone.dst` returns ``None``. + Return the daylight saving time (DST) adjustment, as a :class:`timedelta` + object or ``None`` if DST information isn't known. + Return ``timedelta(0)`` if DST is not in effect. If DST is in effect, return + the offset as a :class:`timedelta` object (see :meth:`utcoffset` for + details). Note that DST offset, if applicable, has already been added to the + UTC offset returned by :meth:`utcoffset`, so there's no need to consult + :meth:`dst` unless you're interested in obtaining DST info separately. For + example, :meth:`datetime.timetuple` calls its :attr:`~datetime.tzinfo` + attribute's :meth:`dst` method to determine how the :attr:`tm_isdst` flag + should be set. -.. method:: timezone.tzname(dt) + Most implementations of :meth:`dst` will probably look like one of these + two:: - Return the time zone name corresponding to the :class:`datetime` object - *dt*, as a string. Nothing about string names is defined by the - :class:`datetime` module, and there’s no requirement that it mean anything - in particular. For example, “GMT”, “UTC”, “-500”, “-5:00”, “EDT”, - “US/Eastern”, “America/New York” are all valid replies. Return ``None`` if - a string name isn’t known. Note that this is a method rather than a fixed - string primarily because some :class:`timezone` subclasses will wish to - return different names depending on the specific value of *dt* passed, - especially if the :class:`timezone` class is accounting for daylight time. - - The default implementation of :meth:`timezone.tzname` returns the fixed - value specified when the :class:`timezone` instance is constructed. - If *name* is not provided in the constructor, the name returned by - ``tzname()`` is generated from the value of the ``offset`` as follows. - If *offset* is ``timedelta(0)``, the name is “UTC”, otherwise it returns - the string provided by :meth:`timezone.isoformat` method. - -These methods are called by a :class:`datetime` object, in response to their -methods of the same names. A :class:`datetime` object passes *self* as *dt* -argument. + def dst(self, dt): + # a fixed-offset class: doesn't account for DST + return timedelta(0) + or:: -Class attributes -^^^^^^^^^^^^^^^^ + def dst(self, dt): + # Code to set dston and dstoff to the time zone's DST + # transition times based on the input dt.year, and expressed + # in standard local time. -.. attribute:: timezone.utc + if dston <= dt.replace(tzinfo=None) < dstoff: + return timedelta(hours=1) + else: + return timedelta(0) - The UTC timezone, ``timezone(timedelta(0))``. + The default implementation raises :exc:`NotImplementedError`. -Class methods -^^^^^^^^^^^^^ +These methods are called by a :class:`datetime` or :class:`time` object, in +response to their methods of the same names. A :class:`datetime` object passes +itself as the argument, and a :class:`time` object passes ``None`` as the +argument. A :class:`tzinfo` subclass's methods should therefore be prepared to +accept a *dt* argument of ``None``, or of class :class:`datetime`. -.. class:: timezone(offset, name=None) +When ``None`` is passed, it's up to the class designer to decide the best +response. For example, returning ``None`` is appropriate if the class wishes to +say that time objects don't participate in the :class:`tzinfo` protocols. It +may be more useful for ``utcoffset(None)`` to return the standard UTC offset, +as there is no other convention for discovering the standard offset. - The *offset* argument must be specified as a :class:`timedelta` - object representing the difference between the local time and UTC. - It must be strictly between ``timedelta(hours=-24)`` and - ``timedelta(hours=24)``, otherwise :exc:`ValueError` is raised. +When a :class:`datetime` object is passed in response to a :class:`datetime` +method, ``dt.tzinfo`` is the same object as *self*. :class:`tzinfo` methods can +rely on this, unless user code calls :class:`tzinfo` methods directly. The +intent is that the :class:`tzinfo` methods interpret *dt* as being in local +time, and not need worry about objects in other timezones. - The *name* argument is optional. If specified it must be a string - that will be used as the value returned by the :meth:`datetime.tzname` - method. +There is one more :class:`tzinfo` method that a subclass may wish to override: +.. method:: tzinfo.fromutc(dt) -.. method:: timezone.isoformat(dt) + This is called from the default :class:`datetime.astimezone()` + implementation. When called from that, ``dt.tzinfo`` is *self*, and *dt*'s + date and time data are to be viewed as expressing a UTC time. The purpose of + :meth:`fromutc` is to adjust the date and time data, returning an equivalent + datetime in *self*'s local time. - Return a string in the format ``UTC±HH:MM``, where ``±`` is the sign of - *offset* from UTC, ``HH`` and ``MM`` are two digits of offset's hours and - offset's minutes respectively. If *offset* is ``timedelta(0)``, “UTC” - is returned. + Most :class:`tzinfo` subclasses should be able to inherit the default + :meth:`fromutc` implementation without problems. It's strong enough to + handle fixed-offset time zones, and time zones accounting for both standard + and daylight time, and the latter even if the DST transition times differ in + different years. - If *utc* is ``False``, this method always returns ``±HH:MM``. + The default implementations of :meth:`astimezone` and :meth:`fromutc` may + not produce the result you want if the result is one of the hours straddling + the moment the standard offset changes. Such cases must be computed and + handled by a user's implementation via :attr:`datetime.fold`. - *dt* is needed in determining the right offset; it can be ``None``. - -Examples of usage -^^^^^^^^^^^^^^^^^ +Example of usage +^^^^^^^^^^^^^^^^ `Central European Time `_ (CET), used in most parts of Europe and a few North African countries, is a @@ -383,43 +420,49 @@ those that during the winter use CET use Central European Summer Time (CEST) (or: UTC+02:00, daylight saving time) in summer (from last Sunday of March to last Sunday of October). :: - import datetime - - class Cet(datetime.timezone): - def __init__(self): - super().__init__(datetime.timedelta(hours=1), "CET") + class Cet(tzinfo): + def utcoffset(self, dt): + h = 2 if self.isdst(dt)[0] else 1 + return timedelta(hours=h) def dst(self, dt): - return datetime.timedelta(hours=1) if self.isdst(dt) else datetime.timedelta(0) + h = 1 if self.isdst(dt)[0] else 0 + return timedelta(hours=h) def tzname(self, dt): - return 'CEST' if self.isdst(dt) else 'CET' + return "CEST" if self.isdst(dt)[0] else "CET" + + def fromutc(self, dt): + assert dt.tzinfo is self + isdst, fold = self.isdst(dt, utc=True) + h = 2 if isdst else 1 + dt += timedelta(hours=h) + dt = dt.replace(fold=fold) + return dt - def isdst(self, dt): + def isdst(self, dt, utc=False): if dt is None: - return False - year, month, day, hour, minute, second, tz = dt.tuple() + return False, None + + year = dt.year if not 2000 <= year < 2100: + # Formulas below are valid in the range [2000; 2100) raise ValueError - if 3 < month < 10: - return True - if month == 3: - beg = 31 - (5*year//4 + 4) % 7 # last Sunday of March - if day < beg: return False - if day > beg: return True - return hour >= 3 - if month == 10: - end = 31 - (5*year//4 + 1) % 7 # last Sunday of October - if day < end: return True - if day > end: return False - return hour < 3 - return False - - tz = Cet() - print(tz.isoformat(datetime(2011, 1, 1))) # UTC+01:00 - print(tz.tzname (datetime(2011, 1, 1))) # CET - print(tz.isoformat(datetime(2011, 8, 1))) # UTC+02:00 - print(tz.tzname (datetime(2011, 8, 1))) # CEST + + hour = 1 if utc else 3 + day = 31 - (5 * year // 4 + 4) % 7 # last Sunday of March + beg = datetime(year, 3, day, hour) + day = 31 - (5 * year // 4 + 1) % 7 # last Sunday of October + end = datetime(year, 10, day, hour) + + dt = dt.replace(tzinfo=None) + if utc: + fold = 1 if end <= dt < end + timedelta(hours=1) else 0 + else: + fold = dt.fold + isdst = beg <= dt < end + return isdst, fold + The two formulas above are a simplification of the general `Gauss's algorithm (disparate variation) @@ -463,24 +506,514 @@ which produces the following output for March and October:: w(year) = (5*year//4 + 1) % 7 # 2000 <= year < 2100 +:class:`timezone` Objects +----------------------------------------------------------------------------- + +The :class:`!timezone` class is a subclass of :class:`tzinfo`, each instance of +which represents a timezone defined by a fixed offset from UTC. + +An instance of :class:`!timezone` can be passed to the constructors for +:class:`datetime` and :class:`time`. The latter objects view their attributes +as being in local time, and the :class:`!timezone` object supports methods +revealing offset of local time from UTC, the name of the time zone, and DST +offset, all relative to a date-time object passed to them. + + +Constructors +^^^^^^^^^^^^ + +.. class:: timezone(offset, name=None) + + The *offset* argument must be specified as a :class:`timedelta` object + representing the difference between the local time and UTC. It must be + strictly between ``-timedelta(hours=24)`` and ``timedelta(hours=24)``, + otherwise :exc:`ValueError` is raised. + + The *name* argument is optional. If specified it must be a string. + + +Class attributes +^^^^^^^^^^^^^^^^ + +.. attribute:: timezone.utc + + The UTC timezone, ``timezone(timedelta(0))``. + + +Class methods +^^^^^^^^^^^^^ + +.. method:: timezone.utcoffset(dt) + + Return the fixed value specified when the :class:`timezone` instance is + constructed. + + The *dt* argument is ignored. The return value is a :class:`timedelta` + instance equal to the difference between the local time and UTC. + +.. method:: timezone.dst(dt) + + Always returns ``None``. + +.. method:: timezone.tzname(dt) + + Return the fixed value specified when the :class:`timezone` instance is + constructed. + + If *name* is not provided in the constructor, the name returned by + ``tzname(dt)`` is generated from the value of the ``offset`` as a string in + the format ``UTC±HH:MM``. + +.. method:: timezone.fromutc(dt) + + Return ``dt + offset``. The *dt* argument must be an aware + :class:`datetime` instance, with ``tzinfo`` set to ``self``. + + +:class:`date` Objects +----------------------------------------------------------------------------- + +A :class:`!date` object represents a date (year, month and day). :class:`!date` +assumes the current Gregorian calendar extended in both directions, past and +future. January 1 of year 1 is called day number 1, January 2 of year 1 is +called day number 2, and so on. + +With respect to the Python module `datetime +`_, this implementation +differs in: + + * ``__repr__()`` produces a different, yet compatible, output. + * ``ctime()``, ``strftime()`` and ``__format__()`` are not implemented. + * ``fromisocalendar()`` and ``isocalendar()`` are not implemented. + + +Constructors +^^^^^^^^^^^^ + +.. class:: date(year, month, day) + + All arguments are required. Arguments must be integers, in the following + ranges: + + * ``MINYEAR <= year <= MAXYEAR`` + * ``1 <= month <= 12`` + * ``1 <= day <= number of days in the given month and year`` + + If an argument outside those ranges is given, :exc:`ValueError` is raised. + + +.. classmethod:: date.fromtimestamp(timestamp) + + Return the local date corresponding to the POSIX timestamp, such as is + returned by :func:`time.time`. + + +.. classmethod:: date.today() + + Return the current local date. This is equivalent to + ``date.fromtimestamp(time.time())``. + + +.. classmethod:: date.fromordinal(ordinal) + + Return a :class:`date` corresponding to the proleptic Gregorian ordinal, + where January 1 of year 1 has ordinal 1. + + +.. classmethod:: date.fromisoformat(date_string) + + Return a :class:`date` corresponding to a *date_string* given in the format + ``YYYY-MM-DD``. + + +Class attributes +^^^^^^^^^^^^^^^^ + +.. attribute:: date.min +.. attribute:: date.max + + The earliest (``date(MINYEAR, 1, 1)``) and the latest (``date(MAXYEAR, 12, + 31)``) representable :class:`date`. + + +.. attribute:: date.resolution + + The smallest possible difference between non-equal date objects, + ``timedelta(days=1)``. + +.. attribute:: date.year +.. attribute:: date.month +.. attribute:: date.day + + Year (between :const:`MINYEAR` and :const:`MAXYEAR` inclusive), month + (between 1 and 12 inclusive) and day (between 1 and the number of days in + the given month of the given year) representing the date. If you need two or + more of them, consider using :meth:`~date.tuple` instead. + + +Operations +^^^^^^^^^^ + +The class support a number of operators. + + +Comparison operators +"""""""""""""""""""" + ++---------------------+---------------------------------------------------------------------------------+ +| Operation | Result | ++=====================+=================================================================================+ +| ``d1 < d2`` | True when *t1.toordinal()* is less than, less or equal to, greater or equal to, | ++---------------------+ greater than *t2.toordinal()*. False otherwise. | +| ``d1 <= d2`` | | ++---------------------+ | +| ``d1 >= d2`` | | ++---------------------+ | +| ``d1 > d2`` | | ++---------------------+---------------------------------------------------------------------------------+ +| ``d1 == d2`` | Same as above, but it returns :const:`False` (:const:`True`) even when *d2* is | ++---------------------+ not a :class:`date`. | +| ``d1 != d2`` | | ++---------------------+---------------------------------------------------------------------------------+ + + + +Arithmetic operators +"""""""""""""""""""" + ++---------------------+---------------------------------------------------------------------------------+ +| Operation | Result | ++=====================+=================================================================================+ +| ``d2 = d1 + td`` | *d2* is moved forward (if *td.days > 0*) or backward (if *td.days < 0*) in | +| | time. Afterward *d2 - d1 == td.days*. *td.seconds* and *td.microseconds* are | +| | ignored. | ++---------------------+---------------------------------------------------------------------------------+ +| ``d2 = d1 - td`` | *d2* is moved backward (if *td.days > 0*) or forward (if *td.days < 0*) in | +| | time. Afterward *d2 + td.days == d1*. *td.seconds* and *td.microseconds* are | +| | ignored. | ++---------------------+---------------------------------------------------------------------------------+ +| ``td = d2 - d1`` | A :class:`timedelta`, such that *d1 + td == d2*. *td.seconds* and | +| | *td.microseconds* are always 0. | ++---------------------+---------------------------------------------------------------------------------+ + + +Other operators +""""""""""""""" + ++---------------------+---------------------------------------------------------------------------------+ +| Operation | Result | ++=====================+=================================================================================+ +| ``str(d)`` | A string in the form returned by *d.isoformat()* (see :meth:`~date.isoformat`). | ++---------------------+---------------------------------------------------------------------------------+ +| ``repr(d)`` | A string representation of a constructor call with canonical attribute values. | ++---------------------+---------------------------------------------------------------------------------+ +| ``hash(d)`` | The hash number for dictionary keys. | ++---------------------+---------------------------------------------------------------------------------+ + + +Class methods +^^^^^^^^^^^^^ + +.. method:: date.toordinal() + + Return the proleptic Gregorian ordinal of the date, where January 1 of year + 1 has ordinal 1. For any :class:`date` object *d*, + ``date.fromordinal(d.toordinal()) == d``. + + +.. method:: date.timetuple() + + Return a tuple such as returned by :func:`time.localtime`. The hours, + minutes and seconds are 0, and the DST flag is -1. + + +.. method:: date.replace(year=None, month=None, day=None) + + Return a :class:`date` with the same value, except for those parameters + given new values by whichever keyword arguments are specified. + + +.. method:: date.weekday() + + Return the day of the week as an integer, where Monday is 0 and Sunday is 6. + + +.. method:: date.isoweekday() + + Return the day of the week as an integer, where Monday is 1 and Sunday is 7. + + +.. method:: date.isoformat() + + Return a string representing the date in ISO 8601 format, ``YYYY-MM-DD``. + This is the inverse of :meth:`~date.fromisoformat`. + + +.. method:: date.tuple() + + Return the tuple of attributes ``(year, month, day)``. + + This method should be preferred when two or more attributes are required + because it is less computationally intesive than getting each attribute + separately. + + +:class:`time` Objects +----------------------------------------------------------------------------- + +A :class:`!time` object represents a (local) time of day, independent of any +particular day, and subject to adjustment via a :class:`tzinfo` object. + +With respect to the Python module `datetime +`_, this implementation +differs in: + + * ``__repr__()`` produces a different, yet compatible, output. + * ``__format__()`` is not implemented. + * ``strftime()`` and ``__format__()`` are not implemented. + + +Constructors +^^^^^^^^^^^^ + +.. class:: time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0) + + All arguments are optional. *tzinfo* may be ``None``, or an instance of a + :class:`tzinfo` subclass. The remaining arguments must be integers in the + following ranges: + + * ``0 <= hour < 24``, + * ``0 <= minute < 60``, + * ``0 <= second < 60``, + * ``0 <= microsecond < 1_000_000``, + * ``fold in [0, 1]`` (see :attr:`~time.fold`). + + If an argument outside those ranges is given, :exc:`ValueError` is raised. + + +.. classmethod:: time.fromisoformat(time_string) + + Return a :class:`time` corresponding to a *time_string* in one of the + formats emitted by :meth:`~time.isoformat`. Specifically, this function + supports strings in the format: + + .. code-block:: none + + HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]] + + +Class attributes +^^^^^^^^^^^^^^^^ + +.. attribute:: time.min +.. attribute:: time.max + + The earliest (``time(0, 0, 0, 0)``) and the latest (``time(23, 59, 59, + 999_999)``) representable :class:`time`. + + +.. attribute:: time.resolution + + The smallest possible difference between non-equal :class:`time` objects, + ``timedelta(microseconds=1)``, although note that arithmetic on + :class:`time` objects is not supported. + + +.. attribute:: time.hour +.. attribute:: time.minute +.. attribute:: time.second +.. attribute:: time.microsecond + + Hour (in ``range(24)``), minute (in ``range(60)``), second (in + ``range(60)``), microsecond (in ``range(1_000_000)``) representing the time. + If you need two or more of them, consider using :meth:`~time.tuple` instead. + + +.. attribute:: time.tzinfo + + The object passed as the tzinfo argument to the :class:`time` constructor, + or ``None`` if none was passed. See also :meth:`~time.tuple`. + + +.. attribute:: time.fold + + In ``[0, 1]``. Used to disambiguate wall times during a repeated interval. + The value 0 (1) represents the earlier (later) of the two moments with the + same wall time representation. + + A repeated interval occurs when clocks are rolled back at the end of + daylight saving time (DST), typically in Autumn. Consider a timezone whose + DST ends the minute after 1:59 on the last Sunday of October. There's an + hour that can't be spelled unambiguously in local wall time: the last hour + of daylight time. The local wall clock leaps from 1:59 (daylight time) back + to 1:00 (standard time) again. Local times of the form 1:MM are ambiguous. + + Applications that can't bear wall-time ambiguities should explicitly check + the value *fold* attribute or avoid using hybrid :class:`tzinfo` subclasses. + + There are no ambiguities when using :class:`timezone` or any other + **fixed-offset** :class:`tzinfo` subclass. + + See also :meth:`~time.tuple`. + + +Operations +^^^^^^^^^^ + +The class support a number of operators. + + +Comparison operators +"""""""""""""""""""" + ++---------------------+---------------------------------------------------------------------------------+ +| Operation | Result | ++=====================+=================================================================================+ +| ``t1 < t2`` | Both *t1* and *t2* must be naive or aware datetime objects. When both are | +| | naive, or both are aware and have the same :attr:`~time.tzinfo`, operands | ++---------------------+ return: true when *t1.total_seconds()* is less or greater than | +| ``t1 <= t2`` | *t2.total_seconds()*; when equal, true is returned for operators ``<=`` and | +| | ``>=``. Otherwise, they evaluate to :const:`False`. | ++---------------------+ | +| ``t1 >= t2`` | When both comparands are aware and their :attr:`~time.tzinfo` differs, they are | +| | first adjusted by subtracting their UTC offsets (obtained from | ++---------------------+ :meth:`~time.utcoffset`). The comparison then proceeds as above. | +| ``t1 > t2`` | | +| | When one comparand is naive and the other is aware, :exc:`TypeError` is raised. | ++---------------------+---------------------------------------------------------------------------------+ +| ``t1 == t2`` | Same as above, but *total_seconds()* is compared for (in)equality. | +| | | ++---------------------+ Plus, when one comparand is naive and the other is aware, operations evaluate | +| ``t1 != t2`` | to :const:`False` for ``==`` and to :const:`True` for ``!=``. No exception is | +| | raised. | ++---------------------+---------------------------------------------------------------------------------+ + + +Arithmetic operators +"""""""""""""""""""" + +No arithmetic operations are allowed. + + +Other operators +""""""""""""""" + ++---------------------+---------------------------------------------------------------------------------+ +| Operation | Result | ++=====================+=================================================================================+ +| ``str(t)`` | A string in the form returned by *t.isoformat()* (see :meth:`~time.isoformat`). | ++---------------------+---------------------------------------------------------------------------------+ +| ``repr(t)`` | A string representation of a constructor call with canonical attribute values. | ++---------------------+---------------------------------------------------------------------------------+ +| ``hash(t)`` | The hash number for dictionary keys. | ++---------------------+---------------------------------------------------------------------------------+ + + +Class methods +^^^^^^^^^^^^^ + +.. method:: time.replace(hour=None, minute=None, second=None, \ + microsecond=None, tzinfo=True, *, fold=0) + + Return a :class:`time` with the same value, except for those attributes + given new values by whichever keyword arguments are specified. Note that + ``tzinfo=None`` can be specified to create a naive :class:`time` from an + aware :class:`time`, without conversion of the time data. + + +.. method:: time.isoformat(timespec="auto") + + Return a string representing the time in ISO 8601 format, one of: + + - ``HH:MM:SS.ffffff``, if :attr:`~time.microsecond` is not 0 + - ``HH:MM:SS``, if :attr:`~time.microsecond` is 0 + - ``HH:MM:SS.ffffff+HH:MM[:SS[.ffffff]]``, if :meth:`~time.utcoffset` does + not return ``None`` + - ``HH:MM:SS+HH:MM[:SS[.ffffff]]``, if :attr:`~time.microsecond` is 0 and + :meth:`~time.utcoffset` does not return ``None`` + + The optional argument *timespec* specifies the number of additional + components of the time to include (the default is ``"auto"``). It can be one + of the following: + + - ``"auto"``: same as ``"seconds"`` if :attr:`~time.microsecond` is 0, same + as ``"microseconds"`` otherwise. + - ``"hours"``: include the :attr:`~time.hour` in the two-digit ``HH`` + format. + - ``"minutes"``: include :attr:`~time.hour` and :attr:`~time.minute` in + ``HH:MM`` format. + - ``"seconds"``: include :attr:`~time.hour`, :attr:`~time.minute`, and + :attr:`~time.second` in ``HH:MM:SS`` format. + - ``"milliseconds"``: include full time, but truncate fractional second part + to milliseconds. ``HH:MM:SS.sss`` format. + - ``"microseconds"``: include full time in ``HH:MM:SS.ffffff`` format. + + .. note:: + + Excluded time components are truncated, not rounded. + + +.. method:: time.utcoffset() + + If :attr:`~time.tzinfo` is ``None``, returns ``None``, else returns + ``self.tzinfo.utcoffset(None)``. + + +.. method:: time.dst() + + If :attr:`~time.tzinfo` is ``None``, returns ``None``, else returns + ``self.tzinfo.dst(None)``. + + +.. method:: time.tzname() + + If :attr:`~time.tzinfo` is ``None``, returns ``None``, else returns + ``self.tzinfo.tzname(None)``. + + +.. method:: time.tuple() + + Return the tuple of attributes ``(hour, minute, second, microsecond, tzinfo, + fold)``. + + This method should be preferred when two or more attributes are required + because it is less computationally intesive than getting each attribute + separately. + + :class:`datetime` Objects -------------------------- +----------------------------------------------------------------------------- -A :class:`datetime` object is a single object containing all the information +A :class:`!datetime` object is a single object containing all the information for specifying an absolute date and time point. -:class:`datetime` assumes the current Gregorian calendar extended in both +:class:`!datetime` assumes the current Gregorian calendar extended in both directions, past and future. January 1 of year 1 is called day number 1, January 2 of year 1 is called day number 2, and so on. -:class:`datetime` assumes there are exactly 3600*24 seconds in every day and +:class:`!datetime` assumes there are exactly 3600*24 seconds in every day and subject to adjustment via a :class:`timezone` object. +With respect to the Python module `datetime +`_, this implementation +differs in: + + * ``__repr__()`` produces a different, yet compatible, output. + * ``today()`` is not provided. Use :meth:`~datetime.now` instead. + * ``utcnow()`` is not provided. Use ``datetime.now(timezone.utc)`` + instead. + * ``utcfromtimestamp()`` is not implemented. Use + ``datetime.fromtimestamp(timestamp, tz=timezone.utc)`` instead. + * ``utctimetuple()`` is not implemented. Use + :meth:`~datetime.timetuple` on an aware object made with + ``datetime.replace(tzinfo=timezone.utc)``. + * ``ctime()``, ``strftime()`` and ``__format__()`` are not implemented. + Constructors ^^^^^^^^^^^^ -.. class:: datetime(self, year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None) +.. class:: datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0) The *year*, *month* and *day* arguments are required. *tzinfo* may be ``None``, or an instance of a :class:`timezone` class. The remaining @@ -488,196 +1021,371 @@ Constructors * ``MINYEAR <= year <= MAXYEAR``, * ``1 <= month <= 12``, - * ``1 <= day <= number of days in the given month and year``, + * ``1 <= day <= d``, where ``d`` is the number of days in the given month and year, * ``0 <= hour < 24``, * ``0 <= minute < 60``, * ``0 <= second < 60``, - * ``0 <= microsecond < 999_999``, + * ``0 <= microsecond < 1_000_000``, + * ``fold in [0, 1]`` (see :attr:`~datetime.fold`). If an argument outside those ranges is given, :exc:`ValueError` is raised. -.. function:: fromisoformat(date_string) +.. classmethod:: datetime.now(tz=None) - Return a :class:`datetime` corresponding to a *date_string* in the format - emitted by :meth:`datetime.isoformat`. + Return the current local date and time. - Specifically, this function supports strings in the format:: + If *tz* is not ``None``, it must be an instance of a :class:`tzinfo` + subclass, and the current date and time are converted to *tz*’s time zone. - YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]] - where ``*`` can match any single character. +.. classmethod:: datetime.fromtimestamp(timestamp, tz=None) + + Return the local date and time corresponding to the timestamp defined by + :attr:`~datetime.EPOCH`, such as is returned by :func:`time.time`. + If optional argument *tz* is ``None``, the timestamp is converted to the + platform's local date and time, and the returned :class:`datetime` object is + naive. If *tz* is not ``None``, it must be an instance of a :class:`tzinfo` + subclass, and the timestamp is converted to *tz*’s time zone. -.. function:: fromordinal(n) + .. note:: + + If *tz* is naive, the algorithm relies on platform's + :func:`time.localtime` to perform the conversion which must properly + handle daylight saving time for the timezone of interest in order to + compute meaningful dates and times. + + +.. classmethod:: datetime.fromordinal(n) Return the :class:`datetime` corresponding to the proleptic Gregorian ordinal, where January 1 of year 1 has ordinal 1. :exc:`ValueError` is raised unless ``1 <= ordinal <= datetime.max.toordinal()``. The hour, - minute and second of the result are all 0, and *tzinfo* is ``None``. + minute, second and microsecond of the result are all 0, and + :attr:`~datetime.tzinfo` is ``None``. -.. function:: combine(date, time, tzinfo) +.. classmethod:: datetime.fromisoformat(date_string) + + Return a :class:`datetime` corresponding to a *date_string* in the format + emitted by :meth:`~datetime.isoformat`. Specifically, this function supports + strings in the format: + + .. code-block:: none + + YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]] + + where ``*`` can match any single character. + - Return a new :class:`datetime` object whose date components are equal to - the given *date* object’s (see :meth:`datetime.date`), and whose time +.. classmethod:: datetime.combine(date, time, tzinfo) + + Return a new :class:`datetime` object whose date components are equal to the + given *date* object’s (see :meth:`~datetime.date`), and whose time components are equal to the given *time* object’s (see - :meth:`datetime.time`). If the *tzinfo* argument is provided, its value - is used to set the *tzinfo* attribute of the result, otherwise the - *tzinfo* attribute of the *date* argument is used. + :meth:`~datetime.time`). If the *tzinfo* argument is provided, its value is + used to set the *tzinfo* attribute of the result, otherwise the *tzinfo* + attribute of the *time* argument is used. Class attributes ^^^^^^^^^^^^^^^^ -.. attribute:: datetime.MINYEAR +.. attribute:: datetime.EPOCH - The smallest year number allowed in a :class:`datetime` object. - :attr:`datetime.MINYEAR` is ``1``. + :class:`datetime` object representing the same time epoch as :mod:`time`'s, + typically 2000-01-01 00:00:00 UTC for embedded ports and 1970-01-01 00:00:00 + UTC for Unix port. + + +.. attribute:: datetime.year +.. attribute:: datetime.month +.. attribute:: datetime.day +.. attribute:: datetime.hour +.. attribute:: datetime.minute +.. attribute:: datetime.second +.. attribute:: datetime.microsecond + + Year (between :const:`MINYEAR` and :const:`MAXYEAR` inclusive), month + (between 1 and 12 inclusive), day (between 1 and the number of days in the + given month of the given year), hour (in ``range(24)``), minute (in + ``range(60)``), second (in ``range(60)``) and microsecond (in + ``range(1_000_000)`` representing the date and time. If you need two or more + of them, consider using :meth:`~datetime.tuple` instead. + + +.. attribute:: datetime.tzinfo + + The object passed as the *tzinfo* argument to the + :class:`~datetime.datetime` constructor, or ``None`` if none was passed. See + also :meth:`~datetime.tuple`. + + +.. attribute:: datetime.fold + + In ``[0, 1]``. Used to disambiguate wall times during a repeated interval. + The value 0 (1) represents the earlier (later) of the two moments with the + same wall time representation. See :attr:`time.fold` for a thorough + explanation. + + See also :meth:`~datetime.tuple`. + + +Operations +^^^^^^^^^^ + +The class support a number of operators. + + +Comparison operators +"""""""""""""""""""" + ++---------------------+---------------------------------------------------------------------------------+ +| Operation | Result | ++=====================+=================================================================================+ +| ``dt1 < dt2`` | Both *dt1* and *dt2* must be naive or aware datetime objects. When both are | +| | naive, or both are aware and have the same :attr:`~datetime.tzinfo`, operands | ++---------------------+ return: true when *dt1.date()* is less or greater than *dt2.date()*; when | +| ``dt1 <= dt2`` | equal, true is returned when *dt1.time()* is less or greater than *dt2.time()*; | +| | when equal, true is returned for operators ``<=`` and ``>=``. Otherwise, they | ++---------------------+ evaluate to :const:`False`. | +| ``dt1 >= dt2`` | | +| | When both comparands are aware and their :attr:`~datetime.tzinfo` differs, they | ++---------------------+ are first adjusted by subtracting their UTC offsets (obtained from | +| ``dt1 > dt2`` | :meth:`~datetime.utcoffset`). The comparison then proceeds as above. | +| | | +| | When one comparand is naive and the other is aware, :exc:`TypeError` is raised. | ++---------------------+---------------------------------------------------------------------------------+ +| ``dt1 == dt2`` | Same as above, but *date()* and *time()* are compared for (in)equality. | +| | | ++---------------------+ Plus, when one comparand is naive and the other is aware, operations evaluate | +| ``dt1 != dt2`` | to :const:`False` for ``==`` and to :const:`True` for ``!=``. No exception is | +| | raised. | ++---------------------+---------------------------------------------------------------------------------+ + + +Arithmetic operators +"""""""""""""""""""" + ++---------------------+---------------------------------------------------------------------------------+ +| Operation | Result | ++=====================+=================================================================================+ +| ``dt2 = dt1 + td`` | A :class:`datetime`, moved forward in time if ``td.days`` > 0, or backward if | +| | ``td.days`` < 0. Afterwards, *dt2 - dt1 == td*. *dt2* has the same | +| | :attr:`~datetime.tzinfo` attribute as *dt1*. | ++---------------------+---------------------------------------------------------------------------------+ +| ``dt2 = dt1 - td`` | A :class:`datetime`, moved backward or forward in time. Same as *dt1 + (-td)*. | ++---------------------+---------------------------------------------------------------------------------+ +| ``td = dt2 - dt1`` | A :class:`timedelta`, such that *dt1 + td == dt2*. | +| | | +| | Both *dt1* and *dt2* must be naive or aware datetime objects. When both are | +| | naive, or both are aware and have the same :attr:`~datetime.tzinfo`, *tzinfo* | +| | attributes are ignored and no time zone adjustments are done. | +| | | +| | If both are aware and have different *tzinfo* attributes, *dt1* and *dt2* are | +| | first adjusted by subtracting their UTC offsets (obtained from | +| | :meth:`~datetime.utcoffset`). | +| | | +| | If one is aware and the other is naive, :exc:`TypeError` is raised. | ++---------------------+---------------------------------------------------------------------------------+ + + +Other operators +""""""""""""""" + ++---------------------+---------------------------------------------------------------------------------+ +| Operation | Result | ++=====================+=================================================================================+ +| ``str(dt)`` | A string in the form returned by *dt.isoformat(" ")* | +| | (see :meth:`~datetime.isoformat`). | ++---------------------+---------------------------------------------------------------------------------+ +| ``repr(dt)`` | A string representation of a constructor call with canonical attribute values. | ++---------------------+---------------------------------------------------------------------------------+ +| ``hash(dt)`` | The hash number for dictionary keys. | ++---------------------+---------------------------------------------------------------------------------+ -.. attribute:: datetime.MAXYEAR +Class methods +^^^^^^^^^^^^^ - The largest year number allowed in a :class:`datetime` object. - :attr:`datetime.MAXYEAR` is ``9999``. +.. method:: datetime.date() + Return :class:`date` object with same year, month and day. -.. attribute:: datetime.EPOCH - :class:`datetime` object representing the time epoch of 2000-01-01 00:00:00 - UTC (same as :mod:`time`'s epoch). +.. method:: datetime.time() + Return :class:`time` object with same hour, minute, second, microsecond and + fold. :attr:`~datetime.tzinfo` is ``None``. See also method + :meth:`~datetime.timetz`. -.. attribute:: datetime.timezone - The object passed as the *tzinfo* argument to the :class:`datetime` - constructor, or ``None`` if none was passed. +.. method:: datetime.timetz() + Return :class:`time` object with same hour, minute, second, microsecond, + fold, and tzinfo attributes. See also method :meth:`~datetime.time`. -Class methods -^^^^^^^^^^^^^ -.. method:: datetime.__add__(other) +.. method:: datetime.replace(year=None, month=None, day=None, hour=None, \ + minute=None, second=None, nanosecond=None, tzinfo=True, *, fold=0) - In the expression ``datetime2 = datetime1.__add__(timedelta)``, ``datetime2`` - is a duration of ``timedelta`` removed from ``datetime1``, moving forward - in time if ``timedelta > 0``, or backward if ``timedelta < 0``. The result - has the same :class:`timezone` attribute as the input ``datetime1``, and - ``datetime2 - datetime1 == timedelta`` after. + Return a :class:`datetime` with the same attributes, except for those + attributes given new values by whichever keyword arguments are specified. + Note that ``tzinfo=None`` can be specified to create a naive + :class:`datetime` from an aware :class:`datetime` with no conversion of date + and time data. - Note that no time zone adjustments are done even if the input is an aware - object. +.. method:: datetime.astimezone(tz=None) -.. method:: datetime.__sub__(other) + Return a :class:`datetime` object with new :attr:`~datetime.tzinfo` + attribute *tz*, adjusting the date and time data so the result is the same + UTC time as *self*, but in *tz*’s local time. - If *other* is an instance of :class:`timedelta`, the expression - ``datetime2 = datetime1.__sub__(timedelta)`` computes the ``datetime2`` such - that ``datetime2 + timedelta == datetime1``. As for addition, the result has - the same :class:`timezone` attribute as the input ``datetime1``, and no time - zone adjustments are done even if the input is aware. + *self* can be aware or naive. If it is naive, it is presumed to represent + time in the system timezone. - If *other* is an instance of :class:`datetime`, subtraction - ``timedelta = datetime2.__sub__(datetime1)`` is defined only if both operands - are naive, or if both are aware. If one is aware and the other is naive, - :exc:`TypeError` is raised. + If provided, *tz* must be an instance of a :class:`tzinfo` subclass. Its + :meth:`tzinfo.utcoffset` and :meth:`tzinfo.dst` methods must not return + :const:`None`. If *tz* is not provided, the system local timezone is assumed + for the target timezone: the :attr:`~datetime.tzinfo` will be set to an + instance of :class:`timezone` with the offset obtained from the OS. - If both are naive, or both are aware and have the same :class:`timezone` - attribute, the :class:`timezone` attributes are ignored, and the result - is a :class:`timedelta` object *t* such that ``datetime2 + t == datetime1``. - No time zone adjustments are done in this case. + If you merely want to attach a :class:`timezone` object *tz* to a + :class:`datetime` *dt* without adjustment of date and time data, use + ``dt.replace(tzinfo=tz)``. If you merely want to remove the + :class:`timezone` object from an aware :class:`datetime` *dt* without + conversion of date and time data, use ``dt.replace(tzinfo=None)``. - If both are aware and have different :class:`timezone` attributes, ``a-b`` - acts as if *a* and *b* were first converted to naive UTC datetimes first. + .. note:: + If *self* is naive, the algorithm relies on platform's + :func:`time.localtime` to perform the conversion which must properly + handle daylight saving time for the timezone of interest in order to + compute meaningful dates and times. -.. method:: datetime.__lt__(other) - Equivalent to ``dt1.toordinal() < dt2.toordinal()``. +.. method:: datetime.utcoffset() + If :attr:`~datetime.tzinfo` is ``None``, returns ``None``, else returns a + :class:`timedelta` object with magnitude less than one day. -.. method:: datetime.__le__(other) - Equivalent to ``dt1.toordinal() <= dt2.toordinal()``. +.. method:: datetime.dst() + If :attr:`~datetime.tzinfo` is ``None``, returns ``None``, else returns + ``self.tzinfo.dst(self)``. -.. method:: datetime.__eq__(other) - Equivalent to ``dt1.toordinal() == dt2.toordinal()``. +.. method:: datetime.tzname() + If :attr:`~datetime.tzinfo` is ``None``, returns ``None``, else returns + ``self.tzinfo.tzname(self)``. -.. method:: datetime.__ge__(other) - Equivalent to ``dt1.toordinal() >= dt2.toordinal()``. +.. method:: datetime.timetuple() + Return a tuple such as returned by :func:`time.localtime`. -.. method:: datetime.__gt__(other) + .. note:: - Equivalent to ``dt1.toordinal() > dt2.toordinal()``. + If *self* is naive, the algorithm relies on platform's + :func:`time.localtime` to perform the conversion which must properly + handle daylight saving time for the timezone of interest in order to + compute meaningful dates and times. -.. method:: datetime.utcoffset() +.. method:: datetime.toordinal() - If *tzinfo* is ``None``, returns ``None``, else returns a - :class:`timedelta` object with magnitude less than one day. + Return the proleptic Gregorian ordinal of the date. The same as + ``self.date().toordinal()``. -.. method:: datetime.replace(year=None, month=None, day=None, hour=None, minute=None, second=None, microsecond=None, tzinfo=True) +.. method:: datetime.timestamp() - Return a :class:`datetime` with the same attributes, except for those - attributes given new values by whichever keyword arguments are specified. - Note that ``tzinfo=None`` can be specified to create a naive - :class:`datetime` from an aware :class:`datetime` with no conversion of - date and time data. + Return a timestamp since :attr:`EPOCH` and corresponding to the + :class:`datetime` instance. The return value is a :class:`float` similar to + that returned by :func:`time.time`. + For aware :class:`datetime` instances, the return value is computed + as:: -.. method:: datetime.astimezone(tz) + (dt - datetime.EPOCH).total_seconds() - Return a :class:`datetime` object with new *tzinfo* attribute - *tz*, adjusting the date and time data so the result is the same UTC time - as *self*, but in *tz*’s local time. *self* must be aware. + Naive :class:`datetime` instances are assumed to represent local time. - If you merely want to attach a :class:`timezone` object *tz* to a - :class:`datetime` *dt* without adjustment of date and time data, use - ``dt.replace(tzinfo=tz)``. If you merely want to remove the :class:`timezone` - object from an aware :class:`datetime` *dt* without conversion of date and - time data, use ``dt.replace(tzinfo=None)``. + .. note:: + If *self* is naive, the algorithm relies on platform's + :func:`time.localtime` to perform the conversion which must properly + handle daylight saving time for the timezone of interest in order to + compute meaningful dates and times. -.. method:: datetime.isoformat(sep='T') - Return a string representing the date and time in ISO 8601 format - ``YYYY-MM-DDTHH:MM:SS``. If :meth:`datetime.utcoffset` does not return - ``None``, a string is appended, giving the UTC offset: - ``YYYY-MM-DDTHH:MM:SS+HH:MM``. +.. method:: datetime.weekday() + Return the day of the week as an integer, where Monday is 0 and Sunday is 6. + The same as ``self.date().weekday()``. See also + :meth:`~datetime.isoweekday`. -.. method:: datetime.date() - Return a :class:`datetime` instance whose date and time zone components - are equal to the input object and time is set to midnight. +.. method:: datetime.isoweekday() + Return the day of the week as an integer, where Monday is 1 and Sunday is 7. + The same as ``self.date().isoweekday()``. See also + :meth:`~datetiem.weekday`. -.. method:: datetime.time() - Return a :class:`timedelta` instance whose time components are equal to - the input object. +.. method:: datetime.isoformat(sep="T", timespec="auto") + Return a string representing the date and time in ISO 8601 format: -.. method:: datetime.toordinal() + - ``YYYY-MM-DDTHH:MM:SS.ffffff``, + if :attr:`~datetiem.microsecond` is not 0 + - ``YYYY-MM-DDTHH:MM:SS``, + if :attr:`~datetiem.microsecond` is 0 - Return the proleptic Gregorian ordinal of the date. + If :meth:`~datetiem.utcoffset` does not return ``None``, a string is + appended, giving the UTC offset: + - ``YYYY-MM-DDTHH:MM:SS.ffffff+HH:MM[:SS[.ffffff]]``, + if :attr:`~datetiem.microsecond` is not 0 + - ``YYYY-MM-DDTHH:MM:SS+HH:MM[:SS[.ffffff]]``, + if :attr:`~datetiem.microsecond` is 0 -.. method:: datetime.isoweekday() + The optional argument *sep* (default ``"T"``) is a one-character separator, + placed between the date and time portions of the result. + + The optional argument *timespec* specifies the number of additional + components of the time to include (the default is ``"auto"``). It can be one + of the following: + + - ``"auto"``: same as ``"seconds"`` if :attr:`~datetiem.microsecond` is 0, + same as ``"microseconds"`` otherwise. + - ``"hours"``: include the :attr:`~datetiem.hour` in the two-digit ``HH`` + format. + - ``"minutes"``: include :attr:`~datetiem.hour` and :attr:`~datetiem.minute` + in ``HH:MM`` format. + - ``"seconds"``: include :attr:`~datetiem.hour`, :attr:`~datetiem.minute`, + and :attr:`~datetiem.second` in ``HH:MM:SS`` format. + - ``"milliseconds"``: include full time, but truncate fractional second part + to milliseconds. ``HH:MM:SS.sss`` format. + - ``"microseconds"``: include full time in ``HH:MM:SS.ffffff`` format. - Return the day of the week as an integer, where Monday is 1 and Sunday - is 7. For example, ``date(2002, 12, 4).isoweekday() == 3``, a Wednesday. + .. note:: + + Excluded time components are truncated, not rounded. .. method:: datetime.tuple() - Return the tuple ``(year, month, day, hour, minute, second, microsecond, tzinfo)``. + Return the tuple of attributes ``(year, month, day, hour, minute, second, + microsecond, tzinfo, fold)``. + + This method should be preferred when two or more attributes are required + because it is less computationally intesive than getting each attribute + separately. Examples of usage @@ -685,13 +1393,42 @@ Examples of usage Examples of working with :class:`datetime` objects:: - from datetime import timedelta, timezone, datetime, fromisoformat + from datetime import timedelta, timezone, datetime print(datetime(2005, 7, 14, 12, 30)) # 2005-07-14 12:30:00 - dt = fromisoformat('2006-11-21 16:30+01:00') - print(dt.add(timedelta(hours=23))) # 2006-11-22 15:30:00+01:00 + dt = datetime.fromisoformat('2006-11-21 16:30+01:00') + print(dt + timedelta(hours=23)) # 2006-11-22 15:30:00+01:00 tz1 = timezone(timedelta(hours=4, minutes=30)) print(tz1) # UTC+04:30 dt = datetime(1900, 11, 21, 3, 30, tzinfo=tz1) print(dt) # 1900-11-21 03:30:00+04:30 print(dt.astimezone(timezone.utc)) # 1900-11-20 23:00:00+00:00 + + +Resource Optimization +----------------------------------------------------------------------------- + +Class :class:`datetime` has been implemented to be lightly dependent from +:class:`date` and :class:`time` classes. Several source code lines can be +deleted from ``datetime.py`` as to save precious resources, when needed. + +If :class:`date` class is not required, delete: + + - class ``date`` + - methods ``datetime.combine`` and ``datetime.date`` + +If :class:`time` class is not required, delete: + + - class ``time`` + - methods ``datetime.combine``, ``datetime.time`` and ``datetime.timetz`` + +If :meth:`datetime.fromisoformat` is not required, delete: + + - functions ``_iso2d`` and ``_iso2t`` + - methods ``date.fromisoformat``, ``time.fromisoformat`` and + ``datetime.fromisoformat`` + +If :meth:`datetime.isoformat` is not required, delete: + + - functions ``_d2iso`` and ``_t2iso`` + - methods ``date.isoformat``, ``time.isoformat`` and ``datetime.isoformat`` From 3a523691a0c77fb0dda564cfb6c3cf229bbd007d Mon Sep 17 00:00:00 2001 From: Lorenzo Cappelletti Date: Thu, 23 Dec 2021 10:46:42 +0100 Subject: [PATCH 6/6] docs/library/datetime.rst: Remove naive support due to time.localtime(). --- docs/library/datetime.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/library/datetime.rst b/docs/library/datetime.rst index f39dc3d079750..5dd409f92ea06 100644 --- a/docs/library/datetime.rst +++ b/docs/library/datetime.rst @@ -1044,17 +1044,16 @@ Constructors Return the local date and time corresponding to the timestamp defined by :attr:`~datetime.EPOCH`, such as is returned by :func:`time.time`. - If optional argument *tz* is ``None``, the timestamp is converted to the - platform's local date and time, and the returned :class:`datetime` object is - naive. If *tz* is not ``None``, it must be an instance of a :class:`tzinfo` - subclass, and the timestamp is converted to *tz*’s time zone. + *tz* must be an instance of a :class:`tzinfo` subclass, and the timestamp is + converted to *tz*’s time zone. ``tz=None`` is not supported. .. note:: - If *tz* is naive, the algorithm relies on platform's + If *tz* is naive, the CPython algorithm relies on platform's :func:`time.localtime` to perform the conversion which must properly handle daylight saving time for the timezone of interest in order to - compute meaningful dates and times. + compute meaningful dates and times. Micropython board ports do not + support timezones. .. classmethod:: datetime.fromordinal(n) @@ -1243,8 +1242,7 @@ Class methods attribute *tz*, adjusting the date and time data so the result is the same UTC time as *self*, but in *tz*’s local time. - *self* can be aware or naive. If it is naive, it is presumed to represent - time in the system timezone. + *self* must be aware. If provided, *tz* must be an instance of a :class:`tzinfo` subclass. Its :meth:`tzinfo.utcoffset` and :meth:`tzinfo.dst` methods must not return @@ -1260,10 +1258,11 @@ Class methods .. note:: - If *self* is naive, the algorithm relies on platform's + If *self* is naive, the CPython algorithm relies on platform's :func:`time.localtime` to perform the conversion which must properly handle daylight saving time for the timezone of interest in order to - compute meaningful dates and times. + compute meaningful dates and times. Micropython board ports do not + support timezones. .. method:: datetime.utcoffset() @@ -1313,14 +1312,15 @@ Class methods (dt - datetime.EPOCH).total_seconds() - Naive :class:`datetime` instances are assumed to represent local time. + Naive :class:`datetime` instances are not supported. .. note:: - If *self* is naive, the algorithm relies on platform's + If *self* is naive, the CPython algorithm relies on platform's :func:`time.localtime` to perform the conversion which must properly handle daylight saving time for the timezone of interest in order to - compute meaningful dates and times. + compute meaningful dates and times. Micropython board ports do not + support timezones. .. method:: datetime.weekday() pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy