1*cda5da8dSAndroid Build Coastguard Worker"""Concrete date/time and related types. 2*cda5da8dSAndroid Build Coastguard Worker 3*cda5da8dSAndroid Build Coastguard WorkerSee http://www.iana.org/time-zones/repository/tz-link.html for 4*cda5da8dSAndroid Build Coastguard Workertime zone and DST data sources. 5*cda5da8dSAndroid Build Coastguard Worker""" 6*cda5da8dSAndroid Build Coastguard Worker 7*cda5da8dSAndroid Build Coastguard Worker__all__ = ("date", "datetime", "time", "timedelta", "timezone", "tzinfo", 8*cda5da8dSAndroid Build Coastguard Worker "MINYEAR", "MAXYEAR", "UTC") 9*cda5da8dSAndroid Build Coastguard Worker 10*cda5da8dSAndroid Build Coastguard Worker 11*cda5da8dSAndroid Build Coastguard Workerimport time as _time 12*cda5da8dSAndroid Build Coastguard Workerimport math as _math 13*cda5da8dSAndroid Build Coastguard Workerimport sys 14*cda5da8dSAndroid Build Coastguard Workerfrom operator import index as _index 15*cda5da8dSAndroid Build Coastguard Worker 16*cda5da8dSAndroid Build Coastguard Workerdef _cmp(x, y): 17*cda5da8dSAndroid Build Coastguard Worker return 0 if x == y else 1 if x > y else -1 18*cda5da8dSAndroid Build Coastguard Worker 19*cda5da8dSAndroid Build Coastguard WorkerMINYEAR = 1 20*cda5da8dSAndroid Build Coastguard WorkerMAXYEAR = 9999 21*cda5da8dSAndroid Build Coastguard Worker_MAXORDINAL = 3652059 # date.max.toordinal() 22*cda5da8dSAndroid Build Coastguard Worker 23*cda5da8dSAndroid Build Coastguard Worker# Utility functions, adapted from Python's Demo/classes/Dates.py, which 24*cda5da8dSAndroid Build Coastguard Worker# also assumes the current Gregorian calendar indefinitely extended in 25*cda5da8dSAndroid Build Coastguard Worker# both directions. Difference: Dates.py calls January 1 of year 0 day 26*cda5da8dSAndroid Build Coastguard Worker# number 1. The code here calls January 1 of year 1 day number 1. This is 27*cda5da8dSAndroid Build Coastguard Worker# to match the definition of the "proleptic Gregorian" calendar in Dershowitz 28*cda5da8dSAndroid Build Coastguard Worker# and Reingold's "Calendrical Calculations", where it's the base calendar 29*cda5da8dSAndroid Build Coastguard Worker# for all computations. See the book for algorithms for converting between 30*cda5da8dSAndroid Build Coastguard Worker# proleptic Gregorian ordinals and many other calendar systems. 31*cda5da8dSAndroid Build Coastguard Worker 32*cda5da8dSAndroid Build Coastguard Worker# -1 is a placeholder for indexing purposes. 33*cda5da8dSAndroid Build Coastguard Worker_DAYS_IN_MONTH = [-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] 34*cda5da8dSAndroid Build Coastguard Worker 35*cda5da8dSAndroid Build Coastguard Worker_DAYS_BEFORE_MONTH = [-1] # -1 is a placeholder for indexing purposes. 36*cda5da8dSAndroid Build Coastguard Workerdbm = 0 37*cda5da8dSAndroid Build Coastguard Workerfor dim in _DAYS_IN_MONTH[1:]: 38*cda5da8dSAndroid Build Coastguard Worker _DAYS_BEFORE_MONTH.append(dbm) 39*cda5da8dSAndroid Build Coastguard Worker dbm += dim 40*cda5da8dSAndroid Build Coastguard Workerdel dbm, dim 41*cda5da8dSAndroid Build Coastguard Worker 42*cda5da8dSAndroid Build Coastguard Workerdef _is_leap(year): 43*cda5da8dSAndroid Build Coastguard Worker "year -> 1 if leap year, else 0." 44*cda5da8dSAndroid Build Coastguard Worker return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0) 45*cda5da8dSAndroid Build Coastguard Worker 46*cda5da8dSAndroid Build Coastguard Workerdef _days_before_year(year): 47*cda5da8dSAndroid Build Coastguard Worker "year -> number of days before January 1st of year." 48*cda5da8dSAndroid Build Coastguard Worker y = year - 1 49*cda5da8dSAndroid Build Coastguard Worker return y*365 + y//4 - y//100 + y//400 50*cda5da8dSAndroid Build Coastguard Worker 51*cda5da8dSAndroid Build Coastguard Workerdef _days_in_month(year, month): 52*cda5da8dSAndroid Build Coastguard Worker "year, month -> number of days in that month in that year." 53*cda5da8dSAndroid Build Coastguard Worker assert 1 <= month <= 12, month 54*cda5da8dSAndroid Build Coastguard Worker if month == 2 and _is_leap(year): 55*cda5da8dSAndroid Build Coastguard Worker return 29 56*cda5da8dSAndroid Build Coastguard Worker return _DAYS_IN_MONTH[month] 57*cda5da8dSAndroid Build Coastguard Worker 58*cda5da8dSAndroid Build Coastguard Workerdef _days_before_month(year, month): 59*cda5da8dSAndroid Build Coastguard Worker "year, month -> number of days in year preceding first day of month." 60*cda5da8dSAndroid Build Coastguard Worker assert 1 <= month <= 12, 'month must be in 1..12' 61*cda5da8dSAndroid Build Coastguard Worker return _DAYS_BEFORE_MONTH[month] + (month > 2 and _is_leap(year)) 62*cda5da8dSAndroid Build Coastguard Worker 63*cda5da8dSAndroid Build Coastguard Workerdef _ymd2ord(year, month, day): 64*cda5da8dSAndroid Build Coastguard Worker "year, month, day -> ordinal, considering 01-Jan-0001 as day 1." 65*cda5da8dSAndroid Build Coastguard Worker assert 1 <= month <= 12, 'month must be in 1..12' 66*cda5da8dSAndroid Build Coastguard Worker dim = _days_in_month(year, month) 67*cda5da8dSAndroid Build Coastguard Worker assert 1 <= day <= dim, ('day must be in 1..%d' % dim) 68*cda5da8dSAndroid Build Coastguard Worker return (_days_before_year(year) + 69*cda5da8dSAndroid Build Coastguard Worker _days_before_month(year, month) + 70*cda5da8dSAndroid Build Coastguard Worker day) 71*cda5da8dSAndroid Build Coastguard Worker 72*cda5da8dSAndroid Build Coastguard Worker_DI400Y = _days_before_year(401) # number of days in 400 years 73*cda5da8dSAndroid Build Coastguard Worker_DI100Y = _days_before_year(101) # " " " " 100 " 74*cda5da8dSAndroid Build Coastguard Worker_DI4Y = _days_before_year(5) # " " " " 4 " 75*cda5da8dSAndroid Build Coastguard Worker 76*cda5da8dSAndroid Build Coastguard Worker# A 4-year cycle has an extra leap day over what we'd get from pasting 77*cda5da8dSAndroid Build Coastguard Worker# together 4 single years. 78*cda5da8dSAndroid Build Coastguard Workerassert _DI4Y == 4 * 365 + 1 79*cda5da8dSAndroid Build Coastguard Worker 80*cda5da8dSAndroid Build Coastguard Worker# Similarly, a 400-year cycle has an extra leap day over what we'd get from 81*cda5da8dSAndroid Build Coastguard Worker# pasting together 4 100-year cycles. 82*cda5da8dSAndroid Build Coastguard Workerassert _DI400Y == 4 * _DI100Y + 1 83*cda5da8dSAndroid Build Coastguard Worker 84*cda5da8dSAndroid Build Coastguard Worker# OTOH, a 100-year cycle has one fewer leap day than we'd get from 85*cda5da8dSAndroid Build Coastguard Worker# pasting together 25 4-year cycles. 86*cda5da8dSAndroid Build Coastguard Workerassert _DI100Y == 25 * _DI4Y - 1 87*cda5da8dSAndroid Build Coastguard Worker 88*cda5da8dSAndroid Build Coastguard Workerdef _ord2ymd(n): 89*cda5da8dSAndroid Build Coastguard Worker "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1." 90*cda5da8dSAndroid Build Coastguard Worker 91*cda5da8dSAndroid Build Coastguard Worker # n is a 1-based index, starting at 1-Jan-1. The pattern of leap years 92*cda5da8dSAndroid Build Coastguard Worker # repeats exactly every 400 years. The basic strategy is to find the 93*cda5da8dSAndroid Build Coastguard Worker # closest 400-year boundary at or before n, then work with the offset 94*cda5da8dSAndroid Build Coastguard Worker # from that boundary to n. Life is much clearer if we subtract 1 from 95*cda5da8dSAndroid Build Coastguard Worker # n first -- then the values of n at 400-year boundaries are exactly 96*cda5da8dSAndroid Build Coastguard Worker # those divisible by _DI400Y: 97*cda5da8dSAndroid Build Coastguard Worker # 98*cda5da8dSAndroid Build Coastguard Worker # D M Y n n-1 99*cda5da8dSAndroid Build Coastguard Worker # -- --- ---- ---------- ---------------- 100*cda5da8dSAndroid Build Coastguard Worker # 31 Dec -400 -_DI400Y -_DI400Y -1 101*cda5da8dSAndroid Build Coastguard Worker # 1 Jan -399 -_DI400Y +1 -_DI400Y 400-year boundary 102*cda5da8dSAndroid Build Coastguard Worker # ... 103*cda5da8dSAndroid Build Coastguard Worker # 30 Dec 000 -1 -2 104*cda5da8dSAndroid Build Coastguard Worker # 31 Dec 000 0 -1 105*cda5da8dSAndroid Build Coastguard Worker # 1 Jan 001 1 0 400-year boundary 106*cda5da8dSAndroid Build Coastguard Worker # 2 Jan 001 2 1 107*cda5da8dSAndroid Build Coastguard Worker # 3 Jan 001 3 2 108*cda5da8dSAndroid Build Coastguard Worker # ... 109*cda5da8dSAndroid Build Coastguard Worker # 31 Dec 400 _DI400Y _DI400Y -1 110*cda5da8dSAndroid Build Coastguard Worker # 1 Jan 401 _DI400Y +1 _DI400Y 400-year boundary 111*cda5da8dSAndroid Build Coastguard Worker n -= 1 112*cda5da8dSAndroid Build Coastguard Worker n400, n = divmod(n, _DI400Y) 113*cda5da8dSAndroid Build Coastguard Worker year = n400 * 400 + 1 # ..., -399, 1, 401, ... 114*cda5da8dSAndroid Build Coastguard Worker 115*cda5da8dSAndroid Build Coastguard Worker # Now n is the (non-negative) offset, in days, from January 1 of year, to 116*cda5da8dSAndroid Build Coastguard Worker # the desired date. Now compute how many 100-year cycles precede n. 117*cda5da8dSAndroid Build Coastguard Worker # Note that it's possible for n100 to equal 4! In that case 4 full 118*cda5da8dSAndroid Build Coastguard Worker # 100-year cycles precede the desired day, which implies the desired 119*cda5da8dSAndroid Build Coastguard Worker # day is December 31 at the end of a 400-year cycle. 120*cda5da8dSAndroid Build Coastguard Worker n100, n = divmod(n, _DI100Y) 121*cda5da8dSAndroid Build Coastguard Worker 122*cda5da8dSAndroid Build Coastguard Worker # Now compute how many 4-year cycles precede it. 123*cda5da8dSAndroid Build Coastguard Worker n4, n = divmod(n, _DI4Y) 124*cda5da8dSAndroid Build Coastguard Worker 125*cda5da8dSAndroid Build Coastguard Worker # And now how many single years. Again n1 can be 4, and again meaning 126*cda5da8dSAndroid Build Coastguard Worker # that the desired day is December 31 at the end of the 4-year cycle. 127*cda5da8dSAndroid Build Coastguard Worker n1, n = divmod(n, 365) 128*cda5da8dSAndroid Build Coastguard Worker 129*cda5da8dSAndroid Build Coastguard Worker year += n100 * 100 + n4 * 4 + n1 130*cda5da8dSAndroid Build Coastguard Worker if n1 == 4 or n100 == 4: 131*cda5da8dSAndroid Build Coastguard Worker assert n == 0 132*cda5da8dSAndroid Build Coastguard Worker return year-1, 12, 31 133*cda5da8dSAndroid Build Coastguard Worker 134*cda5da8dSAndroid Build Coastguard Worker # Now the year is correct, and n is the offset from January 1. We find 135*cda5da8dSAndroid Build Coastguard Worker # the month via an estimate that's either exact or one too large. 136*cda5da8dSAndroid Build Coastguard Worker leapyear = n1 == 3 and (n4 != 24 or n100 == 3) 137*cda5da8dSAndroid Build Coastguard Worker assert leapyear == _is_leap(year) 138*cda5da8dSAndroid Build Coastguard Worker month = (n + 50) >> 5 139*cda5da8dSAndroid Build Coastguard Worker preceding = _DAYS_BEFORE_MONTH[month] + (month > 2 and leapyear) 140*cda5da8dSAndroid Build Coastguard Worker if preceding > n: # estimate is too large 141*cda5da8dSAndroid Build Coastguard Worker month -= 1 142*cda5da8dSAndroid Build Coastguard Worker preceding -= _DAYS_IN_MONTH[month] + (month == 2 and leapyear) 143*cda5da8dSAndroid Build Coastguard Worker n -= preceding 144*cda5da8dSAndroid Build Coastguard Worker assert 0 <= n < _days_in_month(year, month) 145*cda5da8dSAndroid Build Coastguard Worker 146*cda5da8dSAndroid Build Coastguard Worker # Now the year and month are correct, and n is the offset from the 147*cda5da8dSAndroid Build Coastguard Worker # start of that month: we're done! 148*cda5da8dSAndroid Build Coastguard Worker return year, month, n+1 149*cda5da8dSAndroid Build Coastguard Worker 150*cda5da8dSAndroid Build Coastguard Worker# Month and day names. For localized versions, see the calendar module. 151*cda5da8dSAndroid Build Coastguard Worker_MONTHNAMES = [None, "Jan", "Feb", "Mar", "Apr", "May", "Jun", 152*cda5da8dSAndroid Build Coastguard Worker "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] 153*cda5da8dSAndroid Build Coastguard Worker_DAYNAMES = [None, "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] 154*cda5da8dSAndroid Build Coastguard Worker 155*cda5da8dSAndroid Build Coastguard Worker 156*cda5da8dSAndroid Build Coastguard Workerdef _build_struct_time(y, m, d, hh, mm, ss, dstflag): 157*cda5da8dSAndroid Build Coastguard Worker wday = (_ymd2ord(y, m, d) + 6) % 7 158*cda5da8dSAndroid Build Coastguard Worker dnum = _days_before_month(y, m) + d 159*cda5da8dSAndroid Build Coastguard Worker return _time.struct_time((y, m, d, hh, mm, ss, wday, dnum, dstflag)) 160*cda5da8dSAndroid Build Coastguard Worker 161*cda5da8dSAndroid Build Coastguard Workerdef _format_time(hh, mm, ss, us, timespec='auto'): 162*cda5da8dSAndroid Build Coastguard Worker specs = { 163*cda5da8dSAndroid Build Coastguard Worker 'hours': '{:02d}', 164*cda5da8dSAndroid Build Coastguard Worker 'minutes': '{:02d}:{:02d}', 165*cda5da8dSAndroid Build Coastguard Worker 'seconds': '{:02d}:{:02d}:{:02d}', 166*cda5da8dSAndroid Build Coastguard Worker 'milliseconds': '{:02d}:{:02d}:{:02d}.{:03d}', 167*cda5da8dSAndroid Build Coastguard Worker 'microseconds': '{:02d}:{:02d}:{:02d}.{:06d}' 168*cda5da8dSAndroid Build Coastguard Worker } 169*cda5da8dSAndroid Build Coastguard Worker 170*cda5da8dSAndroid Build Coastguard Worker if timespec == 'auto': 171*cda5da8dSAndroid Build Coastguard Worker # Skip trailing microseconds when us==0. 172*cda5da8dSAndroid Build Coastguard Worker timespec = 'microseconds' if us else 'seconds' 173*cda5da8dSAndroid Build Coastguard Worker elif timespec == 'milliseconds': 174*cda5da8dSAndroid Build Coastguard Worker us //= 1000 175*cda5da8dSAndroid Build Coastguard Worker try: 176*cda5da8dSAndroid Build Coastguard Worker fmt = specs[timespec] 177*cda5da8dSAndroid Build Coastguard Worker except KeyError: 178*cda5da8dSAndroid Build Coastguard Worker raise ValueError('Unknown timespec value') 179*cda5da8dSAndroid Build Coastguard Worker else: 180*cda5da8dSAndroid Build Coastguard Worker return fmt.format(hh, mm, ss, us) 181*cda5da8dSAndroid Build Coastguard Worker 182*cda5da8dSAndroid Build Coastguard Workerdef _format_offset(off): 183*cda5da8dSAndroid Build Coastguard Worker s = '' 184*cda5da8dSAndroid Build Coastguard Worker if off is not None: 185*cda5da8dSAndroid Build Coastguard Worker if off.days < 0: 186*cda5da8dSAndroid Build Coastguard Worker sign = "-" 187*cda5da8dSAndroid Build Coastguard Worker off = -off 188*cda5da8dSAndroid Build Coastguard Worker else: 189*cda5da8dSAndroid Build Coastguard Worker sign = "+" 190*cda5da8dSAndroid Build Coastguard Worker hh, mm = divmod(off, timedelta(hours=1)) 191*cda5da8dSAndroid Build Coastguard Worker mm, ss = divmod(mm, timedelta(minutes=1)) 192*cda5da8dSAndroid Build Coastguard Worker s += "%s%02d:%02d" % (sign, hh, mm) 193*cda5da8dSAndroid Build Coastguard Worker if ss or ss.microseconds: 194*cda5da8dSAndroid Build Coastguard Worker s += ":%02d" % ss.seconds 195*cda5da8dSAndroid Build Coastguard Worker 196*cda5da8dSAndroid Build Coastguard Worker if ss.microseconds: 197*cda5da8dSAndroid Build Coastguard Worker s += '.%06d' % ss.microseconds 198*cda5da8dSAndroid Build Coastguard Worker return s 199*cda5da8dSAndroid Build Coastguard Worker 200*cda5da8dSAndroid Build Coastguard Worker# Correctly substitute for %z and %Z escapes in strftime formats. 201*cda5da8dSAndroid Build Coastguard Workerdef _wrap_strftime(object, format, timetuple): 202*cda5da8dSAndroid Build Coastguard Worker # Don't call utcoffset() or tzname() unless actually needed. 203*cda5da8dSAndroid Build Coastguard Worker freplace = None # the string to use for %f 204*cda5da8dSAndroid Build Coastguard Worker zreplace = None # the string to use for %z 205*cda5da8dSAndroid Build Coastguard Worker Zreplace = None # the string to use for %Z 206*cda5da8dSAndroid Build Coastguard Worker 207*cda5da8dSAndroid Build Coastguard Worker # Scan format for %z and %Z escapes, replacing as needed. 208*cda5da8dSAndroid Build Coastguard Worker newformat = [] 209*cda5da8dSAndroid Build Coastguard Worker push = newformat.append 210*cda5da8dSAndroid Build Coastguard Worker i, n = 0, len(format) 211*cda5da8dSAndroid Build Coastguard Worker while i < n: 212*cda5da8dSAndroid Build Coastguard Worker ch = format[i] 213*cda5da8dSAndroid Build Coastguard Worker i += 1 214*cda5da8dSAndroid Build Coastguard Worker if ch == '%': 215*cda5da8dSAndroid Build Coastguard Worker if i < n: 216*cda5da8dSAndroid Build Coastguard Worker ch = format[i] 217*cda5da8dSAndroid Build Coastguard Worker i += 1 218*cda5da8dSAndroid Build Coastguard Worker if ch == 'f': 219*cda5da8dSAndroid Build Coastguard Worker if freplace is None: 220*cda5da8dSAndroid Build Coastguard Worker freplace = '%06d' % getattr(object, 221*cda5da8dSAndroid Build Coastguard Worker 'microsecond', 0) 222*cda5da8dSAndroid Build Coastguard Worker newformat.append(freplace) 223*cda5da8dSAndroid Build Coastguard Worker elif ch == 'z': 224*cda5da8dSAndroid Build Coastguard Worker if zreplace is None: 225*cda5da8dSAndroid Build Coastguard Worker zreplace = "" 226*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, "utcoffset"): 227*cda5da8dSAndroid Build Coastguard Worker offset = object.utcoffset() 228*cda5da8dSAndroid Build Coastguard Worker if offset is not None: 229*cda5da8dSAndroid Build Coastguard Worker sign = '+' 230*cda5da8dSAndroid Build Coastguard Worker if offset.days < 0: 231*cda5da8dSAndroid Build Coastguard Worker offset = -offset 232*cda5da8dSAndroid Build Coastguard Worker sign = '-' 233*cda5da8dSAndroid Build Coastguard Worker h, rest = divmod(offset, timedelta(hours=1)) 234*cda5da8dSAndroid Build Coastguard Worker m, rest = divmod(rest, timedelta(minutes=1)) 235*cda5da8dSAndroid Build Coastguard Worker s = rest.seconds 236*cda5da8dSAndroid Build Coastguard Worker u = offset.microseconds 237*cda5da8dSAndroid Build Coastguard Worker if u: 238*cda5da8dSAndroid Build Coastguard Worker zreplace = '%c%02d%02d%02d.%06d' % (sign, h, m, s, u) 239*cda5da8dSAndroid Build Coastguard Worker elif s: 240*cda5da8dSAndroid Build Coastguard Worker zreplace = '%c%02d%02d%02d' % (sign, h, m, s) 241*cda5da8dSAndroid Build Coastguard Worker else: 242*cda5da8dSAndroid Build Coastguard Worker zreplace = '%c%02d%02d' % (sign, h, m) 243*cda5da8dSAndroid Build Coastguard Worker assert '%' not in zreplace 244*cda5da8dSAndroid Build Coastguard Worker newformat.append(zreplace) 245*cda5da8dSAndroid Build Coastguard Worker elif ch == 'Z': 246*cda5da8dSAndroid Build Coastguard Worker if Zreplace is None: 247*cda5da8dSAndroid Build Coastguard Worker Zreplace = "" 248*cda5da8dSAndroid Build Coastguard Worker if hasattr(object, "tzname"): 249*cda5da8dSAndroid Build Coastguard Worker s = object.tzname() 250*cda5da8dSAndroid Build Coastguard Worker if s is not None: 251*cda5da8dSAndroid Build Coastguard Worker # strftime is going to have at this: escape % 252*cda5da8dSAndroid Build Coastguard Worker Zreplace = s.replace('%', '%%') 253*cda5da8dSAndroid Build Coastguard Worker newformat.append(Zreplace) 254*cda5da8dSAndroid Build Coastguard Worker else: 255*cda5da8dSAndroid Build Coastguard Worker push('%') 256*cda5da8dSAndroid Build Coastguard Worker push(ch) 257*cda5da8dSAndroid Build Coastguard Worker else: 258*cda5da8dSAndroid Build Coastguard Worker push('%') 259*cda5da8dSAndroid Build Coastguard Worker else: 260*cda5da8dSAndroid Build Coastguard Worker push(ch) 261*cda5da8dSAndroid Build Coastguard Worker newformat = "".join(newformat) 262*cda5da8dSAndroid Build Coastguard Worker return _time.strftime(newformat, timetuple) 263*cda5da8dSAndroid Build Coastguard Worker 264*cda5da8dSAndroid Build Coastguard Worker# Helpers for parsing the result of isoformat() 265*cda5da8dSAndroid Build Coastguard Workerdef _is_ascii_digit(c): 266*cda5da8dSAndroid Build Coastguard Worker return c in "0123456789" 267*cda5da8dSAndroid Build Coastguard Worker 268*cda5da8dSAndroid Build Coastguard Workerdef _find_isoformat_datetime_separator(dtstr): 269*cda5da8dSAndroid Build Coastguard Worker # See the comment in _datetimemodule.c:_find_isoformat_datetime_separator 270*cda5da8dSAndroid Build Coastguard Worker len_dtstr = len(dtstr) 271*cda5da8dSAndroid Build Coastguard Worker if len_dtstr == 7: 272*cda5da8dSAndroid Build Coastguard Worker return 7 273*cda5da8dSAndroid Build Coastguard Worker 274*cda5da8dSAndroid Build Coastguard Worker assert len_dtstr > 7 275*cda5da8dSAndroid Build Coastguard Worker date_separator = "-" 276*cda5da8dSAndroid Build Coastguard Worker week_indicator = "W" 277*cda5da8dSAndroid Build Coastguard Worker 278*cda5da8dSAndroid Build Coastguard Worker if dtstr[4] == date_separator: 279*cda5da8dSAndroid Build Coastguard Worker if dtstr[5] == week_indicator: 280*cda5da8dSAndroid Build Coastguard Worker if len_dtstr < 8: 281*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Invalid ISO string") 282*cda5da8dSAndroid Build Coastguard Worker if len_dtstr > 8 and dtstr[8] == date_separator: 283*cda5da8dSAndroid Build Coastguard Worker if len_dtstr == 9: 284*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Invalid ISO string") 285*cda5da8dSAndroid Build Coastguard Worker if len_dtstr > 10 and _is_ascii_digit(dtstr[10]): 286*cda5da8dSAndroid Build Coastguard Worker # This is as far as we need to resolve the ambiguity for 287*cda5da8dSAndroid Build Coastguard Worker # the moment - if we have YYYY-Www-##, the separator is 288*cda5da8dSAndroid Build Coastguard Worker # either a hyphen at 8 or a number at 10. 289*cda5da8dSAndroid Build Coastguard Worker # 290*cda5da8dSAndroid Build Coastguard Worker # We'll assume it's a hyphen at 8 because it's way more 291*cda5da8dSAndroid Build Coastguard Worker # likely that someone will use a hyphen as a separator than 292*cda5da8dSAndroid Build Coastguard Worker # a number, but at this point it's really best effort 293*cda5da8dSAndroid Build Coastguard Worker # because this is an extension of the spec anyway. 294*cda5da8dSAndroid Build Coastguard Worker # TODO(pganssle): Document this 295*cda5da8dSAndroid Build Coastguard Worker return 8 296*cda5da8dSAndroid Build Coastguard Worker return 10 297*cda5da8dSAndroid Build Coastguard Worker else: 298*cda5da8dSAndroid Build Coastguard Worker # YYYY-Www (8) 299*cda5da8dSAndroid Build Coastguard Worker return 8 300*cda5da8dSAndroid Build Coastguard Worker else: 301*cda5da8dSAndroid Build Coastguard Worker # YYYY-MM-DD (10) 302*cda5da8dSAndroid Build Coastguard Worker return 10 303*cda5da8dSAndroid Build Coastguard Worker else: 304*cda5da8dSAndroid Build Coastguard Worker if dtstr[4] == week_indicator: 305*cda5da8dSAndroid Build Coastguard Worker # YYYYWww (7) or YYYYWwwd (8) 306*cda5da8dSAndroid Build Coastguard Worker idx = 7 307*cda5da8dSAndroid Build Coastguard Worker while idx < len_dtstr: 308*cda5da8dSAndroid Build Coastguard Worker if not _is_ascii_digit(dtstr[idx]): 309*cda5da8dSAndroid Build Coastguard Worker break 310*cda5da8dSAndroid Build Coastguard Worker idx += 1 311*cda5da8dSAndroid Build Coastguard Worker 312*cda5da8dSAndroid Build Coastguard Worker if idx < 9: 313*cda5da8dSAndroid Build Coastguard Worker return idx 314*cda5da8dSAndroid Build Coastguard Worker 315*cda5da8dSAndroid Build Coastguard Worker if idx % 2 == 0: 316*cda5da8dSAndroid Build Coastguard Worker # If the index of the last number is even, it's YYYYWwwd 317*cda5da8dSAndroid Build Coastguard Worker return 7 318*cda5da8dSAndroid Build Coastguard Worker else: 319*cda5da8dSAndroid Build Coastguard Worker return 8 320*cda5da8dSAndroid Build Coastguard Worker else: 321*cda5da8dSAndroid Build Coastguard Worker # YYYYMMDD (8) 322*cda5da8dSAndroid Build Coastguard Worker return 8 323*cda5da8dSAndroid Build Coastguard Worker 324*cda5da8dSAndroid Build Coastguard Worker 325*cda5da8dSAndroid Build Coastguard Workerdef _parse_isoformat_date(dtstr): 326*cda5da8dSAndroid Build Coastguard Worker # It is assumed that this is an ASCII-only string of lengths 7, 8 or 10, 327*cda5da8dSAndroid Build Coastguard Worker # see the comment on Modules/_datetimemodule.c:_find_isoformat_datetime_separator 328*cda5da8dSAndroid Build Coastguard Worker assert len(dtstr) in (7, 8, 10) 329*cda5da8dSAndroid Build Coastguard Worker year = int(dtstr[0:4]) 330*cda5da8dSAndroid Build Coastguard Worker has_sep = dtstr[4] == '-' 331*cda5da8dSAndroid Build Coastguard Worker 332*cda5da8dSAndroid Build Coastguard Worker pos = 4 + has_sep 333*cda5da8dSAndroid Build Coastguard Worker if dtstr[pos:pos + 1] == "W": 334*cda5da8dSAndroid Build Coastguard Worker # YYYY-?Www-?D? 335*cda5da8dSAndroid Build Coastguard Worker pos += 1 336*cda5da8dSAndroid Build Coastguard Worker weekno = int(dtstr[pos:pos + 2]) 337*cda5da8dSAndroid Build Coastguard Worker pos += 2 338*cda5da8dSAndroid Build Coastguard Worker 339*cda5da8dSAndroid Build Coastguard Worker dayno = 1 340*cda5da8dSAndroid Build Coastguard Worker if len(dtstr) > pos: 341*cda5da8dSAndroid Build Coastguard Worker if (dtstr[pos:pos + 1] == '-') != has_sep: 342*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Inconsistent use of dash separator") 343*cda5da8dSAndroid Build Coastguard Worker 344*cda5da8dSAndroid Build Coastguard Worker pos += has_sep 345*cda5da8dSAndroid Build Coastguard Worker 346*cda5da8dSAndroid Build Coastguard Worker dayno = int(dtstr[pos:pos + 1]) 347*cda5da8dSAndroid Build Coastguard Worker 348*cda5da8dSAndroid Build Coastguard Worker return list(_isoweek_to_gregorian(year, weekno, dayno)) 349*cda5da8dSAndroid Build Coastguard Worker else: 350*cda5da8dSAndroid Build Coastguard Worker month = int(dtstr[pos:pos + 2]) 351*cda5da8dSAndroid Build Coastguard Worker pos += 2 352*cda5da8dSAndroid Build Coastguard Worker if (dtstr[pos:pos + 1] == "-") != has_sep: 353*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Inconsistent use of dash separator") 354*cda5da8dSAndroid Build Coastguard Worker 355*cda5da8dSAndroid Build Coastguard Worker pos += has_sep 356*cda5da8dSAndroid Build Coastguard Worker day = int(dtstr[pos:pos + 2]) 357*cda5da8dSAndroid Build Coastguard Worker 358*cda5da8dSAndroid Build Coastguard Worker return [year, month, day] 359*cda5da8dSAndroid Build Coastguard Worker 360*cda5da8dSAndroid Build Coastguard Worker 361*cda5da8dSAndroid Build Coastguard Worker_FRACTION_CORRECTION = [100000, 10000, 1000, 100, 10] 362*cda5da8dSAndroid Build Coastguard Worker 363*cda5da8dSAndroid Build Coastguard Worker 364*cda5da8dSAndroid Build Coastguard Workerdef _parse_hh_mm_ss_ff(tstr): 365*cda5da8dSAndroid Build Coastguard Worker # Parses things of the form HH[:?MM[:?SS[{.,}fff[fff]]]] 366*cda5da8dSAndroid Build Coastguard Worker len_str = len(tstr) 367*cda5da8dSAndroid Build Coastguard Worker 368*cda5da8dSAndroid Build Coastguard Worker time_comps = [0, 0, 0, 0] 369*cda5da8dSAndroid Build Coastguard Worker pos = 0 370*cda5da8dSAndroid Build Coastguard Worker for comp in range(0, 3): 371*cda5da8dSAndroid Build Coastguard Worker if (len_str - pos) < 2: 372*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Incomplete time component") 373*cda5da8dSAndroid Build Coastguard Worker 374*cda5da8dSAndroid Build Coastguard Worker time_comps[comp] = int(tstr[pos:pos+2]) 375*cda5da8dSAndroid Build Coastguard Worker 376*cda5da8dSAndroid Build Coastguard Worker pos += 2 377*cda5da8dSAndroid Build Coastguard Worker next_char = tstr[pos:pos+1] 378*cda5da8dSAndroid Build Coastguard Worker 379*cda5da8dSAndroid Build Coastguard Worker if comp == 0: 380*cda5da8dSAndroid Build Coastguard Worker has_sep = next_char == ':' 381*cda5da8dSAndroid Build Coastguard Worker 382*cda5da8dSAndroid Build Coastguard Worker if not next_char or comp >= 2: 383*cda5da8dSAndroid Build Coastguard Worker break 384*cda5da8dSAndroid Build Coastguard Worker 385*cda5da8dSAndroid Build Coastguard Worker if has_sep and next_char != ':': 386*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Invalid time separator: %c" % next_char) 387*cda5da8dSAndroid Build Coastguard Worker 388*cda5da8dSAndroid Build Coastguard Worker pos += has_sep 389*cda5da8dSAndroid Build Coastguard Worker 390*cda5da8dSAndroid Build Coastguard Worker if pos < len_str: 391*cda5da8dSAndroid Build Coastguard Worker if tstr[pos] not in '.,': 392*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Invalid microsecond component") 393*cda5da8dSAndroid Build Coastguard Worker else: 394*cda5da8dSAndroid Build Coastguard Worker pos += 1 395*cda5da8dSAndroid Build Coastguard Worker 396*cda5da8dSAndroid Build Coastguard Worker len_remainder = len_str - pos 397*cda5da8dSAndroid Build Coastguard Worker 398*cda5da8dSAndroid Build Coastguard Worker if len_remainder >= 6: 399*cda5da8dSAndroid Build Coastguard Worker to_parse = 6 400*cda5da8dSAndroid Build Coastguard Worker else: 401*cda5da8dSAndroid Build Coastguard Worker to_parse = len_remainder 402*cda5da8dSAndroid Build Coastguard Worker 403*cda5da8dSAndroid Build Coastguard Worker time_comps[3] = int(tstr[pos:(pos+to_parse)]) 404*cda5da8dSAndroid Build Coastguard Worker if to_parse < 6: 405*cda5da8dSAndroid Build Coastguard Worker time_comps[3] *= _FRACTION_CORRECTION[to_parse-1] 406*cda5da8dSAndroid Build Coastguard Worker if (len_remainder > to_parse 407*cda5da8dSAndroid Build Coastguard Worker and not all(map(_is_ascii_digit, tstr[(pos+to_parse):]))): 408*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Non-digit values in unparsed fraction") 409*cda5da8dSAndroid Build Coastguard Worker 410*cda5da8dSAndroid Build Coastguard Worker return time_comps 411*cda5da8dSAndroid Build Coastguard Worker 412*cda5da8dSAndroid Build Coastguard Workerdef _parse_isoformat_time(tstr): 413*cda5da8dSAndroid Build Coastguard Worker # Format supported is HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]] 414*cda5da8dSAndroid Build Coastguard Worker len_str = len(tstr) 415*cda5da8dSAndroid Build Coastguard Worker if len_str < 2: 416*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Isoformat time too short") 417*cda5da8dSAndroid Build Coastguard Worker 418*cda5da8dSAndroid Build Coastguard Worker # This is equivalent to re.search('[+-Z]', tstr), but faster 419*cda5da8dSAndroid Build Coastguard Worker tz_pos = (tstr.find('-') + 1 or tstr.find('+') + 1 or tstr.find('Z') + 1) 420*cda5da8dSAndroid Build Coastguard Worker timestr = tstr[:tz_pos-1] if tz_pos > 0 else tstr 421*cda5da8dSAndroid Build Coastguard Worker 422*cda5da8dSAndroid Build Coastguard Worker time_comps = _parse_hh_mm_ss_ff(timestr) 423*cda5da8dSAndroid Build Coastguard Worker 424*cda5da8dSAndroid Build Coastguard Worker tzi = None 425*cda5da8dSAndroid Build Coastguard Worker if tz_pos == len_str and tstr[-1] == 'Z': 426*cda5da8dSAndroid Build Coastguard Worker tzi = timezone.utc 427*cda5da8dSAndroid Build Coastguard Worker elif tz_pos > 0: 428*cda5da8dSAndroid Build Coastguard Worker tzstr = tstr[tz_pos:] 429*cda5da8dSAndroid Build Coastguard Worker 430*cda5da8dSAndroid Build Coastguard Worker # Valid time zone strings are: 431*cda5da8dSAndroid Build Coastguard Worker # HH len: 2 432*cda5da8dSAndroid Build Coastguard Worker # HHMM len: 4 433*cda5da8dSAndroid Build Coastguard Worker # HH:MM len: 5 434*cda5da8dSAndroid Build Coastguard Worker # HHMMSS len: 6 435*cda5da8dSAndroid Build Coastguard Worker # HHMMSS.f+ len: 7+ 436*cda5da8dSAndroid Build Coastguard Worker # HH:MM:SS len: 8 437*cda5da8dSAndroid Build Coastguard Worker # HH:MM:SS.f+ len: 10+ 438*cda5da8dSAndroid Build Coastguard Worker 439*cda5da8dSAndroid Build Coastguard Worker if len(tzstr) in (0, 1, 3): 440*cda5da8dSAndroid Build Coastguard Worker raise ValueError("Malformed time zone string") 441*cda5da8dSAndroid Build Coastguard Worker 442*cda5da8dSAndroid Build Coastguard Worker tz_comps = _parse_hh_mm_ss_ff(tzstr) 443*cda5da8dSAndroid Build Coastguard Worker 444*cda5da8dSAndroid Build Coastguard Worker if all(x == 0 for x in tz_comps): 445*cda5da8dSAndroid Build Coastguard Worker tzi = timezone.utc 446*cda5da8dSAndroid Build Coastguard Worker else: 447*cda5da8dSAndroid Build Coastguard Worker tzsign = -1 if tstr[tz_pos - 1] == '-' else 1 448*cda5da8dSAndroid Build Coastguard Worker 449*cda5da8dSAndroid Build Coastguard Worker td = timedelta(hours=tz_comps[0], minutes=tz_comps[1], 450*cda5da8dSAndroid Build Coastguard Worker seconds=tz_comps[2], microseconds=tz_comps[3]) 451*cda5da8dSAndroid Build Coastguard Worker 452*cda5da8dSAndroid Build Coastguard Worker tzi = timezone(tzsign * td) 453*cda5da8dSAndroid Build Coastguard Worker 454*cda5da8dSAndroid Build Coastguard Worker time_comps.append(tzi) 455*cda5da8dSAndroid Build Coastguard Worker 456*cda5da8dSAndroid Build Coastguard Worker return time_comps 457*cda5da8dSAndroid Build Coastguard Worker 458*cda5da8dSAndroid Build Coastguard Worker# tuple[int, int, int] -> tuple[int, int, int] version of date.fromisocalendar 459*cda5da8dSAndroid Build Coastguard Workerdef _isoweek_to_gregorian(year, week, day): 460*cda5da8dSAndroid Build Coastguard Worker # Year is bounded this way because 9999-12-31 is (9999, 52, 5) 461*cda5da8dSAndroid Build Coastguard Worker if not MINYEAR <= year <= MAXYEAR: 462*cda5da8dSAndroid Build Coastguard Worker raise ValueError(f"Year is out of range: {year}") 463*cda5da8dSAndroid Build Coastguard Worker 464*cda5da8dSAndroid Build Coastguard Worker if not 0 < week < 53: 465*cda5da8dSAndroid Build Coastguard Worker out_of_range = True 466*cda5da8dSAndroid Build Coastguard Worker 467*cda5da8dSAndroid Build Coastguard Worker if week == 53: 468*cda5da8dSAndroid Build Coastguard Worker # ISO years have 53 weeks in them on years starting with a 469*cda5da8dSAndroid Build Coastguard Worker # Thursday and leap years starting on a Wednesday 470*cda5da8dSAndroid Build Coastguard Worker first_weekday = _ymd2ord(year, 1, 1) % 7 471*cda5da8dSAndroid Build Coastguard Worker if (first_weekday == 4 or (first_weekday == 3 and 472*cda5da8dSAndroid Build Coastguard Worker _is_leap(year))): 473*cda5da8dSAndroid Build Coastguard Worker out_of_range = False 474*cda5da8dSAndroid Build Coastguard Worker 475*cda5da8dSAndroid Build Coastguard Worker if out_of_range: 476*cda5da8dSAndroid Build Coastguard Worker raise ValueError(f"Invalid week: {week}") 477*cda5da8dSAndroid Build Coastguard Worker 478*cda5da8dSAndroid Build Coastguard Worker if not 0 < day < 8: 479*cda5da8dSAndroid Build Coastguard Worker raise ValueError(f"Invalid weekday: {day} (range is [1, 7])") 480*cda5da8dSAndroid Build Coastguard Worker 481*cda5da8dSAndroid Build Coastguard Worker # Now compute the offset from (Y, 1, 1) in days: 482*cda5da8dSAndroid Build Coastguard Worker day_offset = (week - 1) * 7 + (day - 1) 483*cda5da8dSAndroid Build Coastguard Worker 484*cda5da8dSAndroid Build Coastguard Worker # Calculate the ordinal day for monday, week 1 485*cda5da8dSAndroid Build Coastguard Worker day_1 = _isoweek1monday(year) 486*cda5da8dSAndroid Build Coastguard Worker ord_day = day_1 + day_offset 487*cda5da8dSAndroid Build Coastguard Worker 488*cda5da8dSAndroid Build Coastguard Worker return _ord2ymd(ord_day) 489*cda5da8dSAndroid Build Coastguard Worker 490*cda5da8dSAndroid Build Coastguard Worker 491*cda5da8dSAndroid Build Coastguard Worker# Just raise TypeError if the arg isn't None or a string. 492*cda5da8dSAndroid Build Coastguard Workerdef _check_tzname(name): 493*cda5da8dSAndroid Build Coastguard Worker if name is not None and not isinstance(name, str): 494*cda5da8dSAndroid Build Coastguard Worker raise TypeError("tzinfo.tzname() must return None or string, " 495*cda5da8dSAndroid Build Coastguard Worker "not '%s'" % type(name)) 496*cda5da8dSAndroid Build Coastguard Worker 497*cda5da8dSAndroid Build Coastguard Worker# name is the offset-producing method, "utcoffset" or "dst". 498*cda5da8dSAndroid Build Coastguard Worker# offset is what it returned. 499*cda5da8dSAndroid Build Coastguard Worker# If offset isn't None or timedelta, raises TypeError. 500*cda5da8dSAndroid Build Coastguard Worker# If offset is None, returns None. 501*cda5da8dSAndroid Build Coastguard Worker# Else offset is checked for being in range. 502*cda5da8dSAndroid Build Coastguard Worker# If it is, its integer value is returned. Else ValueError is raised. 503*cda5da8dSAndroid Build Coastguard Workerdef _check_utc_offset(name, offset): 504*cda5da8dSAndroid Build Coastguard Worker assert name in ("utcoffset", "dst") 505*cda5da8dSAndroid Build Coastguard Worker if offset is None: 506*cda5da8dSAndroid Build Coastguard Worker return 507*cda5da8dSAndroid Build Coastguard Worker if not isinstance(offset, timedelta): 508*cda5da8dSAndroid Build Coastguard Worker raise TypeError("tzinfo.%s() must return None " 509*cda5da8dSAndroid Build Coastguard Worker "or timedelta, not '%s'" % (name, type(offset))) 510*cda5da8dSAndroid Build Coastguard Worker if not -timedelta(1) < offset < timedelta(1): 511*cda5da8dSAndroid Build Coastguard Worker raise ValueError("%s()=%s, must be strictly between " 512*cda5da8dSAndroid Build Coastguard Worker "-timedelta(hours=24) and timedelta(hours=24)" % 513*cda5da8dSAndroid Build Coastguard Worker (name, offset)) 514*cda5da8dSAndroid Build Coastguard Worker 515*cda5da8dSAndroid Build Coastguard Workerdef _check_date_fields(year, month, day): 516*cda5da8dSAndroid Build Coastguard Worker year = _index(year) 517*cda5da8dSAndroid Build Coastguard Worker month = _index(month) 518*cda5da8dSAndroid Build Coastguard Worker day = _index(day) 519*cda5da8dSAndroid Build Coastguard Worker if not MINYEAR <= year <= MAXYEAR: 520*cda5da8dSAndroid Build Coastguard Worker raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year) 521*cda5da8dSAndroid Build Coastguard Worker if not 1 <= month <= 12: 522*cda5da8dSAndroid Build Coastguard Worker raise ValueError('month must be in 1..12', month) 523*cda5da8dSAndroid Build Coastguard Worker dim = _days_in_month(year, month) 524*cda5da8dSAndroid Build Coastguard Worker if not 1 <= day <= dim: 525*cda5da8dSAndroid Build Coastguard Worker raise ValueError('day must be in 1..%d' % dim, day) 526*cda5da8dSAndroid Build Coastguard Worker return year, month, day 527*cda5da8dSAndroid Build Coastguard Worker 528*cda5da8dSAndroid Build Coastguard Workerdef _check_time_fields(hour, minute, second, microsecond, fold): 529*cda5da8dSAndroid Build Coastguard Worker hour = _index(hour) 530*cda5da8dSAndroid Build Coastguard Worker minute = _index(minute) 531*cda5da8dSAndroid Build Coastguard Worker second = _index(second) 532*cda5da8dSAndroid Build Coastguard Worker microsecond = _index(microsecond) 533*cda5da8dSAndroid Build Coastguard Worker if not 0 <= hour <= 23: 534*cda5da8dSAndroid Build Coastguard Worker raise ValueError('hour must be in 0..23', hour) 535*cda5da8dSAndroid Build Coastguard Worker if not 0 <= minute <= 59: 536*cda5da8dSAndroid Build Coastguard Worker raise ValueError('minute must be in 0..59', minute) 537*cda5da8dSAndroid Build Coastguard Worker if not 0 <= second <= 59: 538*cda5da8dSAndroid Build Coastguard Worker raise ValueError('second must be in 0..59', second) 539*cda5da8dSAndroid Build Coastguard Worker if not 0 <= microsecond <= 999999: 540*cda5da8dSAndroid Build Coastguard Worker raise ValueError('microsecond must be in 0..999999', microsecond) 541*cda5da8dSAndroid Build Coastguard Worker if fold not in (0, 1): 542*cda5da8dSAndroid Build Coastguard Worker raise ValueError('fold must be either 0 or 1', fold) 543*cda5da8dSAndroid Build Coastguard Worker return hour, minute, second, microsecond, fold 544*cda5da8dSAndroid Build Coastguard Worker 545*cda5da8dSAndroid Build Coastguard Workerdef _check_tzinfo_arg(tz): 546*cda5da8dSAndroid Build Coastguard Worker if tz is not None and not isinstance(tz, tzinfo): 547*cda5da8dSAndroid Build Coastguard Worker raise TypeError("tzinfo argument must be None or of a tzinfo subclass") 548*cda5da8dSAndroid Build Coastguard Worker 549*cda5da8dSAndroid Build Coastguard Workerdef _cmperror(x, y): 550*cda5da8dSAndroid Build Coastguard Worker raise TypeError("can't compare '%s' to '%s'" % ( 551*cda5da8dSAndroid Build Coastguard Worker type(x).__name__, type(y).__name__)) 552*cda5da8dSAndroid Build Coastguard Worker 553*cda5da8dSAndroid Build Coastguard Workerdef _divide_and_round(a, b): 554*cda5da8dSAndroid Build Coastguard Worker """divide a by b and round result to the nearest integer 555*cda5da8dSAndroid Build Coastguard Worker 556*cda5da8dSAndroid Build Coastguard Worker When the ratio is exactly half-way between two integers, 557*cda5da8dSAndroid Build Coastguard Worker the even integer is returned. 558*cda5da8dSAndroid Build Coastguard Worker """ 559*cda5da8dSAndroid Build Coastguard Worker # Based on the reference implementation for divmod_near 560*cda5da8dSAndroid Build Coastguard Worker # in Objects/longobject.c. 561*cda5da8dSAndroid Build Coastguard Worker q, r = divmod(a, b) 562*cda5da8dSAndroid Build Coastguard Worker # round up if either r / b > 0.5, or r / b == 0.5 and q is odd. 563*cda5da8dSAndroid Build Coastguard Worker # The expression r / b > 0.5 is equivalent to 2 * r > b if b is 564*cda5da8dSAndroid Build Coastguard Worker # positive, 2 * r < b if b negative. 565*cda5da8dSAndroid Build Coastguard Worker r *= 2 566*cda5da8dSAndroid Build Coastguard Worker greater_than_half = r > b if b > 0 else r < b 567*cda5da8dSAndroid Build Coastguard Worker if greater_than_half or r == b and q % 2 == 1: 568*cda5da8dSAndroid Build Coastguard Worker q += 1 569*cda5da8dSAndroid Build Coastguard Worker 570*cda5da8dSAndroid Build Coastguard Worker return q 571*cda5da8dSAndroid Build Coastguard Worker 572*cda5da8dSAndroid Build Coastguard Worker 573*cda5da8dSAndroid Build Coastguard Workerclass timedelta: 574*cda5da8dSAndroid Build Coastguard Worker """Represent the difference between two datetime objects. 575*cda5da8dSAndroid Build Coastguard Worker 576*cda5da8dSAndroid Build Coastguard Worker Supported operators: 577*cda5da8dSAndroid Build Coastguard Worker 578*cda5da8dSAndroid Build Coastguard Worker - add, subtract timedelta 579*cda5da8dSAndroid Build Coastguard Worker - unary plus, minus, abs 580*cda5da8dSAndroid Build Coastguard Worker - compare to timedelta 581*cda5da8dSAndroid Build Coastguard Worker - multiply, divide by int 582*cda5da8dSAndroid Build Coastguard Worker 583*cda5da8dSAndroid Build Coastguard Worker In addition, datetime supports subtraction of two datetime objects 584*cda5da8dSAndroid Build Coastguard Worker returning a timedelta, and addition or subtraction of a datetime 585*cda5da8dSAndroid Build Coastguard Worker and a timedelta giving a datetime. 586*cda5da8dSAndroid Build Coastguard Worker 587*cda5da8dSAndroid Build Coastguard Worker Representation: (days, seconds, microseconds). Why? Because I 588*cda5da8dSAndroid Build Coastguard Worker felt like it. 589*cda5da8dSAndroid Build Coastguard Worker """ 590*cda5da8dSAndroid Build Coastguard Worker __slots__ = '_days', '_seconds', '_microseconds', '_hashcode' 591*cda5da8dSAndroid Build Coastguard Worker 592*cda5da8dSAndroid Build Coastguard Worker def __new__(cls, days=0, seconds=0, microseconds=0, 593*cda5da8dSAndroid Build Coastguard Worker milliseconds=0, minutes=0, hours=0, weeks=0): 594*cda5da8dSAndroid Build Coastguard Worker # Doing this efficiently and accurately in C is going to be difficult 595*cda5da8dSAndroid Build Coastguard Worker # and error-prone, due to ubiquitous overflow possibilities, and that 596*cda5da8dSAndroid Build Coastguard Worker # C double doesn't have enough bits of precision to represent 597*cda5da8dSAndroid Build Coastguard Worker # microseconds over 10K years faithfully. The code here tries to make 598*cda5da8dSAndroid Build Coastguard Worker # explicit where go-fast assumptions can be relied on, in order to 599*cda5da8dSAndroid Build Coastguard Worker # guide the C implementation; it's way more convoluted than speed- 600*cda5da8dSAndroid Build Coastguard Worker # ignoring auto-overflow-to-long idiomatic Python could be. 601*cda5da8dSAndroid Build Coastguard Worker 602*cda5da8dSAndroid Build Coastguard Worker # XXX Check that all inputs are ints or floats. 603*cda5da8dSAndroid Build Coastguard Worker 604*cda5da8dSAndroid Build Coastguard Worker # Final values, all integer. 605*cda5da8dSAndroid Build Coastguard Worker # s and us fit in 32-bit signed ints; d isn't bounded. 606*cda5da8dSAndroid Build Coastguard Worker d = s = us = 0 607*cda5da8dSAndroid Build Coastguard Worker 608*cda5da8dSAndroid Build Coastguard Worker # Normalize everything to days, seconds, microseconds. 609*cda5da8dSAndroid Build Coastguard Worker days += weeks*7 610*cda5da8dSAndroid Build Coastguard Worker seconds += minutes*60 + hours*3600 611*cda5da8dSAndroid Build Coastguard Worker microseconds += milliseconds*1000 612*cda5da8dSAndroid Build Coastguard Worker 613*cda5da8dSAndroid Build Coastguard Worker # Get rid of all fractions, and normalize s and us. 614*cda5da8dSAndroid Build Coastguard Worker # Take a deep breath <wink>. 615*cda5da8dSAndroid Build Coastguard Worker if isinstance(days, float): 616*cda5da8dSAndroid Build Coastguard Worker dayfrac, days = _math.modf(days) 617*cda5da8dSAndroid Build Coastguard Worker daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.)) 618*cda5da8dSAndroid Build Coastguard Worker assert daysecondswhole == int(daysecondswhole) # can't overflow 619*cda5da8dSAndroid Build Coastguard Worker s = int(daysecondswhole) 620*cda5da8dSAndroid Build Coastguard Worker assert days == int(days) 621*cda5da8dSAndroid Build Coastguard Worker d = int(days) 622*cda5da8dSAndroid Build Coastguard Worker else: 623*cda5da8dSAndroid Build Coastguard Worker daysecondsfrac = 0.0 624*cda5da8dSAndroid Build Coastguard Worker d = days 625*cda5da8dSAndroid Build Coastguard Worker assert isinstance(daysecondsfrac, float) 626*cda5da8dSAndroid Build Coastguard Worker assert abs(daysecondsfrac) <= 1.0 627*cda5da8dSAndroid Build Coastguard Worker assert isinstance(d, int) 628*cda5da8dSAndroid Build Coastguard Worker assert abs(s) <= 24 * 3600 629*cda5da8dSAndroid Build Coastguard Worker # days isn't referenced again before redefinition 630*cda5da8dSAndroid Build Coastguard Worker 631*cda5da8dSAndroid Build Coastguard Worker if isinstance(seconds, float): 632*cda5da8dSAndroid Build Coastguard Worker secondsfrac, seconds = _math.modf(seconds) 633*cda5da8dSAndroid Build Coastguard Worker assert seconds == int(seconds) 634*cda5da8dSAndroid Build Coastguard Worker seconds = int(seconds) 635*cda5da8dSAndroid Build Coastguard Worker secondsfrac += daysecondsfrac 636*cda5da8dSAndroid Build Coastguard Worker assert abs(secondsfrac) <= 2.0 637*cda5da8dSAndroid Build Coastguard Worker else: 638*cda5da8dSAndroid Build Coastguard Worker secondsfrac = daysecondsfrac 639*cda5da8dSAndroid Build Coastguard Worker # daysecondsfrac isn't referenced again 640*cda5da8dSAndroid Build Coastguard Worker assert isinstance(secondsfrac, float) 641*cda5da8dSAndroid Build Coastguard Worker assert abs(secondsfrac) <= 2.0 642*cda5da8dSAndroid Build Coastguard Worker 643*cda5da8dSAndroid Build Coastguard Worker assert isinstance(seconds, int) 644*cda5da8dSAndroid Build Coastguard Worker days, seconds = divmod(seconds, 24*3600) 645*cda5da8dSAndroid Build Coastguard Worker d += days 646*cda5da8dSAndroid Build Coastguard Worker s += int(seconds) # can't overflow 647*cda5da8dSAndroid Build Coastguard Worker assert isinstance(s, int) 648*cda5da8dSAndroid Build Coastguard Worker assert abs(s) <= 2 * 24 * 3600 649*cda5da8dSAndroid Build Coastguard Worker # seconds isn't referenced again before redefinition 650*cda5da8dSAndroid Build Coastguard Worker 651*cda5da8dSAndroid Build Coastguard Worker usdouble = secondsfrac * 1e6 652*cda5da8dSAndroid Build Coastguard Worker assert abs(usdouble) < 2.1e6 # exact value not critical 653*cda5da8dSAndroid Build Coastguard Worker # secondsfrac isn't referenced again 654*cda5da8dSAndroid Build Coastguard Worker 655*cda5da8dSAndroid Build Coastguard Worker if isinstance(microseconds, float): 656*cda5da8dSAndroid Build Coastguard Worker microseconds = round(microseconds + usdouble) 657*cda5da8dSAndroid Build Coastguard Worker seconds, microseconds = divmod(microseconds, 1000000) 658*cda5da8dSAndroid Build Coastguard Worker days, seconds = divmod(seconds, 24*3600) 659*cda5da8dSAndroid Build Coastguard Worker d += days 660*cda5da8dSAndroid Build Coastguard Worker s += seconds 661*cda5da8dSAndroid Build Coastguard Worker else: 662*cda5da8dSAndroid Build Coastguard Worker microseconds = int(microseconds) 663*cda5da8dSAndroid Build Coastguard Worker seconds, microseconds = divmod(microseconds, 1000000) 664*cda5da8dSAndroid Build Coastguard Worker days, seconds = divmod(seconds, 24*3600) 665*cda5da8dSAndroid Build Coastguard Worker d += days 666*cda5da8dSAndroid Build Coastguard Worker s += seconds 667*cda5da8dSAndroid Build Coastguard Worker microseconds = round(microseconds + usdouble) 668*cda5da8dSAndroid Build Coastguard Worker assert isinstance(s, int) 669*cda5da8dSAndroid Build Coastguard Worker assert isinstance(microseconds, int) 670*cda5da8dSAndroid Build Coastguard Worker assert abs(s) <= 3 * 24 * 3600 671*cda5da8dSAndroid Build Coastguard Worker assert abs(microseconds) < 3.1e6 672*cda5da8dSAndroid Build Coastguard Worker 673*cda5da8dSAndroid Build Coastguard Worker # Just a little bit of carrying possible for microseconds and seconds. 674*cda5da8dSAndroid Build Coastguard Worker seconds, us = divmod(microseconds, 1000000) 675*cda5da8dSAndroid Build Coastguard Worker s += seconds 676*cda5da8dSAndroid Build Coastguard Worker days, s = divmod(s, 24*3600) 677*cda5da8dSAndroid Build Coastguard Worker d += days 678*cda5da8dSAndroid Build Coastguard Worker 679*cda5da8dSAndroid Build Coastguard Worker assert isinstance(d, int) 680*cda5da8dSAndroid Build Coastguard Worker assert isinstance(s, int) and 0 <= s < 24*3600 681*cda5da8dSAndroid Build Coastguard Worker assert isinstance(us, int) and 0 <= us < 1000000 682*cda5da8dSAndroid Build Coastguard Worker 683*cda5da8dSAndroid Build Coastguard Worker if abs(d) > 999999999: 684*cda5da8dSAndroid Build Coastguard Worker raise OverflowError("timedelta # of days is too large: %d" % d) 685*cda5da8dSAndroid Build Coastguard Worker 686*cda5da8dSAndroid Build Coastguard Worker self = object.__new__(cls) 687*cda5da8dSAndroid Build Coastguard Worker self._days = d 688*cda5da8dSAndroid Build Coastguard Worker self._seconds = s 689*cda5da8dSAndroid Build Coastguard Worker self._microseconds = us 690*cda5da8dSAndroid Build Coastguard Worker self._hashcode = -1 691*cda5da8dSAndroid Build Coastguard Worker return self 692*cda5da8dSAndroid Build Coastguard Worker 693*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 694*cda5da8dSAndroid Build Coastguard Worker args = [] 695*cda5da8dSAndroid Build Coastguard Worker if self._days: 696*cda5da8dSAndroid Build Coastguard Worker args.append("days=%d" % self._days) 697*cda5da8dSAndroid Build Coastguard Worker if self._seconds: 698*cda5da8dSAndroid Build Coastguard Worker args.append("seconds=%d" % self._seconds) 699*cda5da8dSAndroid Build Coastguard Worker if self._microseconds: 700*cda5da8dSAndroid Build Coastguard Worker args.append("microseconds=%d" % self._microseconds) 701*cda5da8dSAndroid Build Coastguard Worker if not args: 702*cda5da8dSAndroid Build Coastguard Worker args.append('0') 703*cda5da8dSAndroid Build Coastguard Worker return "%s.%s(%s)" % (self.__class__.__module__, 704*cda5da8dSAndroid Build Coastguard Worker self.__class__.__qualname__, 705*cda5da8dSAndroid Build Coastguard Worker ', '.join(args)) 706*cda5da8dSAndroid Build Coastguard Worker 707*cda5da8dSAndroid Build Coastguard Worker def __str__(self): 708*cda5da8dSAndroid Build Coastguard Worker mm, ss = divmod(self._seconds, 60) 709*cda5da8dSAndroid Build Coastguard Worker hh, mm = divmod(mm, 60) 710*cda5da8dSAndroid Build Coastguard Worker s = "%d:%02d:%02d" % (hh, mm, ss) 711*cda5da8dSAndroid Build Coastguard Worker if self._days: 712*cda5da8dSAndroid Build Coastguard Worker def plural(n): 713*cda5da8dSAndroid Build Coastguard Worker return n, abs(n) != 1 and "s" or "" 714*cda5da8dSAndroid Build Coastguard Worker s = ("%d day%s, " % plural(self._days)) + s 715*cda5da8dSAndroid Build Coastguard Worker if self._microseconds: 716*cda5da8dSAndroid Build Coastguard Worker s = s + ".%06d" % self._microseconds 717*cda5da8dSAndroid Build Coastguard Worker return s 718*cda5da8dSAndroid Build Coastguard Worker 719*cda5da8dSAndroid Build Coastguard Worker def total_seconds(self): 720*cda5da8dSAndroid Build Coastguard Worker """Total seconds in the duration.""" 721*cda5da8dSAndroid Build Coastguard Worker return ((self.days * 86400 + self.seconds) * 10**6 + 722*cda5da8dSAndroid Build Coastguard Worker self.microseconds) / 10**6 723*cda5da8dSAndroid Build Coastguard Worker 724*cda5da8dSAndroid Build Coastguard Worker # Read-only field accessors 725*cda5da8dSAndroid Build Coastguard Worker @property 726*cda5da8dSAndroid Build Coastguard Worker def days(self): 727*cda5da8dSAndroid Build Coastguard Worker """days""" 728*cda5da8dSAndroid Build Coastguard Worker return self._days 729*cda5da8dSAndroid Build Coastguard Worker 730*cda5da8dSAndroid Build Coastguard Worker @property 731*cda5da8dSAndroid Build Coastguard Worker def seconds(self): 732*cda5da8dSAndroid Build Coastguard Worker """seconds""" 733*cda5da8dSAndroid Build Coastguard Worker return self._seconds 734*cda5da8dSAndroid Build Coastguard Worker 735*cda5da8dSAndroid Build Coastguard Worker @property 736*cda5da8dSAndroid Build Coastguard Worker def microseconds(self): 737*cda5da8dSAndroid Build Coastguard Worker """microseconds""" 738*cda5da8dSAndroid Build Coastguard Worker return self._microseconds 739*cda5da8dSAndroid Build Coastguard Worker 740*cda5da8dSAndroid Build Coastguard Worker def __add__(self, other): 741*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 742*cda5da8dSAndroid Build Coastguard Worker # for CPython compatibility, we cannot use 743*cda5da8dSAndroid Build Coastguard Worker # our __class__ here, but need a real timedelta 744*cda5da8dSAndroid Build Coastguard Worker return timedelta(self._days + other._days, 745*cda5da8dSAndroid Build Coastguard Worker self._seconds + other._seconds, 746*cda5da8dSAndroid Build Coastguard Worker self._microseconds + other._microseconds) 747*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 748*cda5da8dSAndroid Build Coastguard Worker 749*cda5da8dSAndroid Build Coastguard Worker __radd__ = __add__ 750*cda5da8dSAndroid Build Coastguard Worker 751*cda5da8dSAndroid Build Coastguard Worker def __sub__(self, other): 752*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 753*cda5da8dSAndroid Build Coastguard Worker # for CPython compatibility, we cannot use 754*cda5da8dSAndroid Build Coastguard Worker # our __class__ here, but need a real timedelta 755*cda5da8dSAndroid Build Coastguard Worker return timedelta(self._days - other._days, 756*cda5da8dSAndroid Build Coastguard Worker self._seconds - other._seconds, 757*cda5da8dSAndroid Build Coastguard Worker self._microseconds - other._microseconds) 758*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 759*cda5da8dSAndroid Build Coastguard Worker 760*cda5da8dSAndroid Build Coastguard Worker def __rsub__(self, other): 761*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 762*cda5da8dSAndroid Build Coastguard Worker return -self + other 763*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 764*cda5da8dSAndroid Build Coastguard Worker 765*cda5da8dSAndroid Build Coastguard Worker def __neg__(self): 766*cda5da8dSAndroid Build Coastguard Worker # for CPython compatibility, we cannot use 767*cda5da8dSAndroid Build Coastguard Worker # our __class__ here, but need a real timedelta 768*cda5da8dSAndroid Build Coastguard Worker return timedelta(-self._days, 769*cda5da8dSAndroid Build Coastguard Worker -self._seconds, 770*cda5da8dSAndroid Build Coastguard Worker -self._microseconds) 771*cda5da8dSAndroid Build Coastguard Worker 772*cda5da8dSAndroid Build Coastguard Worker def __pos__(self): 773*cda5da8dSAndroid Build Coastguard Worker return self 774*cda5da8dSAndroid Build Coastguard Worker 775*cda5da8dSAndroid Build Coastguard Worker def __abs__(self): 776*cda5da8dSAndroid Build Coastguard Worker if self._days < 0: 777*cda5da8dSAndroid Build Coastguard Worker return -self 778*cda5da8dSAndroid Build Coastguard Worker else: 779*cda5da8dSAndroid Build Coastguard Worker return self 780*cda5da8dSAndroid Build Coastguard Worker 781*cda5da8dSAndroid Build Coastguard Worker def __mul__(self, other): 782*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, int): 783*cda5da8dSAndroid Build Coastguard Worker # for CPython compatibility, we cannot use 784*cda5da8dSAndroid Build Coastguard Worker # our __class__ here, but need a real timedelta 785*cda5da8dSAndroid Build Coastguard Worker return timedelta(self._days * other, 786*cda5da8dSAndroid Build Coastguard Worker self._seconds * other, 787*cda5da8dSAndroid Build Coastguard Worker self._microseconds * other) 788*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, float): 789*cda5da8dSAndroid Build Coastguard Worker usec = self._to_microseconds() 790*cda5da8dSAndroid Build Coastguard Worker a, b = other.as_integer_ratio() 791*cda5da8dSAndroid Build Coastguard Worker return timedelta(0, 0, _divide_and_round(usec * a, b)) 792*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 793*cda5da8dSAndroid Build Coastguard Worker 794*cda5da8dSAndroid Build Coastguard Worker __rmul__ = __mul__ 795*cda5da8dSAndroid Build Coastguard Worker 796*cda5da8dSAndroid Build Coastguard Worker def _to_microseconds(self): 797*cda5da8dSAndroid Build Coastguard Worker return ((self._days * (24*3600) + self._seconds) * 1000000 + 798*cda5da8dSAndroid Build Coastguard Worker self._microseconds) 799*cda5da8dSAndroid Build Coastguard Worker 800*cda5da8dSAndroid Build Coastguard Worker def __floordiv__(self, other): 801*cda5da8dSAndroid Build Coastguard Worker if not isinstance(other, (int, timedelta)): 802*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 803*cda5da8dSAndroid Build Coastguard Worker usec = self._to_microseconds() 804*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 805*cda5da8dSAndroid Build Coastguard Worker return usec // other._to_microseconds() 806*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, int): 807*cda5da8dSAndroid Build Coastguard Worker return timedelta(0, 0, usec // other) 808*cda5da8dSAndroid Build Coastguard Worker 809*cda5da8dSAndroid Build Coastguard Worker def __truediv__(self, other): 810*cda5da8dSAndroid Build Coastguard Worker if not isinstance(other, (int, float, timedelta)): 811*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 812*cda5da8dSAndroid Build Coastguard Worker usec = self._to_microseconds() 813*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 814*cda5da8dSAndroid Build Coastguard Worker return usec / other._to_microseconds() 815*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, int): 816*cda5da8dSAndroid Build Coastguard Worker return timedelta(0, 0, _divide_and_round(usec, other)) 817*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, float): 818*cda5da8dSAndroid Build Coastguard Worker a, b = other.as_integer_ratio() 819*cda5da8dSAndroid Build Coastguard Worker return timedelta(0, 0, _divide_and_round(b * usec, a)) 820*cda5da8dSAndroid Build Coastguard Worker 821*cda5da8dSAndroid Build Coastguard Worker def __mod__(self, other): 822*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 823*cda5da8dSAndroid Build Coastguard Worker r = self._to_microseconds() % other._to_microseconds() 824*cda5da8dSAndroid Build Coastguard Worker return timedelta(0, 0, r) 825*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 826*cda5da8dSAndroid Build Coastguard Worker 827*cda5da8dSAndroid Build Coastguard Worker def __divmod__(self, other): 828*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 829*cda5da8dSAndroid Build Coastguard Worker q, r = divmod(self._to_microseconds(), 830*cda5da8dSAndroid Build Coastguard Worker other._to_microseconds()) 831*cda5da8dSAndroid Build Coastguard Worker return q, timedelta(0, 0, r) 832*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 833*cda5da8dSAndroid Build Coastguard Worker 834*cda5da8dSAndroid Build Coastguard Worker # Comparisons of timedelta objects with other. 835*cda5da8dSAndroid Build Coastguard Worker 836*cda5da8dSAndroid Build Coastguard Worker def __eq__(self, other): 837*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 838*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) == 0 839*cda5da8dSAndroid Build Coastguard Worker else: 840*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 841*cda5da8dSAndroid Build Coastguard Worker 842*cda5da8dSAndroid Build Coastguard Worker def __le__(self, other): 843*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 844*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) <= 0 845*cda5da8dSAndroid Build Coastguard Worker else: 846*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 847*cda5da8dSAndroid Build Coastguard Worker 848*cda5da8dSAndroid Build Coastguard Worker def __lt__(self, other): 849*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 850*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) < 0 851*cda5da8dSAndroid Build Coastguard Worker else: 852*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 853*cda5da8dSAndroid Build Coastguard Worker 854*cda5da8dSAndroid Build Coastguard Worker def __ge__(self, other): 855*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 856*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) >= 0 857*cda5da8dSAndroid Build Coastguard Worker else: 858*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 859*cda5da8dSAndroid Build Coastguard Worker 860*cda5da8dSAndroid Build Coastguard Worker def __gt__(self, other): 861*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 862*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) > 0 863*cda5da8dSAndroid Build Coastguard Worker else: 864*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 865*cda5da8dSAndroid Build Coastguard Worker 866*cda5da8dSAndroid Build Coastguard Worker def _cmp(self, other): 867*cda5da8dSAndroid Build Coastguard Worker assert isinstance(other, timedelta) 868*cda5da8dSAndroid Build Coastguard Worker return _cmp(self._getstate(), other._getstate()) 869*cda5da8dSAndroid Build Coastguard Worker 870*cda5da8dSAndroid Build Coastguard Worker def __hash__(self): 871*cda5da8dSAndroid Build Coastguard Worker if self._hashcode == -1: 872*cda5da8dSAndroid Build Coastguard Worker self._hashcode = hash(self._getstate()) 873*cda5da8dSAndroid Build Coastguard Worker return self._hashcode 874*cda5da8dSAndroid Build Coastguard Worker 875*cda5da8dSAndroid Build Coastguard Worker def __bool__(self): 876*cda5da8dSAndroid Build Coastguard Worker return (self._days != 0 or 877*cda5da8dSAndroid Build Coastguard Worker self._seconds != 0 or 878*cda5da8dSAndroid Build Coastguard Worker self._microseconds != 0) 879*cda5da8dSAndroid Build Coastguard Worker 880*cda5da8dSAndroid Build Coastguard Worker # Pickle support. 881*cda5da8dSAndroid Build Coastguard Worker 882*cda5da8dSAndroid Build Coastguard Worker def _getstate(self): 883*cda5da8dSAndroid Build Coastguard Worker return (self._days, self._seconds, self._microseconds) 884*cda5da8dSAndroid Build Coastguard Worker 885*cda5da8dSAndroid Build Coastguard Worker def __reduce__(self): 886*cda5da8dSAndroid Build Coastguard Worker return (self.__class__, self._getstate()) 887*cda5da8dSAndroid Build Coastguard Worker 888*cda5da8dSAndroid Build Coastguard Workertimedelta.min = timedelta(-999999999) 889*cda5da8dSAndroid Build Coastguard Workertimedelta.max = timedelta(days=999999999, hours=23, minutes=59, seconds=59, 890*cda5da8dSAndroid Build Coastguard Worker microseconds=999999) 891*cda5da8dSAndroid Build Coastguard Workertimedelta.resolution = timedelta(microseconds=1) 892*cda5da8dSAndroid Build Coastguard Worker 893*cda5da8dSAndroid Build Coastguard Workerclass date: 894*cda5da8dSAndroid Build Coastguard Worker """Concrete date type. 895*cda5da8dSAndroid Build Coastguard Worker 896*cda5da8dSAndroid Build Coastguard Worker Constructors: 897*cda5da8dSAndroid Build Coastguard Worker 898*cda5da8dSAndroid Build Coastguard Worker __new__() 899*cda5da8dSAndroid Build Coastguard Worker fromtimestamp() 900*cda5da8dSAndroid Build Coastguard Worker today() 901*cda5da8dSAndroid Build Coastguard Worker fromordinal() 902*cda5da8dSAndroid Build Coastguard Worker 903*cda5da8dSAndroid Build Coastguard Worker Operators: 904*cda5da8dSAndroid Build Coastguard Worker 905*cda5da8dSAndroid Build Coastguard Worker __repr__, __str__ 906*cda5da8dSAndroid Build Coastguard Worker __eq__, __le__, __lt__, __ge__, __gt__, __hash__ 907*cda5da8dSAndroid Build Coastguard Worker __add__, __radd__, __sub__ (add/radd only with timedelta arg) 908*cda5da8dSAndroid Build Coastguard Worker 909*cda5da8dSAndroid Build Coastguard Worker Methods: 910*cda5da8dSAndroid Build Coastguard Worker 911*cda5da8dSAndroid Build Coastguard Worker timetuple() 912*cda5da8dSAndroid Build Coastguard Worker toordinal() 913*cda5da8dSAndroid Build Coastguard Worker weekday() 914*cda5da8dSAndroid Build Coastguard Worker isoweekday(), isocalendar(), isoformat() 915*cda5da8dSAndroid Build Coastguard Worker ctime() 916*cda5da8dSAndroid Build Coastguard Worker strftime() 917*cda5da8dSAndroid Build Coastguard Worker 918*cda5da8dSAndroid Build Coastguard Worker Properties (readonly): 919*cda5da8dSAndroid Build Coastguard Worker year, month, day 920*cda5da8dSAndroid Build Coastguard Worker """ 921*cda5da8dSAndroid Build Coastguard Worker __slots__ = '_year', '_month', '_day', '_hashcode' 922*cda5da8dSAndroid Build Coastguard Worker 923*cda5da8dSAndroid Build Coastguard Worker def __new__(cls, year, month=None, day=None): 924*cda5da8dSAndroid Build Coastguard Worker """Constructor. 925*cda5da8dSAndroid Build Coastguard Worker 926*cda5da8dSAndroid Build Coastguard Worker Arguments: 927*cda5da8dSAndroid Build Coastguard Worker 928*cda5da8dSAndroid Build Coastguard Worker year, month, day (required, base 1) 929*cda5da8dSAndroid Build Coastguard Worker """ 930*cda5da8dSAndroid Build Coastguard Worker if (month is None and 931*cda5da8dSAndroid Build Coastguard Worker isinstance(year, (bytes, str)) and len(year) == 4 and 932*cda5da8dSAndroid Build Coastguard Worker 1 <= ord(year[2:3]) <= 12): 933*cda5da8dSAndroid Build Coastguard Worker # Pickle support 934*cda5da8dSAndroid Build Coastguard Worker if isinstance(year, str): 935*cda5da8dSAndroid Build Coastguard Worker try: 936*cda5da8dSAndroid Build Coastguard Worker year = year.encode('latin1') 937*cda5da8dSAndroid Build Coastguard Worker except UnicodeEncodeError: 938*cda5da8dSAndroid Build Coastguard Worker # More informative error message. 939*cda5da8dSAndroid Build Coastguard Worker raise ValueError( 940*cda5da8dSAndroid Build Coastguard Worker "Failed to encode latin1 string when unpickling " 941*cda5da8dSAndroid Build Coastguard Worker "a date object. " 942*cda5da8dSAndroid Build Coastguard Worker "pickle.load(data, encoding='latin1') is assumed.") 943*cda5da8dSAndroid Build Coastguard Worker self = object.__new__(cls) 944*cda5da8dSAndroid Build Coastguard Worker self.__setstate(year) 945*cda5da8dSAndroid Build Coastguard Worker self._hashcode = -1 946*cda5da8dSAndroid Build Coastguard Worker return self 947*cda5da8dSAndroid Build Coastguard Worker year, month, day = _check_date_fields(year, month, day) 948*cda5da8dSAndroid Build Coastguard Worker self = object.__new__(cls) 949*cda5da8dSAndroid Build Coastguard Worker self._year = year 950*cda5da8dSAndroid Build Coastguard Worker self._month = month 951*cda5da8dSAndroid Build Coastguard Worker self._day = day 952*cda5da8dSAndroid Build Coastguard Worker self._hashcode = -1 953*cda5da8dSAndroid Build Coastguard Worker return self 954*cda5da8dSAndroid Build Coastguard Worker 955*cda5da8dSAndroid Build Coastguard Worker # Additional constructors 956*cda5da8dSAndroid Build Coastguard Worker 957*cda5da8dSAndroid Build Coastguard Worker @classmethod 958*cda5da8dSAndroid Build Coastguard Worker def fromtimestamp(cls, t): 959*cda5da8dSAndroid Build Coastguard Worker "Construct a date from a POSIX timestamp (like time.time())." 960*cda5da8dSAndroid Build Coastguard Worker y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t) 961*cda5da8dSAndroid Build Coastguard Worker return cls(y, m, d) 962*cda5da8dSAndroid Build Coastguard Worker 963*cda5da8dSAndroid Build Coastguard Worker @classmethod 964*cda5da8dSAndroid Build Coastguard Worker def today(cls): 965*cda5da8dSAndroid Build Coastguard Worker "Construct a date from time.time()." 966*cda5da8dSAndroid Build Coastguard Worker t = _time.time() 967*cda5da8dSAndroid Build Coastguard Worker return cls.fromtimestamp(t) 968*cda5da8dSAndroid Build Coastguard Worker 969*cda5da8dSAndroid Build Coastguard Worker @classmethod 970*cda5da8dSAndroid Build Coastguard Worker def fromordinal(cls, n): 971*cda5da8dSAndroid Build Coastguard Worker """Construct a date from a proleptic Gregorian ordinal. 972*cda5da8dSAndroid Build Coastguard Worker 973*cda5da8dSAndroid Build Coastguard Worker January 1 of year 1 is day 1. Only the year, month and day are 974*cda5da8dSAndroid Build Coastguard Worker non-zero in the result. 975*cda5da8dSAndroid Build Coastguard Worker """ 976*cda5da8dSAndroid Build Coastguard Worker y, m, d = _ord2ymd(n) 977*cda5da8dSAndroid Build Coastguard Worker return cls(y, m, d) 978*cda5da8dSAndroid Build Coastguard Worker 979*cda5da8dSAndroid Build Coastguard Worker @classmethod 980*cda5da8dSAndroid Build Coastguard Worker def fromisoformat(cls, date_string): 981*cda5da8dSAndroid Build Coastguard Worker """Construct a date from a string in ISO 8601 format.""" 982*cda5da8dSAndroid Build Coastguard Worker if not isinstance(date_string, str): 983*cda5da8dSAndroid Build Coastguard Worker raise TypeError('fromisoformat: argument must be str') 984*cda5da8dSAndroid Build Coastguard Worker 985*cda5da8dSAndroid Build Coastguard Worker if len(date_string) not in (7, 8, 10): 986*cda5da8dSAndroid Build Coastguard Worker raise ValueError(f'Invalid isoformat string: {date_string!r}') 987*cda5da8dSAndroid Build Coastguard Worker 988*cda5da8dSAndroid Build Coastguard Worker try: 989*cda5da8dSAndroid Build Coastguard Worker return cls(*_parse_isoformat_date(date_string)) 990*cda5da8dSAndroid Build Coastguard Worker except Exception: 991*cda5da8dSAndroid Build Coastguard Worker raise ValueError(f'Invalid isoformat string: {date_string!r}') 992*cda5da8dSAndroid Build Coastguard Worker 993*cda5da8dSAndroid Build Coastguard Worker @classmethod 994*cda5da8dSAndroid Build Coastguard Worker def fromisocalendar(cls, year, week, day): 995*cda5da8dSAndroid Build Coastguard Worker """Construct a date from the ISO year, week number and weekday. 996*cda5da8dSAndroid Build Coastguard Worker 997*cda5da8dSAndroid Build Coastguard Worker This is the inverse of the date.isocalendar() function""" 998*cda5da8dSAndroid Build Coastguard Worker return cls(*_isoweek_to_gregorian(year, week, day)) 999*cda5da8dSAndroid Build Coastguard Worker 1000*cda5da8dSAndroid Build Coastguard Worker # Conversions to string 1001*cda5da8dSAndroid Build Coastguard Worker 1002*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 1003*cda5da8dSAndroid Build Coastguard Worker """Convert to formal string, for repr(). 1004*cda5da8dSAndroid Build Coastguard Worker 1005*cda5da8dSAndroid Build Coastguard Worker >>> dt = datetime(2010, 1, 1) 1006*cda5da8dSAndroid Build Coastguard Worker >>> repr(dt) 1007*cda5da8dSAndroid Build Coastguard Worker 'datetime.datetime(2010, 1, 1, 0, 0)' 1008*cda5da8dSAndroid Build Coastguard Worker 1009*cda5da8dSAndroid Build Coastguard Worker >>> dt = datetime(2010, 1, 1, tzinfo=timezone.utc) 1010*cda5da8dSAndroid Build Coastguard Worker >>> repr(dt) 1011*cda5da8dSAndroid Build Coastguard Worker 'datetime.datetime(2010, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)' 1012*cda5da8dSAndroid Build Coastguard Worker """ 1013*cda5da8dSAndroid Build Coastguard Worker return "%s.%s(%d, %d, %d)" % (self.__class__.__module__, 1014*cda5da8dSAndroid Build Coastguard Worker self.__class__.__qualname__, 1015*cda5da8dSAndroid Build Coastguard Worker self._year, 1016*cda5da8dSAndroid Build Coastguard Worker self._month, 1017*cda5da8dSAndroid Build Coastguard Worker self._day) 1018*cda5da8dSAndroid Build Coastguard Worker # XXX These shouldn't depend on time.localtime(), because that 1019*cda5da8dSAndroid Build Coastguard Worker # clips the usable dates to [1970 .. 2038). At least ctime() is 1020*cda5da8dSAndroid Build Coastguard Worker # easily done without using strftime() -- that's better too because 1021*cda5da8dSAndroid Build Coastguard Worker # strftime("%c", ...) is locale specific. 1022*cda5da8dSAndroid Build Coastguard Worker 1023*cda5da8dSAndroid Build Coastguard Worker 1024*cda5da8dSAndroid Build Coastguard Worker def ctime(self): 1025*cda5da8dSAndroid Build Coastguard Worker "Return ctime() style string." 1026*cda5da8dSAndroid Build Coastguard Worker weekday = self.toordinal() % 7 or 7 1027*cda5da8dSAndroid Build Coastguard Worker return "%s %s %2d 00:00:00 %04d" % ( 1028*cda5da8dSAndroid Build Coastguard Worker _DAYNAMES[weekday], 1029*cda5da8dSAndroid Build Coastguard Worker _MONTHNAMES[self._month], 1030*cda5da8dSAndroid Build Coastguard Worker self._day, self._year) 1031*cda5da8dSAndroid Build Coastguard Worker 1032*cda5da8dSAndroid Build Coastguard Worker def strftime(self, fmt): 1033*cda5da8dSAndroid Build Coastguard Worker """ 1034*cda5da8dSAndroid Build Coastguard Worker Format using strftime(). 1035*cda5da8dSAndroid Build Coastguard Worker 1036*cda5da8dSAndroid Build Coastguard Worker Example: "%d/%m/%Y, %H:%M:%S" 1037*cda5da8dSAndroid Build Coastguard Worker """ 1038*cda5da8dSAndroid Build Coastguard Worker return _wrap_strftime(self, fmt, self.timetuple()) 1039*cda5da8dSAndroid Build Coastguard Worker 1040*cda5da8dSAndroid Build Coastguard Worker def __format__(self, fmt): 1041*cda5da8dSAndroid Build Coastguard Worker if not isinstance(fmt, str): 1042*cda5da8dSAndroid Build Coastguard Worker raise TypeError("must be str, not %s" % type(fmt).__name__) 1043*cda5da8dSAndroid Build Coastguard Worker if len(fmt) != 0: 1044*cda5da8dSAndroid Build Coastguard Worker return self.strftime(fmt) 1045*cda5da8dSAndroid Build Coastguard Worker return str(self) 1046*cda5da8dSAndroid Build Coastguard Worker 1047*cda5da8dSAndroid Build Coastguard Worker def isoformat(self): 1048*cda5da8dSAndroid Build Coastguard Worker """Return the date formatted according to ISO. 1049*cda5da8dSAndroid Build Coastguard Worker 1050*cda5da8dSAndroid Build Coastguard Worker This is 'YYYY-MM-DD'. 1051*cda5da8dSAndroid Build Coastguard Worker 1052*cda5da8dSAndroid Build Coastguard Worker References: 1053*cda5da8dSAndroid Build Coastguard Worker - http://www.w3.org/TR/NOTE-datetime 1054*cda5da8dSAndroid Build Coastguard Worker - http://www.cl.cam.ac.uk/~mgk25/iso-time.html 1055*cda5da8dSAndroid Build Coastguard Worker """ 1056*cda5da8dSAndroid Build Coastguard Worker return "%04d-%02d-%02d" % (self._year, self._month, self._day) 1057*cda5da8dSAndroid Build Coastguard Worker 1058*cda5da8dSAndroid Build Coastguard Worker __str__ = isoformat 1059*cda5da8dSAndroid Build Coastguard Worker 1060*cda5da8dSAndroid Build Coastguard Worker # Read-only field accessors 1061*cda5da8dSAndroid Build Coastguard Worker @property 1062*cda5da8dSAndroid Build Coastguard Worker def year(self): 1063*cda5da8dSAndroid Build Coastguard Worker """year (1-9999)""" 1064*cda5da8dSAndroid Build Coastguard Worker return self._year 1065*cda5da8dSAndroid Build Coastguard Worker 1066*cda5da8dSAndroid Build Coastguard Worker @property 1067*cda5da8dSAndroid Build Coastguard Worker def month(self): 1068*cda5da8dSAndroid Build Coastguard Worker """month (1-12)""" 1069*cda5da8dSAndroid Build Coastguard Worker return self._month 1070*cda5da8dSAndroid Build Coastguard Worker 1071*cda5da8dSAndroid Build Coastguard Worker @property 1072*cda5da8dSAndroid Build Coastguard Worker def day(self): 1073*cda5da8dSAndroid Build Coastguard Worker """day (1-31)""" 1074*cda5da8dSAndroid Build Coastguard Worker return self._day 1075*cda5da8dSAndroid Build Coastguard Worker 1076*cda5da8dSAndroid Build Coastguard Worker # Standard conversions, __eq__, __le__, __lt__, __ge__, __gt__, 1077*cda5da8dSAndroid Build Coastguard Worker # __hash__ (and helpers) 1078*cda5da8dSAndroid Build Coastguard Worker 1079*cda5da8dSAndroid Build Coastguard Worker def timetuple(self): 1080*cda5da8dSAndroid Build Coastguard Worker "Return local time tuple compatible with time.localtime()." 1081*cda5da8dSAndroid Build Coastguard Worker return _build_struct_time(self._year, self._month, self._day, 1082*cda5da8dSAndroid Build Coastguard Worker 0, 0, 0, -1) 1083*cda5da8dSAndroid Build Coastguard Worker 1084*cda5da8dSAndroid Build Coastguard Worker def toordinal(self): 1085*cda5da8dSAndroid Build Coastguard Worker """Return proleptic Gregorian ordinal for the year, month and day. 1086*cda5da8dSAndroid Build Coastguard Worker 1087*cda5da8dSAndroid Build Coastguard Worker January 1 of year 1 is day 1. Only the year, month and day values 1088*cda5da8dSAndroid Build Coastguard Worker contribute to the result. 1089*cda5da8dSAndroid Build Coastguard Worker """ 1090*cda5da8dSAndroid Build Coastguard Worker return _ymd2ord(self._year, self._month, self._day) 1091*cda5da8dSAndroid Build Coastguard Worker 1092*cda5da8dSAndroid Build Coastguard Worker def replace(self, year=None, month=None, day=None): 1093*cda5da8dSAndroid Build Coastguard Worker """Return a new date with new values for the specified fields.""" 1094*cda5da8dSAndroid Build Coastguard Worker if year is None: 1095*cda5da8dSAndroid Build Coastguard Worker year = self._year 1096*cda5da8dSAndroid Build Coastguard Worker if month is None: 1097*cda5da8dSAndroid Build Coastguard Worker month = self._month 1098*cda5da8dSAndroid Build Coastguard Worker if day is None: 1099*cda5da8dSAndroid Build Coastguard Worker day = self._day 1100*cda5da8dSAndroid Build Coastguard Worker return type(self)(year, month, day) 1101*cda5da8dSAndroid Build Coastguard Worker 1102*cda5da8dSAndroid Build Coastguard Worker # Comparisons of date objects with other. 1103*cda5da8dSAndroid Build Coastguard Worker 1104*cda5da8dSAndroid Build Coastguard Worker def __eq__(self, other): 1105*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, date): 1106*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) == 0 1107*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 1108*cda5da8dSAndroid Build Coastguard Worker 1109*cda5da8dSAndroid Build Coastguard Worker def __le__(self, other): 1110*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, date): 1111*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) <= 0 1112*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 1113*cda5da8dSAndroid Build Coastguard Worker 1114*cda5da8dSAndroid Build Coastguard Worker def __lt__(self, other): 1115*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, date): 1116*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) < 0 1117*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 1118*cda5da8dSAndroid Build Coastguard Worker 1119*cda5da8dSAndroid Build Coastguard Worker def __ge__(self, other): 1120*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, date): 1121*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) >= 0 1122*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 1123*cda5da8dSAndroid Build Coastguard Worker 1124*cda5da8dSAndroid Build Coastguard Worker def __gt__(self, other): 1125*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, date): 1126*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) > 0 1127*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 1128*cda5da8dSAndroid Build Coastguard Worker 1129*cda5da8dSAndroid Build Coastguard Worker def _cmp(self, other): 1130*cda5da8dSAndroid Build Coastguard Worker assert isinstance(other, date) 1131*cda5da8dSAndroid Build Coastguard Worker y, m, d = self._year, self._month, self._day 1132*cda5da8dSAndroid Build Coastguard Worker y2, m2, d2 = other._year, other._month, other._day 1133*cda5da8dSAndroid Build Coastguard Worker return _cmp((y, m, d), (y2, m2, d2)) 1134*cda5da8dSAndroid Build Coastguard Worker 1135*cda5da8dSAndroid Build Coastguard Worker def __hash__(self): 1136*cda5da8dSAndroid Build Coastguard Worker "Hash." 1137*cda5da8dSAndroid Build Coastguard Worker if self._hashcode == -1: 1138*cda5da8dSAndroid Build Coastguard Worker self._hashcode = hash(self._getstate()) 1139*cda5da8dSAndroid Build Coastguard Worker return self._hashcode 1140*cda5da8dSAndroid Build Coastguard Worker 1141*cda5da8dSAndroid Build Coastguard Worker # Computations 1142*cda5da8dSAndroid Build Coastguard Worker 1143*cda5da8dSAndroid Build Coastguard Worker def __add__(self, other): 1144*cda5da8dSAndroid Build Coastguard Worker "Add a date to a timedelta." 1145*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 1146*cda5da8dSAndroid Build Coastguard Worker o = self.toordinal() + other.days 1147*cda5da8dSAndroid Build Coastguard Worker if 0 < o <= _MAXORDINAL: 1148*cda5da8dSAndroid Build Coastguard Worker return type(self).fromordinal(o) 1149*cda5da8dSAndroid Build Coastguard Worker raise OverflowError("result out of range") 1150*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 1151*cda5da8dSAndroid Build Coastguard Worker 1152*cda5da8dSAndroid Build Coastguard Worker __radd__ = __add__ 1153*cda5da8dSAndroid Build Coastguard Worker 1154*cda5da8dSAndroid Build Coastguard Worker def __sub__(self, other): 1155*cda5da8dSAndroid Build Coastguard Worker """Subtract two dates, or a date and a timedelta.""" 1156*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 1157*cda5da8dSAndroid Build Coastguard Worker return self + timedelta(-other.days) 1158*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, date): 1159*cda5da8dSAndroid Build Coastguard Worker days1 = self.toordinal() 1160*cda5da8dSAndroid Build Coastguard Worker days2 = other.toordinal() 1161*cda5da8dSAndroid Build Coastguard Worker return timedelta(days1 - days2) 1162*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 1163*cda5da8dSAndroid Build Coastguard Worker 1164*cda5da8dSAndroid Build Coastguard Worker def weekday(self): 1165*cda5da8dSAndroid Build Coastguard Worker "Return day of the week, where Monday == 0 ... Sunday == 6." 1166*cda5da8dSAndroid Build Coastguard Worker return (self.toordinal() + 6) % 7 1167*cda5da8dSAndroid Build Coastguard Worker 1168*cda5da8dSAndroid Build Coastguard Worker # Day-of-the-week and week-of-the-year, according to ISO 1169*cda5da8dSAndroid Build Coastguard Worker 1170*cda5da8dSAndroid Build Coastguard Worker def isoweekday(self): 1171*cda5da8dSAndroid Build Coastguard Worker "Return day of the week, where Monday == 1 ... Sunday == 7." 1172*cda5da8dSAndroid Build Coastguard Worker # 1-Jan-0001 is a Monday 1173*cda5da8dSAndroid Build Coastguard Worker return self.toordinal() % 7 or 7 1174*cda5da8dSAndroid Build Coastguard Worker 1175*cda5da8dSAndroid Build Coastguard Worker def isocalendar(self): 1176*cda5da8dSAndroid Build Coastguard Worker """Return a named tuple containing ISO year, week number, and weekday. 1177*cda5da8dSAndroid Build Coastguard Worker 1178*cda5da8dSAndroid Build Coastguard Worker The first ISO week of the year is the (Mon-Sun) week 1179*cda5da8dSAndroid Build Coastguard Worker containing the year's first Thursday; everything else derives 1180*cda5da8dSAndroid Build Coastguard Worker from that. 1181*cda5da8dSAndroid Build Coastguard Worker 1182*cda5da8dSAndroid Build Coastguard Worker The first week is 1; Monday is 1 ... Sunday is 7. 1183*cda5da8dSAndroid Build Coastguard Worker 1184*cda5da8dSAndroid Build Coastguard Worker ISO calendar algorithm taken from 1185*cda5da8dSAndroid Build Coastguard Worker http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm 1186*cda5da8dSAndroid Build Coastguard Worker (used with permission) 1187*cda5da8dSAndroid Build Coastguard Worker """ 1188*cda5da8dSAndroid Build Coastguard Worker year = self._year 1189*cda5da8dSAndroid Build Coastguard Worker week1monday = _isoweek1monday(year) 1190*cda5da8dSAndroid Build Coastguard Worker today = _ymd2ord(self._year, self._month, self._day) 1191*cda5da8dSAndroid Build Coastguard Worker # Internally, week and day have origin 0 1192*cda5da8dSAndroid Build Coastguard Worker week, day = divmod(today - week1monday, 7) 1193*cda5da8dSAndroid Build Coastguard Worker if week < 0: 1194*cda5da8dSAndroid Build Coastguard Worker year -= 1 1195*cda5da8dSAndroid Build Coastguard Worker week1monday = _isoweek1monday(year) 1196*cda5da8dSAndroid Build Coastguard Worker week, day = divmod(today - week1monday, 7) 1197*cda5da8dSAndroid Build Coastguard Worker elif week >= 52: 1198*cda5da8dSAndroid Build Coastguard Worker if today >= _isoweek1monday(year+1): 1199*cda5da8dSAndroid Build Coastguard Worker year += 1 1200*cda5da8dSAndroid Build Coastguard Worker week = 0 1201*cda5da8dSAndroid Build Coastguard Worker return _IsoCalendarDate(year, week+1, day+1) 1202*cda5da8dSAndroid Build Coastguard Worker 1203*cda5da8dSAndroid Build Coastguard Worker # Pickle support. 1204*cda5da8dSAndroid Build Coastguard Worker 1205*cda5da8dSAndroid Build Coastguard Worker def _getstate(self): 1206*cda5da8dSAndroid Build Coastguard Worker yhi, ylo = divmod(self._year, 256) 1207*cda5da8dSAndroid Build Coastguard Worker return bytes([yhi, ylo, self._month, self._day]), 1208*cda5da8dSAndroid Build Coastguard Worker 1209*cda5da8dSAndroid Build Coastguard Worker def __setstate(self, string): 1210*cda5da8dSAndroid Build Coastguard Worker yhi, ylo, self._month, self._day = string 1211*cda5da8dSAndroid Build Coastguard Worker self._year = yhi * 256 + ylo 1212*cda5da8dSAndroid Build Coastguard Worker 1213*cda5da8dSAndroid Build Coastguard Worker def __reduce__(self): 1214*cda5da8dSAndroid Build Coastguard Worker return (self.__class__, self._getstate()) 1215*cda5da8dSAndroid Build Coastguard Worker 1216*cda5da8dSAndroid Build Coastguard Worker_date_class = date # so functions w/ args named "date" can get at the class 1217*cda5da8dSAndroid Build Coastguard Worker 1218*cda5da8dSAndroid Build Coastguard Workerdate.min = date(1, 1, 1) 1219*cda5da8dSAndroid Build Coastguard Workerdate.max = date(9999, 12, 31) 1220*cda5da8dSAndroid Build Coastguard Workerdate.resolution = timedelta(days=1) 1221*cda5da8dSAndroid Build Coastguard Worker 1222*cda5da8dSAndroid Build Coastguard Worker 1223*cda5da8dSAndroid Build Coastguard Workerclass tzinfo: 1224*cda5da8dSAndroid Build Coastguard Worker """Abstract base class for time zone info classes. 1225*cda5da8dSAndroid Build Coastguard Worker 1226*cda5da8dSAndroid Build Coastguard Worker Subclasses must override the name(), utcoffset() and dst() methods. 1227*cda5da8dSAndroid Build Coastguard Worker """ 1228*cda5da8dSAndroid Build Coastguard Worker __slots__ = () 1229*cda5da8dSAndroid Build Coastguard Worker 1230*cda5da8dSAndroid Build Coastguard Worker def tzname(self, dt): 1231*cda5da8dSAndroid Build Coastguard Worker "datetime -> string name of time zone." 1232*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError("tzinfo subclass must override tzname()") 1233*cda5da8dSAndroid Build Coastguard Worker 1234*cda5da8dSAndroid Build Coastguard Worker def utcoffset(self, dt): 1235*cda5da8dSAndroid Build Coastguard Worker "datetime -> timedelta, positive for east of UTC, negative for west of UTC" 1236*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError("tzinfo subclass must override utcoffset()") 1237*cda5da8dSAndroid Build Coastguard Worker 1238*cda5da8dSAndroid Build Coastguard Worker def dst(self, dt): 1239*cda5da8dSAndroid Build Coastguard Worker """datetime -> DST offset as timedelta, positive for east of UTC. 1240*cda5da8dSAndroid Build Coastguard Worker 1241*cda5da8dSAndroid Build Coastguard Worker Return 0 if DST not in effect. utcoffset() must include the DST 1242*cda5da8dSAndroid Build Coastguard Worker offset. 1243*cda5da8dSAndroid Build Coastguard Worker """ 1244*cda5da8dSAndroid Build Coastguard Worker raise NotImplementedError("tzinfo subclass must override dst()") 1245*cda5da8dSAndroid Build Coastguard Worker 1246*cda5da8dSAndroid Build Coastguard Worker def fromutc(self, dt): 1247*cda5da8dSAndroid Build Coastguard Worker "datetime in UTC -> datetime in local time." 1248*cda5da8dSAndroid Build Coastguard Worker 1249*cda5da8dSAndroid Build Coastguard Worker if not isinstance(dt, datetime): 1250*cda5da8dSAndroid Build Coastguard Worker raise TypeError("fromutc() requires a datetime argument") 1251*cda5da8dSAndroid Build Coastguard Worker if dt.tzinfo is not self: 1252*cda5da8dSAndroid Build Coastguard Worker raise ValueError("dt.tzinfo is not self") 1253*cda5da8dSAndroid Build Coastguard Worker 1254*cda5da8dSAndroid Build Coastguard Worker dtoff = dt.utcoffset() 1255*cda5da8dSAndroid Build Coastguard Worker if dtoff is None: 1256*cda5da8dSAndroid Build Coastguard Worker raise ValueError("fromutc() requires a non-None utcoffset() " 1257*cda5da8dSAndroid Build Coastguard Worker "result") 1258*cda5da8dSAndroid Build Coastguard Worker 1259*cda5da8dSAndroid Build Coastguard Worker # See the long comment block at the end of this file for an 1260*cda5da8dSAndroid Build Coastguard Worker # explanation of this algorithm. 1261*cda5da8dSAndroid Build Coastguard Worker dtdst = dt.dst() 1262*cda5da8dSAndroid Build Coastguard Worker if dtdst is None: 1263*cda5da8dSAndroid Build Coastguard Worker raise ValueError("fromutc() requires a non-None dst() result") 1264*cda5da8dSAndroid Build Coastguard Worker delta = dtoff - dtdst 1265*cda5da8dSAndroid Build Coastguard Worker if delta: 1266*cda5da8dSAndroid Build Coastguard Worker dt += delta 1267*cda5da8dSAndroid Build Coastguard Worker dtdst = dt.dst() 1268*cda5da8dSAndroid Build Coastguard Worker if dtdst is None: 1269*cda5da8dSAndroid Build Coastguard Worker raise ValueError("fromutc(): dt.dst gave inconsistent " 1270*cda5da8dSAndroid Build Coastguard Worker "results; cannot convert") 1271*cda5da8dSAndroid Build Coastguard Worker return dt + dtdst 1272*cda5da8dSAndroid Build Coastguard Worker 1273*cda5da8dSAndroid Build Coastguard Worker # Pickle support. 1274*cda5da8dSAndroid Build Coastguard Worker 1275*cda5da8dSAndroid Build Coastguard Worker def __reduce__(self): 1276*cda5da8dSAndroid Build Coastguard Worker getinitargs = getattr(self, "__getinitargs__", None) 1277*cda5da8dSAndroid Build Coastguard Worker if getinitargs: 1278*cda5da8dSAndroid Build Coastguard Worker args = getinitargs() 1279*cda5da8dSAndroid Build Coastguard Worker else: 1280*cda5da8dSAndroid Build Coastguard Worker args = () 1281*cda5da8dSAndroid Build Coastguard Worker return (self.__class__, args, self.__getstate__()) 1282*cda5da8dSAndroid Build Coastguard Worker 1283*cda5da8dSAndroid Build Coastguard Worker 1284*cda5da8dSAndroid Build Coastguard Workerclass IsoCalendarDate(tuple): 1285*cda5da8dSAndroid Build Coastguard Worker 1286*cda5da8dSAndroid Build Coastguard Worker def __new__(cls, year, week, weekday, /): 1287*cda5da8dSAndroid Build Coastguard Worker return super().__new__(cls, (year, week, weekday)) 1288*cda5da8dSAndroid Build Coastguard Worker 1289*cda5da8dSAndroid Build Coastguard Worker @property 1290*cda5da8dSAndroid Build Coastguard Worker def year(self): 1291*cda5da8dSAndroid Build Coastguard Worker return self[0] 1292*cda5da8dSAndroid Build Coastguard Worker 1293*cda5da8dSAndroid Build Coastguard Worker @property 1294*cda5da8dSAndroid Build Coastguard Worker def week(self): 1295*cda5da8dSAndroid Build Coastguard Worker return self[1] 1296*cda5da8dSAndroid Build Coastguard Worker 1297*cda5da8dSAndroid Build Coastguard Worker @property 1298*cda5da8dSAndroid Build Coastguard Worker def weekday(self): 1299*cda5da8dSAndroid Build Coastguard Worker return self[2] 1300*cda5da8dSAndroid Build Coastguard Worker 1301*cda5da8dSAndroid Build Coastguard Worker def __reduce__(self): 1302*cda5da8dSAndroid Build Coastguard Worker # This code is intended to pickle the object without making the 1303*cda5da8dSAndroid Build Coastguard Worker # class public. See https://bugs.python.org/msg352381 1304*cda5da8dSAndroid Build Coastguard Worker return (tuple, (tuple(self),)) 1305*cda5da8dSAndroid Build Coastguard Worker 1306*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 1307*cda5da8dSAndroid Build Coastguard Worker return (f'{self.__class__.__name__}' 1308*cda5da8dSAndroid Build Coastguard Worker f'(year={self[0]}, week={self[1]}, weekday={self[2]})') 1309*cda5da8dSAndroid Build Coastguard Worker 1310*cda5da8dSAndroid Build Coastguard Worker 1311*cda5da8dSAndroid Build Coastguard Worker_IsoCalendarDate = IsoCalendarDate 1312*cda5da8dSAndroid Build Coastguard Workerdel IsoCalendarDate 1313*cda5da8dSAndroid Build Coastguard Worker_tzinfo_class = tzinfo 1314*cda5da8dSAndroid Build Coastguard Worker 1315*cda5da8dSAndroid Build Coastguard Workerclass time: 1316*cda5da8dSAndroid Build Coastguard Worker """Time with time zone. 1317*cda5da8dSAndroid Build Coastguard Worker 1318*cda5da8dSAndroid Build Coastguard Worker Constructors: 1319*cda5da8dSAndroid Build Coastguard Worker 1320*cda5da8dSAndroid Build Coastguard Worker __new__() 1321*cda5da8dSAndroid Build Coastguard Worker 1322*cda5da8dSAndroid Build Coastguard Worker Operators: 1323*cda5da8dSAndroid Build Coastguard Worker 1324*cda5da8dSAndroid Build Coastguard Worker __repr__, __str__ 1325*cda5da8dSAndroid Build Coastguard Worker __eq__, __le__, __lt__, __ge__, __gt__, __hash__ 1326*cda5da8dSAndroid Build Coastguard Worker 1327*cda5da8dSAndroid Build Coastguard Worker Methods: 1328*cda5da8dSAndroid Build Coastguard Worker 1329*cda5da8dSAndroid Build Coastguard Worker strftime() 1330*cda5da8dSAndroid Build Coastguard Worker isoformat() 1331*cda5da8dSAndroid Build Coastguard Worker utcoffset() 1332*cda5da8dSAndroid Build Coastguard Worker tzname() 1333*cda5da8dSAndroid Build Coastguard Worker dst() 1334*cda5da8dSAndroid Build Coastguard Worker 1335*cda5da8dSAndroid Build Coastguard Worker Properties (readonly): 1336*cda5da8dSAndroid Build Coastguard Worker hour, minute, second, microsecond, tzinfo, fold 1337*cda5da8dSAndroid Build Coastguard Worker """ 1338*cda5da8dSAndroid Build Coastguard Worker __slots__ = '_hour', '_minute', '_second', '_microsecond', '_tzinfo', '_hashcode', '_fold' 1339*cda5da8dSAndroid Build Coastguard Worker 1340*cda5da8dSAndroid Build Coastguard Worker def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0): 1341*cda5da8dSAndroid Build Coastguard Worker """Constructor. 1342*cda5da8dSAndroid Build Coastguard Worker 1343*cda5da8dSAndroid Build Coastguard Worker Arguments: 1344*cda5da8dSAndroid Build Coastguard Worker 1345*cda5da8dSAndroid Build Coastguard Worker hour, minute (required) 1346*cda5da8dSAndroid Build Coastguard Worker second, microsecond (default to zero) 1347*cda5da8dSAndroid Build Coastguard Worker tzinfo (default to None) 1348*cda5da8dSAndroid Build Coastguard Worker fold (keyword only, default to zero) 1349*cda5da8dSAndroid Build Coastguard Worker """ 1350*cda5da8dSAndroid Build Coastguard Worker if (isinstance(hour, (bytes, str)) and len(hour) == 6 and 1351*cda5da8dSAndroid Build Coastguard Worker ord(hour[0:1])&0x7F < 24): 1352*cda5da8dSAndroid Build Coastguard Worker # Pickle support 1353*cda5da8dSAndroid Build Coastguard Worker if isinstance(hour, str): 1354*cda5da8dSAndroid Build Coastguard Worker try: 1355*cda5da8dSAndroid Build Coastguard Worker hour = hour.encode('latin1') 1356*cda5da8dSAndroid Build Coastguard Worker except UnicodeEncodeError: 1357*cda5da8dSAndroid Build Coastguard Worker # More informative error message. 1358*cda5da8dSAndroid Build Coastguard Worker raise ValueError( 1359*cda5da8dSAndroid Build Coastguard Worker "Failed to encode latin1 string when unpickling " 1360*cda5da8dSAndroid Build Coastguard Worker "a time object. " 1361*cda5da8dSAndroid Build Coastguard Worker "pickle.load(data, encoding='latin1') is assumed.") 1362*cda5da8dSAndroid Build Coastguard Worker self = object.__new__(cls) 1363*cda5da8dSAndroid Build Coastguard Worker self.__setstate(hour, minute or None) 1364*cda5da8dSAndroid Build Coastguard Worker self._hashcode = -1 1365*cda5da8dSAndroid Build Coastguard Worker return self 1366*cda5da8dSAndroid Build Coastguard Worker hour, minute, second, microsecond, fold = _check_time_fields( 1367*cda5da8dSAndroid Build Coastguard Worker hour, minute, second, microsecond, fold) 1368*cda5da8dSAndroid Build Coastguard Worker _check_tzinfo_arg(tzinfo) 1369*cda5da8dSAndroid Build Coastguard Worker self = object.__new__(cls) 1370*cda5da8dSAndroid Build Coastguard Worker self._hour = hour 1371*cda5da8dSAndroid Build Coastguard Worker self._minute = minute 1372*cda5da8dSAndroid Build Coastguard Worker self._second = second 1373*cda5da8dSAndroid Build Coastguard Worker self._microsecond = microsecond 1374*cda5da8dSAndroid Build Coastguard Worker self._tzinfo = tzinfo 1375*cda5da8dSAndroid Build Coastguard Worker self._hashcode = -1 1376*cda5da8dSAndroid Build Coastguard Worker self._fold = fold 1377*cda5da8dSAndroid Build Coastguard Worker return self 1378*cda5da8dSAndroid Build Coastguard Worker 1379*cda5da8dSAndroid Build Coastguard Worker # Read-only field accessors 1380*cda5da8dSAndroid Build Coastguard Worker @property 1381*cda5da8dSAndroid Build Coastguard Worker def hour(self): 1382*cda5da8dSAndroid Build Coastguard Worker """hour (0-23)""" 1383*cda5da8dSAndroid Build Coastguard Worker return self._hour 1384*cda5da8dSAndroid Build Coastguard Worker 1385*cda5da8dSAndroid Build Coastguard Worker @property 1386*cda5da8dSAndroid Build Coastguard Worker def minute(self): 1387*cda5da8dSAndroid Build Coastguard Worker """minute (0-59)""" 1388*cda5da8dSAndroid Build Coastguard Worker return self._minute 1389*cda5da8dSAndroid Build Coastguard Worker 1390*cda5da8dSAndroid Build Coastguard Worker @property 1391*cda5da8dSAndroid Build Coastguard Worker def second(self): 1392*cda5da8dSAndroid Build Coastguard Worker """second (0-59)""" 1393*cda5da8dSAndroid Build Coastguard Worker return self._second 1394*cda5da8dSAndroid Build Coastguard Worker 1395*cda5da8dSAndroid Build Coastguard Worker @property 1396*cda5da8dSAndroid Build Coastguard Worker def microsecond(self): 1397*cda5da8dSAndroid Build Coastguard Worker """microsecond (0-999999)""" 1398*cda5da8dSAndroid Build Coastguard Worker return self._microsecond 1399*cda5da8dSAndroid Build Coastguard Worker 1400*cda5da8dSAndroid Build Coastguard Worker @property 1401*cda5da8dSAndroid Build Coastguard Worker def tzinfo(self): 1402*cda5da8dSAndroid Build Coastguard Worker """timezone info object""" 1403*cda5da8dSAndroid Build Coastguard Worker return self._tzinfo 1404*cda5da8dSAndroid Build Coastguard Worker 1405*cda5da8dSAndroid Build Coastguard Worker @property 1406*cda5da8dSAndroid Build Coastguard Worker def fold(self): 1407*cda5da8dSAndroid Build Coastguard Worker return self._fold 1408*cda5da8dSAndroid Build Coastguard Worker 1409*cda5da8dSAndroid Build Coastguard Worker # Standard conversions, __hash__ (and helpers) 1410*cda5da8dSAndroid Build Coastguard Worker 1411*cda5da8dSAndroid Build Coastguard Worker # Comparisons of time objects with other. 1412*cda5da8dSAndroid Build Coastguard Worker 1413*cda5da8dSAndroid Build Coastguard Worker def __eq__(self, other): 1414*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, time): 1415*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other, allow_mixed=True) == 0 1416*cda5da8dSAndroid Build Coastguard Worker else: 1417*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 1418*cda5da8dSAndroid Build Coastguard Worker 1419*cda5da8dSAndroid Build Coastguard Worker def __le__(self, other): 1420*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, time): 1421*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) <= 0 1422*cda5da8dSAndroid Build Coastguard Worker else: 1423*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 1424*cda5da8dSAndroid Build Coastguard Worker 1425*cda5da8dSAndroid Build Coastguard Worker def __lt__(self, other): 1426*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, time): 1427*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) < 0 1428*cda5da8dSAndroid Build Coastguard Worker else: 1429*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 1430*cda5da8dSAndroid Build Coastguard Worker 1431*cda5da8dSAndroid Build Coastguard Worker def __ge__(self, other): 1432*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, time): 1433*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) >= 0 1434*cda5da8dSAndroid Build Coastguard Worker else: 1435*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 1436*cda5da8dSAndroid Build Coastguard Worker 1437*cda5da8dSAndroid Build Coastguard Worker def __gt__(self, other): 1438*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, time): 1439*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) > 0 1440*cda5da8dSAndroid Build Coastguard Worker else: 1441*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 1442*cda5da8dSAndroid Build Coastguard Worker 1443*cda5da8dSAndroid Build Coastguard Worker def _cmp(self, other, allow_mixed=False): 1444*cda5da8dSAndroid Build Coastguard Worker assert isinstance(other, time) 1445*cda5da8dSAndroid Build Coastguard Worker mytz = self._tzinfo 1446*cda5da8dSAndroid Build Coastguard Worker ottz = other._tzinfo 1447*cda5da8dSAndroid Build Coastguard Worker myoff = otoff = None 1448*cda5da8dSAndroid Build Coastguard Worker 1449*cda5da8dSAndroid Build Coastguard Worker if mytz is ottz: 1450*cda5da8dSAndroid Build Coastguard Worker base_compare = True 1451*cda5da8dSAndroid Build Coastguard Worker else: 1452*cda5da8dSAndroid Build Coastguard Worker myoff = self.utcoffset() 1453*cda5da8dSAndroid Build Coastguard Worker otoff = other.utcoffset() 1454*cda5da8dSAndroid Build Coastguard Worker base_compare = myoff == otoff 1455*cda5da8dSAndroid Build Coastguard Worker 1456*cda5da8dSAndroid Build Coastguard Worker if base_compare: 1457*cda5da8dSAndroid Build Coastguard Worker return _cmp((self._hour, self._minute, self._second, 1458*cda5da8dSAndroid Build Coastguard Worker self._microsecond), 1459*cda5da8dSAndroid Build Coastguard Worker (other._hour, other._minute, other._second, 1460*cda5da8dSAndroid Build Coastguard Worker other._microsecond)) 1461*cda5da8dSAndroid Build Coastguard Worker if myoff is None or otoff is None: 1462*cda5da8dSAndroid Build Coastguard Worker if allow_mixed: 1463*cda5da8dSAndroid Build Coastguard Worker return 2 # arbitrary non-zero value 1464*cda5da8dSAndroid Build Coastguard Worker else: 1465*cda5da8dSAndroid Build Coastguard Worker raise TypeError("cannot compare naive and aware times") 1466*cda5da8dSAndroid Build Coastguard Worker myhhmm = self._hour * 60 + self._minute - myoff//timedelta(minutes=1) 1467*cda5da8dSAndroid Build Coastguard Worker othhmm = other._hour * 60 + other._minute - otoff//timedelta(minutes=1) 1468*cda5da8dSAndroid Build Coastguard Worker return _cmp((myhhmm, self._second, self._microsecond), 1469*cda5da8dSAndroid Build Coastguard Worker (othhmm, other._second, other._microsecond)) 1470*cda5da8dSAndroid Build Coastguard Worker 1471*cda5da8dSAndroid Build Coastguard Worker def __hash__(self): 1472*cda5da8dSAndroid Build Coastguard Worker """Hash.""" 1473*cda5da8dSAndroid Build Coastguard Worker if self._hashcode == -1: 1474*cda5da8dSAndroid Build Coastguard Worker if self.fold: 1475*cda5da8dSAndroid Build Coastguard Worker t = self.replace(fold=0) 1476*cda5da8dSAndroid Build Coastguard Worker else: 1477*cda5da8dSAndroid Build Coastguard Worker t = self 1478*cda5da8dSAndroid Build Coastguard Worker tzoff = t.utcoffset() 1479*cda5da8dSAndroid Build Coastguard Worker if not tzoff: # zero or None 1480*cda5da8dSAndroid Build Coastguard Worker self._hashcode = hash(t._getstate()[0]) 1481*cda5da8dSAndroid Build Coastguard Worker else: 1482*cda5da8dSAndroid Build Coastguard Worker h, m = divmod(timedelta(hours=self.hour, minutes=self.minute) - tzoff, 1483*cda5da8dSAndroid Build Coastguard Worker timedelta(hours=1)) 1484*cda5da8dSAndroid Build Coastguard Worker assert not m % timedelta(minutes=1), "whole minute" 1485*cda5da8dSAndroid Build Coastguard Worker m //= timedelta(minutes=1) 1486*cda5da8dSAndroid Build Coastguard Worker if 0 <= h < 24: 1487*cda5da8dSAndroid Build Coastguard Worker self._hashcode = hash(time(h, m, self.second, self.microsecond)) 1488*cda5da8dSAndroid Build Coastguard Worker else: 1489*cda5da8dSAndroid Build Coastguard Worker self._hashcode = hash((h, m, self.second, self.microsecond)) 1490*cda5da8dSAndroid Build Coastguard Worker return self._hashcode 1491*cda5da8dSAndroid Build Coastguard Worker 1492*cda5da8dSAndroid Build Coastguard Worker # Conversion to string 1493*cda5da8dSAndroid Build Coastguard Worker 1494*cda5da8dSAndroid Build Coastguard Worker def _tzstr(self): 1495*cda5da8dSAndroid Build Coastguard Worker """Return formatted timezone offset (+xx:xx) or an empty string.""" 1496*cda5da8dSAndroid Build Coastguard Worker off = self.utcoffset() 1497*cda5da8dSAndroid Build Coastguard Worker return _format_offset(off) 1498*cda5da8dSAndroid Build Coastguard Worker 1499*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 1500*cda5da8dSAndroid Build Coastguard Worker """Convert to formal string, for repr().""" 1501*cda5da8dSAndroid Build Coastguard Worker if self._microsecond != 0: 1502*cda5da8dSAndroid Build Coastguard Worker s = ", %d, %d" % (self._second, self._microsecond) 1503*cda5da8dSAndroid Build Coastguard Worker elif self._second != 0: 1504*cda5da8dSAndroid Build Coastguard Worker s = ", %d" % self._second 1505*cda5da8dSAndroid Build Coastguard Worker else: 1506*cda5da8dSAndroid Build Coastguard Worker s = "" 1507*cda5da8dSAndroid Build Coastguard Worker s= "%s.%s(%d, %d%s)" % (self.__class__.__module__, 1508*cda5da8dSAndroid Build Coastguard Worker self.__class__.__qualname__, 1509*cda5da8dSAndroid Build Coastguard Worker self._hour, self._minute, s) 1510*cda5da8dSAndroid Build Coastguard Worker if self._tzinfo is not None: 1511*cda5da8dSAndroid Build Coastguard Worker assert s[-1:] == ")" 1512*cda5da8dSAndroid Build Coastguard Worker s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")" 1513*cda5da8dSAndroid Build Coastguard Worker if self._fold: 1514*cda5da8dSAndroid Build Coastguard Worker assert s[-1:] == ")" 1515*cda5da8dSAndroid Build Coastguard Worker s = s[:-1] + ", fold=1)" 1516*cda5da8dSAndroid Build Coastguard Worker return s 1517*cda5da8dSAndroid Build Coastguard Worker 1518*cda5da8dSAndroid Build Coastguard Worker def isoformat(self, timespec='auto'): 1519*cda5da8dSAndroid Build Coastguard Worker """Return the time formatted according to ISO. 1520*cda5da8dSAndroid Build Coastguard Worker 1521*cda5da8dSAndroid Build Coastguard Worker The full format is 'HH:MM:SS.mmmmmm+zz:zz'. By default, the fractional 1522*cda5da8dSAndroid Build Coastguard Worker part is omitted if self.microsecond == 0. 1523*cda5da8dSAndroid Build Coastguard Worker 1524*cda5da8dSAndroid Build Coastguard Worker The optional argument timespec specifies the number of additional 1525*cda5da8dSAndroid Build Coastguard Worker terms of the time to include. Valid options are 'auto', 'hours', 1526*cda5da8dSAndroid Build Coastguard Worker 'minutes', 'seconds', 'milliseconds' and 'microseconds'. 1527*cda5da8dSAndroid Build Coastguard Worker """ 1528*cda5da8dSAndroid Build Coastguard Worker s = _format_time(self._hour, self._minute, self._second, 1529*cda5da8dSAndroid Build Coastguard Worker self._microsecond, timespec) 1530*cda5da8dSAndroid Build Coastguard Worker tz = self._tzstr() 1531*cda5da8dSAndroid Build Coastguard Worker if tz: 1532*cda5da8dSAndroid Build Coastguard Worker s += tz 1533*cda5da8dSAndroid Build Coastguard Worker return s 1534*cda5da8dSAndroid Build Coastguard Worker 1535*cda5da8dSAndroid Build Coastguard Worker __str__ = isoformat 1536*cda5da8dSAndroid Build Coastguard Worker 1537*cda5da8dSAndroid Build Coastguard Worker @classmethod 1538*cda5da8dSAndroid Build Coastguard Worker def fromisoformat(cls, time_string): 1539*cda5da8dSAndroid Build Coastguard Worker """Construct a time from a string in one of the ISO 8601 formats.""" 1540*cda5da8dSAndroid Build Coastguard Worker if not isinstance(time_string, str): 1541*cda5da8dSAndroid Build Coastguard Worker raise TypeError('fromisoformat: argument must be str') 1542*cda5da8dSAndroid Build Coastguard Worker 1543*cda5da8dSAndroid Build Coastguard Worker # The spec actually requires that time-only ISO 8601 strings start with 1544*cda5da8dSAndroid Build Coastguard Worker # T, but the extended format allows this to be omitted as long as there 1545*cda5da8dSAndroid Build Coastguard Worker # is no ambiguity with date strings. 1546*cda5da8dSAndroid Build Coastguard Worker time_string = time_string.removeprefix('T') 1547*cda5da8dSAndroid Build Coastguard Worker 1548*cda5da8dSAndroid Build Coastguard Worker try: 1549*cda5da8dSAndroid Build Coastguard Worker return cls(*_parse_isoformat_time(time_string)) 1550*cda5da8dSAndroid Build Coastguard Worker except Exception: 1551*cda5da8dSAndroid Build Coastguard Worker raise ValueError(f'Invalid isoformat string: {time_string!r}') 1552*cda5da8dSAndroid Build Coastguard Worker 1553*cda5da8dSAndroid Build Coastguard Worker 1554*cda5da8dSAndroid Build Coastguard Worker def strftime(self, fmt): 1555*cda5da8dSAndroid Build Coastguard Worker """Format using strftime(). The date part of the timestamp passed 1556*cda5da8dSAndroid Build Coastguard Worker to underlying strftime should not be used. 1557*cda5da8dSAndroid Build Coastguard Worker """ 1558*cda5da8dSAndroid Build Coastguard Worker # The year must be >= 1000 else Python's strftime implementation 1559*cda5da8dSAndroid Build Coastguard Worker # can raise a bogus exception. 1560*cda5da8dSAndroid Build Coastguard Worker timetuple = (1900, 1, 1, 1561*cda5da8dSAndroid Build Coastguard Worker self._hour, self._minute, self._second, 1562*cda5da8dSAndroid Build Coastguard Worker 0, 1, -1) 1563*cda5da8dSAndroid Build Coastguard Worker return _wrap_strftime(self, fmt, timetuple) 1564*cda5da8dSAndroid Build Coastguard Worker 1565*cda5da8dSAndroid Build Coastguard Worker def __format__(self, fmt): 1566*cda5da8dSAndroid Build Coastguard Worker if not isinstance(fmt, str): 1567*cda5da8dSAndroid Build Coastguard Worker raise TypeError("must be str, not %s" % type(fmt).__name__) 1568*cda5da8dSAndroid Build Coastguard Worker if len(fmt) != 0: 1569*cda5da8dSAndroid Build Coastguard Worker return self.strftime(fmt) 1570*cda5da8dSAndroid Build Coastguard Worker return str(self) 1571*cda5da8dSAndroid Build Coastguard Worker 1572*cda5da8dSAndroid Build Coastguard Worker # Timezone functions 1573*cda5da8dSAndroid Build Coastguard Worker 1574*cda5da8dSAndroid Build Coastguard Worker def utcoffset(self): 1575*cda5da8dSAndroid Build Coastguard Worker """Return the timezone offset as timedelta, positive east of UTC 1576*cda5da8dSAndroid Build Coastguard Worker (negative west of UTC).""" 1577*cda5da8dSAndroid Build Coastguard Worker if self._tzinfo is None: 1578*cda5da8dSAndroid Build Coastguard Worker return None 1579*cda5da8dSAndroid Build Coastguard Worker offset = self._tzinfo.utcoffset(None) 1580*cda5da8dSAndroid Build Coastguard Worker _check_utc_offset("utcoffset", offset) 1581*cda5da8dSAndroid Build Coastguard Worker return offset 1582*cda5da8dSAndroid Build Coastguard Worker 1583*cda5da8dSAndroid Build Coastguard Worker def tzname(self): 1584*cda5da8dSAndroid Build Coastguard Worker """Return the timezone name. 1585*cda5da8dSAndroid Build Coastguard Worker 1586*cda5da8dSAndroid Build Coastguard Worker Note that the name is 100% informational -- there's no requirement that 1587*cda5da8dSAndroid Build Coastguard Worker it mean anything in particular. For example, "GMT", "UTC", "-500", 1588*cda5da8dSAndroid Build Coastguard Worker "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies. 1589*cda5da8dSAndroid Build Coastguard Worker """ 1590*cda5da8dSAndroid Build Coastguard Worker if self._tzinfo is None: 1591*cda5da8dSAndroid Build Coastguard Worker return None 1592*cda5da8dSAndroid Build Coastguard Worker name = self._tzinfo.tzname(None) 1593*cda5da8dSAndroid Build Coastguard Worker _check_tzname(name) 1594*cda5da8dSAndroid Build Coastguard Worker return name 1595*cda5da8dSAndroid Build Coastguard Worker 1596*cda5da8dSAndroid Build Coastguard Worker def dst(self): 1597*cda5da8dSAndroid Build Coastguard Worker """Return 0 if DST is not in effect, or the DST offset (as timedelta 1598*cda5da8dSAndroid Build Coastguard Worker positive eastward) if DST is in effect. 1599*cda5da8dSAndroid Build Coastguard Worker 1600*cda5da8dSAndroid Build Coastguard Worker This is purely informational; the DST offset has already been added to 1601*cda5da8dSAndroid Build Coastguard Worker the UTC offset returned by utcoffset() if applicable, so there's no 1602*cda5da8dSAndroid Build Coastguard Worker need to consult dst() unless you're interested in displaying the DST 1603*cda5da8dSAndroid Build Coastguard Worker info. 1604*cda5da8dSAndroid Build Coastguard Worker """ 1605*cda5da8dSAndroid Build Coastguard Worker if self._tzinfo is None: 1606*cda5da8dSAndroid Build Coastguard Worker return None 1607*cda5da8dSAndroid Build Coastguard Worker offset = self._tzinfo.dst(None) 1608*cda5da8dSAndroid Build Coastguard Worker _check_utc_offset("dst", offset) 1609*cda5da8dSAndroid Build Coastguard Worker return offset 1610*cda5da8dSAndroid Build Coastguard Worker 1611*cda5da8dSAndroid Build Coastguard Worker def replace(self, hour=None, minute=None, second=None, microsecond=None, 1612*cda5da8dSAndroid Build Coastguard Worker tzinfo=True, *, fold=None): 1613*cda5da8dSAndroid Build Coastguard Worker """Return a new time with new values for the specified fields.""" 1614*cda5da8dSAndroid Build Coastguard Worker if hour is None: 1615*cda5da8dSAndroid Build Coastguard Worker hour = self.hour 1616*cda5da8dSAndroid Build Coastguard Worker if minute is None: 1617*cda5da8dSAndroid Build Coastguard Worker minute = self.minute 1618*cda5da8dSAndroid Build Coastguard Worker if second is None: 1619*cda5da8dSAndroid Build Coastguard Worker second = self.second 1620*cda5da8dSAndroid Build Coastguard Worker if microsecond is None: 1621*cda5da8dSAndroid Build Coastguard Worker microsecond = self.microsecond 1622*cda5da8dSAndroid Build Coastguard Worker if tzinfo is True: 1623*cda5da8dSAndroid Build Coastguard Worker tzinfo = self.tzinfo 1624*cda5da8dSAndroid Build Coastguard Worker if fold is None: 1625*cda5da8dSAndroid Build Coastguard Worker fold = self._fold 1626*cda5da8dSAndroid Build Coastguard Worker return type(self)(hour, minute, second, microsecond, tzinfo, fold=fold) 1627*cda5da8dSAndroid Build Coastguard Worker 1628*cda5da8dSAndroid Build Coastguard Worker # Pickle support. 1629*cda5da8dSAndroid Build Coastguard Worker 1630*cda5da8dSAndroid Build Coastguard Worker def _getstate(self, protocol=3): 1631*cda5da8dSAndroid Build Coastguard Worker us2, us3 = divmod(self._microsecond, 256) 1632*cda5da8dSAndroid Build Coastguard Worker us1, us2 = divmod(us2, 256) 1633*cda5da8dSAndroid Build Coastguard Worker h = self._hour 1634*cda5da8dSAndroid Build Coastguard Worker if self._fold and protocol > 3: 1635*cda5da8dSAndroid Build Coastguard Worker h += 128 1636*cda5da8dSAndroid Build Coastguard Worker basestate = bytes([h, self._minute, self._second, 1637*cda5da8dSAndroid Build Coastguard Worker us1, us2, us3]) 1638*cda5da8dSAndroid Build Coastguard Worker if self._tzinfo is None: 1639*cda5da8dSAndroid Build Coastguard Worker return (basestate,) 1640*cda5da8dSAndroid Build Coastguard Worker else: 1641*cda5da8dSAndroid Build Coastguard Worker return (basestate, self._tzinfo) 1642*cda5da8dSAndroid Build Coastguard Worker 1643*cda5da8dSAndroid Build Coastguard Worker def __setstate(self, string, tzinfo): 1644*cda5da8dSAndroid Build Coastguard Worker if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class): 1645*cda5da8dSAndroid Build Coastguard Worker raise TypeError("bad tzinfo state arg") 1646*cda5da8dSAndroid Build Coastguard Worker h, self._minute, self._second, us1, us2, us3 = string 1647*cda5da8dSAndroid Build Coastguard Worker if h > 127: 1648*cda5da8dSAndroid Build Coastguard Worker self._fold = 1 1649*cda5da8dSAndroid Build Coastguard Worker self._hour = h - 128 1650*cda5da8dSAndroid Build Coastguard Worker else: 1651*cda5da8dSAndroid Build Coastguard Worker self._fold = 0 1652*cda5da8dSAndroid Build Coastguard Worker self._hour = h 1653*cda5da8dSAndroid Build Coastguard Worker self._microsecond = (((us1 << 8) | us2) << 8) | us3 1654*cda5da8dSAndroid Build Coastguard Worker self._tzinfo = tzinfo 1655*cda5da8dSAndroid Build Coastguard Worker 1656*cda5da8dSAndroid Build Coastguard Worker def __reduce_ex__(self, protocol): 1657*cda5da8dSAndroid Build Coastguard Worker return (self.__class__, self._getstate(protocol)) 1658*cda5da8dSAndroid Build Coastguard Worker 1659*cda5da8dSAndroid Build Coastguard Worker def __reduce__(self): 1660*cda5da8dSAndroid Build Coastguard Worker return self.__reduce_ex__(2) 1661*cda5da8dSAndroid Build Coastguard Worker 1662*cda5da8dSAndroid Build Coastguard Worker_time_class = time # so functions w/ args named "time" can get at the class 1663*cda5da8dSAndroid Build Coastguard Worker 1664*cda5da8dSAndroid Build Coastguard Workertime.min = time(0, 0, 0) 1665*cda5da8dSAndroid Build Coastguard Workertime.max = time(23, 59, 59, 999999) 1666*cda5da8dSAndroid Build Coastguard Workertime.resolution = timedelta(microseconds=1) 1667*cda5da8dSAndroid Build Coastguard Worker 1668*cda5da8dSAndroid Build Coastguard Worker 1669*cda5da8dSAndroid Build Coastguard Workerclass datetime(date): 1670*cda5da8dSAndroid Build Coastguard Worker """datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]]) 1671*cda5da8dSAndroid Build Coastguard Worker 1672*cda5da8dSAndroid Build Coastguard Worker The year, month and day arguments are required. tzinfo may be None, or an 1673*cda5da8dSAndroid Build Coastguard Worker instance of a tzinfo subclass. The remaining arguments may be ints. 1674*cda5da8dSAndroid Build Coastguard Worker """ 1675*cda5da8dSAndroid Build Coastguard Worker __slots__ = date.__slots__ + time.__slots__ 1676*cda5da8dSAndroid Build Coastguard Worker 1677*cda5da8dSAndroid Build Coastguard Worker def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0, 1678*cda5da8dSAndroid Build Coastguard Worker microsecond=0, tzinfo=None, *, fold=0): 1679*cda5da8dSAndroid Build Coastguard Worker if (isinstance(year, (bytes, str)) and len(year) == 10 and 1680*cda5da8dSAndroid Build Coastguard Worker 1 <= ord(year[2:3])&0x7F <= 12): 1681*cda5da8dSAndroid Build Coastguard Worker # Pickle support 1682*cda5da8dSAndroid Build Coastguard Worker if isinstance(year, str): 1683*cda5da8dSAndroid Build Coastguard Worker try: 1684*cda5da8dSAndroid Build Coastguard Worker year = bytes(year, 'latin1') 1685*cda5da8dSAndroid Build Coastguard Worker except UnicodeEncodeError: 1686*cda5da8dSAndroid Build Coastguard Worker # More informative error message. 1687*cda5da8dSAndroid Build Coastguard Worker raise ValueError( 1688*cda5da8dSAndroid Build Coastguard Worker "Failed to encode latin1 string when unpickling " 1689*cda5da8dSAndroid Build Coastguard Worker "a datetime object. " 1690*cda5da8dSAndroid Build Coastguard Worker "pickle.load(data, encoding='latin1') is assumed.") 1691*cda5da8dSAndroid Build Coastguard Worker self = object.__new__(cls) 1692*cda5da8dSAndroid Build Coastguard Worker self.__setstate(year, month) 1693*cda5da8dSAndroid Build Coastguard Worker self._hashcode = -1 1694*cda5da8dSAndroid Build Coastguard Worker return self 1695*cda5da8dSAndroid Build Coastguard Worker year, month, day = _check_date_fields(year, month, day) 1696*cda5da8dSAndroid Build Coastguard Worker hour, minute, second, microsecond, fold = _check_time_fields( 1697*cda5da8dSAndroid Build Coastguard Worker hour, minute, second, microsecond, fold) 1698*cda5da8dSAndroid Build Coastguard Worker _check_tzinfo_arg(tzinfo) 1699*cda5da8dSAndroid Build Coastguard Worker self = object.__new__(cls) 1700*cda5da8dSAndroid Build Coastguard Worker self._year = year 1701*cda5da8dSAndroid Build Coastguard Worker self._month = month 1702*cda5da8dSAndroid Build Coastguard Worker self._day = day 1703*cda5da8dSAndroid Build Coastguard Worker self._hour = hour 1704*cda5da8dSAndroid Build Coastguard Worker self._minute = minute 1705*cda5da8dSAndroid Build Coastguard Worker self._second = second 1706*cda5da8dSAndroid Build Coastguard Worker self._microsecond = microsecond 1707*cda5da8dSAndroid Build Coastguard Worker self._tzinfo = tzinfo 1708*cda5da8dSAndroid Build Coastguard Worker self._hashcode = -1 1709*cda5da8dSAndroid Build Coastguard Worker self._fold = fold 1710*cda5da8dSAndroid Build Coastguard Worker return self 1711*cda5da8dSAndroid Build Coastguard Worker 1712*cda5da8dSAndroid Build Coastguard Worker # Read-only field accessors 1713*cda5da8dSAndroid Build Coastguard Worker @property 1714*cda5da8dSAndroid Build Coastguard Worker def hour(self): 1715*cda5da8dSAndroid Build Coastguard Worker """hour (0-23)""" 1716*cda5da8dSAndroid Build Coastguard Worker return self._hour 1717*cda5da8dSAndroid Build Coastguard Worker 1718*cda5da8dSAndroid Build Coastguard Worker @property 1719*cda5da8dSAndroid Build Coastguard Worker def minute(self): 1720*cda5da8dSAndroid Build Coastguard Worker """minute (0-59)""" 1721*cda5da8dSAndroid Build Coastguard Worker return self._minute 1722*cda5da8dSAndroid Build Coastguard Worker 1723*cda5da8dSAndroid Build Coastguard Worker @property 1724*cda5da8dSAndroid Build Coastguard Worker def second(self): 1725*cda5da8dSAndroid Build Coastguard Worker """second (0-59)""" 1726*cda5da8dSAndroid Build Coastguard Worker return self._second 1727*cda5da8dSAndroid Build Coastguard Worker 1728*cda5da8dSAndroid Build Coastguard Worker @property 1729*cda5da8dSAndroid Build Coastguard Worker def microsecond(self): 1730*cda5da8dSAndroid Build Coastguard Worker """microsecond (0-999999)""" 1731*cda5da8dSAndroid Build Coastguard Worker return self._microsecond 1732*cda5da8dSAndroid Build Coastguard Worker 1733*cda5da8dSAndroid Build Coastguard Worker @property 1734*cda5da8dSAndroid Build Coastguard Worker def tzinfo(self): 1735*cda5da8dSAndroid Build Coastguard Worker """timezone info object""" 1736*cda5da8dSAndroid Build Coastguard Worker return self._tzinfo 1737*cda5da8dSAndroid Build Coastguard Worker 1738*cda5da8dSAndroid Build Coastguard Worker @property 1739*cda5da8dSAndroid Build Coastguard Worker def fold(self): 1740*cda5da8dSAndroid Build Coastguard Worker return self._fold 1741*cda5da8dSAndroid Build Coastguard Worker 1742*cda5da8dSAndroid Build Coastguard Worker @classmethod 1743*cda5da8dSAndroid Build Coastguard Worker def _fromtimestamp(cls, t, utc, tz): 1744*cda5da8dSAndroid Build Coastguard Worker """Construct a datetime from a POSIX timestamp (like time.time()). 1745*cda5da8dSAndroid Build Coastguard Worker 1746*cda5da8dSAndroid Build Coastguard Worker A timezone info object may be passed in as well. 1747*cda5da8dSAndroid Build Coastguard Worker """ 1748*cda5da8dSAndroid Build Coastguard Worker frac, t = _math.modf(t) 1749*cda5da8dSAndroid Build Coastguard Worker us = round(frac * 1e6) 1750*cda5da8dSAndroid Build Coastguard Worker if us >= 1000000: 1751*cda5da8dSAndroid Build Coastguard Worker t += 1 1752*cda5da8dSAndroid Build Coastguard Worker us -= 1000000 1753*cda5da8dSAndroid Build Coastguard Worker elif us < 0: 1754*cda5da8dSAndroid Build Coastguard Worker t -= 1 1755*cda5da8dSAndroid Build Coastguard Worker us += 1000000 1756*cda5da8dSAndroid Build Coastguard Worker 1757*cda5da8dSAndroid Build Coastguard Worker converter = _time.gmtime if utc else _time.localtime 1758*cda5da8dSAndroid Build Coastguard Worker y, m, d, hh, mm, ss, weekday, jday, dst = converter(t) 1759*cda5da8dSAndroid Build Coastguard Worker ss = min(ss, 59) # clamp out leap seconds if the platform has them 1760*cda5da8dSAndroid Build Coastguard Worker result = cls(y, m, d, hh, mm, ss, us, tz) 1761*cda5da8dSAndroid Build Coastguard Worker if tz is None and not utc: 1762*cda5da8dSAndroid Build Coastguard Worker # As of version 2015f max fold in IANA database is 1763*cda5da8dSAndroid Build Coastguard Worker # 23 hours at 1969-09-30 13:00:00 in Kwajalein. 1764*cda5da8dSAndroid Build Coastguard Worker # Let's probe 24 hours in the past to detect a transition: 1765*cda5da8dSAndroid Build Coastguard Worker max_fold_seconds = 24 * 3600 1766*cda5da8dSAndroid Build Coastguard Worker 1767*cda5da8dSAndroid Build Coastguard Worker # On Windows localtime_s throws an OSError for negative values, 1768*cda5da8dSAndroid Build Coastguard Worker # thus we can't perform fold detection for values of time less 1769*cda5da8dSAndroid Build Coastguard Worker # than the max time fold. See comments in _datetimemodule's 1770*cda5da8dSAndroid Build Coastguard Worker # version of this method for more details. 1771*cda5da8dSAndroid Build Coastguard Worker if t < max_fold_seconds and sys.platform.startswith("win"): 1772*cda5da8dSAndroid Build Coastguard Worker return result 1773*cda5da8dSAndroid Build Coastguard Worker 1774*cda5da8dSAndroid Build Coastguard Worker y, m, d, hh, mm, ss = converter(t - max_fold_seconds)[:6] 1775*cda5da8dSAndroid Build Coastguard Worker probe1 = cls(y, m, d, hh, mm, ss, us, tz) 1776*cda5da8dSAndroid Build Coastguard Worker trans = result - probe1 - timedelta(0, max_fold_seconds) 1777*cda5da8dSAndroid Build Coastguard Worker if trans.days < 0: 1778*cda5da8dSAndroid Build Coastguard Worker y, m, d, hh, mm, ss = converter(t + trans // timedelta(0, 1))[:6] 1779*cda5da8dSAndroid Build Coastguard Worker probe2 = cls(y, m, d, hh, mm, ss, us, tz) 1780*cda5da8dSAndroid Build Coastguard Worker if probe2 == result: 1781*cda5da8dSAndroid Build Coastguard Worker result._fold = 1 1782*cda5da8dSAndroid Build Coastguard Worker elif tz is not None: 1783*cda5da8dSAndroid Build Coastguard Worker result = tz.fromutc(result) 1784*cda5da8dSAndroid Build Coastguard Worker return result 1785*cda5da8dSAndroid Build Coastguard Worker 1786*cda5da8dSAndroid Build Coastguard Worker @classmethod 1787*cda5da8dSAndroid Build Coastguard Worker def fromtimestamp(cls, t, tz=None): 1788*cda5da8dSAndroid Build Coastguard Worker """Construct a datetime from a POSIX timestamp (like time.time()). 1789*cda5da8dSAndroid Build Coastguard Worker 1790*cda5da8dSAndroid Build Coastguard Worker A timezone info object may be passed in as well. 1791*cda5da8dSAndroid Build Coastguard Worker """ 1792*cda5da8dSAndroid Build Coastguard Worker _check_tzinfo_arg(tz) 1793*cda5da8dSAndroid Build Coastguard Worker 1794*cda5da8dSAndroid Build Coastguard Worker return cls._fromtimestamp(t, tz is not None, tz) 1795*cda5da8dSAndroid Build Coastguard Worker 1796*cda5da8dSAndroid Build Coastguard Worker @classmethod 1797*cda5da8dSAndroid Build Coastguard Worker def utcfromtimestamp(cls, t): 1798*cda5da8dSAndroid Build Coastguard Worker """Construct a naive UTC datetime from a POSIX timestamp.""" 1799*cda5da8dSAndroid Build Coastguard Worker return cls._fromtimestamp(t, True, None) 1800*cda5da8dSAndroid Build Coastguard Worker 1801*cda5da8dSAndroid Build Coastguard Worker @classmethod 1802*cda5da8dSAndroid Build Coastguard Worker def now(cls, tz=None): 1803*cda5da8dSAndroid Build Coastguard Worker "Construct a datetime from time.time() and optional time zone info." 1804*cda5da8dSAndroid Build Coastguard Worker t = _time.time() 1805*cda5da8dSAndroid Build Coastguard Worker return cls.fromtimestamp(t, tz) 1806*cda5da8dSAndroid Build Coastguard Worker 1807*cda5da8dSAndroid Build Coastguard Worker @classmethod 1808*cda5da8dSAndroid Build Coastguard Worker def utcnow(cls): 1809*cda5da8dSAndroid Build Coastguard Worker "Construct a UTC datetime from time.time()." 1810*cda5da8dSAndroid Build Coastguard Worker t = _time.time() 1811*cda5da8dSAndroid Build Coastguard Worker return cls.utcfromtimestamp(t) 1812*cda5da8dSAndroid Build Coastguard Worker 1813*cda5da8dSAndroid Build Coastguard Worker @classmethod 1814*cda5da8dSAndroid Build Coastguard Worker def combine(cls, date, time, tzinfo=True): 1815*cda5da8dSAndroid Build Coastguard Worker "Construct a datetime from a given date and a given time." 1816*cda5da8dSAndroid Build Coastguard Worker if not isinstance(date, _date_class): 1817*cda5da8dSAndroid Build Coastguard Worker raise TypeError("date argument must be a date instance") 1818*cda5da8dSAndroid Build Coastguard Worker if not isinstance(time, _time_class): 1819*cda5da8dSAndroid Build Coastguard Worker raise TypeError("time argument must be a time instance") 1820*cda5da8dSAndroid Build Coastguard Worker if tzinfo is True: 1821*cda5da8dSAndroid Build Coastguard Worker tzinfo = time.tzinfo 1822*cda5da8dSAndroid Build Coastguard Worker return cls(date.year, date.month, date.day, 1823*cda5da8dSAndroid Build Coastguard Worker time.hour, time.minute, time.second, time.microsecond, 1824*cda5da8dSAndroid Build Coastguard Worker tzinfo, fold=time.fold) 1825*cda5da8dSAndroid Build Coastguard Worker 1826*cda5da8dSAndroid Build Coastguard Worker @classmethod 1827*cda5da8dSAndroid Build Coastguard Worker def fromisoformat(cls, date_string): 1828*cda5da8dSAndroid Build Coastguard Worker """Construct a datetime from a string in one of the ISO 8601 formats.""" 1829*cda5da8dSAndroid Build Coastguard Worker if not isinstance(date_string, str): 1830*cda5da8dSAndroid Build Coastguard Worker raise TypeError('fromisoformat: argument must be str') 1831*cda5da8dSAndroid Build Coastguard Worker 1832*cda5da8dSAndroid Build Coastguard Worker if len(date_string) < 7: 1833*cda5da8dSAndroid Build Coastguard Worker raise ValueError(f'Invalid isoformat string: {date_string!r}') 1834*cda5da8dSAndroid Build Coastguard Worker 1835*cda5da8dSAndroid Build Coastguard Worker # Split this at the separator 1836*cda5da8dSAndroid Build Coastguard Worker try: 1837*cda5da8dSAndroid Build Coastguard Worker separator_location = _find_isoformat_datetime_separator(date_string) 1838*cda5da8dSAndroid Build Coastguard Worker dstr = date_string[0:separator_location] 1839*cda5da8dSAndroid Build Coastguard Worker tstr = date_string[(separator_location+1):] 1840*cda5da8dSAndroid Build Coastguard Worker 1841*cda5da8dSAndroid Build Coastguard Worker date_components = _parse_isoformat_date(dstr) 1842*cda5da8dSAndroid Build Coastguard Worker except ValueError: 1843*cda5da8dSAndroid Build Coastguard Worker raise ValueError( 1844*cda5da8dSAndroid Build Coastguard Worker f'Invalid isoformat string: {date_string!r}') from None 1845*cda5da8dSAndroid Build Coastguard Worker 1846*cda5da8dSAndroid Build Coastguard Worker if tstr: 1847*cda5da8dSAndroid Build Coastguard Worker try: 1848*cda5da8dSAndroid Build Coastguard Worker time_components = _parse_isoformat_time(tstr) 1849*cda5da8dSAndroid Build Coastguard Worker except ValueError: 1850*cda5da8dSAndroid Build Coastguard Worker raise ValueError( 1851*cda5da8dSAndroid Build Coastguard Worker f'Invalid isoformat string: {date_string!r}') from None 1852*cda5da8dSAndroid Build Coastguard Worker else: 1853*cda5da8dSAndroid Build Coastguard Worker time_components = [0, 0, 0, 0, None] 1854*cda5da8dSAndroid Build Coastguard Worker 1855*cda5da8dSAndroid Build Coastguard Worker return cls(*(date_components + time_components)) 1856*cda5da8dSAndroid Build Coastguard Worker 1857*cda5da8dSAndroid Build Coastguard Worker def timetuple(self): 1858*cda5da8dSAndroid Build Coastguard Worker "Return local time tuple compatible with time.localtime()." 1859*cda5da8dSAndroid Build Coastguard Worker dst = self.dst() 1860*cda5da8dSAndroid Build Coastguard Worker if dst is None: 1861*cda5da8dSAndroid Build Coastguard Worker dst = -1 1862*cda5da8dSAndroid Build Coastguard Worker elif dst: 1863*cda5da8dSAndroid Build Coastguard Worker dst = 1 1864*cda5da8dSAndroid Build Coastguard Worker else: 1865*cda5da8dSAndroid Build Coastguard Worker dst = 0 1866*cda5da8dSAndroid Build Coastguard Worker return _build_struct_time(self.year, self.month, self.day, 1867*cda5da8dSAndroid Build Coastguard Worker self.hour, self.minute, self.second, 1868*cda5da8dSAndroid Build Coastguard Worker dst) 1869*cda5da8dSAndroid Build Coastguard Worker 1870*cda5da8dSAndroid Build Coastguard Worker def _mktime(self): 1871*cda5da8dSAndroid Build Coastguard Worker """Return integer POSIX timestamp.""" 1872*cda5da8dSAndroid Build Coastguard Worker epoch = datetime(1970, 1, 1) 1873*cda5da8dSAndroid Build Coastguard Worker max_fold_seconds = 24 * 3600 1874*cda5da8dSAndroid Build Coastguard Worker t = (self - epoch) // timedelta(0, 1) 1875*cda5da8dSAndroid Build Coastguard Worker def local(u): 1876*cda5da8dSAndroid Build Coastguard Worker y, m, d, hh, mm, ss = _time.localtime(u)[:6] 1877*cda5da8dSAndroid Build Coastguard Worker return (datetime(y, m, d, hh, mm, ss) - epoch) // timedelta(0, 1) 1878*cda5da8dSAndroid Build Coastguard Worker 1879*cda5da8dSAndroid Build Coastguard Worker # Our goal is to solve t = local(u) for u. 1880*cda5da8dSAndroid Build Coastguard Worker a = local(t) - t 1881*cda5da8dSAndroid Build Coastguard Worker u1 = t - a 1882*cda5da8dSAndroid Build Coastguard Worker t1 = local(u1) 1883*cda5da8dSAndroid Build Coastguard Worker if t1 == t: 1884*cda5da8dSAndroid Build Coastguard Worker # We found one solution, but it may not be the one we need. 1885*cda5da8dSAndroid Build Coastguard Worker # Look for an earlier solution (if `fold` is 0), or a 1886*cda5da8dSAndroid Build Coastguard Worker # later one (if `fold` is 1). 1887*cda5da8dSAndroid Build Coastguard Worker u2 = u1 + (-max_fold_seconds, max_fold_seconds)[self.fold] 1888*cda5da8dSAndroid Build Coastguard Worker b = local(u2) - u2 1889*cda5da8dSAndroid Build Coastguard Worker if a == b: 1890*cda5da8dSAndroid Build Coastguard Worker return u1 1891*cda5da8dSAndroid Build Coastguard Worker else: 1892*cda5da8dSAndroid Build Coastguard Worker b = t1 - u1 1893*cda5da8dSAndroid Build Coastguard Worker assert a != b 1894*cda5da8dSAndroid Build Coastguard Worker u2 = t - b 1895*cda5da8dSAndroid Build Coastguard Worker t2 = local(u2) 1896*cda5da8dSAndroid Build Coastguard Worker if t2 == t: 1897*cda5da8dSAndroid Build Coastguard Worker return u2 1898*cda5da8dSAndroid Build Coastguard Worker if t1 == t: 1899*cda5da8dSAndroid Build Coastguard Worker return u1 1900*cda5da8dSAndroid Build Coastguard Worker # We have found both offsets a and b, but neither t - a nor t - b is 1901*cda5da8dSAndroid Build Coastguard Worker # a solution. This means t is in the gap. 1902*cda5da8dSAndroid Build Coastguard Worker return (max, min)[self.fold](u1, u2) 1903*cda5da8dSAndroid Build Coastguard Worker 1904*cda5da8dSAndroid Build Coastguard Worker 1905*cda5da8dSAndroid Build Coastguard Worker def timestamp(self): 1906*cda5da8dSAndroid Build Coastguard Worker "Return POSIX timestamp as float" 1907*cda5da8dSAndroid Build Coastguard Worker if self._tzinfo is None: 1908*cda5da8dSAndroid Build Coastguard Worker s = self._mktime() 1909*cda5da8dSAndroid Build Coastguard Worker return s + self.microsecond / 1e6 1910*cda5da8dSAndroid Build Coastguard Worker else: 1911*cda5da8dSAndroid Build Coastguard Worker return (self - _EPOCH).total_seconds() 1912*cda5da8dSAndroid Build Coastguard Worker 1913*cda5da8dSAndroid Build Coastguard Worker def utctimetuple(self): 1914*cda5da8dSAndroid Build Coastguard Worker "Return UTC time tuple compatible with time.gmtime()." 1915*cda5da8dSAndroid Build Coastguard Worker offset = self.utcoffset() 1916*cda5da8dSAndroid Build Coastguard Worker if offset: 1917*cda5da8dSAndroid Build Coastguard Worker self -= offset 1918*cda5da8dSAndroid Build Coastguard Worker y, m, d = self.year, self.month, self.day 1919*cda5da8dSAndroid Build Coastguard Worker hh, mm, ss = self.hour, self.minute, self.second 1920*cda5da8dSAndroid Build Coastguard Worker return _build_struct_time(y, m, d, hh, mm, ss, 0) 1921*cda5da8dSAndroid Build Coastguard Worker 1922*cda5da8dSAndroid Build Coastguard Worker def date(self): 1923*cda5da8dSAndroid Build Coastguard Worker "Return the date part." 1924*cda5da8dSAndroid Build Coastguard Worker return date(self._year, self._month, self._day) 1925*cda5da8dSAndroid Build Coastguard Worker 1926*cda5da8dSAndroid Build Coastguard Worker def time(self): 1927*cda5da8dSAndroid Build Coastguard Worker "Return the time part, with tzinfo None." 1928*cda5da8dSAndroid Build Coastguard Worker return time(self.hour, self.minute, self.second, self.microsecond, fold=self.fold) 1929*cda5da8dSAndroid Build Coastguard Worker 1930*cda5da8dSAndroid Build Coastguard Worker def timetz(self): 1931*cda5da8dSAndroid Build Coastguard Worker "Return the time part, with same tzinfo." 1932*cda5da8dSAndroid Build Coastguard Worker return time(self.hour, self.minute, self.second, self.microsecond, 1933*cda5da8dSAndroid Build Coastguard Worker self._tzinfo, fold=self.fold) 1934*cda5da8dSAndroid Build Coastguard Worker 1935*cda5da8dSAndroid Build Coastguard Worker def replace(self, year=None, month=None, day=None, hour=None, 1936*cda5da8dSAndroid Build Coastguard Worker minute=None, second=None, microsecond=None, tzinfo=True, 1937*cda5da8dSAndroid Build Coastguard Worker *, fold=None): 1938*cda5da8dSAndroid Build Coastguard Worker """Return a new datetime with new values for the specified fields.""" 1939*cda5da8dSAndroid Build Coastguard Worker if year is None: 1940*cda5da8dSAndroid Build Coastguard Worker year = self.year 1941*cda5da8dSAndroid Build Coastguard Worker if month is None: 1942*cda5da8dSAndroid Build Coastguard Worker month = self.month 1943*cda5da8dSAndroid Build Coastguard Worker if day is None: 1944*cda5da8dSAndroid Build Coastguard Worker day = self.day 1945*cda5da8dSAndroid Build Coastguard Worker if hour is None: 1946*cda5da8dSAndroid Build Coastguard Worker hour = self.hour 1947*cda5da8dSAndroid Build Coastguard Worker if minute is None: 1948*cda5da8dSAndroid Build Coastguard Worker minute = self.minute 1949*cda5da8dSAndroid Build Coastguard Worker if second is None: 1950*cda5da8dSAndroid Build Coastguard Worker second = self.second 1951*cda5da8dSAndroid Build Coastguard Worker if microsecond is None: 1952*cda5da8dSAndroid Build Coastguard Worker microsecond = self.microsecond 1953*cda5da8dSAndroid Build Coastguard Worker if tzinfo is True: 1954*cda5da8dSAndroid Build Coastguard Worker tzinfo = self.tzinfo 1955*cda5da8dSAndroid Build Coastguard Worker if fold is None: 1956*cda5da8dSAndroid Build Coastguard Worker fold = self.fold 1957*cda5da8dSAndroid Build Coastguard Worker return type(self)(year, month, day, hour, minute, second, 1958*cda5da8dSAndroid Build Coastguard Worker microsecond, tzinfo, fold=fold) 1959*cda5da8dSAndroid Build Coastguard Worker 1960*cda5da8dSAndroid Build Coastguard Worker def _local_timezone(self): 1961*cda5da8dSAndroid Build Coastguard Worker if self.tzinfo is None: 1962*cda5da8dSAndroid Build Coastguard Worker ts = self._mktime() 1963*cda5da8dSAndroid Build Coastguard Worker else: 1964*cda5da8dSAndroid Build Coastguard Worker ts = (self - _EPOCH) // timedelta(seconds=1) 1965*cda5da8dSAndroid Build Coastguard Worker localtm = _time.localtime(ts) 1966*cda5da8dSAndroid Build Coastguard Worker local = datetime(*localtm[:6]) 1967*cda5da8dSAndroid Build Coastguard Worker # Extract TZ data 1968*cda5da8dSAndroid Build Coastguard Worker gmtoff = localtm.tm_gmtoff 1969*cda5da8dSAndroid Build Coastguard Worker zone = localtm.tm_zone 1970*cda5da8dSAndroid Build Coastguard Worker return timezone(timedelta(seconds=gmtoff), zone) 1971*cda5da8dSAndroid Build Coastguard Worker 1972*cda5da8dSAndroid Build Coastguard Worker def astimezone(self, tz=None): 1973*cda5da8dSAndroid Build Coastguard Worker if tz is None: 1974*cda5da8dSAndroid Build Coastguard Worker tz = self._local_timezone() 1975*cda5da8dSAndroid Build Coastguard Worker elif not isinstance(tz, tzinfo): 1976*cda5da8dSAndroid Build Coastguard Worker raise TypeError("tz argument must be an instance of tzinfo") 1977*cda5da8dSAndroid Build Coastguard Worker 1978*cda5da8dSAndroid Build Coastguard Worker mytz = self.tzinfo 1979*cda5da8dSAndroid Build Coastguard Worker if mytz is None: 1980*cda5da8dSAndroid Build Coastguard Worker mytz = self._local_timezone() 1981*cda5da8dSAndroid Build Coastguard Worker myoffset = mytz.utcoffset(self) 1982*cda5da8dSAndroid Build Coastguard Worker else: 1983*cda5da8dSAndroid Build Coastguard Worker myoffset = mytz.utcoffset(self) 1984*cda5da8dSAndroid Build Coastguard Worker if myoffset is None: 1985*cda5da8dSAndroid Build Coastguard Worker mytz = self.replace(tzinfo=None)._local_timezone() 1986*cda5da8dSAndroid Build Coastguard Worker myoffset = mytz.utcoffset(self) 1987*cda5da8dSAndroid Build Coastguard Worker 1988*cda5da8dSAndroid Build Coastguard Worker if tz is mytz: 1989*cda5da8dSAndroid Build Coastguard Worker return self 1990*cda5da8dSAndroid Build Coastguard Worker 1991*cda5da8dSAndroid Build Coastguard Worker # Convert self to UTC, and attach the new time zone object. 1992*cda5da8dSAndroid Build Coastguard Worker utc = (self - myoffset).replace(tzinfo=tz) 1993*cda5da8dSAndroid Build Coastguard Worker 1994*cda5da8dSAndroid Build Coastguard Worker # Convert from UTC to tz's local time. 1995*cda5da8dSAndroid Build Coastguard Worker return tz.fromutc(utc) 1996*cda5da8dSAndroid Build Coastguard Worker 1997*cda5da8dSAndroid Build Coastguard Worker # Ways to produce a string. 1998*cda5da8dSAndroid Build Coastguard Worker 1999*cda5da8dSAndroid Build Coastguard Worker def ctime(self): 2000*cda5da8dSAndroid Build Coastguard Worker "Return ctime() style string." 2001*cda5da8dSAndroid Build Coastguard Worker weekday = self.toordinal() % 7 or 7 2002*cda5da8dSAndroid Build Coastguard Worker return "%s %s %2d %02d:%02d:%02d %04d" % ( 2003*cda5da8dSAndroid Build Coastguard Worker _DAYNAMES[weekday], 2004*cda5da8dSAndroid Build Coastguard Worker _MONTHNAMES[self._month], 2005*cda5da8dSAndroid Build Coastguard Worker self._day, 2006*cda5da8dSAndroid Build Coastguard Worker self._hour, self._minute, self._second, 2007*cda5da8dSAndroid Build Coastguard Worker self._year) 2008*cda5da8dSAndroid Build Coastguard Worker 2009*cda5da8dSAndroid Build Coastguard Worker def isoformat(self, sep='T', timespec='auto'): 2010*cda5da8dSAndroid Build Coastguard Worker """Return the time formatted according to ISO. 2011*cda5da8dSAndroid Build Coastguard Worker 2012*cda5da8dSAndroid Build Coastguard Worker The full format looks like 'YYYY-MM-DD HH:MM:SS.mmmmmm'. 2013*cda5da8dSAndroid Build Coastguard Worker By default, the fractional part is omitted if self.microsecond == 0. 2014*cda5da8dSAndroid Build Coastguard Worker 2015*cda5da8dSAndroid Build Coastguard Worker If self.tzinfo is not None, the UTC offset is also attached, giving 2016*cda5da8dSAndroid Build Coastguard Worker giving a full format of 'YYYY-MM-DD HH:MM:SS.mmmmmm+HH:MM'. 2017*cda5da8dSAndroid Build Coastguard Worker 2018*cda5da8dSAndroid Build Coastguard Worker Optional argument sep specifies the separator between date and 2019*cda5da8dSAndroid Build Coastguard Worker time, default 'T'. 2020*cda5da8dSAndroid Build Coastguard Worker 2021*cda5da8dSAndroid Build Coastguard Worker The optional argument timespec specifies the number of additional 2022*cda5da8dSAndroid Build Coastguard Worker terms of the time to include. Valid options are 'auto', 'hours', 2023*cda5da8dSAndroid Build Coastguard Worker 'minutes', 'seconds', 'milliseconds' and 'microseconds'. 2024*cda5da8dSAndroid Build Coastguard Worker """ 2025*cda5da8dSAndroid Build Coastguard Worker s = ("%04d-%02d-%02d%c" % (self._year, self._month, self._day, sep) + 2026*cda5da8dSAndroid Build Coastguard Worker _format_time(self._hour, self._minute, self._second, 2027*cda5da8dSAndroid Build Coastguard Worker self._microsecond, timespec)) 2028*cda5da8dSAndroid Build Coastguard Worker 2029*cda5da8dSAndroid Build Coastguard Worker off = self.utcoffset() 2030*cda5da8dSAndroid Build Coastguard Worker tz = _format_offset(off) 2031*cda5da8dSAndroid Build Coastguard Worker if tz: 2032*cda5da8dSAndroid Build Coastguard Worker s += tz 2033*cda5da8dSAndroid Build Coastguard Worker 2034*cda5da8dSAndroid Build Coastguard Worker return s 2035*cda5da8dSAndroid Build Coastguard Worker 2036*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 2037*cda5da8dSAndroid Build Coastguard Worker """Convert to formal string, for repr().""" 2038*cda5da8dSAndroid Build Coastguard Worker L = [self._year, self._month, self._day, # These are never zero 2039*cda5da8dSAndroid Build Coastguard Worker self._hour, self._minute, self._second, self._microsecond] 2040*cda5da8dSAndroid Build Coastguard Worker if L[-1] == 0: 2041*cda5da8dSAndroid Build Coastguard Worker del L[-1] 2042*cda5da8dSAndroid Build Coastguard Worker if L[-1] == 0: 2043*cda5da8dSAndroid Build Coastguard Worker del L[-1] 2044*cda5da8dSAndroid Build Coastguard Worker s = "%s.%s(%s)" % (self.__class__.__module__, 2045*cda5da8dSAndroid Build Coastguard Worker self.__class__.__qualname__, 2046*cda5da8dSAndroid Build Coastguard Worker ", ".join(map(str, L))) 2047*cda5da8dSAndroid Build Coastguard Worker if self._tzinfo is not None: 2048*cda5da8dSAndroid Build Coastguard Worker assert s[-1:] == ")" 2049*cda5da8dSAndroid Build Coastguard Worker s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")" 2050*cda5da8dSAndroid Build Coastguard Worker if self._fold: 2051*cda5da8dSAndroid Build Coastguard Worker assert s[-1:] == ")" 2052*cda5da8dSAndroid Build Coastguard Worker s = s[:-1] + ", fold=1)" 2053*cda5da8dSAndroid Build Coastguard Worker return s 2054*cda5da8dSAndroid Build Coastguard Worker 2055*cda5da8dSAndroid Build Coastguard Worker def __str__(self): 2056*cda5da8dSAndroid Build Coastguard Worker "Convert to string, for str()." 2057*cda5da8dSAndroid Build Coastguard Worker return self.isoformat(sep=' ') 2058*cda5da8dSAndroid Build Coastguard Worker 2059*cda5da8dSAndroid Build Coastguard Worker @classmethod 2060*cda5da8dSAndroid Build Coastguard Worker def strptime(cls, date_string, format): 2061*cda5da8dSAndroid Build Coastguard Worker 'string, format -> new datetime parsed from a string (like time.strptime()).' 2062*cda5da8dSAndroid Build Coastguard Worker import _strptime 2063*cda5da8dSAndroid Build Coastguard Worker return _strptime._strptime_datetime(cls, date_string, format) 2064*cda5da8dSAndroid Build Coastguard Worker 2065*cda5da8dSAndroid Build Coastguard Worker def utcoffset(self): 2066*cda5da8dSAndroid Build Coastguard Worker """Return the timezone offset as timedelta positive east of UTC (negative west of 2067*cda5da8dSAndroid Build Coastguard Worker UTC).""" 2068*cda5da8dSAndroid Build Coastguard Worker if self._tzinfo is None: 2069*cda5da8dSAndroid Build Coastguard Worker return None 2070*cda5da8dSAndroid Build Coastguard Worker offset = self._tzinfo.utcoffset(self) 2071*cda5da8dSAndroid Build Coastguard Worker _check_utc_offset("utcoffset", offset) 2072*cda5da8dSAndroid Build Coastguard Worker return offset 2073*cda5da8dSAndroid Build Coastguard Worker 2074*cda5da8dSAndroid Build Coastguard Worker def tzname(self): 2075*cda5da8dSAndroid Build Coastguard Worker """Return the timezone name. 2076*cda5da8dSAndroid Build Coastguard Worker 2077*cda5da8dSAndroid Build Coastguard Worker Note that the name is 100% informational -- there's no requirement that 2078*cda5da8dSAndroid Build Coastguard Worker it mean anything in particular. For example, "GMT", "UTC", "-500", 2079*cda5da8dSAndroid Build Coastguard Worker "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies. 2080*cda5da8dSAndroid Build Coastguard Worker """ 2081*cda5da8dSAndroid Build Coastguard Worker if self._tzinfo is None: 2082*cda5da8dSAndroid Build Coastguard Worker return None 2083*cda5da8dSAndroid Build Coastguard Worker name = self._tzinfo.tzname(self) 2084*cda5da8dSAndroid Build Coastguard Worker _check_tzname(name) 2085*cda5da8dSAndroid Build Coastguard Worker return name 2086*cda5da8dSAndroid Build Coastguard Worker 2087*cda5da8dSAndroid Build Coastguard Worker def dst(self): 2088*cda5da8dSAndroid Build Coastguard Worker """Return 0 if DST is not in effect, or the DST offset (as timedelta 2089*cda5da8dSAndroid Build Coastguard Worker positive eastward) if DST is in effect. 2090*cda5da8dSAndroid Build Coastguard Worker 2091*cda5da8dSAndroid Build Coastguard Worker This is purely informational; the DST offset has already been added to 2092*cda5da8dSAndroid Build Coastguard Worker the UTC offset returned by utcoffset() if applicable, so there's no 2093*cda5da8dSAndroid Build Coastguard Worker need to consult dst() unless you're interested in displaying the DST 2094*cda5da8dSAndroid Build Coastguard Worker info. 2095*cda5da8dSAndroid Build Coastguard Worker """ 2096*cda5da8dSAndroid Build Coastguard Worker if self._tzinfo is None: 2097*cda5da8dSAndroid Build Coastguard Worker return None 2098*cda5da8dSAndroid Build Coastguard Worker offset = self._tzinfo.dst(self) 2099*cda5da8dSAndroid Build Coastguard Worker _check_utc_offset("dst", offset) 2100*cda5da8dSAndroid Build Coastguard Worker return offset 2101*cda5da8dSAndroid Build Coastguard Worker 2102*cda5da8dSAndroid Build Coastguard Worker # Comparisons of datetime objects with other. 2103*cda5da8dSAndroid Build Coastguard Worker 2104*cda5da8dSAndroid Build Coastguard Worker def __eq__(self, other): 2105*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, datetime): 2106*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other, allow_mixed=True) == 0 2107*cda5da8dSAndroid Build Coastguard Worker elif not isinstance(other, date): 2108*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 2109*cda5da8dSAndroid Build Coastguard Worker else: 2110*cda5da8dSAndroid Build Coastguard Worker return False 2111*cda5da8dSAndroid Build Coastguard Worker 2112*cda5da8dSAndroid Build Coastguard Worker def __le__(self, other): 2113*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, datetime): 2114*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) <= 0 2115*cda5da8dSAndroid Build Coastguard Worker elif not isinstance(other, date): 2116*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 2117*cda5da8dSAndroid Build Coastguard Worker else: 2118*cda5da8dSAndroid Build Coastguard Worker _cmperror(self, other) 2119*cda5da8dSAndroid Build Coastguard Worker 2120*cda5da8dSAndroid Build Coastguard Worker def __lt__(self, other): 2121*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, datetime): 2122*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) < 0 2123*cda5da8dSAndroid Build Coastguard Worker elif not isinstance(other, date): 2124*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 2125*cda5da8dSAndroid Build Coastguard Worker else: 2126*cda5da8dSAndroid Build Coastguard Worker _cmperror(self, other) 2127*cda5da8dSAndroid Build Coastguard Worker 2128*cda5da8dSAndroid Build Coastguard Worker def __ge__(self, other): 2129*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, datetime): 2130*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) >= 0 2131*cda5da8dSAndroid Build Coastguard Worker elif not isinstance(other, date): 2132*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 2133*cda5da8dSAndroid Build Coastguard Worker else: 2134*cda5da8dSAndroid Build Coastguard Worker _cmperror(self, other) 2135*cda5da8dSAndroid Build Coastguard Worker 2136*cda5da8dSAndroid Build Coastguard Worker def __gt__(self, other): 2137*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, datetime): 2138*cda5da8dSAndroid Build Coastguard Worker return self._cmp(other) > 0 2139*cda5da8dSAndroid Build Coastguard Worker elif not isinstance(other, date): 2140*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 2141*cda5da8dSAndroid Build Coastguard Worker else: 2142*cda5da8dSAndroid Build Coastguard Worker _cmperror(self, other) 2143*cda5da8dSAndroid Build Coastguard Worker 2144*cda5da8dSAndroid Build Coastguard Worker def _cmp(self, other, allow_mixed=False): 2145*cda5da8dSAndroid Build Coastguard Worker assert isinstance(other, datetime) 2146*cda5da8dSAndroid Build Coastguard Worker mytz = self._tzinfo 2147*cda5da8dSAndroid Build Coastguard Worker ottz = other._tzinfo 2148*cda5da8dSAndroid Build Coastguard Worker myoff = otoff = None 2149*cda5da8dSAndroid Build Coastguard Worker 2150*cda5da8dSAndroid Build Coastguard Worker if mytz is ottz: 2151*cda5da8dSAndroid Build Coastguard Worker base_compare = True 2152*cda5da8dSAndroid Build Coastguard Worker else: 2153*cda5da8dSAndroid Build Coastguard Worker myoff = self.utcoffset() 2154*cda5da8dSAndroid Build Coastguard Worker otoff = other.utcoffset() 2155*cda5da8dSAndroid Build Coastguard Worker # Assume that allow_mixed means that we are called from __eq__ 2156*cda5da8dSAndroid Build Coastguard Worker if allow_mixed: 2157*cda5da8dSAndroid Build Coastguard Worker if myoff != self.replace(fold=not self.fold).utcoffset(): 2158*cda5da8dSAndroid Build Coastguard Worker return 2 2159*cda5da8dSAndroid Build Coastguard Worker if otoff != other.replace(fold=not other.fold).utcoffset(): 2160*cda5da8dSAndroid Build Coastguard Worker return 2 2161*cda5da8dSAndroid Build Coastguard Worker base_compare = myoff == otoff 2162*cda5da8dSAndroid Build Coastguard Worker 2163*cda5da8dSAndroid Build Coastguard Worker if base_compare: 2164*cda5da8dSAndroid Build Coastguard Worker return _cmp((self._year, self._month, self._day, 2165*cda5da8dSAndroid Build Coastguard Worker self._hour, self._minute, self._second, 2166*cda5da8dSAndroid Build Coastguard Worker self._microsecond), 2167*cda5da8dSAndroid Build Coastguard Worker (other._year, other._month, other._day, 2168*cda5da8dSAndroid Build Coastguard Worker other._hour, other._minute, other._second, 2169*cda5da8dSAndroid Build Coastguard Worker other._microsecond)) 2170*cda5da8dSAndroid Build Coastguard Worker if myoff is None or otoff is None: 2171*cda5da8dSAndroid Build Coastguard Worker if allow_mixed: 2172*cda5da8dSAndroid Build Coastguard Worker return 2 # arbitrary non-zero value 2173*cda5da8dSAndroid Build Coastguard Worker else: 2174*cda5da8dSAndroid Build Coastguard Worker raise TypeError("cannot compare naive and aware datetimes") 2175*cda5da8dSAndroid Build Coastguard Worker # XXX What follows could be done more efficiently... 2176*cda5da8dSAndroid Build Coastguard Worker diff = self - other # this will take offsets into account 2177*cda5da8dSAndroid Build Coastguard Worker if diff.days < 0: 2178*cda5da8dSAndroid Build Coastguard Worker return -1 2179*cda5da8dSAndroid Build Coastguard Worker return diff and 1 or 0 2180*cda5da8dSAndroid Build Coastguard Worker 2181*cda5da8dSAndroid Build Coastguard Worker def __add__(self, other): 2182*cda5da8dSAndroid Build Coastguard Worker "Add a datetime and a timedelta." 2183*cda5da8dSAndroid Build Coastguard Worker if not isinstance(other, timedelta): 2184*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 2185*cda5da8dSAndroid Build Coastguard Worker delta = timedelta(self.toordinal(), 2186*cda5da8dSAndroid Build Coastguard Worker hours=self._hour, 2187*cda5da8dSAndroid Build Coastguard Worker minutes=self._minute, 2188*cda5da8dSAndroid Build Coastguard Worker seconds=self._second, 2189*cda5da8dSAndroid Build Coastguard Worker microseconds=self._microsecond) 2190*cda5da8dSAndroid Build Coastguard Worker delta += other 2191*cda5da8dSAndroid Build Coastguard Worker hour, rem = divmod(delta.seconds, 3600) 2192*cda5da8dSAndroid Build Coastguard Worker minute, second = divmod(rem, 60) 2193*cda5da8dSAndroid Build Coastguard Worker if 0 < delta.days <= _MAXORDINAL: 2194*cda5da8dSAndroid Build Coastguard Worker return type(self).combine(date.fromordinal(delta.days), 2195*cda5da8dSAndroid Build Coastguard Worker time(hour, minute, second, 2196*cda5da8dSAndroid Build Coastguard Worker delta.microseconds, 2197*cda5da8dSAndroid Build Coastguard Worker tzinfo=self._tzinfo)) 2198*cda5da8dSAndroid Build Coastguard Worker raise OverflowError("result out of range") 2199*cda5da8dSAndroid Build Coastguard Worker 2200*cda5da8dSAndroid Build Coastguard Worker __radd__ = __add__ 2201*cda5da8dSAndroid Build Coastguard Worker 2202*cda5da8dSAndroid Build Coastguard Worker def __sub__(self, other): 2203*cda5da8dSAndroid Build Coastguard Worker "Subtract two datetimes, or a datetime and a timedelta." 2204*cda5da8dSAndroid Build Coastguard Worker if not isinstance(other, datetime): 2205*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timedelta): 2206*cda5da8dSAndroid Build Coastguard Worker return self + -other 2207*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 2208*cda5da8dSAndroid Build Coastguard Worker 2209*cda5da8dSAndroid Build Coastguard Worker days1 = self.toordinal() 2210*cda5da8dSAndroid Build Coastguard Worker days2 = other.toordinal() 2211*cda5da8dSAndroid Build Coastguard Worker secs1 = self._second + self._minute * 60 + self._hour * 3600 2212*cda5da8dSAndroid Build Coastguard Worker secs2 = other._second + other._minute * 60 + other._hour * 3600 2213*cda5da8dSAndroid Build Coastguard Worker base = timedelta(days1 - days2, 2214*cda5da8dSAndroid Build Coastguard Worker secs1 - secs2, 2215*cda5da8dSAndroid Build Coastguard Worker self._microsecond - other._microsecond) 2216*cda5da8dSAndroid Build Coastguard Worker if self._tzinfo is other._tzinfo: 2217*cda5da8dSAndroid Build Coastguard Worker return base 2218*cda5da8dSAndroid Build Coastguard Worker myoff = self.utcoffset() 2219*cda5da8dSAndroid Build Coastguard Worker otoff = other.utcoffset() 2220*cda5da8dSAndroid Build Coastguard Worker if myoff == otoff: 2221*cda5da8dSAndroid Build Coastguard Worker return base 2222*cda5da8dSAndroid Build Coastguard Worker if myoff is None or otoff is None: 2223*cda5da8dSAndroid Build Coastguard Worker raise TypeError("cannot mix naive and timezone-aware time") 2224*cda5da8dSAndroid Build Coastguard Worker return base + otoff - myoff 2225*cda5da8dSAndroid Build Coastguard Worker 2226*cda5da8dSAndroid Build Coastguard Worker def __hash__(self): 2227*cda5da8dSAndroid Build Coastguard Worker if self._hashcode == -1: 2228*cda5da8dSAndroid Build Coastguard Worker if self.fold: 2229*cda5da8dSAndroid Build Coastguard Worker t = self.replace(fold=0) 2230*cda5da8dSAndroid Build Coastguard Worker else: 2231*cda5da8dSAndroid Build Coastguard Worker t = self 2232*cda5da8dSAndroid Build Coastguard Worker tzoff = t.utcoffset() 2233*cda5da8dSAndroid Build Coastguard Worker if tzoff is None: 2234*cda5da8dSAndroid Build Coastguard Worker self._hashcode = hash(t._getstate()[0]) 2235*cda5da8dSAndroid Build Coastguard Worker else: 2236*cda5da8dSAndroid Build Coastguard Worker days = _ymd2ord(self.year, self.month, self.day) 2237*cda5da8dSAndroid Build Coastguard Worker seconds = self.hour * 3600 + self.minute * 60 + self.second 2238*cda5da8dSAndroid Build Coastguard Worker self._hashcode = hash(timedelta(days, seconds, self.microsecond) - tzoff) 2239*cda5da8dSAndroid Build Coastguard Worker return self._hashcode 2240*cda5da8dSAndroid Build Coastguard Worker 2241*cda5da8dSAndroid Build Coastguard Worker # Pickle support. 2242*cda5da8dSAndroid Build Coastguard Worker 2243*cda5da8dSAndroid Build Coastguard Worker def _getstate(self, protocol=3): 2244*cda5da8dSAndroid Build Coastguard Worker yhi, ylo = divmod(self._year, 256) 2245*cda5da8dSAndroid Build Coastguard Worker us2, us3 = divmod(self._microsecond, 256) 2246*cda5da8dSAndroid Build Coastguard Worker us1, us2 = divmod(us2, 256) 2247*cda5da8dSAndroid Build Coastguard Worker m = self._month 2248*cda5da8dSAndroid Build Coastguard Worker if self._fold and protocol > 3: 2249*cda5da8dSAndroid Build Coastguard Worker m += 128 2250*cda5da8dSAndroid Build Coastguard Worker basestate = bytes([yhi, ylo, m, self._day, 2251*cda5da8dSAndroid Build Coastguard Worker self._hour, self._minute, self._second, 2252*cda5da8dSAndroid Build Coastguard Worker us1, us2, us3]) 2253*cda5da8dSAndroid Build Coastguard Worker if self._tzinfo is None: 2254*cda5da8dSAndroid Build Coastguard Worker return (basestate,) 2255*cda5da8dSAndroid Build Coastguard Worker else: 2256*cda5da8dSAndroid Build Coastguard Worker return (basestate, self._tzinfo) 2257*cda5da8dSAndroid Build Coastguard Worker 2258*cda5da8dSAndroid Build Coastguard Worker def __setstate(self, string, tzinfo): 2259*cda5da8dSAndroid Build Coastguard Worker if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class): 2260*cda5da8dSAndroid Build Coastguard Worker raise TypeError("bad tzinfo state arg") 2261*cda5da8dSAndroid Build Coastguard Worker (yhi, ylo, m, self._day, self._hour, 2262*cda5da8dSAndroid Build Coastguard Worker self._minute, self._second, us1, us2, us3) = string 2263*cda5da8dSAndroid Build Coastguard Worker if m > 127: 2264*cda5da8dSAndroid Build Coastguard Worker self._fold = 1 2265*cda5da8dSAndroid Build Coastguard Worker self._month = m - 128 2266*cda5da8dSAndroid Build Coastguard Worker else: 2267*cda5da8dSAndroid Build Coastguard Worker self._fold = 0 2268*cda5da8dSAndroid Build Coastguard Worker self._month = m 2269*cda5da8dSAndroid Build Coastguard Worker self._year = yhi * 256 + ylo 2270*cda5da8dSAndroid Build Coastguard Worker self._microsecond = (((us1 << 8) | us2) << 8) | us3 2271*cda5da8dSAndroid Build Coastguard Worker self._tzinfo = tzinfo 2272*cda5da8dSAndroid Build Coastguard Worker 2273*cda5da8dSAndroid Build Coastguard Worker def __reduce_ex__(self, protocol): 2274*cda5da8dSAndroid Build Coastguard Worker return (self.__class__, self._getstate(protocol)) 2275*cda5da8dSAndroid Build Coastguard Worker 2276*cda5da8dSAndroid Build Coastguard Worker def __reduce__(self): 2277*cda5da8dSAndroid Build Coastguard Worker return self.__reduce_ex__(2) 2278*cda5da8dSAndroid Build Coastguard Worker 2279*cda5da8dSAndroid Build Coastguard Worker 2280*cda5da8dSAndroid Build Coastguard Workerdatetime.min = datetime(1, 1, 1) 2281*cda5da8dSAndroid Build Coastguard Workerdatetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999) 2282*cda5da8dSAndroid Build Coastguard Workerdatetime.resolution = timedelta(microseconds=1) 2283*cda5da8dSAndroid Build Coastguard Worker 2284*cda5da8dSAndroid Build Coastguard Worker 2285*cda5da8dSAndroid Build Coastguard Workerdef _isoweek1monday(year): 2286*cda5da8dSAndroid Build Coastguard Worker # Helper to calculate the day number of the Monday starting week 1 2287*cda5da8dSAndroid Build Coastguard Worker # XXX This could be done more efficiently 2288*cda5da8dSAndroid Build Coastguard Worker THURSDAY = 3 2289*cda5da8dSAndroid Build Coastguard Worker firstday = _ymd2ord(year, 1, 1) 2290*cda5da8dSAndroid Build Coastguard Worker firstweekday = (firstday + 6) % 7 # See weekday() above 2291*cda5da8dSAndroid Build Coastguard Worker week1monday = firstday - firstweekday 2292*cda5da8dSAndroid Build Coastguard Worker if firstweekday > THURSDAY: 2293*cda5da8dSAndroid Build Coastguard Worker week1monday += 7 2294*cda5da8dSAndroid Build Coastguard Worker return week1monday 2295*cda5da8dSAndroid Build Coastguard Worker 2296*cda5da8dSAndroid Build Coastguard Worker 2297*cda5da8dSAndroid Build Coastguard Workerclass timezone(tzinfo): 2298*cda5da8dSAndroid Build Coastguard Worker __slots__ = '_offset', '_name' 2299*cda5da8dSAndroid Build Coastguard Worker 2300*cda5da8dSAndroid Build Coastguard Worker # Sentinel value to disallow None 2301*cda5da8dSAndroid Build Coastguard Worker _Omitted = object() 2302*cda5da8dSAndroid Build Coastguard Worker def __new__(cls, offset, name=_Omitted): 2303*cda5da8dSAndroid Build Coastguard Worker if not isinstance(offset, timedelta): 2304*cda5da8dSAndroid Build Coastguard Worker raise TypeError("offset must be a timedelta") 2305*cda5da8dSAndroid Build Coastguard Worker if name is cls._Omitted: 2306*cda5da8dSAndroid Build Coastguard Worker if not offset: 2307*cda5da8dSAndroid Build Coastguard Worker return cls.utc 2308*cda5da8dSAndroid Build Coastguard Worker name = None 2309*cda5da8dSAndroid Build Coastguard Worker elif not isinstance(name, str): 2310*cda5da8dSAndroid Build Coastguard Worker raise TypeError("name must be a string") 2311*cda5da8dSAndroid Build Coastguard Worker if not cls._minoffset <= offset <= cls._maxoffset: 2312*cda5da8dSAndroid Build Coastguard Worker raise ValueError("offset must be a timedelta " 2313*cda5da8dSAndroid Build Coastguard Worker "strictly between -timedelta(hours=24) and " 2314*cda5da8dSAndroid Build Coastguard Worker "timedelta(hours=24).") 2315*cda5da8dSAndroid Build Coastguard Worker return cls._create(offset, name) 2316*cda5da8dSAndroid Build Coastguard Worker 2317*cda5da8dSAndroid Build Coastguard Worker @classmethod 2318*cda5da8dSAndroid Build Coastguard Worker def _create(cls, offset, name=None): 2319*cda5da8dSAndroid Build Coastguard Worker self = tzinfo.__new__(cls) 2320*cda5da8dSAndroid Build Coastguard Worker self._offset = offset 2321*cda5da8dSAndroid Build Coastguard Worker self._name = name 2322*cda5da8dSAndroid Build Coastguard Worker return self 2323*cda5da8dSAndroid Build Coastguard Worker 2324*cda5da8dSAndroid Build Coastguard Worker def __getinitargs__(self): 2325*cda5da8dSAndroid Build Coastguard Worker """pickle support""" 2326*cda5da8dSAndroid Build Coastguard Worker if self._name is None: 2327*cda5da8dSAndroid Build Coastguard Worker return (self._offset,) 2328*cda5da8dSAndroid Build Coastguard Worker return (self._offset, self._name) 2329*cda5da8dSAndroid Build Coastguard Worker 2330*cda5da8dSAndroid Build Coastguard Worker def __eq__(self, other): 2331*cda5da8dSAndroid Build Coastguard Worker if isinstance(other, timezone): 2332*cda5da8dSAndroid Build Coastguard Worker return self._offset == other._offset 2333*cda5da8dSAndroid Build Coastguard Worker return NotImplemented 2334*cda5da8dSAndroid Build Coastguard Worker 2335*cda5da8dSAndroid Build Coastguard Worker def __hash__(self): 2336*cda5da8dSAndroid Build Coastguard Worker return hash(self._offset) 2337*cda5da8dSAndroid Build Coastguard Worker 2338*cda5da8dSAndroid Build Coastguard Worker def __repr__(self): 2339*cda5da8dSAndroid Build Coastguard Worker """Convert to formal string, for repr(). 2340*cda5da8dSAndroid Build Coastguard Worker 2341*cda5da8dSAndroid Build Coastguard Worker >>> tz = timezone.utc 2342*cda5da8dSAndroid Build Coastguard Worker >>> repr(tz) 2343*cda5da8dSAndroid Build Coastguard Worker 'datetime.timezone.utc' 2344*cda5da8dSAndroid Build Coastguard Worker >>> tz = timezone(timedelta(hours=-5), 'EST') 2345*cda5da8dSAndroid Build Coastguard Worker >>> repr(tz) 2346*cda5da8dSAndroid Build Coastguard Worker "datetime.timezone(datetime.timedelta(-1, 68400), 'EST')" 2347*cda5da8dSAndroid Build Coastguard Worker """ 2348*cda5da8dSAndroid Build Coastguard Worker if self is self.utc: 2349*cda5da8dSAndroid Build Coastguard Worker return 'datetime.timezone.utc' 2350*cda5da8dSAndroid Build Coastguard Worker if self._name is None: 2351*cda5da8dSAndroid Build Coastguard Worker return "%s.%s(%r)" % (self.__class__.__module__, 2352*cda5da8dSAndroid Build Coastguard Worker self.__class__.__qualname__, 2353*cda5da8dSAndroid Build Coastguard Worker self._offset) 2354*cda5da8dSAndroid Build Coastguard Worker return "%s.%s(%r, %r)" % (self.__class__.__module__, 2355*cda5da8dSAndroid Build Coastguard Worker self.__class__.__qualname__, 2356*cda5da8dSAndroid Build Coastguard Worker self._offset, self._name) 2357*cda5da8dSAndroid Build Coastguard Worker 2358*cda5da8dSAndroid Build Coastguard Worker def __str__(self): 2359*cda5da8dSAndroid Build Coastguard Worker return self.tzname(None) 2360*cda5da8dSAndroid Build Coastguard Worker 2361*cda5da8dSAndroid Build Coastguard Worker def utcoffset(self, dt): 2362*cda5da8dSAndroid Build Coastguard Worker if isinstance(dt, datetime) or dt is None: 2363*cda5da8dSAndroid Build Coastguard Worker return self._offset 2364*cda5da8dSAndroid Build Coastguard Worker raise TypeError("utcoffset() argument must be a datetime instance" 2365*cda5da8dSAndroid Build Coastguard Worker " or None") 2366*cda5da8dSAndroid Build Coastguard Worker 2367*cda5da8dSAndroid Build Coastguard Worker def tzname(self, dt): 2368*cda5da8dSAndroid Build Coastguard Worker if isinstance(dt, datetime) or dt is None: 2369*cda5da8dSAndroid Build Coastguard Worker if self._name is None: 2370*cda5da8dSAndroid Build Coastguard Worker return self._name_from_offset(self._offset) 2371*cda5da8dSAndroid Build Coastguard Worker return self._name 2372*cda5da8dSAndroid Build Coastguard Worker raise TypeError("tzname() argument must be a datetime instance" 2373*cda5da8dSAndroid Build Coastguard Worker " or None") 2374*cda5da8dSAndroid Build Coastguard Worker 2375*cda5da8dSAndroid Build Coastguard Worker def dst(self, dt): 2376*cda5da8dSAndroid Build Coastguard Worker if isinstance(dt, datetime) or dt is None: 2377*cda5da8dSAndroid Build Coastguard Worker return None 2378*cda5da8dSAndroid Build Coastguard Worker raise TypeError("dst() argument must be a datetime instance" 2379*cda5da8dSAndroid Build Coastguard Worker " or None") 2380*cda5da8dSAndroid Build Coastguard Worker 2381*cda5da8dSAndroid Build Coastguard Worker def fromutc(self, dt): 2382*cda5da8dSAndroid Build Coastguard Worker if isinstance(dt, datetime): 2383*cda5da8dSAndroid Build Coastguard Worker if dt.tzinfo is not self: 2384*cda5da8dSAndroid Build Coastguard Worker raise ValueError("fromutc: dt.tzinfo " 2385*cda5da8dSAndroid Build Coastguard Worker "is not self") 2386*cda5da8dSAndroid Build Coastguard Worker return dt + self._offset 2387*cda5da8dSAndroid Build Coastguard Worker raise TypeError("fromutc() argument must be a datetime instance" 2388*cda5da8dSAndroid Build Coastguard Worker " or None") 2389*cda5da8dSAndroid Build Coastguard Worker 2390*cda5da8dSAndroid Build Coastguard Worker _maxoffset = timedelta(hours=24, microseconds=-1) 2391*cda5da8dSAndroid Build Coastguard Worker _minoffset = -_maxoffset 2392*cda5da8dSAndroid Build Coastguard Worker 2393*cda5da8dSAndroid Build Coastguard Worker @staticmethod 2394*cda5da8dSAndroid Build Coastguard Worker def _name_from_offset(delta): 2395*cda5da8dSAndroid Build Coastguard Worker if not delta: 2396*cda5da8dSAndroid Build Coastguard Worker return 'UTC' 2397*cda5da8dSAndroid Build Coastguard Worker if delta < timedelta(0): 2398*cda5da8dSAndroid Build Coastguard Worker sign = '-' 2399*cda5da8dSAndroid Build Coastguard Worker delta = -delta 2400*cda5da8dSAndroid Build Coastguard Worker else: 2401*cda5da8dSAndroid Build Coastguard Worker sign = '+' 2402*cda5da8dSAndroid Build Coastguard Worker hours, rest = divmod(delta, timedelta(hours=1)) 2403*cda5da8dSAndroid Build Coastguard Worker minutes, rest = divmod(rest, timedelta(minutes=1)) 2404*cda5da8dSAndroid Build Coastguard Worker seconds = rest.seconds 2405*cda5da8dSAndroid Build Coastguard Worker microseconds = rest.microseconds 2406*cda5da8dSAndroid Build Coastguard Worker if microseconds: 2407*cda5da8dSAndroid Build Coastguard Worker return (f'UTC{sign}{hours:02d}:{minutes:02d}:{seconds:02d}' 2408*cda5da8dSAndroid Build Coastguard Worker f'.{microseconds:06d}') 2409*cda5da8dSAndroid Build Coastguard Worker if seconds: 2410*cda5da8dSAndroid Build Coastguard Worker return f'UTC{sign}{hours:02d}:{minutes:02d}:{seconds:02d}' 2411*cda5da8dSAndroid Build Coastguard Worker return f'UTC{sign}{hours:02d}:{minutes:02d}' 2412*cda5da8dSAndroid Build Coastguard Worker 2413*cda5da8dSAndroid Build Coastguard WorkerUTC = timezone.utc = timezone._create(timedelta(0)) 2414*cda5da8dSAndroid Build Coastguard Worker 2415*cda5da8dSAndroid Build Coastguard Worker# bpo-37642: These attributes are rounded to the nearest minute for backwards 2416*cda5da8dSAndroid Build Coastguard Worker# compatibility, even though the constructor will accept a wider range of 2417*cda5da8dSAndroid Build Coastguard Worker# values. This may change in the future. 2418*cda5da8dSAndroid Build Coastguard Workertimezone.min = timezone._create(-timedelta(hours=23, minutes=59)) 2419*cda5da8dSAndroid Build Coastguard Workertimezone.max = timezone._create(timedelta(hours=23, minutes=59)) 2420*cda5da8dSAndroid Build Coastguard Worker_EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc) 2421*cda5da8dSAndroid Build Coastguard Worker 2422*cda5da8dSAndroid Build Coastguard Worker# Some time zone algebra. For a datetime x, let 2423*cda5da8dSAndroid Build Coastguard Worker# x.n = x stripped of its timezone -- its naive time. 2424*cda5da8dSAndroid Build Coastguard Worker# x.o = x.utcoffset(), and assuming that doesn't raise an exception or 2425*cda5da8dSAndroid Build Coastguard Worker# return None 2426*cda5da8dSAndroid Build Coastguard Worker# x.d = x.dst(), and assuming that doesn't raise an exception or 2427*cda5da8dSAndroid Build Coastguard Worker# return None 2428*cda5da8dSAndroid Build Coastguard Worker# x.s = x's standard offset, x.o - x.d 2429*cda5da8dSAndroid Build Coastguard Worker# 2430*cda5da8dSAndroid Build Coastguard Worker# Now some derived rules, where k is a duration (timedelta). 2431*cda5da8dSAndroid Build Coastguard Worker# 2432*cda5da8dSAndroid Build Coastguard Worker# 1. x.o = x.s + x.d 2433*cda5da8dSAndroid Build Coastguard Worker# This follows from the definition of x.s. 2434*cda5da8dSAndroid Build Coastguard Worker# 2435*cda5da8dSAndroid Build Coastguard Worker# 2. If x and y have the same tzinfo member, x.s = y.s. 2436*cda5da8dSAndroid Build Coastguard Worker# This is actually a requirement, an assumption we need to make about 2437*cda5da8dSAndroid Build Coastguard Worker# sane tzinfo classes. 2438*cda5da8dSAndroid Build Coastguard Worker# 2439*cda5da8dSAndroid Build Coastguard Worker# 3. The naive UTC time corresponding to x is x.n - x.o. 2440*cda5da8dSAndroid Build Coastguard Worker# This is again a requirement for a sane tzinfo class. 2441*cda5da8dSAndroid Build Coastguard Worker# 2442*cda5da8dSAndroid Build Coastguard Worker# 4. (x+k).s = x.s 2443*cda5da8dSAndroid Build Coastguard Worker# This follows from #2, and that datetime.timetz+timedelta preserves tzinfo. 2444*cda5da8dSAndroid Build Coastguard Worker# 2445*cda5da8dSAndroid Build Coastguard Worker# 5. (x+k).n = x.n + k 2446*cda5da8dSAndroid Build Coastguard Worker# Again follows from how arithmetic is defined. 2447*cda5da8dSAndroid Build Coastguard Worker# 2448*cda5da8dSAndroid Build Coastguard Worker# Now we can explain tz.fromutc(x). Let's assume it's an interesting case 2449*cda5da8dSAndroid Build Coastguard Worker# (meaning that the various tzinfo methods exist, and don't blow up or return 2450*cda5da8dSAndroid Build Coastguard Worker# None when called). 2451*cda5da8dSAndroid Build Coastguard Worker# 2452*cda5da8dSAndroid Build Coastguard Worker# The function wants to return a datetime y with timezone tz, equivalent to x. 2453*cda5da8dSAndroid Build Coastguard Worker# x is already in UTC. 2454*cda5da8dSAndroid Build Coastguard Worker# 2455*cda5da8dSAndroid Build Coastguard Worker# By #3, we want 2456*cda5da8dSAndroid Build Coastguard Worker# 2457*cda5da8dSAndroid Build Coastguard Worker# y.n - y.o = x.n [1] 2458*cda5da8dSAndroid Build Coastguard Worker# 2459*cda5da8dSAndroid Build Coastguard Worker# The algorithm starts by attaching tz to x.n, and calling that y. So 2460*cda5da8dSAndroid Build Coastguard Worker# x.n = y.n at the start. Then it wants to add a duration k to y, so that [1] 2461*cda5da8dSAndroid Build Coastguard Worker# becomes true; in effect, we want to solve [2] for k: 2462*cda5da8dSAndroid Build Coastguard Worker# 2463*cda5da8dSAndroid Build Coastguard Worker# (y+k).n - (y+k).o = x.n [2] 2464*cda5da8dSAndroid Build Coastguard Worker# 2465*cda5da8dSAndroid Build Coastguard Worker# By #1, this is the same as 2466*cda5da8dSAndroid Build Coastguard Worker# 2467*cda5da8dSAndroid Build Coastguard Worker# (y+k).n - ((y+k).s + (y+k).d) = x.n [3] 2468*cda5da8dSAndroid Build Coastguard Worker# 2469*cda5da8dSAndroid Build Coastguard Worker# By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start. 2470*cda5da8dSAndroid Build Coastguard Worker# Substituting that into [3], 2471*cda5da8dSAndroid Build Coastguard Worker# 2472*cda5da8dSAndroid Build Coastguard Worker# x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving 2473*cda5da8dSAndroid Build Coastguard Worker# k - (y+k).s - (y+k).d = 0; rearranging, 2474*cda5da8dSAndroid Build Coastguard Worker# k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so 2475*cda5da8dSAndroid Build Coastguard Worker# k = y.s - (y+k).d 2476*cda5da8dSAndroid Build Coastguard Worker# 2477*cda5da8dSAndroid Build Coastguard Worker# On the RHS, (y+k).d can't be computed directly, but y.s can be, and we 2478*cda5da8dSAndroid Build Coastguard Worker# approximate k by ignoring the (y+k).d term at first. Note that k can't be 2479*cda5da8dSAndroid Build Coastguard Worker# very large, since all offset-returning methods return a duration of magnitude 2480*cda5da8dSAndroid Build Coastguard Worker# less than 24 hours. For that reason, if y is firmly in std time, (y+k).d must 2481*cda5da8dSAndroid Build Coastguard Worker# be 0, so ignoring it has no consequence then. 2482*cda5da8dSAndroid Build Coastguard Worker# 2483*cda5da8dSAndroid Build Coastguard Worker# In any case, the new value is 2484*cda5da8dSAndroid Build Coastguard Worker# 2485*cda5da8dSAndroid Build Coastguard Worker# z = y + y.s [4] 2486*cda5da8dSAndroid Build Coastguard Worker# 2487*cda5da8dSAndroid Build Coastguard Worker# It's helpful to step back at look at [4] from a higher level: it's simply 2488*cda5da8dSAndroid Build Coastguard Worker# mapping from UTC to tz's standard time. 2489*cda5da8dSAndroid Build Coastguard Worker# 2490*cda5da8dSAndroid Build Coastguard Worker# At this point, if 2491*cda5da8dSAndroid Build Coastguard Worker# 2492*cda5da8dSAndroid Build Coastguard Worker# z.n - z.o = x.n [5] 2493*cda5da8dSAndroid Build Coastguard Worker# 2494*cda5da8dSAndroid Build Coastguard Worker# we have an equivalent time, and are almost done. The insecurity here is 2495*cda5da8dSAndroid Build Coastguard Worker# at the start of daylight time. Picture US Eastern for concreteness. The wall 2496*cda5da8dSAndroid Build Coastguard Worker# time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good 2497*cda5da8dSAndroid Build Coastguard Worker# sense then. The docs ask that an Eastern tzinfo class consider such a time to 2498*cda5da8dSAndroid Build Coastguard Worker# be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST 2499*cda5da8dSAndroid Build Coastguard Worker# on the day DST starts. We want to return the 1:MM EST spelling because that's 2500*cda5da8dSAndroid Build Coastguard Worker# the only spelling that makes sense on the local wall clock. 2501*cda5da8dSAndroid Build Coastguard Worker# 2502*cda5da8dSAndroid Build Coastguard Worker# In fact, if [5] holds at this point, we do have the standard-time spelling, 2503*cda5da8dSAndroid Build Coastguard Worker# but that takes a bit of proof. We first prove a stronger result. What's the 2504*cda5da8dSAndroid Build Coastguard Worker# difference between the LHS and RHS of [5]? Let 2505*cda5da8dSAndroid Build Coastguard Worker# 2506*cda5da8dSAndroid Build Coastguard Worker# diff = x.n - (z.n - z.o) [6] 2507*cda5da8dSAndroid Build Coastguard Worker# 2508*cda5da8dSAndroid Build Coastguard Worker# Now 2509*cda5da8dSAndroid Build Coastguard Worker# z.n = by [4] 2510*cda5da8dSAndroid Build Coastguard Worker# (y + y.s).n = by #5 2511*cda5da8dSAndroid Build Coastguard Worker# y.n + y.s = since y.n = x.n 2512*cda5da8dSAndroid Build Coastguard Worker# x.n + y.s = since z and y are have the same tzinfo member, 2513*cda5da8dSAndroid Build Coastguard Worker# y.s = z.s by #2 2514*cda5da8dSAndroid Build Coastguard Worker# x.n + z.s 2515*cda5da8dSAndroid Build Coastguard Worker# 2516*cda5da8dSAndroid Build Coastguard Worker# Plugging that back into [6] gives 2517*cda5da8dSAndroid Build Coastguard Worker# 2518*cda5da8dSAndroid Build Coastguard Worker# diff = 2519*cda5da8dSAndroid Build Coastguard Worker# x.n - ((x.n + z.s) - z.o) = expanding 2520*cda5da8dSAndroid Build Coastguard Worker# x.n - x.n - z.s + z.o = cancelling 2521*cda5da8dSAndroid Build Coastguard Worker# - z.s + z.o = by #2 2522*cda5da8dSAndroid Build Coastguard Worker# z.d 2523*cda5da8dSAndroid Build Coastguard Worker# 2524*cda5da8dSAndroid Build Coastguard Worker# So diff = z.d. 2525*cda5da8dSAndroid Build Coastguard Worker# 2526*cda5da8dSAndroid Build Coastguard Worker# If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time 2527*cda5da8dSAndroid Build Coastguard Worker# spelling we wanted in the endcase described above. We're done. Contrarily, 2528*cda5da8dSAndroid Build Coastguard Worker# if z.d = 0, then we have a UTC equivalent, and are also done. 2529*cda5da8dSAndroid Build Coastguard Worker# 2530*cda5da8dSAndroid Build Coastguard Worker# If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to 2531*cda5da8dSAndroid Build Coastguard Worker# add to z (in effect, z is in tz's standard time, and we need to shift the 2532*cda5da8dSAndroid Build Coastguard Worker# local clock into tz's daylight time). 2533*cda5da8dSAndroid Build Coastguard Worker# 2534*cda5da8dSAndroid Build Coastguard Worker# Let 2535*cda5da8dSAndroid Build Coastguard Worker# 2536*cda5da8dSAndroid Build Coastguard Worker# z' = z + z.d = z + diff [7] 2537*cda5da8dSAndroid Build Coastguard Worker# 2538*cda5da8dSAndroid Build Coastguard Worker# and we can again ask whether 2539*cda5da8dSAndroid Build Coastguard Worker# 2540*cda5da8dSAndroid Build Coastguard Worker# z'.n - z'.o = x.n [8] 2541*cda5da8dSAndroid Build Coastguard Worker# 2542*cda5da8dSAndroid Build Coastguard Worker# If so, we're done. If not, the tzinfo class is insane, according to the 2543*cda5da8dSAndroid Build Coastguard Worker# assumptions we've made. This also requires a bit of proof. As before, let's 2544*cda5da8dSAndroid Build Coastguard Worker# compute the difference between the LHS and RHS of [8] (and skipping some of 2545*cda5da8dSAndroid Build Coastguard Worker# the justifications for the kinds of substitutions we've done several times 2546*cda5da8dSAndroid Build Coastguard Worker# already): 2547*cda5da8dSAndroid Build Coastguard Worker# 2548*cda5da8dSAndroid Build Coastguard Worker# diff' = x.n - (z'.n - z'.o) = replacing z'.n via [7] 2549*cda5da8dSAndroid Build Coastguard Worker# x.n - (z.n + diff - z'.o) = replacing diff via [6] 2550*cda5da8dSAndroid Build Coastguard Worker# x.n - (z.n + x.n - (z.n - z.o) - z'.o) = 2551*cda5da8dSAndroid Build Coastguard Worker# x.n - z.n - x.n + z.n - z.o + z'.o = cancel x.n 2552*cda5da8dSAndroid Build Coastguard Worker# - z.n + z.n - z.o + z'.o = cancel z.n 2553*cda5da8dSAndroid Build Coastguard Worker# - z.o + z'.o = #1 twice 2554*cda5da8dSAndroid Build Coastguard Worker# -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo 2555*cda5da8dSAndroid Build Coastguard Worker# z'.d - z.d 2556*cda5da8dSAndroid Build Coastguard Worker# 2557*cda5da8dSAndroid Build Coastguard Worker# So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal, 2558*cda5da8dSAndroid Build Coastguard Worker# we've found the UTC-equivalent so are done. In fact, we stop with [7] and 2559*cda5da8dSAndroid Build Coastguard Worker# return z', not bothering to compute z'.d. 2560*cda5da8dSAndroid Build Coastguard Worker# 2561*cda5da8dSAndroid Build Coastguard Worker# How could z.d and z'd differ? z' = z + z.d [7], so merely moving z' by 2562*cda5da8dSAndroid Build Coastguard Worker# a dst() offset, and starting *from* a time already in DST (we know z.d != 0), 2563*cda5da8dSAndroid Build Coastguard Worker# would have to change the result dst() returns: we start in DST, and moving 2564*cda5da8dSAndroid Build Coastguard Worker# a little further into it takes us out of DST. 2565*cda5da8dSAndroid Build Coastguard Worker# 2566*cda5da8dSAndroid Build Coastguard Worker# There isn't a sane case where this can happen. The closest it gets is at 2567*cda5da8dSAndroid Build Coastguard Worker# the end of DST, where there's an hour in UTC with no spelling in a hybrid 2568*cda5da8dSAndroid Build Coastguard Worker# tzinfo class. In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT. During 2569*cda5da8dSAndroid Build Coastguard Worker# that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM 2570*cda5da8dSAndroid Build Coastguard Worker# UTC) because the docs insist on that, but 0:MM is taken as being in daylight 2571*cda5da8dSAndroid Build Coastguard Worker# time (4:MM UTC). There is no local time mapping to 5:MM UTC. The local 2572*cda5da8dSAndroid Build Coastguard Worker# clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in 2573*cda5da8dSAndroid Build Coastguard Worker# standard time. Since that's what the local clock *does*, we want to map both 2574*cda5da8dSAndroid Build Coastguard Worker# UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous 2575*cda5da8dSAndroid Build Coastguard Worker# in local time, but so it goes -- it's the way the local clock works. 2576*cda5da8dSAndroid Build Coastguard Worker# 2577*cda5da8dSAndroid Build Coastguard Worker# When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0, 2578*cda5da8dSAndroid Build Coastguard Worker# so z=0:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going. 2579*cda5da8dSAndroid Build Coastguard Worker# z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8] 2580*cda5da8dSAndroid Build Coastguard Worker# (correctly) concludes that z' is not UTC-equivalent to x. 2581*cda5da8dSAndroid Build Coastguard Worker# 2582*cda5da8dSAndroid Build Coastguard Worker# Because we know z.d said z was in daylight time (else [5] would have held and 2583*cda5da8dSAndroid Build Coastguard Worker# we would have stopped then), and we know z.d != z'.d (else [8] would have held 2584*cda5da8dSAndroid Build Coastguard Worker# and we have stopped then), and there are only 2 possible values dst() can 2585*cda5da8dSAndroid Build Coastguard Worker# return in Eastern, it follows that z'.d must be 0 (which it is in the example, 2586*cda5da8dSAndroid Build Coastguard Worker# but the reasoning doesn't depend on the example -- it depends on there being 2587*cda5da8dSAndroid Build Coastguard Worker# two possible dst() outcomes, one zero and the other non-zero). Therefore 2588*cda5da8dSAndroid Build Coastguard Worker# z' must be in standard time, and is the spelling we want in this case. 2589*cda5da8dSAndroid Build Coastguard Worker# 2590*cda5da8dSAndroid Build Coastguard Worker# Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is 2591*cda5da8dSAndroid Build Coastguard Worker# concerned (because it takes z' as being in standard time rather than the 2592*cda5da8dSAndroid Build Coastguard Worker# daylight time we intend here), but returning it gives the real-life "local 2593*cda5da8dSAndroid Build Coastguard Worker# clock repeats an hour" behavior when mapping the "unspellable" UTC hour into 2594*cda5da8dSAndroid Build Coastguard Worker# tz. 2595*cda5da8dSAndroid Build Coastguard Worker# 2596*cda5da8dSAndroid Build Coastguard Worker# When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with 2597*cda5da8dSAndroid Build Coastguard Worker# the 1:MM standard time spelling we want. 2598*cda5da8dSAndroid Build Coastguard Worker# 2599*cda5da8dSAndroid Build Coastguard Worker# So how can this break? One of the assumptions must be violated. Two 2600*cda5da8dSAndroid Build Coastguard Worker# possibilities: 2601*cda5da8dSAndroid Build Coastguard Worker# 2602*cda5da8dSAndroid Build Coastguard Worker# 1) [2] effectively says that y.s is invariant across all y belong to a given 2603*cda5da8dSAndroid Build Coastguard Worker# time zone. This isn't true if, for political reasons or continental drift, 2604*cda5da8dSAndroid Build Coastguard Worker# a region decides to change its base offset from UTC. 2605*cda5da8dSAndroid Build Coastguard Worker# 2606*cda5da8dSAndroid Build Coastguard Worker# 2) There may be versions of "double daylight" time where the tail end of 2607*cda5da8dSAndroid Build Coastguard Worker# the analysis gives up a step too early. I haven't thought about that 2608*cda5da8dSAndroid Build Coastguard Worker# enough to say. 2609*cda5da8dSAndroid Build Coastguard Worker# 2610*cda5da8dSAndroid Build Coastguard Worker# In any case, it's clear that the default fromutc() is strong enough to handle 2611*cda5da8dSAndroid Build Coastguard Worker# "almost all" time zones: so long as the standard offset is invariant, it 2612*cda5da8dSAndroid Build Coastguard Worker# doesn't matter if daylight time transition points change from year to year, or 2613*cda5da8dSAndroid Build Coastguard Worker# if daylight time is skipped in some years; it doesn't matter how large or 2614*cda5da8dSAndroid Build Coastguard Worker# small dst() may get within its bounds; and it doesn't even matter if some 2615*cda5da8dSAndroid Build Coastguard Worker# perverse time zone returns a negative dst()). So a breaking case must be 2616*cda5da8dSAndroid Build Coastguard Worker# pretty bizarre, and a tzinfo subclass can override fromutc() if it is. 2617*cda5da8dSAndroid Build Coastguard Worker 2618*cda5da8dSAndroid Build Coastguard Workertry: 2619*cda5da8dSAndroid Build Coastguard Worker from _datetime import * 2620*cda5da8dSAndroid Build Coastguard Workerexcept ImportError: 2621*cda5da8dSAndroid Build Coastguard Worker pass 2622*cda5da8dSAndroid Build Coastguard Workerelse: 2623*cda5da8dSAndroid Build Coastguard Worker # Clean up unused names 2624*cda5da8dSAndroid Build Coastguard Worker del (_DAYNAMES, _DAYS_BEFORE_MONTH, _DAYS_IN_MONTH, _DI100Y, _DI400Y, 2625*cda5da8dSAndroid Build Coastguard Worker _DI4Y, _EPOCH, _MAXORDINAL, _MONTHNAMES, _build_struct_time, 2626*cda5da8dSAndroid Build Coastguard Worker _check_date_fields, _check_time_fields, 2627*cda5da8dSAndroid Build Coastguard Worker _check_tzinfo_arg, _check_tzname, _check_utc_offset, _cmp, _cmperror, 2628*cda5da8dSAndroid Build Coastguard Worker _date_class, _days_before_month, _days_before_year, _days_in_month, 2629*cda5da8dSAndroid Build Coastguard Worker _format_time, _format_offset, _index, _is_leap, _isoweek1monday, _math, 2630*cda5da8dSAndroid Build Coastguard Worker _ord2ymd, _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord, 2631*cda5da8dSAndroid Build Coastguard Worker _divide_and_round, _parse_isoformat_date, _parse_isoformat_time, 2632*cda5da8dSAndroid Build Coastguard Worker _parse_hh_mm_ss_ff, _IsoCalendarDate, _isoweek_to_gregorian, 2633*cda5da8dSAndroid Build Coastguard Worker _find_isoformat_datetime_separator, _FRACTION_CORRECTION, 2634*cda5da8dSAndroid Build Coastguard Worker _is_ascii_digit) 2635*cda5da8dSAndroid Build Coastguard Worker # XXX Since import * above excludes names that start with _, 2636*cda5da8dSAndroid Build Coastguard Worker # docstring does not get overwritten. In the future, it may be 2637*cda5da8dSAndroid Build Coastguard Worker # appropriate to maintain a single module level docstring and 2638*cda5da8dSAndroid Build Coastguard Worker # remove the following line. 2639*cda5da8dSAndroid Build Coastguard Worker from _datetime import __doc__ 2640