Source code for iris.time

# Copyright Iris contributors
#
# This file is part of Iris and is released under the LGPL license.
# See COPYING and COPYING.LESSER in the root of the repository for full
# licensing details.
"""
Time handling.

"""

import functools


[docs]@functools.total_ordering class PartialDateTime: """ A :class:`PartialDateTime` object specifies values for some subset of the calendar/time fields (year, month, hour, etc.) for comparing with :class:`datetime.datetime`-like instances. Comparisons are defined against any other class with all of the attributes: year, month, day, hour, minute, and second. Notably, this includes :class:`datetime.datetime` and :class:`cftime.datetime`. Comparison also extends to the microsecond attribute for classes, such as :class:`datetime.datetime`, which define it. A :class:`PartialDateTime` object is not limited to any particular calendar, so no restriction is placed on the range of values allowed in its component fields. Thus, it is perfectly legitimate to create an instance as: `PartialDateTime(month=2, day=30)`. """ __slots__ = ( "year", "month", "day", "hour", "minute", "second", "microsecond", ) #: A dummy value provided as a workaround to allow comparisons with #: :class:`datetime.datetime`. #: See http://bugs.python.org/issue8005. # NB. It doesn't even matter what this value is. timetuple = None def __init__( self, year=None, month=None, day=None, hour=None, minute=None, second=None, microsecond=None, ): """ Allows partial comparisons against datetime-like objects. Args: * year (int): * month (int): * day (int): * hour (int): * minute (int): * second (int): * microsecond (int): For example, to select any days of the year after the 3rd of April: >>> from iris.time import PartialDateTime >>> import datetime >>> pdt = PartialDateTime(month=4, day=3) >>> datetime.datetime(2014, 4, 1) > pdt False >>> datetime.datetime(2014, 4, 5) > pdt True >>> datetime.datetime(2014, 5, 1) > pdt True >>> datetime.datetime(2015, 2, 1) > pdt False """ #: The year number as an integer, or None. self.year = year #: The month number as an integer, or None. self.month = month #: The day number as an integer, or None. self.day = day #: The hour number as an integer, or None. self.hour = hour #: The minute number as an integer, or None. self.minute = minute #: The second number as an integer, or None. self.second = second #: The microsecond number as an integer, or None. self.microsecond = microsecond def __repr__(self): attr_pieces = [ "{}={}".format(name, getattr(self, name)) for name in self.__slots__ if getattr(self, name) is not None ] result = "{}({})".format(type(self).__name__, ", ".join(attr_pieces)) return result def __gt__(self, other): if isinstance(other, type(self)): raise TypeError("Cannot order PartialDateTime instances.") result = False try: # Everything except 'microsecond' is mandatory for attr_name in self.__slots__[:-1]: attr = getattr(self, attr_name) other_attr = getattr(other, attr_name) if attr is not None and attr != other_attr: result = attr > other_attr break # 'microsecond' is optional if result and hasattr(other, "microsecond"): attr = self.microsecond other_attr = other.microsecond if attr is not None and attr != other_attr: result = attr > other_attr except AttributeError: result = NotImplemented return result def __eq__(self, other): if isinstance(other, type(self)): slots = self.__slots__ self_tuple = tuple(getattr(self, name) for name in slots) other_tuple = tuple(getattr(other, name) for name in slots) result = self_tuple == other_tuple else: result = True try: # Everything except 'microsecond' is mandatory for attr_name in self.__slots__[:-1]: attr = getattr(self, attr_name) other_attr = getattr(other, attr_name) if attr is not None and attr != other_attr: result = False break # 'microsecond' is optional if result and hasattr(other, "microsecond"): attr = self.microsecond other_attr = other.microsecond if attr is not None and attr != other_attr: result = False except AttributeError: result = other.__eq__(self) if result is NotImplemented: # Equality is undefined between these objects. We don't # want Python to fall back to the default `object` # behaviour (which compares using object IDs), so we raise # an exception here instead. fmt = "unable to compare PartialDateTime with {}" raise TypeError(fmt.format(type(other))) return result def __ne__(self, other): result = self.__eq__(other) if result is not NotImplemented: result = not result return result