def to_duration(self): """Convert to a Duration.""" date_time_unit, multiplier = self.KEYS[self.unit] amount = self.amount if self.sign == self.SIGN_DEFAULT: # negative amount = -amount return Duration(**{date_time_unit: multiplier * amount})
def get_inferred_child(self, string): """Return an instance with 'string' amounts of my non-zero units.""" interval = interval_parse(self.value) amount_per_unit = int(string) unit_amounts = {} for attribute in [ "years", "months", "weeks", "days", "hours", "minutes", "seconds" ]: if getattr(interval, attribute): unit_amounts[attribute] = amount_per_unit interval = Duration(**unit_amounts) return ISO8601Interval(str(interval))
def get_next_after(recurrence, timepoint): if recurrence._get_is_in_bounds(timepoint): if recurrence.duration is not None and not ( recurrence.duration.years or recurrence.duration.months): # Since it's exact, we can do maths instead of iterating iterations, seconds_since = divmod( (timepoint - recurrence.start_point).get_seconds(), recurrence.duration.get_seconds()) return timepoint + (recurrence.duration - Duration(seconds=floor(seconds_since))) else: # Since duration is inexact, we have to iterate current = recurrence.start_point while current is not None and current <= timepoint: current = recurrence.get_next(current) return current elif timepoint < recurrence.start_point: return recurrence.start_point return None
def date_shift(self, time_point=None, offset=None): """Return a date string with an offset. time_point -- A time point or time point string. Otherwise, use current time. offset -- If specified, it should be a string containing the offset that has the format "[+/-]nU[nU...]" where "n" is an integer, and U is a unit matching a key in self.UNITS. """ if time_point is None: time_point = self.date_parse()[0] # Offset if offset: sign = "+" if offset.startswith("-") or offset.startswith("+"): sign = offset[0] offset = offset[1:] if offset.startswith("P"): # Parse and apply. try: duration = self.duration_parser.parse(offset) except ValueError: raise OffsetValueError(offset) if sign == "-": time_point -= duration else: time_point += duration else: # Backwards compatibility for e.g. "-1h" if not self.is_offset(offset): raise OffsetValueError(offset) for num, unit in self.REC_OFFSET_FIND.findall(offset.lower()): num = int(num) if sign == "-": num = -num key = self.UNITS[unit] time_point += Duration(**{key: num}) return time_point
def __str__(self): return str(Duration(seconds=self, standardize=True))
def get_seconds_as_interval_string(seconds): """Convert a number of seconds into an ISO 8601 duration string.""" from metomi.isodatetime.data import Duration return str(Duration(seconds=seconds, standardize=True))
def _do_test_dates(self, my_date): """Performs a series of tests against a given date. This method does some time consuming operations, which are not IO bound, so this method is a good candidate to be run concurrently. :param my_date: a date to be tested :type my_date: datetime.datetime """ ctrl_data = my_date.isocalendar() test_date = TimePoint(year=my_date.year, month_of_year=my_date.month, day_of_month=my_date.day) test_week_date = test_date.to_week_date() test_data = test_week_date.get_week_date() self.assertEqual(test_data, ctrl_data) ctrl_data = (my_date.year, my_date.month, my_date.day) test_data = test_week_date.get_calendar_date() self.assertEqual(test_data, ctrl_data) ctrl_data = my_date.toordinal() year, day_of_year = test_date.get_ordinal_date() test_data = day_of_year test_data += get_days_since_1_ad(year - 1) self.assertEqual(test_data, ctrl_data) for attribute, attr_max in test_duration_attributes: kwargs = {attribute: random.randrange(0, attr_max)} ctrl_data = my_date + datetime.timedelta(**kwargs) ctrl_data = ctrl_data.year, ctrl_data.month, ctrl_data.day test_data = ((test_date + Duration(**kwargs)).get_calendar_date()) self.assertEqual(test_data, ctrl_data) ctrl_data = my_date - datetime.timedelta(**kwargs) ctrl_data = ctrl_data.year, ctrl_data.month, ctrl_data.day # TBD: the subtraction is quite slow. Much slower than other # operations. Could be related to the fact it converts the value # in kwargs to negative multiplying by -1 (i.e. from __sub__ to # __mul__), and also adds it to the date (i.e. __add__). # Profiling the tests, the __sub__ operation used in the next # line will appear amongst the top of time consuming operations. test_data = ((test_date - Duration(**kwargs)).get_calendar_date()) self.assertEqual(test_data, ctrl_data) kwargs = {} for attribute, attr_max in test_duration_attributes: kwargs[attribute] = random.randrange(0, attr_max) test_date_minus = test_date - Duration(**kwargs) test_data = test_date - test_date_minus ctrl_data = Duration(**kwargs) self.assertEqual(test_data, ctrl_data) test_data = test_date_minus + (test_date - test_date_minus) ctrl_data = test_date self.assertEqual(test_data, ctrl_data) test_data = (test_date_minus + Duration(**kwargs)) ctrl_data = test_date self.assertEqual(test_data, ctrl_data) ctrl_data = (my_date + datetime.timedelta(minutes=450) + datetime.timedelta(hours=5) - datetime.timedelta(seconds=500, weeks=5)) ctrl_data = [(ctrl_data.year, ctrl_data.month, ctrl_data.day), (ctrl_data.hour, ctrl_data.minute, ctrl_data.second)] test_data = (test_date + Duration(minutes=450) + Duration(hours=5) - Duration(weeks=5, seconds=500)) test_data = [ test_data.get_calendar_date(), test_data.get_hour_minute_second() ] self.assertEqual(test_data, ctrl_data)
def _test_timepoint(test_year): my_date = datetime.datetime(test_year, 1, 1) stop_date = datetime.datetime(test_year + 1, 1, 1) for date in daterange(my_date, stop_date): ctrl_data = date.isocalendar() test_date = TimePoint(year=date.year, month_of_year=date.month, day_of_month=date.day) test_week_date = test_date.to_week_date() test_data = test_week_date.get_week_date() assert test_data == ctrl_data ctrl_data = (date.year, date.month, date.day) test_data = test_week_date.get_calendar_date() assert test_data == ctrl_data ctrl_data = date.toordinal() year, day_of_year = test_date.get_ordinal_date() test_data = day_of_year test_data += get_days_since_1_ad(year - 1) assert test_data == ctrl_data for attribute, attr_max in test_duration_attributes: kwargs = {attribute: random.randrange(0, attr_max)} ctrl_data = date + datetime.timedelta(**kwargs) ctrl_data = ctrl_data.year, ctrl_data.month, ctrl_data.day test_data = ((test_date + Duration(**kwargs)).get_calendar_date()) assert test_data == ctrl_data ctrl_data = date - datetime.timedelta(**kwargs) ctrl_data = ctrl_data.year, ctrl_data.month, ctrl_data.day # TBD: the subtraction is quite slow. Much slower than other # operations. Could be related to the fact it converts the # value in kwargs to negative multiplying by -1 (i.e. from # __sub__ to __mul__), and also adds it to the date (i.e. # __add__). Profiling the tests, the __sub__ operation used in # the next line will appear amongst the top of time consuming # operations. test_data = ((test_date - Duration(**kwargs)).get_calendar_date()) assert test_data == ctrl_data kwargs = {} for attribute, attr_max in test_duration_attributes: kwargs[attribute] = random.randrange(0, attr_max) test_date_minus = test_date - Duration(**kwargs) test_data = test_date - test_date_minus ctrl_data = Duration(**kwargs) assert test_data == ctrl_data test_data = test_date_minus + (test_date - test_date_minus) ctrl_data = test_date assert test_data == ctrl_data test_data = (test_date_minus + Duration(**kwargs)) ctrl_data = test_date assert test_data == ctrl_data ctrl_data = (date + datetime.timedelta(minutes=450) + datetime.timedelta(hours=5) - datetime.timedelta(seconds=500, weeks=5)) ctrl_data = [(ctrl_data.year, ctrl_data.month, ctrl_data.day), (ctrl_data.hour, ctrl_data.minute, ctrl_data.second)] test_data = (test_date + Duration(minutes=450) + Duration(hours=5) - Duration(weeks=5, seconds=500)) test_data = [ test_data.get_calendar_date(), test_data.get_hour_minute_second() ] assert test_data == ctrl_data