def _strict_date(self, lean): if lean == EARLIEST: try: r = self.lower._strict_date(lean) if r is None: raise AttributeError return r except AttributeError: # it's a string, or no date. Result depends on the upper date upper = self.upper._strict_date(LATEST) return apply_delta(sub, upper, appsettings.DELTA_IF_UNKNOWN) else: try: r = self.upper._strict_date(lean) if r is None: raise AttributeError return r except AttributeError: # an 'unknown' or 'open' string - depends on the lower date if self.upper and (self.upper == "open" or self.upper.date == "open"): return dt_to_struct_time( date.today()) # it's still happening else: lower = self.lower._strict_date(EARLIEST) return apply_delta(add, lower, appsettings.DELTA_IF_UNKNOWN)
def test_dt_to_struct_time_for_datetime(self): now = datetime.now() st = convert.dt_to_struct_time(now) # Check equal year, month, day, hours, minutes, seconds self.assertEqual(st[:6], now.timetuple()[:6]) # Confirm 'extra' fields are set to defaults self.assertEqual(st[6:], (0, 0, -1))
def __le__(self, other): if isinstance(other, EDTFObject): return self.lower_strict() <= other.lower_strict() elif isinstance(other, date): return self.lower_strict() <= dt_to_struct_time(other) elif isinstance(other, struct_time): return self.lower_strict() <= trim_struct_time(other) raise TypeError("can't compare %s with %s" % (type(self).__name__, type(other).__name__))
def test_dt_to_struct_time_for_date(self): today = date.today() st = convert.dt_to_struct_time(today) # Check equal year, month, day self.assertEqual(st[:3], today.timetuple()[:3]) # Confirm time fields are zeroed self.assertEqual(st[3:6], (0, 0, 0)) # Confirm 'extra' fields are set to defaults self.assertEqual(st[6:], (0, 0, -1))
def _strict_date(self, lean): if lean == EARLIEST: try: r = self.lower._strict_date(lean) if r is None: raise AttributeError return r except AttributeError: # it's a string, or no date. Result depends on the upper date upper = self.upper._strict_date(LATEST) return apply_delta(sub, upper, appsettings.DELTA_IF_UNKNOWN) else: try: r = self.upper._strict_date(lean) if r is None: raise AttributeError return r except AttributeError: # an 'unknown' or 'open' string - depends on the lower date if self.upper and (self.upper == "open" or self.upper.date == "open"): return dt_to_struct_time(date.today()) # it's still happening else: lower = self.lower._strict_date(EARLIEST) return apply_delta(add, lower, appsettings.DELTA_IF_UNKNOWN)
def apply_delta(op, time_struct, delta): """ Apply a `relativedelta` to a `struct_time` data structure. `op` is an operator function, probably always `add` or `sub`tract to correspond to `a_date + a_delta` and `a_date - a_delta`. This function is required because we cannot use standard `datetime` module objects for conversion when the date/time is, or will become, outside the boundary years 1 AD to 9999 AD. """ if not delta: return time_struct # No work to do try: dt_result = op(datetime(*time_struct[:6]), delta) return dt_to_struct_time(dt_result) except (OverflowError, ValueError): # Year is not within supported 1 to 9999 AD range pass # Here we fake the year to one in the acceptable range to avoid having to # write our own date rolling logic # Adjust the year to be close to the 2000 millenium in 1,000 year # increments to try and retain accurate relative leap years actual_year = time_struct.tm_year millenium = int(float(actual_year) / 1000) millenium_diff = (2 - millenium) * 1000 adjusted_year = actual_year + millenium_diff # Apply delta to the date/time with adjusted year dt = datetime(*(adjusted_year,) + time_struct[1:6]) dt_result = op(dt, delta) # Convert result year back to its original millenium final_year = dt_result.year - millenium_diff return struct_time( (final_year,) + dt_result.timetuple()[1:6] + tuple(TIME_EMPTY_EXTRAS))
def apply_delta(op, time_struct, delta): """ Apply a `relativedelta` to a `struct_time` data structure. `op` is an operator function, probably always `add` or `sub`tract to correspond to `a_date + a_delta` and `a_date - a_delta`. This function is required because we cannot use standard `datetime` module objects for conversion when the date/time is, or will become, outside the boundary years 1 AD to 9999 AD. """ if not delta: return time_struct # No work to do try: dt_result = op(datetime(*time_struct[:6]), delta) return dt_to_struct_time(dt_result) except (OverflowError, ValueError): # Year is not within supported 1 to 9999 AD range pass # Here we fake the year to one in the acceptable range to avoid having to # write our own date rolling logic # Adjust the year to be close to the 2000 millenium in 1,000 year # increments to try and retain accurate relative leap years actual_year = time_struct.tm_year millenium = int(float(actual_year) / 1000) millenium_diff = (2 - millenium) * 1000 adjusted_year = actual_year + millenium_diff # Apply delta to the date/time with adjusted year dt = datetime(*(adjusted_year, ) + time_struct[1:6]) dt_result = op(dt, delta) # Convert result year back to its original millenium final_year = dt_result.year - millenium_diff return struct_time((final_year, ) + dt_result.timetuple()[1:6] + tuple(TIME_EMPTY_EXTRAS))
def _strict_date(self, lean): if self.date == "open": return dt_to_struct_time(date.today()) if self.date =="unknown": return None # depends on the other date return self.date._strict_date(lean)
def _strict_date(self, lean): if self.date == "open": return dt_to_struct_time(date.today()) if self.date == "unknown": return None # depends on the other date return self.date._strict_date(lean)