1.1 --- a/DateSupport.py Sun Mar 25 21:19:17 2012 +0200
1.2 +++ b/DateSupport.py Mon Mar 26 00:14:22 2012 +0200
1.3 @@ -29,7 +29,7 @@
1.4 month_regexp_str = ur'(?P<year>[0-9]{4})-(?P<month>[0-9]{2})'
1.5 date_regexp_str = ur'(?P<year>[0-9]{4})-(?P<month>[0-9]{2})-(?P<day>[0-9]{2})'
1.6 time_regexp_str = ur'(?P<hour>[0-2][0-9]):(?P<minute>[0-5][0-9])(?::(?P<second>[0-6][0-9]))?'
1.7 -timezone_offset_str = ur'(?P<offset>(UTC)?(?:(?P<sign>[-+])(?P<hours>[0-9]{2})(?::?(?P<minutes>[0-9]{2}))?))'
1.8 +timezone_offset_str = ur'(?P<offset>(UTC)?(?:(?P<sign>[-+])?(?P<hours>[0-9]{2})(?::?(?P<minutes>[0-9]{2}))?))'
1.9 timezone_olson_str = ur'(?P<olson>[a-zA-Z]+(?:/[-_a-zA-Z]+){1,2})'
1.10 timezone_utc_str = ur'UTC'
1.11 timezone_regexp_str = ur'(?P<zone>' + timezone_offset_str + '|' + timezone_olson_str + '|' + timezone_utc_str + ')'
1.12 @@ -56,6 +56,12 @@
1.13
1.14 # Utility functions.
1.15
1.16 +def sign(x):
1.17 + if x < 0:
1.18 + return -1
1.19 + else:
1.20 + return 1
1.21 +
1.22 def int_or_none(x):
1.23 if x is None:
1.24 return x
1.25 @@ -164,10 +170,12 @@
1.26 else:
1.27 data = self.as_tuple()
1.28 other_data = other.as_tuple()
1.29 + direction = self < other and 1 or -1
1.30 +
1.31 if len(data) < len(other_data):
1.32 - return len(self.until(other))
1.33 + return (len(self.until(other)) - 1) * direction
1.34 else:
1.35 - return len(other.until(self))
1.36 + return (len(other.until(self)) - 1) * -direction
1.37
1.38 def _until(self, start, end, nextfn, prevfn):
1.39
1.40 @@ -442,6 +450,25 @@
1.41
1.42 return Date.__cmp__(this, other)
1.43
1.44 + def __sub__(self, other):
1.45 +
1.46 + """
1.47 + Return the difference between this object and the 'other' object at the
1.48 + highest common accuracy of both objects.
1.49 + """
1.50 +
1.51 + if not isinstance(other, Temporal):
1.52 + return NotImplemented
1.53 + elif not other.has_time():
1.54 + return self.as_date() - other
1.55 + else:
1.56 + utc = self.to_utc()
1.57 + other = other.to_utc()
1.58 + days = utc.as_date() - other.as_date()
1.59 + h1, m1, s1 = utc.as_tuple()[3:6]
1.60 + h2, m2, s2 = other.as_tuple()[3:6]
1.61 + return days * 24 * 3600 + (h1 - h2) * 3600 + (m1 - m2) * 60 + s1 - s2
1.62 +
1.63 def has_time(self):
1.64
1.65 """
1.66 @@ -546,12 +573,12 @@
1.67 match = timezone_offset_regexp.match(zone)
1.68 if match:
1.69 if match.group("sign") == "-":
1.70 - sign = -1
1.71 + offset_sign = -1
1.72 else:
1.73 - sign = 1
1.74 + offset_sign = 1
1.75
1.76 - hours = int(match.group("hours")) * sign
1.77 - minutes = int(match.group("minutes") or 0) * sign
1.78 + hours = int(match.group("hours")) * offset_sign
1.79 + minutes = int(match.group("minutes") or 0) * offset_sign
1.80 return hours, minutes
1.81
1.82 # Attempt to handle Olson time zone identifiers.
1.83 @@ -559,9 +586,9 @@
1.84 dt = self.as_olson_datetime()
1.85 if dt:
1.86 seconds = dt.utcoffset().seconds + dt.utcoffset().days * 24 * 3600
1.87 - hours = seconds / 3600
1.88 - minutes = (seconds % 3600) / 60
1.89 - return hours, minutes
1.90 + hours = abs(seconds) / 3600
1.91 + minutes = (abs(seconds) % 3600) / 60
1.92 + return sign(seconds) * hours, sign(seconds) * minutes
1.93
1.94 # Otherwise return None.
1.95