diff env/lib/python3.7/site-packages/isodate/duration.py @ 5:9b1c78e6ba9c draft default tip

"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author shellac
date Mon, 01 Jun 2020 08:59:25 -0400
parents 79f47841a781
children
line wrap: on
line diff
--- a/env/lib/python3.7/site-packages/isodate/duration.py	Thu May 14 16:47:39 2020 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,321 +0,0 @@
-##############################################################################
-# Copyright 2009, Gerhard Weis
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-#  * Redistributions of source code must retain the above copyright notice,
-#    this list of conditions and the following disclaimer.
-#  * Redistributions in binary form must reproduce the above copyright notice,
-#    this list of conditions and the following disclaimer in the documentation
-#    and/or other materials provided with the distribution.
-#  * Neither the name of the authors nor the names of its contributors
-#    may be used to endorse or promote products derived from this software
-#    without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-# CONTRACT, STRICT LIABILITY, OR TORT
-##############################################################################
-'''
-This module defines a Duration class.
-
-The class Duration allows to define durations in years and months and can be
-used as limited replacement for timedelta objects.
-'''
-from datetime import timedelta
-from decimal import Decimal, ROUND_FLOOR
-
-
-def fquotmod(val, low, high):
-    '''
-    A divmod function with boundaries.
-
-    '''
-    # assumes that all the maths is done with Decimals.
-    # divmod for Decimal uses truncate instead of floor as builtin
-    # divmod, so we have to do it manually here.
-    a, b = val - low, high - low
-    div = (a / b).to_integral(ROUND_FLOOR)
-    mod = a - div * b
-    # if we were not usig Decimal, it would look like this.
-    # div, mod = divmod(val - low, high - low)
-    mod += low
-    return int(div), mod
-
-
-def max_days_in_month(year, month):
-    '''
-    Determines the number of days of a specific month in a specific year.
-    '''
-    if month in (1, 3, 5, 7, 8, 10, 12):
-        return 31
-    if month in (4, 6, 9, 11):
-        return 30
-    if ((year % 400) == 0) or ((year % 100) != 0) and ((year % 4) == 0):
-        return 29
-    return 28
-
-
-class Duration(object):
-    '''
-    A class which represents a duration.
-
-    The difference to datetime.timedelta is, that this class handles also
-    differences given in years and months.
-    A Duration treats differences given in year, months separately from all
-    other components.
-
-    A Duration can be used almost like any timedelta object, however there
-    are some restrictions:
-      * It is not really possible to compare Durations, because it is unclear,
-        whether a duration of 1 year is bigger than 365 days or not.
-      * Equality is only tested between the two (year, month vs. timedelta)
-        basic components.
-
-    A Duration can also be converted into a datetime object, but this requires
-    a start date or an end date.
-
-    The algorithm to add a duration to a date is defined at
-    http://www.w3.org/TR/xmlschema-2/#adding-durations-to-dateTimes
-    '''
-
-    def __init__(self, days=0, seconds=0, microseconds=0, milliseconds=0,
-                 minutes=0, hours=0, weeks=0, months=0, years=0):
-        '''
-        Initialise this Duration instance with the given parameters.
-        '''
-        if not isinstance(months, Decimal):
-            months = Decimal(str(months))
-        if not isinstance(years, Decimal):
-            years = Decimal(str(years))
-        self.months = months
-        self.years = years
-        self.tdelta = timedelta(days, seconds, microseconds, milliseconds,
-                                minutes, hours, weeks)
-
-    def __getstate__(self):
-        return self.__dict__
-
-    def __setstate__(self, state):
-        self.__dict__.update(state)
-
-    def __getattr__(self, name):
-        '''
-        Provide direct access to attributes of included timedelta instance.
-        '''
-        return getattr(self.tdelta, name)
-
-    def __str__(self):
-        '''
-        Return a string representation of this duration similar to timedelta.
-        '''
-        params = []
-        if self.years:
-            params.append('%d years' % self.years)
-        if self.months:
-            fmt = "%d months"
-            if self.months <= 1:
-                fmt = "%d month"
-            params.append(fmt % self.months)
-        params.append(str(self.tdelta))
-        return ', '.join(params)
-
-    def __repr__(self):
-        '''
-        Return a string suitable for repr(x) calls.
-        '''
-        return "%s.%s(%d, %d, %d, years=%d, months=%d)" % (
-            self.__class__.__module__, self.__class__.__name__,
-            self.tdelta.days, self.tdelta.seconds,
-            self.tdelta.microseconds, self.years, self.months)
-
-    def __hash__(self):
-        '''
-        Return a hash of this instance so that it can be used in, for
-        example, dicts and sets.
-        '''
-        return hash((self.tdelta, self.months, self.years))
-
-    def __neg__(self):
-        """
-        A simple unary minus.
-
-        Returns a new Duration instance with all it's negated.
-        """
-        negduration = Duration(years=-self.years, months=-self.months)
-        negduration.tdelta = -self.tdelta
-        return negduration
-
-    def __add__(self, other):
-        '''
-        Durations can be added with Duration, timedelta, date and datetime
-        objects.
-        '''
-        if isinstance(other, Duration):
-            newduration = Duration(years=self.years + other.years,
-                                   months=self.months + other.months)
-            newduration.tdelta = self.tdelta + other.tdelta
-            return newduration
-        try:
-            # try anything that looks like a date or datetime
-            # 'other' has attributes year, month, day
-            # and relies on 'timedelta + other' being implemented
-            if (not(float(self.years).is_integer() and
-                    float(self.months).is_integer())):
-                raise ValueError('fractional years or months not supported'
-                                 ' for date calculations')
-            newmonth = other.month + self.months
-            carry, newmonth = fquotmod(newmonth, 1, 13)
-            newyear = other.year + self.years + carry
-            maxdays = max_days_in_month(newyear, newmonth)
-            if other.day > maxdays:
-                newday = maxdays
-            else:
-                newday = other.day
-            newdt = other.replace(year=newyear, month=newmonth, day=newday)
-            # does a timedelta + date/datetime
-            return self.tdelta + newdt
-        except AttributeError:
-            # other probably was not a date/datetime compatible object
-            pass
-        try:
-            # try if other is a timedelta
-            # relies on timedelta + timedelta supported
-            newduration = Duration(years=self.years, months=self.months)
-            newduration.tdelta = self.tdelta + other
-            return newduration
-        except AttributeError:
-            # ignore ... other probably was not a timedelta compatible object
-            pass
-        # we have tried everything .... return a NotImplemented
-        return NotImplemented
-
-    __radd__ = __add__
-
-    def __mul__(self, other):
-        if isinstance(other, int):
-            newduration = Duration(
-                years=self.years * other,
-                months=self.months * other)
-            newduration.tdelta = self.tdelta * other
-            return newduration
-        return NotImplemented
-
-    __rmul__ = __mul__
-
-    def __sub__(self, other):
-        '''
-        It is possible to subtract Duration and timedelta objects from Duration
-        objects.
-        '''
-        if isinstance(other, Duration):
-            newduration = Duration(years=self.years - other.years,
-                                   months=self.months - other.months)
-            newduration.tdelta = self.tdelta - other.tdelta
-            return newduration
-        try:
-            # do maths with our timedelta object ....
-            newduration = Duration(years=self.years, months=self.months)
-            newduration.tdelta = self.tdelta - other
-            return newduration
-        except TypeError:
-            # looks like timedelta - other is not implemented
-            pass
-        return NotImplemented
-
-    def __rsub__(self, other):
-        '''
-        It is possible to subtract Duration objecs from date, datetime and
-        timedelta objects.
-
-        TODO: there is some weird behaviour in date - timedelta ...
-              if timedelta has seconds or microseconds set, then
-              date - timedelta != date + (-timedelta)
-              for now we follow this behaviour to avoid surprises when mixing
-              timedeltas with Durations, but in case this ever changes in
-              the stdlib we can just do:
-                return -self + other
-              instead of all the current code
-        '''
-        if isinstance(other, timedelta):
-            tmpdur = Duration()
-            tmpdur.tdelta = other
-            return tmpdur - self
-        try:
-            # check if other behaves like a date/datetime object
-            # does it have year, month, day and replace?
-            if (not(float(self.years).is_integer() and
-                    float(self.months).is_integer())):
-                raise ValueError('fractional years or months not supported'
-                                 ' for date calculations')
-            newmonth = other.month - self.months
-            carry, newmonth = fquotmod(newmonth, 1, 13)
-            newyear = other.year - self.years + carry
-            maxdays = max_days_in_month(newyear, newmonth)
-            if other.day > maxdays:
-                newday = maxdays
-            else:
-                newday = other.day
-            newdt = other.replace(year=newyear, month=newmonth, day=newday)
-            return newdt - self.tdelta
-        except AttributeError:
-            # other probably was not compatible with data/datetime
-            pass
-        return NotImplemented
-
-    def __eq__(self, other):
-        '''
-        If the years, month part and the timedelta part are both equal, then
-        the two Durations are considered equal.
-        '''
-        if isinstance(other, Duration):
-            if (((self.years * 12 + self.months) ==
-                 (other.years * 12 + other.months) and
-                 self.tdelta == other.tdelta)):
-                return True
-            return False
-        # check if other con be compared against timedelta object
-        # will raise an AssertionError when optimisation is off
-        if self.years == 0 and self.months == 0:
-            return self.tdelta == other
-        return False
-
-    def __ne__(self, other):
-        '''
-        If the years, month part or the timedelta part is not equal, then
-        the two Durations are considered not equal.
-        '''
-        if isinstance(other, Duration):
-            if (((self.years * 12 + self.months) !=
-                 (other.years * 12 + other.months) or
-                 self.tdelta != other.tdelta)):
-                return True
-            return False
-        # check if other can be compared against timedelta object
-        # will raise an AssertionError when optimisation is off
-        if self.years == 0 and self.months == 0:
-            return self.tdelta != other
-        return True
-
-    def totimedelta(self, start=None, end=None):
-        '''
-        Convert this duration into a timedelta object.
-
-        This method requires a start datetime or end datetimem, but raises
-        an exception if both are given.
-        '''
-        if start is None and end is None:
-            raise ValueError("start or end required")
-        if start is not None and end is not None:
-            raise ValueError("only start or end allowed")
-        if start is not None:
-            return (start + self) - start
-        return end - (end - self)