Mercurial > p > roundup > code
comparison roundup/date.py @ 1896:b3f63a0615db maint-0.6
backport of Date arithmetic fixes from trunk
| author | Anthony Baxter <anthonybaxter@users.sourceforge.net> |
|---|---|
| date | Tue, 04 Nov 2003 12:39:54 +0000 |
| parents | 2047425bf7e7 |
| children | 27b9292a2fe6 |
comparison
equal
deleted
inserted
replaced
| 1895:11010aae4ef0 | 1896:b3f63a0615db |
|---|---|
| 13 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 13 # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| 14 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" | 14 # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" |
| 15 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, | 15 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, |
| 16 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 16 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
| 17 # | 17 # |
| 18 # $Id: date.py,v 1.54 2003-04-23 11:48:05 richard Exp $ | 18 # $Id: date.py,v 1.54.2.1 2003-11-04 12:39:54 anthonybaxter Exp $ |
| 19 | 19 |
| 20 __doc__ = """ | 20 __doc__ = """ |
| 21 Date, time and time interval handling. | 21 Date, time and time interval handling. |
| 22 """ | 22 """ |
| 23 | 23 |
| 202 while month < 1 or month > 12: | 202 while month < 1 or month > 12: |
| 203 if month < 1: year -= 1; month += 12 | 203 if month < 1: year -= 1; month += 12 |
| 204 if month > 12: year += 1; month -= 12 | 204 if month > 12: year += 1; month -= 12 |
| 205 | 205 |
| 206 # now do the days, now that we know what month we're in | 206 # now do the days, now that we know what month we're in |
| 207 mdays = calendar.mdays | 207 def get_mdays(year,month): |
| 208 if month == 2 and calendar.isleap(year): month_days = 29 | 208 if month == 2 and calendar.isleap(year): return 29 |
| 209 else: month_days = mdays[month] | 209 else: return calendar.mdays[month] |
| 210 while month < 1 or month > 12 or day < 0 or day > month_days: | 210 |
| 211 while month < 1 or month > 12 or day < 0 or day > get_mdays(year,month): | |
| 211 # now to day under/over | 212 # now to day under/over |
| 212 if day < 0: month -= 1; day += month_days | 213 if day < 0: |
| 213 elif day > month_days: month += 1; day -= month_days | 214 # When going backwards, decrement month, then increment days |
| 215 month -= 1 | |
| 216 day += get_mdays(year,month) | |
| 217 elif day > get_mdays(year,month): | |
| 218 # When going forwards, decrement days, then increment month | |
| 219 day -= get_mdays(year,month) | |
| 220 month += 1 | |
| 214 | 221 |
| 215 # possibly fix up the month so we're within range | 222 # possibly fix up the month so we're within range |
| 216 while month < 1 or month > 12: | 223 while month < 1 or month > 12: |
| 217 if month < 1: year -= 1; month += 12 | 224 if month < 1: year -= 1; month += 12 ; day += 31 |
| 218 if month > 12: year += 1; month -= 12 | 225 if month > 12: year += 1; month -= 12 |
| 219 | 226 |
| 220 # re-figure the number of days for this month | |
| 221 if month == 2 and calendar.isleap(year): month_days = 29 | |
| 222 else: month_days = mdays[month] | |
| 223 return (year, month, day, hour, minute, second, 0, 0, 0) | 227 return (year, month, day, hour, minute, second, 0, 0, 0) |
| 228 | |
| 229 def differenceDate(self, other): | |
| 230 "Return the difference between this date and another date" | |
| 224 | 231 |
| 225 def applyInterval(self, interval): | 232 def applyInterval(self, interval): |
| 226 ''' Apply the interval to this date | 233 ''' Apply the interval to this date |
| 227 ''' | 234 ''' |
| 228 self.year, self.month, self.day, self.hour, self.minute, \ | 235 self.year, self.month, self.day, self.hour, self.minute, \ |
| 244 other.sign *= -1 | 251 other.sign *= -1 |
| 245 return self.__add__(other) | 252 return self.__add__(other) |
| 246 | 253 |
| 247 assert isinstance(other, Date), 'May only subtract Dates or Intervals' | 254 assert isinstance(other, Date), 'May only subtract Dates or Intervals' |
| 248 | 255 |
| 249 # TODO this code will fall over laughing if the dates cross | 256 return self.dateDelta(other) |
| 250 # leap years, phases of the moon, .... | 257 |
| 258 def dateDelta(self, other): | |
| 259 """ Produce an Interval of the difference between this date | |
| 260 and another date. Only returns days:hours:minutes:seconds. | |
| 261 """ | |
| 262 # Returning intervals larger than a day is almost | |
| 263 # impossible - months, years, weeks, are all so imprecise. | |
| 251 a = calendar.timegm((self.year, self.month, self.day, self.hour, | 264 a = calendar.timegm((self.year, self.month, self.day, self.hour, |
| 252 self.minute, self.second, 0, 0, 0)) | 265 self.minute, self.second, 0, 0, 0)) |
| 253 b = calendar.timegm((other.year, other.month, other.day, | 266 b = calendar.timegm((other.year, other.month, other.day, |
| 254 other.hour, other.minute, other.second, 0, 0, 0)) | 267 other.hour, other.minute, other.second, 0, 0, 0)) |
| 255 diff = a - b | 268 diff = a - b |
| 256 if diff < 0: | 269 if diff > 0: |
| 257 sign = 1 | 270 sign = 1 |
| 271 else: | |
| 272 sign = -1 | |
| 258 diff = -diff | 273 diff = -diff |
| 259 else: | |
| 260 sign = -1 | |
| 261 S = diff%60 | 274 S = diff%60 |
| 262 M = (diff/60)%60 | 275 M = (diff/60)%60 |
| 263 H = (diff/(60*60))%60 | 276 H = (diff/(60*60))%24 |
| 264 if H>1: S = 0 | 277 d = diff/(24*60*60) |
| 265 d = (diff/(24*60*60))%30 | 278 return Interval((0, 0, d, H, M, S), sign=sign) |
| 266 if d>1: H = S = M = 0 | |
| 267 m = (diff/(30*24*60*60))%12 | |
| 268 if m>1: H = S = M = 0 | |
| 269 y = (diff/(365*24*60*60)) | |
| 270 if y>1: d = H = S = M = 0 | |
| 271 return Interval((y, m, d, H, M, S), sign=sign) | |
| 272 | 279 |
| 273 def __cmp__(self, other): | 280 def __cmp__(self, other): |
| 274 """Compare this date to another date.""" | 281 """Compare this date to another date.""" |
| 275 if other is None: | 282 if other is None: |
| 276 return 1 | 283 return 1 |
