datetime.py 74 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143
  1. """Concrete date/time and related types.
  2. See http://www.iana.org/time-zones/repository/tz-link.html for
  3. time zone and DST data sources.
  4. """
  5. import time as _time
  6. import math as _math
  7. def _cmp(x, y):
  8. return 0 if x == y else 1 if x > y else -1
  9. MINYEAR = 1
  10. MAXYEAR = 9999
  11. _MAXORDINAL = 3652059 # date.max.toordinal()
  12. # Utility functions, adapted from Python's Demo/classes/Dates.py, which
  13. # also assumes the current Gregorian calendar indefinitely extended in
  14. # both directions. Difference: Dates.py calls January 1 of year 0 day
  15. # number 1. The code here calls January 1 of year 1 day number 1. This is
  16. # to match the definition of the "proleptic Gregorian" calendar in Dershowitz
  17. # and Reingold's "Calendrical Calculations", where it's the base calendar
  18. # for all computations. See the book for algorithms for converting between
  19. # proleptic Gregorian ordinals and many other calendar systems.
  20. # -1 is a placeholder for indexing purposes.
  21. _DAYS_IN_MONTH = [-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  22. _DAYS_BEFORE_MONTH = [-1] # -1 is a placeholder for indexing purposes.
  23. dbm = 0
  24. for dim in _DAYS_IN_MONTH[1:]:
  25. _DAYS_BEFORE_MONTH.append(dbm)
  26. dbm += dim
  27. del dbm, dim
  28. def _is_leap(year):
  29. "year -> 1 if leap year, else 0."
  30. return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
  31. def _days_before_year(year):
  32. "year -> number of days before January 1st of year."
  33. y = year - 1
  34. return y*365 + y//4 - y//100 + y//400
  35. def _days_in_month(year, month):
  36. "year, month -> number of days in that month in that year."
  37. assert 1 <= month <= 12, month
  38. if month == 2 and _is_leap(year):
  39. return 29
  40. return _DAYS_IN_MONTH[month]
  41. def _days_before_month(year, month):
  42. "year, month -> number of days in year preceding first day of month."
  43. assert 1 <= month <= 12, 'month must be in 1..12'
  44. return _DAYS_BEFORE_MONTH[month] + (month > 2 and _is_leap(year))
  45. def _ymd2ord(year, month, day):
  46. "year, month, day -> ordinal, considering 01-Jan-0001 as day 1."
  47. assert 1 <= month <= 12, 'month must be in 1..12'
  48. dim = _days_in_month(year, month)
  49. assert 1 <= day <= dim, ('day must be in 1..%d' % dim)
  50. return (_days_before_year(year) +
  51. _days_before_month(year, month) +
  52. day)
  53. _DI400Y = _days_before_year(401) # number of days in 400 years
  54. _DI100Y = _days_before_year(101) # " " " " 100 "
  55. _DI4Y = _days_before_year(5) # " " " " 4 "
  56. # A 4-year cycle has an extra leap day over what we'd get from pasting
  57. # together 4 single years.
  58. assert _DI4Y == 4 * 365 + 1
  59. # Similarly, a 400-year cycle has an extra leap day over what we'd get from
  60. # pasting together 4 100-year cycles.
  61. assert _DI400Y == 4 * _DI100Y + 1
  62. # OTOH, a 100-year cycle has one fewer leap day than we'd get from
  63. # pasting together 25 4-year cycles.
  64. assert _DI100Y == 25 * _DI4Y - 1
  65. def _ord2ymd(n):
  66. "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1."
  67. # n is a 1-based index, starting at 1-Jan-1. The pattern of leap years
  68. # repeats exactly every 400 years. The basic strategy is to find the
  69. # closest 400-year boundary at or before n, then work with the offset
  70. # from that boundary to n. Life is much clearer if we subtract 1 from
  71. # n first -- then the values of n at 400-year boundaries are exactly
  72. # those divisible by _DI400Y:
  73. #
  74. # D M Y n n-1
  75. # -- --- ---- ---------- ----------------
  76. # 31 Dec -400 -_DI400Y -_DI400Y -1
  77. # 1 Jan -399 -_DI400Y +1 -_DI400Y 400-year boundary
  78. # ...
  79. # 30 Dec 000 -1 -2
  80. # 31 Dec 000 0 -1
  81. # 1 Jan 001 1 0 400-year boundary
  82. # 2 Jan 001 2 1
  83. # 3 Jan 001 3 2
  84. # ...
  85. # 31 Dec 400 _DI400Y _DI400Y -1
  86. # 1 Jan 401 _DI400Y +1 _DI400Y 400-year boundary
  87. n -= 1
  88. n400, n = divmod(n, _DI400Y)
  89. year = n400 * 400 + 1 # ..., -399, 1, 401, ...
  90. # Now n is the (non-negative) offset, in days, from January 1 of year, to
  91. # the desired date. Now compute how many 100-year cycles precede n.
  92. # Note that it's possible for n100 to equal 4! In that case 4 full
  93. # 100-year cycles precede the desired day, which implies the desired
  94. # day is December 31 at the end of a 400-year cycle.
  95. n100, n = divmod(n, _DI100Y)
  96. # Now compute how many 4-year cycles precede it.
  97. n4, n = divmod(n, _DI4Y)
  98. # And now how many single years. Again n1 can be 4, and again meaning
  99. # that the desired day is December 31 at the end of the 4-year cycle.
  100. n1, n = divmod(n, 365)
  101. year += n100 * 100 + n4 * 4 + n1
  102. if n1 == 4 or n100 == 4:
  103. assert n == 0
  104. return year-1, 12, 31
  105. # Now the year is correct, and n is the offset from January 1. We find
  106. # the month via an estimate that's either exact or one too large.
  107. leapyear = n1 == 3 and (n4 != 24 or n100 == 3)
  108. assert leapyear == _is_leap(year)
  109. month = (n + 50) >> 5
  110. preceding = _DAYS_BEFORE_MONTH[month] + (month > 2 and leapyear)
  111. if preceding > n: # estimate is too large
  112. month -= 1
  113. preceding -= _DAYS_IN_MONTH[month] + (month == 2 and leapyear)
  114. n -= preceding
  115. assert 0 <= n < _days_in_month(year, month)
  116. # Now the year and month are correct, and n is the offset from the
  117. # start of that month: we're done!
  118. return year, month, n+1
  119. # Month and day names. For localized versions, see the calendar module.
  120. _MONTHNAMES = [None, "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  121. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
  122. _DAYNAMES = [None, "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
  123. def _build_struct_time(y, m, d, hh, mm, ss, dstflag):
  124. wday = (_ymd2ord(y, m, d) + 6) % 7
  125. dnum = _days_before_month(y, m) + d
  126. return _time.struct_time((y, m, d, hh, mm, ss, wday, dnum, dstflag))
  127. def _format_time(hh, mm, ss, us):
  128. # Skip trailing microseconds when us==0.
  129. result = "%02d:%02d:%02d" % (hh, mm, ss)
  130. if us:
  131. result += ".%06d" % us
  132. return result
  133. # Correctly substitute for %z and %Z escapes in strftime formats.
  134. def _wrap_strftime(object, format, timetuple):
  135. # Don't call utcoffset() or tzname() unless actually needed.
  136. freplace = None # the string to use for %f
  137. zreplace = None # the string to use for %z
  138. Zreplace = None # the string to use for %Z
  139. # Scan format for %z and %Z escapes, replacing as needed.
  140. newformat = []
  141. push = newformat.append
  142. i, n = 0, len(format)
  143. while i < n:
  144. ch = format[i]
  145. i += 1
  146. if ch == '%':
  147. if i < n:
  148. ch = format[i]
  149. i += 1
  150. if ch == 'f':
  151. if freplace is None:
  152. freplace = '%06d' % getattr(object,
  153. 'microsecond', 0)
  154. newformat.append(freplace)
  155. elif ch == 'z':
  156. if zreplace is None:
  157. zreplace = ""
  158. if hasattr(object, "utcoffset"):
  159. offset = object.utcoffset()
  160. if offset is not None:
  161. sign = '+'
  162. if offset.days < 0:
  163. offset = -offset
  164. sign = '-'
  165. h, m = divmod(offset, timedelta(hours=1))
  166. assert not m % timedelta(minutes=1), "whole minute"
  167. m //= timedelta(minutes=1)
  168. zreplace = '%c%02d%02d' % (sign, h, m)
  169. assert '%' not in zreplace
  170. newformat.append(zreplace)
  171. elif ch == 'Z':
  172. if Zreplace is None:
  173. Zreplace = ""
  174. if hasattr(object, "tzname"):
  175. s = object.tzname()
  176. if s is not None:
  177. # strftime is going to have at this: escape %
  178. Zreplace = s.replace('%', '%%')
  179. newformat.append(Zreplace)
  180. else:
  181. push('%')
  182. push(ch)
  183. else:
  184. push('%')
  185. else:
  186. push(ch)
  187. newformat = "".join(newformat)
  188. return _time.strftime(newformat, timetuple)
  189. # Just raise TypeError if the arg isn't None or a string.
  190. def _check_tzname(name):
  191. if name is not None and not isinstance(name, str):
  192. raise TypeError("tzinfo.tzname() must return None or string, "
  193. "not '%s'" % type(name))
  194. # name is the offset-producing method, "utcoffset" or "dst".
  195. # offset is what it returned.
  196. # If offset isn't None or timedelta, raises TypeError.
  197. # If offset is None, returns None.
  198. # Else offset is checked for being in range, and a whole # of minutes.
  199. # If it is, its integer value is returned. Else ValueError is raised.
  200. def _check_utc_offset(name, offset):
  201. assert name in ("utcoffset", "dst")
  202. if offset is None:
  203. return
  204. if not isinstance(offset, timedelta):
  205. raise TypeError("tzinfo.%s() must return None "
  206. "or timedelta, not '%s'" % (name, type(offset)))
  207. if offset % timedelta(minutes=1) or offset.microseconds:
  208. raise ValueError("tzinfo.%s() must return a whole number "
  209. "of minutes, got %s" % (name, offset))
  210. if not -timedelta(1) < offset < timedelta(1):
  211. raise ValueError("%s()=%s, must be must be strictly between "
  212. "-timedelta(hours=24) and timedelta(hours=24)" %
  213. (name, offset))
  214. def _check_int_field(value):
  215. if isinstance(value, int):
  216. return value
  217. if not isinstance(value, float):
  218. try:
  219. value = value.__int__()
  220. except AttributeError:
  221. pass
  222. else:
  223. if isinstance(value, int):
  224. return value
  225. raise TypeError('__int__ returned non-int (type %s)' %
  226. type(value).__name__)
  227. raise TypeError('an integer is required (got type %s)' %
  228. type(value).__name__)
  229. raise TypeError('integer argument expected, got float')
  230. def _check_date_fields(year, month, day):
  231. year = _check_int_field(year)
  232. month = _check_int_field(month)
  233. day = _check_int_field(day)
  234. if not MINYEAR <= year <= MAXYEAR:
  235. raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year)
  236. if not 1 <= month <= 12:
  237. raise ValueError('month must be in 1..12', month)
  238. dim = _days_in_month(year, month)
  239. if not 1 <= day <= dim:
  240. raise ValueError('day must be in 1..%d' % dim, day)
  241. return year, month, day
  242. def _check_time_fields(hour, minute, second, microsecond):
  243. hour = _check_int_field(hour)
  244. minute = _check_int_field(minute)
  245. second = _check_int_field(second)
  246. microsecond = _check_int_field(microsecond)
  247. if not 0 <= hour <= 23:
  248. raise ValueError('hour must be in 0..23', hour)
  249. if not 0 <= minute <= 59:
  250. raise ValueError('minute must be in 0..59', minute)
  251. if not 0 <= second <= 59:
  252. raise ValueError('second must be in 0..59', second)
  253. if not 0 <= microsecond <= 999999:
  254. raise ValueError('microsecond must be in 0..999999', microsecond)
  255. return hour, minute, second, microsecond
  256. def _check_tzinfo_arg(tz):
  257. if tz is not None and not isinstance(tz, tzinfo):
  258. raise TypeError("tzinfo argument must be None or of a tzinfo subclass")
  259. def _cmperror(x, y):
  260. raise TypeError("can't compare '%s' to '%s'" % (
  261. type(x).__name__, type(y).__name__))
  262. def _divide_and_round(a, b):
  263. """divide a by b and round result to the nearest integer
  264. When the ratio is exactly half-way between two integers,
  265. the even integer is returned.
  266. """
  267. # Based on the reference implementation for divmod_near
  268. # in Objects/longobject.c.
  269. q, r = divmod(a, b)
  270. # round up if either r / b > 0.5, or r / b == 0.5 and q is odd.
  271. # The expression r / b > 0.5 is equivalent to 2 * r > b if b is
  272. # positive, 2 * r < b if b negative.
  273. r *= 2
  274. greater_than_half = r > b if b > 0 else r < b
  275. if greater_than_half or r == b and q % 2 == 1:
  276. q += 1
  277. return q
  278. class timedelta:
  279. """Represent the difference between two datetime objects.
  280. Supported operators:
  281. - add, subtract timedelta
  282. - unary plus, minus, abs
  283. - compare to timedelta
  284. - multiply, divide by int
  285. In addition, datetime supports subtraction of two datetime objects
  286. returning a timedelta, and addition or subtraction of a datetime
  287. and a timedelta giving a datetime.
  288. Representation: (days, seconds, microseconds). Why? Because I
  289. felt like it.
  290. """
  291. __slots__ = '_days', '_seconds', '_microseconds', '_hashcode'
  292. def __new__(cls, days=0, seconds=0, microseconds=0,
  293. milliseconds=0, minutes=0, hours=0, weeks=0):
  294. # Doing this efficiently and accurately in C is going to be difficult
  295. # and error-prone, due to ubiquitous overflow possibilities, and that
  296. # C double doesn't have enough bits of precision to represent
  297. # microseconds over 10K years faithfully. The code here tries to make
  298. # explicit where go-fast assumptions can be relied on, in order to
  299. # guide the C implementation; it's way more convoluted than speed-
  300. # ignoring auto-overflow-to-long idiomatic Python could be.
  301. # XXX Check that all inputs are ints or floats.
  302. # Final values, all integer.
  303. # s and us fit in 32-bit signed ints; d isn't bounded.
  304. d = s = us = 0
  305. # Normalize everything to days, seconds, microseconds.
  306. days += weeks*7
  307. seconds += minutes*60 + hours*3600
  308. microseconds += milliseconds*1000
  309. # Get rid of all fractions, and normalize s and us.
  310. # Take a deep breath <wink>.
  311. if isinstance(days, float):
  312. dayfrac, days = _math.modf(days)
  313. daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.))
  314. assert daysecondswhole == int(daysecondswhole) # can't overflow
  315. s = int(daysecondswhole)
  316. assert days == int(days)
  317. d = int(days)
  318. else:
  319. daysecondsfrac = 0.0
  320. d = days
  321. assert isinstance(daysecondsfrac, float)
  322. assert abs(daysecondsfrac) <= 1.0
  323. assert isinstance(d, int)
  324. assert abs(s) <= 24 * 3600
  325. # days isn't referenced again before redefinition
  326. if isinstance(seconds, float):
  327. secondsfrac, seconds = _math.modf(seconds)
  328. assert seconds == int(seconds)
  329. seconds = int(seconds)
  330. secondsfrac += daysecondsfrac
  331. assert abs(secondsfrac) <= 2.0
  332. else:
  333. secondsfrac = daysecondsfrac
  334. # daysecondsfrac isn't referenced again
  335. assert isinstance(secondsfrac, float)
  336. assert abs(secondsfrac) <= 2.0
  337. assert isinstance(seconds, int)
  338. days, seconds = divmod(seconds, 24*3600)
  339. d += days
  340. s += int(seconds) # can't overflow
  341. assert isinstance(s, int)
  342. assert abs(s) <= 2 * 24 * 3600
  343. # seconds isn't referenced again before redefinition
  344. usdouble = secondsfrac * 1e6
  345. assert abs(usdouble) < 2.1e6 # exact value not critical
  346. # secondsfrac isn't referenced again
  347. if isinstance(microseconds, float):
  348. microseconds = round(microseconds + usdouble)
  349. seconds, microseconds = divmod(microseconds, 1000000)
  350. days, seconds = divmod(seconds, 24*3600)
  351. d += days
  352. s += seconds
  353. else:
  354. microseconds = int(microseconds)
  355. seconds, microseconds = divmod(microseconds, 1000000)
  356. days, seconds = divmod(seconds, 24*3600)
  357. d += days
  358. s += seconds
  359. microseconds = round(microseconds + usdouble)
  360. assert isinstance(s, int)
  361. assert isinstance(microseconds, int)
  362. assert abs(s) <= 3 * 24 * 3600
  363. assert abs(microseconds) < 3.1e6
  364. # Just a little bit of carrying possible for microseconds and seconds.
  365. seconds, us = divmod(microseconds, 1000000)
  366. s += seconds
  367. days, s = divmod(s, 24*3600)
  368. d += days
  369. assert isinstance(d, int)
  370. assert isinstance(s, int) and 0 <= s < 24*3600
  371. assert isinstance(us, int) and 0 <= us < 1000000
  372. if abs(d) > 999999999:
  373. raise OverflowError("timedelta # of days is too large: %d" % d)
  374. self = object.__new__(cls)
  375. self._days = d
  376. self._seconds = s
  377. self._microseconds = us
  378. self._hashcode = -1
  379. return self
  380. def __repr__(self):
  381. if self._microseconds:
  382. return "%s.%s(%d, %d, %d)" % (self.__class__.__module__,
  383. self.__class__.__qualname__,
  384. self._days,
  385. self._seconds,
  386. self._microseconds)
  387. if self._seconds:
  388. return "%s.%s(%d, %d)" % (self.__class__.__module__,
  389. self.__class__.__qualname__,
  390. self._days,
  391. self._seconds)
  392. return "%s.%s(%d)" % (self.__class__.__module__,
  393. self.__class__.__qualname__,
  394. self._days)
  395. def __str__(self):
  396. mm, ss = divmod(self._seconds, 60)
  397. hh, mm = divmod(mm, 60)
  398. s = "%d:%02d:%02d" % (hh, mm, ss)
  399. if self._days:
  400. def plural(n):
  401. return n, abs(n) != 1 and "s" or ""
  402. s = ("%d day%s, " % plural(self._days)) + s
  403. if self._microseconds:
  404. s = s + ".%06d" % self._microseconds
  405. return s
  406. def total_seconds(self):
  407. """Total seconds in the duration."""
  408. return ((self.days * 86400 + self.seconds) * 10**6 +
  409. self.microseconds) / 10**6
  410. # Read-only field accessors
  411. @property
  412. def days(self):
  413. """days"""
  414. return self._days
  415. @property
  416. def seconds(self):
  417. """seconds"""
  418. return self._seconds
  419. @property
  420. def microseconds(self):
  421. """microseconds"""
  422. return self._microseconds
  423. def __add__(self, other):
  424. if isinstance(other, timedelta):
  425. # for CPython compatibility, we cannot use
  426. # our __class__ here, but need a real timedelta
  427. return timedelta(self._days + other._days,
  428. self._seconds + other._seconds,
  429. self._microseconds + other._microseconds)
  430. return NotImplemented
  431. __radd__ = __add__
  432. def __sub__(self, other):
  433. if isinstance(other, timedelta):
  434. # for CPython compatibility, we cannot use
  435. # our __class__ here, but need a real timedelta
  436. return timedelta(self._days - other._days,
  437. self._seconds - other._seconds,
  438. self._microseconds - other._microseconds)
  439. return NotImplemented
  440. def __rsub__(self, other):
  441. if isinstance(other, timedelta):
  442. return -self + other
  443. return NotImplemented
  444. def __neg__(self):
  445. # for CPython compatibility, we cannot use
  446. # our __class__ here, but need a real timedelta
  447. return timedelta(-self._days,
  448. -self._seconds,
  449. -self._microseconds)
  450. def __pos__(self):
  451. return self
  452. def __abs__(self):
  453. if self._days < 0:
  454. return -self
  455. else:
  456. return self
  457. def __mul__(self, other):
  458. if isinstance(other, int):
  459. # for CPython compatibility, we cannot use
  460. # our __class__ here, but need a real timedelta
  461. return timedelta(self._days * other,
  462. self._seconds * other,
  463. self._microseconds * other)
  464. if isinstance(other, float):
  465. usec = self._to_microseconds()
  466. a, b = other.as_integer_ratio()
  467. return timedelta(0, 0, _divide_and_round(usec * a, b))
  468. return NotImplemented
  469. __rmul__ = __mul__
  470. def _to_microseconds(self):
  471. return ((self._days * (24*3600) + self._seconds) * 1000000 +
  472. self._microseconds)
  473. def __floordiv__(self, other):
  474. if not isinstance(other, (int, timedelta)):
  475. return NotImplemented
  476. usec = self._to_microseconds()
  477. if isinstance(other, timedelta):
  478. return usec // other._to_microseconds()
  479. if isinstance(other, int):
  480. return timedelta(0, 0, usec // other)
  481. def __truediv__(self, other):
  482. if not isinstance(other, (int, float, timedelta)):
  483. return NotImplemented
  484. usec = self._to_microseconds()
  485. if isinstance(other, timedelta):
  486. return usec / other._to_microseconds()
  487. if isinstance(other, int):
  488. return timedelta(0, 0, _divide_and_round(usec, other))
  489. if isinstance(other, float):
  490. a, b = other.as_integer_ratio()
  491. return timedelta(0, 0, _divide_and_round(b * usec, a))
  492. def __mod__(self, other):
  493. if isinstance(other, timedelta):
  494. r = self._to_microseconds() % other._to_microseconds()
  495. return timedelta(0, 0, r)
  496. return NotImplemented
  497. def __divmod__(self, other):
  498. if isinstance(other, timedelta):
  499. q, r = divmod(self._to_microseconds(),
  500. other._to_microseconds())
  501. return q, timedelta(0, 0, r)
  502. return NotImplemented
  503. # Comparisons of timedelta objects with other.
  504. def __eq__(self, other):
  505. if isinstance(other, timedelta):
  506. return self._cmp(other) == 0
  507. else:
  508. return False
  509. def __le__(self, other):
  510. if isinstance(other, timedelta):
  511. return self._cmp(other) <= 0
  512. else:
  513. _cmperror(self, other)
  514. def __lt__(self, other):
  515. if isinstance(other, timedelta):
  516. return self._cmp(other) < 0
  517. else:
  518. _cmperror(self, other)
  519. def __ge__(self, other):
  520. if isinstance(other, timedelta):
  521. return self._cmp(other) >= 0
  522. else:
  523. _cmperror(self, other)
  524. def __gt__(self, other):
  525. if isinstance(other, timedelta):
  526. return self._cmp(other) > 0
  527. else:
  528. _cmperror(self, other)
  529. def _cmp(self, other):
  530. assert isinstance(other, timedelta)
  531. return _cmp(self._getstate(), other._getstate())
  532. def __hash__(self):
  533. if self._hashcode == -1:
  534. self._hashcode = hash(self._getstate())
  535. return self._hashcode
  536. def __bool__(self):
  537. return (self._days != 0 or
  538. self._seconds != 0 or
  539. self._microseconds != 0)
  540. # Pickle support.
  541. def _getstate(self):
  542. return (self._days, self._seconds, self._microseconds)
  543. def __reduce__(self):
  544. return (self.__class__, self._getstate())
  545. timedelta.min = timedelta(-999999999)
  546. timedelta.max = timedelta(days=999999999, hours=23, minutes=59, seconds=59,
  547. microseconds=999999)
  548. timedelta.resolution = timedelta(microseconds=1)
  549. class date:
  550. """Concrete date type.
  551. Constructors:
  552. __new__()
  553. fromtimestamp()
  554. today()
  555. fromordinal()
  556. Operators:
  557. __repr__, __str__
  558. __eq__, __le__, __lt__, __ge__, __gt__, __hash__
  559. __add__, __radd__, __sub__ (add/radd only with timedelta arg)
  560. Methods:
  561. timetuple()
  562. toordinal()
  563. weekday()
  564. isoweekday(), isocalendar(), isoformat()
  565. ctime()
  566. strftime()
  567. Properties (readonly):
  568. year, month, day
  569. """
  570. __slots__ = '_year', '_month', '_day', '_hashcode'
  571. def __new__(cls, year, month=None, day=None):
  572. """Constructor.
  573. Arguments:
  574. year, month, day (required, base 1)
  575. """
  576. if month is None and isinstance(year, bytes) and len(year) == 4 and \
  577. 1 <= year[2] <= 12:
  578. # Pickle support
  579. self = object.__new__(cls)
  580. self.__setstate(year)
  581. self._hashcode = -1
  582. return self
  583. year, month, day = _check_date_fields(year, month, day)
  584. self = object.__new__(cls)
  585. self._year = year
  586. self._month = month
  587. self._day = day
  588. self._hashcode = -1
  589. return self
  590. # Additional constructors
  591. @classmethod
  592. def fromtimestamp(cls, t):
  593. "Construct a date from a POSIX timestamp (like time.time())."
  594. y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
  595. return cls(y, m, d)
  596. @classmethod
  597. def today(cls):
  598. "Construct a date from time.time()."
  599. t = _time.time()
  600. return cls.fromtimestamp(t)
  601. @classmethod
  602. def fromordinal(cls, n):
  603. """Contruct a date from a proleptic Gregorian ordinal.
  604. January 1 of year 1 is day 1. Only the year, month and day are
  605. non-zero in the result.
  606. """
  607. y, m, d = _ord2ymd(n)
  608. return cls(y, m, d)
  609. # Conversions to string
  610. def __repr__(self):
  611. """Convert to formal string, for repr().
  612. >>> dt = datetime(2010, 1, 1)
  613. >>> repr(dt)
  614. 'datetime.datetime(2010, 1, 1, 0, 0)'
  615. >>> dt = datetime(2010, 1, 1, tzinfo=timezone.utc)
  616. >>> repr(dt)
  617. 'datetime.datetime(2010, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)'
  618. """
  619. return "%s.%s(%d, %d, %d)" % (self.__class__.__module__,
  620. self.__class__.__qualname__,
  621. self._year,
  622. self._month,
  623. self._day)
  624. # XXX These shouldn't depend on time.localtime(), because that
  625. # clips the usable dates to [1970 .. 2038). At least ctime() is
  626. # easily done without using strftime() -- that's better too because
  627. # strftime("%c", ...) is locale specific.
  628. def ctime(self):
  629. "Return ctime() style string."
  630. weekday = self.toordinal() % 7 or 7
  631. return "%s %s %2d 00:00:00 %04d" % (
  632. _DAYNAMES[weekday],
  633. _MONTHNAMES[self._month],
  634. self._day, self._year)
  635. def strftime(self, fmt):
  636. "Format using strftime()."
  637. return _wrap_strftime(self, fmt, self.timetuple())
  638. def __format__(self, fmt):
  639. if not isinstance(fmt, str):
  640. raise TypeError("must be str, not %s" % type(fmt).__name__)
  641. if len(fmt) != 0:
  642. return self.strftime(fmt)
  643. return str(self)
  644. def isoformat(self):
  645. """Return the date formatted according to ISO.
  646. This is 'YYYY-MM-DD'.
  647. References:
  648. - http://www.w3.org/TR/NOTE-datetime
  649. - http://www.cl.cam.ac.uk/~mgk25/iso-time.html
  650. """
  651. return "%04d-%02d-%02d" % (self._year, self._month, self._day)
  652. __str__ = isoformat
  653. # Read-only field accessors
  654. @property
  655. def year(self):
  656. """year (1-9999)"""
  657. return self._year
  658. @property
  659. def month(self):
  660. """month (1-12)"""
  661. return self._month
  662. @property
  663. def day(self):
  664. """day (1-31)"""
  665. return self._day
  666. # Standard conversions, __eq__, __le__, __lt__, __ge__, __gt__,
  667. # __hash__ (and helpers)
  668. def timetuple(self):
  669. "Return local time tuple compatible with time.localtime()."
  670. return _build_struct_time(self._year, self._month, self._day,
  671. 0, 0, 0, -1)
  672. def toordinal(self):
  673. """Return proleptic Gregorian ordinal for the year, month and day.
  674. January 1 of year 1 is day 1. Only the year, month and day values
  675. contribute to the result.
  676. """
  677. return _ymd2ord(self._year, self._month, self._day)
  678. def replace(self, year=None, month=None, day=None):
  679. """Return a new date with new values for the specified fields."""
  680. if year is None:
  681. year = self._year
  682. if month is None:
  683. month = self._month
  684. if day is None:
  685. day = self._day
  686. return date(year, month, day)
  687. # Comparisons of date objects with other.
  688. def __eq__(self, other):
  689. if isinstance(other, date):
  690. return self._cmp(other) == 0
  691. return NotImplemented
  692. def __le__(self, other):
  693. if isinstance(other, date):
  694. return self._cmp(other) <= 0
  695. return NotImplemented
  696. def __lt__(self, other):
  697. if isinstance(other, date):
  698. return self._cmp(other) < 0
  699. return NotImplemented
  700. def __ge__(self, other):
  701. if isinstance(other, date):
  702. return self._cmp(other) >= 0
  703. return NotImplemented
  704. def __gt__(self, other):
  705. if isinstance(other, date):
  706. return self._cmp(other) > 0
  707. return NotImplemented
  708. def _cmp(self, other):
  709. assert isinstance(other, date)
  710. y, m, d = self._year, self._month, self._day
  711. y2, m2, d2 = other._year, other._month, other._day
  712. return _cmp((y, m, d), (y2, m2, d2))
  713. def __hash__(self):
  714. "Hash."
  715. if self._hashcode == -1:
  716. self._hashcode = hash(self._getstate())
  717. return self._hashcode
  718. # Computations
  719. def __add__(self, other):
  720. "Add a date to a timedelta."
  721. if isinstance(other, timedelta):
  722. o = self.toordinal() + other.days
  723. if 0 < o <= _MAXORDINAL:
  724. return date.fromordinal(o)
  725. raise OverflowError("result out of range")
  726. return NotImplemented
  727. __radd__ = __add__
  728. def __sub__(self, other):
  729. """Subtract two dates, or a date and a timedelta."""
  730. if isinstance(other, timedelta):
  731. return self + timedelta(-other.days)
  732. if isinstance(other, date):
  733. days1 = self.toordinal()
  734. days2 = other.toordinal()
  735. return timedelta(days1 - days2)
  736. return NotImplemented
  737. def weekday(self):
  738. "Return day of the week, where Monday == 0 ... Sunday == 6."
  739. return (self.toordinal() + 6) % 7
  740. # Day-of-the-week and week-of-the-year, according to ISO
  741. def isoweekday(self):
  742. "Return day of the week, where Monday == 1 ... Sunday == 7."
  743. # 1-Jan-0001 is a Monday
  744. return self.toordinal() % 7 or 7
  745. def isocalendar(self):
  746. """Return a 3-tuple containing ISO year, week number, and weekday.
  747. The first ISO week of the year is the (Mon-Sun) week
  748. containing the year's first Thursday; everything else derives
  749. from that.
  750. The first week is 1; Monday is 1 ... Sunday is 7.
  751. ISO calendar algorithm taken from
  752. http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
  753. (used with permission)
  754. """
  755. year = self._year
  756. week1monday = _isoweek1monday(year)
  757. today = _ymd2ord(self._year, self._month, self._day)
  758. # Internally, week and day have origin 0
  759. week, day = divmod(today - week1monday, 7)
  760. if week < 0:
  761. year -= 1
  762. week1monday = _isoweek1monday(year)
  763. week, day = divmod(today - week1monday, 7)
  764. elif week >= 52:
  765. if today >= _isoweek1monday(year+1):
  766. year += 1
  767. week = 0
  768. return year, week+1, day+1
  769. # Pickle support.
  770. def _getstate(self):
  771. yhi, ylo = divmod(self._year, 256)
  772. return bytes([yhi, ylo, self._month, self._day]),
  773. def __setstate(self, string):
  774. yhi, ylo, self._month, self._day = string
  775. self._year = yhi * 256 + ylo
  776. def __reduce__(self):
  777. return (self.__class__, self._getstate())
  778. _date_class = date # so functions w/ args named "date" can get at the class
  779. date.min = date(1, 1, 1)
  780. date.max = date(9999, 12, 31)
  781. date.resolution = timedelta(days=1)
  782. class tzinfo:
  783. """Abstract base class for time zone info classes.
  784. Subclasses must override the name(), utcoffset() and dst() methods.
  785. """
  786. __slots__ = ()
  787. def tzname(self, dt):
  788. "datetime -> string name of time zone."
  789. raise NotImplementedError("tzinfo subclass must override tzname()")
  790. def utcoffset(self, dt):
  791. "datetime -> minutes east of UTC (negative for west of UTC)"
  792. raise NotImplementedError("tzinfo subclass must override utcoffset()")
  793. def dst(self, dt):
  794. """datetime -> DST offset in minutes east of UTC.
  795. Return 0 if DST not in effect. utcoffset() must include the DST
  796. offset.
  797. """
  798. raise NotImplementedError("tzinfo subclass must override dst()")
  799. def fromutc(self, dt):
  800. "datetime in UTC -> datetime in local time."
  801. if not isinstance(dt, datetime):
  802. raise TypeError("fromutc() requires a datetime argument")
  803. if dt.tzinfo is not self:
  804. raise ValueError("dt.tzinfo is not self")
  805. dtoff = dt.utcoffset()
  806. if dtoff is None:
  807. raise ValueError("fromutc() requires a non-None utcoffset() "
  808. "result")
  809. # See the long comment block at the end of this file for an
  810. # explanation of this algorithm.
  811. dtdst = dt.dst()
  812. if dtdst is None:
  813. raise ValueError("fromutc() requires a non-None dst() result")
  814. delta = dtoff - dtdst
  815. if delta:
  816. dt += delta
  817. dtdst = dt.dst()
  818. if dtdst is None:
  819. raise ValueError("fromutc(): dt.dst gave inconsistent "
  820. "results; cannot convert")
  821. return dt + dtdst
  822. # Pickle support.
  823. def __reduce__(self):
  824. getinitargs = getattr(self, "__getinitargs__", None)
  825. if getinitargs:
  826. args = getinitargs()
  827. else:
  828. args = ()
  829. getstate = getattr(self, "__getstate__", None)
  830. if getstate:
  831. state = getstate()
  832. else:
  833. state = getattr(self, "__dict__", None) or None
  834. if state is None:
  835. return (self.__class__, args)
  836. else:
  837. return (self.__class__, args, state)
  838. _tzinfo_class = tzinfo
  839. class time:
  840. """Time with time zone.
  841. Constructors:
  842. __new__()
  843. Operators:
  844. __repr__, __str__
  845. __eq__, __le__, __lt__, __ge__, __gt__, __hash__
  846. Methods:
  847. strftime()
  848. isoformat()
  849. utcoffset()
  850. tzname()
  851. dst()
  852. Properties (readonly):
  853. hour, minute, second, microsecond, tzinfo
  854. """
  855. __slots__ = '_hour', '_minute', '_second', '_microsecond', '_tzinfo', '_hashcode'
  856. def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None):
  857. """Constructor.
  858. Arguments:
  859. hour, minute (required)
  860. second, microsecond (default to zero)
  861. tzinfo (default to None)
  862. """
  863. if isinstance(hour, bytes) and len(hour) == 6 and hour[0] < 24:
  864. # Pickle support
  865. self = object.__new__(cls)
  866. self.__setstate(hour, minute or None)
  867. self._hashcode = -1
  868. return self
  869. hour, minute, second, microsecond = _check_time_fields(
  870. hour, minute, second, microsecond)
  871. _check_tzinfo_arg(tzinfo)
  872. self = object.__new__(cls)
  873. self._hour = hour
  874. self._minute = minute
  875. self._second = second
  876. self._microsecond = microsecond
  877. self._tzinfo = tzinfo
  878. self._hashcode = -1
  879. return self
  880. # Read-only field accessors
  881. @property
  882. def hour(self):
  883. """hour (0-23)"""
  884. return self._hour
  885. @property
  886. def minute(self):
  887. """minute (0-59)"""
  888. return self._minute
  889. @property
  890. def second(self):
  891. """second (0-59)"""
  892. return self._second
  893. @property
  894. def microsecond(self):
  895. """microsecond (0-999999)"""
  896. return self._microsecond
  897. @property
  898. def tzinfo(self):
  899. """timezone info object"""
  900. return self._tzinfo
  901. # Standard conversions, __hash__ (and helpers)
  902. # Comparisons of time objects with other.
  903. def __eq__(self, other):
  904. if isinstance(other, time):
  905. return self._cmp(other, allow_mixed=True) == 0
  906. else:
  907. return False
  908. def __le__(self, other):
  909. if isinstance(other, time):
  910. return self._cmp(other) <= 0
  911. else:
  912. _cmperror(self, other)
  913. def __lt__(self, other):
  914. if isinstance(other, time):
  915. return self._cmp(other) < 0
  916. else:
  917. _cmperror(self, other)
  918. def __ge__(self, other):
  919. if isinstance(other, time):
  920. return self._cmp(other) >= 0
  921. else:
  922. _cmperror(self, other)
  923. def __gt__(self, other):
  924. if isinstance(other, time):
  925. return self._cmp(other) > 0
  926. else:
  927. _cmperror(self, other)
  928. def _cmp(self, other, allow_mixed=False):
  929. assert isinstance(other, time)
  930. mytz = self._tzinfo
  931. ottz = other._tzinfo
  932. myoff = otoff = None
  933. if mytz is ottz:
  934. base_compare = True
  935. else:
  936. myoff = self.utcoffset()
  937. otoff = other.utcoffset()
  938. base_compare = myoff == otoff
  939. if base_compare:
  940. return _cmp((self._hour, self._minute, self._second,
  941. self._microsecond),
  942. (other._hour, other._minute, other._second,
  943. other._microsecond))
  944. if myoff is None or otoff is None:
  945. if allow_mixed:
  946. return 2 # arbitrary non-zero value
  947. else:
  948. raise TypeError("cannot compare naive and aware times")
  949. myhhmm = self._hour * 60 + self._minute - myoff//timedelta(minutes=1)
  950. othhmm = other._hour * 60 + other._minute - otoff//timedelta(minutes=1)
  951. return _cmp((myhhmm, self._second, self._microsecond),
  952. (othhmm, other._second, other._microsecond))
  953. def __hash__(self):
  954. """Hash."""
  955. if self._hashcode == -1:
  956. tzoff = self.utcoffset()
  957. if not tzoff: # zero or None
  958. self._hashcode = hash(self._getstate()[0])
  959. else:
  960. h, m = divmod(timedelta(hours=self.hour, minutes=self.minute) - tzoff,
  961. timedelta(hours=1))
  962. assert not m % timedelta(minutes=1), "whole minute"
  963. m //= timedelta(minutes=1)
  964. if 0 <= h < 24:
  965. self._hashcode = hash(time(h, m, self.second, self.microsecond))
  966. else:
  967. self._hashcode = hash((h, m, self.second, self.microsecond))
  968. return self._hashcode
  969. # Conversion to string
  970. def _tzstr(self, sep=":"):
  971. """Return formatted timezone offset (+xx:xx) or None."""
  972. off = self.utcoffset()
  973. if off is not None:
  974. if off.days < 0:
  975. sign = "-"
  976. off = -off
  977. else:
  978. sign = "+"
  979. hh, mm = divmod(off, timedelta(hours=1))
  980. assert not mm % timedelta(minutes=1), "whole minute"
  981. mm //= timedelta(minutes=1)
  982. assert 0 <= hh < 24
  983. off = "%s%02d%s%02d" % (sign, hh, sep, mm)
  984. return off
  985. def __repr__(self):
  986. """Convert to formal string, for repr()."""
  987. if self._microsecond != 0:
  988. s = ", %d, %d" % (self._second, self._microsecond)
  989. elif self._second != 0:
  990. s = ", %d" % self._second
  991. else:
  992. s = ""
  993. s= "%s.%s(%d, %d%s)" % (self.__class__.__module__,
  994. self.__class__.__qualname__,
  995. self._hour, self._minute, s)
  996. if self._tzinfo is not None:
  997. assert s[-1:] == ")"
  998. s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
  999. return s
  1000. def isoformat(self):
  1001. """Return the time formatted according to ISO.
  1002. This is 'HH:MM:SS.mmmmmm+zz:zz', or 'HH:MM:SS+zz:zz' if
  1003. self.microsecond == 0.
  1004. """
  1005. s = _format_time(self._hour, self._minute, self._second,
  1006. self._microsecond)
  1007. tz = self._tzstr()
  1008. if tz:
  1009. s += tz
  1010. return s
  1011. __str__ = isoformat
  1012. def strftime(self, fmt):
  1013. """Format using strftime(). The date part of the timestamp passed
  1014. to underlying strftime should not be used.
  1015. """
  1016. # The year must be >= 1000 else Python's strftime implementation
  1017. # can raise a bogus exception.
  1018. timetuple = (1900, 1, 1,
  1019. self._hour, self._minute, self._second,
  1020. 0, 1, -1)
  1021. return _wrap_strftime(self, fmt, timetuple)
  1022. def __format__(self, fmt):
  1023. if not isinstance(fmt, str):
  1024. raise TypeError("must be str, not %s" % type(fmt).__name__)
  1025. if len(fmt) != 0:
  1026. return self.strftime(fmt)
  1027. return str(self)
  1028. # Timezone functions
  1029. def utcoffset(self):
  1030. """Return the timezone offset in minutes east of UTC (negative west of
  1031. UTC)."""
  1032. if self._tzinfo is None:
  1033. return None
  1034. offset = self._tzinfo.utcoffset(None)
  1035. _check_utc_offset("utcoffset", offset)
  1036. return offset
  1037. def tzname(self):
  1038. """Return the timezone name.
  1039. Note that the name is 100% informational -- there's no requirement that
  1040. it mean anything in particular. For example, "GMT", "UTC", "-500",
  1041. "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
  1042. """
  1043. if self._tzinfo is None:
  1044. return None
  1045. name = self._tzinfo.tzname(None)
  1046. _check_tzname(name)
  1047. return name
  1048. def dst(self):
  1049. """Return 0 if DST is not in effect, or the DST offset (in minutes
  1050. eastward) if DST is in effect.
  1051. This is purely informational; the DST offset has already been added to
  1052. the UTC offset returned by utcoffset() if applicable, so there's no
  1053. need to consult dst() unless you're interested in displaying the DST
  1054. info.
  1055. """
  1056. if self._tzinfo is None:
  1057. return None
  1058. offset = self._tzinfo.dst(None)
  1059. _check_utc_offset("dst", offset)
  1060. return offset
  1061. def replace(self, hour=None, minute=None, second=None, microsecond=None,
  1062. tzinfo=True):
  1063. """Return a new time with new values for the specified fields."""
  1064. if hour is None:
  1065. hour = self.hour
  1066. if minute is None:
  1067. minute = self.minute
  1068. if second is None:
  1069. second = self.second
  1070. if microsecond is None:
  1071. microsecond = self.microsecond
  1072. if tzinfo is True:
  1073. tzinfo = self.tzinfo
  1074. return time(hour, minute, second, microsecond, tzinfo)
  1075. # Pickle support.
  1076. def _getstate(self):
  1077. us2, us3 = divmod(self._microsecond, 256)
  1078. us1, us2 = divmod(us2, 256)
  1079. basestate = bytes([self._hour, self._minute, self._second,
  1080. us1, us2, us3])
  1081. if self._tzinfo is None:
  1082. return (basestate,)
  1083. else:
  1084. return (basestate, self._tzinfo)
  1085. def __setstate(self, string, tzinfo):
  1086. if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
  1087. raise TypeError("bad tzinfo state arg")
  1088. self._hour, self._minute, self._second, us1, us2, us3 = string
  1089. self._microsecond = (((us1 << 8) | us2) << 8) | us3
  1090. self._tzinfo = tzinfo
  1091. def __reduce__(self):
  1092. return (time, self._getstate())
  1093. _time_class = time # so functions w/ args named "time" can get at the class
  1094. time.min = time(0, 0, 0)
  1095. time.max = time(23, 59, 59, 999999)
  1096. time.resolution = timedelta(microseconds=1)
  1097. class datetime(date):
  1098. """datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
  1099. The year, month and day arguments are required. tzinfo may be None, or an
  1100. instance of a tzinfo subclass. The remaining arguments may be ints.
  1101. """
  1102. __slots__ = date.__slots__ + time.__slots__
  1103. def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
  1104. microsecond=0, tzinfo=None):
  1105. if isinstance(year, bytes) and len(year) == 10 and 1 <= year[2] <= 12:
  1106. # Pickle support
  1107. self = object.__new__(cls)
  1108. self.__setstate(year, month)
  1109. self._hashcode = -1
  1110. return self
  1111. year, month, day = _check_date_fields(year, month, day)
  1112. hour, minute, second, microsecond = _check_time_fields(
  1113. hour, minute, second, microsecond)
  1114. _check_tzinfo_arg(tzinfo)
  1115. self = object.__new__(cls)
  1116. self._year = year
  1117. self._month = month
  1118. self._day = day
  1119. self._hour = hour
  1120. self._minute = minute
  1121. self._second = second
  1122. self._microsecond = microsecond
  1123. self._tzinfo = tzinfo
  1124. self._hashcode = -1
  1125. return self
  1126. # Read-only field accessors
  1127. @property
  1128. def hour(self):
  1129. """hour (0-23)"""
  1130. return self._hour
  1131. @property
  1132. def minute(self):
  1133. """minute (0-59)"""
  1134. return self._minute
  1135. @property
  1136. def second(self):
  1137. """second (0-59)"""
  1138. return self._second
  1139. @property
  1140. def microsecond(self):
  1141. """microsecond (0-999999)"""
  1142. return self._microsecond
  1143. @property
  1144. def tzinfo(self):
  1145. """timezone info object"""
  1146. return self._tzinfo
  1147. @classmethod
  1148. def _fromtimestamp(cls, t, utc, tz):
  1149. """Construct a datetime from a POSIX timestamp (like time.time()).
  1150. A timezone info object may be passed in as well.
  1151. """
  1152. frac, t = _math.modf(t)
  1153. us = round(frac * 1e6)
  1154. if us >= 1000000:
  1155. t += 1
  1156. us -= 1000000
  1157. elif us < 0:
  1158. t -= 1
  1159. us += 1000000
  1160. converter = _time.gmtime if utc else _time.localtime
  1161. y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
  1162. ss = min(ss, 59) # clamp out leap seconds if the platform has them
  1163. return cls(y, m, d, hh, mm, ss, us, tz)
  1164. @classmethod
  1165. def fromtimestamp(cls, t, tz=None):
  1166. """Construct a datetime from a POSIX timestamp (like time.time()).
  1167. A timezone info object may be passed in as well.
  1168. """
  1169. _check_tzinfo_arg(tz)
  1170. result = cls._fromtimestamp(t, tz is not None, tz)
  1171. if tz is not None:
  1172. result = tz.fromutc(result)
  1173. return result
  1174. @classmethod
  1175. def utcfromtimestamp(cls, t):
  1176. """Construct a naive UTC datetime from a POSIX timestamp."""
  1177. return cls._fromtimestamp(t, True, None)
  1178. @classmethod
  1179. def now(cls, tz=None):
  1180. "Construct a datetime from time.time() and optional time zone info."
  1181. t = _time.time()
  1182. return cls.fromtimestamp(t, tz)
  1183. @classmethod
  1184. def utcnow(cls):
  1185. "Construct a UTC datetime from time.time()."
  1186. t = _time.time()
  1187. return cls.utcfromtimestamp(t)
  1188. @classmethod
  1189. def combine(cls, date, time):
  1190. "Construct a datetime from a given date and a given time."
  1191. if not isinstance(date, _date_class):
  1192. raise TypeError("date argument must be a date instance")
  1193. if not isinstance(time, _time_class):
  1194. raise TypeError("time argument must be a time instance")
  1195. return cls(date.year, date.month, date.day,
  1196. time.hour, time.minute, time.second, time.microsecond,
  1197. time.tzinfo)
  1198. def timetuple(self):
  1199. "Return local time tuple compatible with time.localtime()."
  1200. dst = self.dst()
  1201. if dst is None:
  1202. dst = -1
  1203. elif dst:
  1204. dst = 1
  1205. else:
  1206. dst = 0
  1207. return _build_struct_time(self.year, self.month, self.day,
  1208. self.hour, self.minute, self.second,
  1209. dst)
  1210. def timestamp(self):
  1211. "Return POSIX timestamp as float"
  1212. if self._tzinfo is None:
  1213. return _time.mktime((self.year, self.month, self.day,
  1214. self.hour, self.minute, self.second,
  1215. -1, -1, -1)) + self.microsecond / 1e6
  1216. else:
  1217. return (self - _EPOCH).total_seconds()
  1218. def utctimetuple(self):
  1219. "Return UTC time tuple compatible with time.gmtime()."
  1220. offset = self.utcoffset()
  1221. if offset:
  1222. self -= offset
  1223. y, m, d = self.year, self.month, self.day
  1224. hh, mm, ss = self.hour, self.minute, self.second
  1225. return _build_struct_time(y, m, d, hh, mm, ss, 0)
  1226. def date(self):
  1227. "Return the date part."
  1228. return date(self._year, self._month, self._day)
  1229. def time(self):
  1230. "Return the time part, with tzinfo None."
  1231. return time(self.hour, self.minute, self.second, self.microsecond)
  1232. def timetz(self):
  1233. "Return the time part, with same tzinfo."
  1234. return time(self.hour, self.minute, self.second, self.microsecond,
  1235. self._tzinfo)
  1236. def replace(self, year=None, month=None, day=None, hour=None,
  1237. minute=None, second=None, microsecond=None, tzinfo=True):
  1238. """Return a new datetime with new values for the specified fields."""
  1239. if year is None:
  1240. year = self.year
  1241. if month is None:
  1242. month = self.month
  1243. if day is None:
  1244. day = self.day
  1245. if hour is None:
  1246. hour = self.hour
  1247. if minute is None:
  1248. minute = self.minute
  1249. if second is None:
  1250. second = self.second
  1251. if microsecond is None:
  1252. microsecond = self.microsecond
  1253. if tzinfo is True:
  1254. tzinfo = self.tzinfo
  1255. return datetime(year, month, day, hour, minute, second, microsecond,
  1256. tzinfo)
  1257. def astimezone(self, tz=None):
  1258. if tz is None:
  1259. if self.tzinfo is None:
  1260. raise ValueError("astimezone() requires an aware datetime")
  1261. ts = (self - _EPOCH) // timedelta(seconds=1)
  1262. localtm = _time.localtime(ts)
  1263. local = datetime(*localtm[:6])
  1264. try:
  1265. # Extract TZ data if available
  1266. gmtoff = localtm.tm_gmtoff
  1267. zone = localtm.tm_zone
  1268. except AttributeError:
  1269. # Compute UTC offset and compare with the value implied
  1270. # by tm_isdst. If the values match, use the zone name
  1271. # implied by tm_isdst.
  1272. delta = local - datetime(*_time.gmtime(ts)[:6])
  1273. dst = _time.daylight and localtm.tm_isdst > 0
  1274. gmtoff = -(_time.altzone if dst else _time.timezone)
  1275. if delta == timedelta(seconds=gmtoff):
  1276. tz = timezone(delta, _time.tzname[dst])
  1277. else:
  1278. tz = timezone(delta)
  1279. else:
  1280. tz = timezone(timedelta(seconds=gmtoff), zone)
  1281. elif not isinstance(tz, tzinfo):
  1282. raise TypeError("tz argument must be an instance of tzinfo")
  1283. mytz = self.tzinfo
  1284. if mytz is None:
  1285. raise ValueError("astimezone() requires an aware datetime")
  1286. if tz is mytz:
  1287. return self
  1288. # Convert self to UTC, and attach the new time zone object.
  1289. myoffset = self.utcoffset()
  1290. if myoffset is None:
  1291. raise ValueError("astimezone() requires an aware datetime")
  1292. utc = (self - myoffset).replace(tzinfo=tz)
  1293. # Convert from UTC to tz's local time.
  1294. return tz.fromutc(utc)
  1295. # Ways to produce a string.
  1296. def ctime(self):
  1297. "Return ctime() style string."
  1298. weekday = self.toordinal() % 7 or 7
  1299. return "%s %s %2d %02d:%02d:%02d %04d" % (
  1300. _DAYNAMES[weekday],
  1301. _MONTHNAMES[self._month],
  1302. self._day,
  1303. self._hour, self._minute, self._second,
  1304. self._year)
  1305. def isoformat(self, sep='T'):
  1306. """Return the time formatted according to ISO.
  1307. This is 'YYYY-MM-DD HH:MM:SS.mmmmmm', or 'YYYY-MM-DD HH:MM:SS' if
  1308. self.microsecond == 0.
  1309. If self.tzinfo is not None, the UTC offset is also attached, giving
  1310. 'YYYY-MM-DD HH:MM:SS.mmmmmm+HH:MM' or 'YYYY-MM-DD HH:MM:SS+HH:MM'.
  1311. Optional argument sep specifies the separator between date and
  1312. time, default 'T'.
  1313. """
  1314. s = ("%04d-%02d-%02d%c" % (self._year, self._month, self._day, sep) +
  1315. _format_time(self._hour, self._minute, self._second,
  1316. self._microsecond))
  1317. off = self.utcoffset()
  1318. if off is not None:
  1319. if off.days < 0:
  1320. sign = "-"
  1321. off = -off
  1322. else:
  1323. sign = "+"
  1324. hh, mm = divmod(off, timedelta(hours=1))
  1325. assert not mm % timedelta(minutes=1), "whole minute"
  1326. mm //= timedelta(minutes=1)
  1327. s += "%s%02d:%02d" % (sign, hh, mm)
  1328. return s
  1329. def __repr__(self):
  1330. """Convert to formal string, for repr()."""
  1331. L = [self._year, self._month, self._day, # These are never zero
  1332. self._hour, self._minute, self._second, self._microsecond]
  1333. if L[-1] == 0:
  1334. del L[-1]
  1335. if L[-1] == 0:
  1336. del L[-1]
  1337. s = "%s.%s(%s)" % (self.__class__.__module__,
  1338. self.__class__.__qualname__,
  1339. ", ".join(map(str, L)))
  1340. if self._tzinfo is not None:
  1341. assert s[-1:] == ")"
  1342. s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
  1343. return s
  1344. def __str__(self):
  1345. "Convert to string, for str()."
  1346. return self.isoformat(sep=' ')
  1347. @classmethod
  1348. def strptime(cls, date_string, format):
  1349. 'string, format -> new datetime parsed from a string (like time.strptime()).'
  1350. import _strptime
  1351. return _strptime._strptime_datetime(cls, date_string, format)
  1352. def utcoffset(self):
  1353. """Return the timezone offset in minutes east of UTC (negative west of
  1354. UTC)."""
  1355. if self._tzinfo is None:
  1356. return None
  1357. offset = self._tzinfo.utcoffset(self)
  1358. _check_utc_offset("utcoffset", offset)
  1359. return offset
  1360. def tzname(self):
  1361. """Return the timezone name.
  1362. Note that the name is 100% informational -- there's no requirement that
  1363. it mean anything in particular. For example, "GMT", "UTC", "-500",
  1364. "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
  1365. """
  1366. if self._tzinfo is None:
  1367. return None
  1368. name = self._tzinfo.tzname(self)
  1369. _check_tzname(name)
  1370. return name
  1371. def dst(self):
  1372. """Return 0 if DST is not in effect, or the DST offset (in minutes
  1373. eastward) if DST is in effect.
  1374. This is purely informational; the DST offset has already been added to
  1375. the UTC offset returned by utcoffset() if applicable, so there's no
  1376. need to consult dst() unless you're interested in displaying the DST
  1377. info.
  1378. """
  1379. if self._tzinfo is None:
  1380. return None
  1381. offset = self._tzinfo.dst(self)
  1382. _check_utc_offset("dst", offset)
  1383. return offset
  1384. # Comparisons of datetime objects with other.
  1385. def __eq__(self, other):
  1386. if isinstance(other, datetime):
  1387. return self._cmp(other, allow_mixed=True) == 0
  1388. elif not isinstance(other, date):
  1389. return NotImplemented
  1390. else:
  1391. return False
  1392. def __le__(self, other):
  1393. if isinstance(other, datetime):
  1394. return self._cmp(other) <= 0
  1395. elif not isinstance(other, date):
  1396. return NotImplemented
  1397. else:
  1398. _cmperror(self, other)
  1399. def __lt__(self, other):
  1400. if isinstance(other, datetime):
  1401. return self._cmp(other) < 0
  1402. elif not isinstance(other, date):
  1403. return NotImplemented
  1404. else:
  1405. _cmperror(self, other)
  1406. def __ge__(self, other):
  1407. if isinstance(other, datetime):
  1408. return self._cmp(other) >= 0
  1409. elif not isinstance(other, date):
  1410. return NotImplemented
  1411. else:
  1412. _cmperror(self, other)
  1413. def __gt__(self, other):
  1414. if isinstance(other, datetime):
  1415. return self._cmp(other) > 0
  1416. elif not isinstance(other, date):
  1417. return NotImplemented
  1418. else:
  1419. _cmperror(self, other)
  1420. def _cmp(self, other, allow_mixed=False):
  1421. assert isinstance(other, datetime)
  1422. mytz = self._tzinfo
  1423. ottz = other._tzinfo
  1424. myoff = otoff = None
  1425. if mytz is ottz:
  1426. base_compare = True
  1427. else:
  1428. myoff = self.utcoffset()
  1429. otoff = other.utcoffset()
  1430. base_compare = myoff == otoff
  1431. if base_compare:
  1432. return _cmp((self._year, self._month, self._day,
  1433. self._hour, self._minute, self._second,
  1434. self._microsecond),
  1435. (other._year, other._month, other._day,
  1436. other._hour, other._minute, other._second,
  1437. other._microsecond))
  1438. if myoff is None or otoff is None:
  1439. if allow_mixed:
  1440. return 2 # arbitrary non-zero value
  1441. else:
  1442. raise TypeError("cannot compare naive and aware datetimes")
  1443. # XXX What follows could be done more efficiently...
  1444. diff = self - other # this will take offsets into account
  1445. if diff.days < 0:
  1446. return -1
  1447. return diff and 1 or 0
  1448. def __add__(self, other):
  1449. "Add a datetime and a timedelta."
  1450. if not isinstance(other, timedelta):
  1451. return NotImplemented
  1452. delta = timedelta(self.toordinal(),
  1453. hours=self._hour,
  1454. minutes=self._minute,
  1455. seconds=self._second,
  1456. microseconds=self._microsecond)
  1457. delta += other
  1458. hour, rem = divmod(delta.seconds, 3600)
  1459. minute, second = divmod(rem, 60)
  1460. if 0 < delta.days <= _MAXORDINAL:
  1461. return datetime.combine(date.fromordinal(delta.days),
  1462. time(hour, minute, second,
  1463. delta.microseconds,
  1464. tzinfo=self._tzinfo))
  1465. raise OverflowError("result out of range")
  1466. __radd__ = __add__
  1467. def __sub__(self, other):
  1468. "Subtract two datetimes, or a datetime and a timedelta."
  1469. if not isinstance(other, datetime):
  1470. if isinstance(other, timedelta):
  1471. return self + -other
  1472. return NotImplemented
  1473. days1 = self.toordinal()
  1474. days2 = other.toordinal()
  1475. secs1 = self._second + self._minute * 60 + self._hour * 3600
  1476. secs2 = other._second + other._minute * 60 + other._hour * 3600
  1477. base = timedelta(days1 - days2,
  1478. secs1 - secs2,
  1479. self._microsecond - other._microsecond)
  1480. if self._tzinfo is other._tzinfo:
  1481. return base
  1482. myoff = self.utcoffset()
  1483. otoff = other.utcoffset()
  1484. if myoff == otoff:
  1485. return base
  1486. if myoff is None or otoff is None:
  1487. raise TypeError("cannot mix naive and timezone-aware time")
  1488. return base + otoff - myoff
  1489. def __hash__(self):
  1490. if self._hashcode == -1:
  1491. tzoff = self.utcoffset()
  1492. if tzoff is None:
  1493. self._hashcode = hash(self._getstate()[0])
  1494. else:
  1495. days = _ymd2ord(self.year, self.month, self.day)
  1496. seconds = self.hour * 3600 + self.minute * 60 + self.second
  1497. self._hashcode = hash(timedelta(days, seconds, self.microsecond) - tzoff)
  1498. return self._hashcode
  1499. # Pickle support.
  1500. def _getstate(self):
  1501. yhi, ylo = divmod(self._year, 256)
  1502. us2, us3 = divmod(self._microsecond, 256)
  1503. us1, us2 = divmod(us2, 256)
  1504. basestate = bytes([yhi, ylo, self._month, self._day,
  1505. self._hour, self._minute, self._second,
  1506. us1, us2, us3])
  1507. if self._tzinfo is None:
  1508. return (basestate,)
  1509. else:
  1510. return (basestate, self._tzinfo)
  1511. def __setstate(self, string, tzinfo):
  1512. if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
  1513. raise TypeError("bad tzinfo state arg")
  1514. (yhi, ylo, self._month, self._day, self._hour,
  1515. self._minute, self._second, us1, us2, us3) = string
  1516. self._year = yhi * 256 + ylo
  1517. self._microsecond = (((us1 << 8) | us2) << 8) | us3
  1518. self._tzinfo = tzinfo
  1519. def __reduce__(self):
  1520. return (self.__class__, self._getstate())
  1521. datetime.min = datetime(1, 1, 1)
  1522. datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999)
  1523. datetime.resolution = timedelta(microseconds=1)
  1524. def _isoweek1monday(year):
  1525. # Helper to calculate the day number of the Monday starting week 1
  1526. # XXX This could be done more efficiently
  1527. THURSDAY = 3
  1528. firstday = _ymd2ord(year, 1, 1)
  1529. firstweekday = (firstday + 6) % 7 # See weekday() above
  1530. week1monday = firstday - firstweekday
  1531. if firstweekday > THURSDAY:
  1532. week1monday += 7
  1533. return week1monday
  1534. class timezone(tzinfo):
  1535. __slots__ = '_offset', '_name'
  1536. # Sentinel value to disallow None
  1537. _Omitted = object()
  1538. def __new__(cls, offset, name=_Omitted):
  1539. if not isinstance(offset, timedelta):
  1540. raise TypeError("offset must be a timedelta")
  1541. if name is cls._Omitted:
  1542. if not offset:
  1543. return cls.utc
  1544. name = None
  1545. elif not isinstance(name, str):
  1546. raise TypeError("name must be a string")
  1547. if not cls._minoffset <= offset <= cls._maxoffset:
  1548. raise ValueError("offset must be a timedelta "
  1549. "strictly between -timedelta(hours=24) and "
  1550. "timedelta(hours=24).")
  1551. if (offset.microseconds != 0 or offset.seconds % 60 != 0):
  1552. raise ValueError("offset must be a timedelta "
  1553. "representing a whole number of minutes")
  1554. return cls._create(offset, name)
  1555. @classmethod
  1556. def _create(cls, offset, name=None):
  1557. self = tzinfo.__new__(cls)
  1558. self._offset = offset
  1559. self._name = name
  1560. return self
  1561. def __getinitargs__(self):
  1562. """pickle support"""
  1563. if self._name is None:
  1564. return (self._offset,)
  1565. return (self._offset, self._name)
  1566. def __eq__(self, other):
  1567. if type(other) != timezone:
  1568. return False
  1569. return self._offset == other._offset
  1570. def __hash__(self):
  1571. return hash(self._offset)
  1572. def __repr__(self):
  1573. """Convert to formal string, for repr().
  1574. >>> tz = timezone.utc
  1575. >>> repr(tz)
  1576. 'datetime.timezone.utc'
  1577. >>> tz = timezone(timedelta(hours=-5), 'EST')
  1578. >>> repr(tz)
  1579. "datetime.timezone(datetime.timedelta(-1, 68400), 'EST')"
  1580. """
  1581. if self is self.utc:
  1582. return 'datetime.timezone.utc'
  1583. if self._name is None:
  1584. return "%s.%s(%r)" % (self.__class__.__module__,
  1585. self.__class__.__qualname__,
  1586. self._offset)
  1587. return "%s.%s(%r, %r)" % (self.__class__.__module__,
  1588. self.__class__.__qualname__,
  1589. self._offset, self._name)
  1590. def __str__(self):
  1591. return self.tzname(None)
  1592. def utcoffset(self, dt):
  1593. if isinstance(dt, datetime) or dt is None:
  1594. return self._offset
  1595. raise TypeError("utcoffset() argument must be a datetime instance"
  1596. " or None")
  1597. def tzname(self, dt):
  1598. if isinstance(dt, datetime) or dt is None:
  1599. if self._name is None:
  1600. return self._name_from_offset(self._offset)
  1601. return self._name
  1602. raise TypeError("tzname() argument must be a datetime instance"
  1603. " or None")
  1604. def dst(self, dt):
  1605. if isinstance(dt, datetime) or dt is None:
  1606. return None
  1607. raise TypeError("dst() argument must be a datetime instance"
  1608. " or None")
  1609. def fromutc(self, dt):
  1610. if isinstance(dt, datetime):
  1611. if dt.tzinfo is not self:
  1612. raise ValueError("fromutc: dt.tzinfo "
  1613. "is not self")
  1614. return dt + self._offset
  1615. raise TypeError("fromutc() argument must be a datetime instance"
  1616. " or None")
  1617. _maxoffset = timedelta(hours=23, minutes=59)
  1618. _minoffset = -_maxoffset
  1619. @staticmethod
  1620. def _name_from_offset(delta):
  1621. if delta < timedelta(0):
  1622. sign = '-'
  1623. delta = -delta
  1624. else:
  1625. sign = '+'
  1626. hours, rest = divmod(delta, timedelta(hours=1))
  1627. minutes = rest // timedelta(minutes=1)
  1628. return 'UTC{}{:02d}:{:02d}'.format(sign, hours, minutes)
  1629. timezone.utc = timezone._create(timedelta(0))
  1630. timezone.min = timezone._create(timezone._minoffset)
  1631. timezone.max = timezone._create(timezone._maxoffset)
  1632. _EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
  1633. # Some time zone algebra. For a datetime x, let
  1634. # x.n = x stripped of its timezone -- its naive time.
  1635. # x.o = x.utcoffset(), and assuming that doesn't raise an exception or
  1636. # return None
  1637. # x.d = x.dst(), and assuming that doesn't raise an exception or
  1638. # return None
  1639. # x.s = x's standard offset, x.o - x.d
  1640. #
  1641. # Now some derived rules, where k is a duration (timedelta).
  1642. #
  1643. # 1. x.o = x.s + x.d
  1644. # This follows from the definition of x.s.
  1645. #
  1646. # 2. If x and y have the same tzinfo member, x.s = y.s.
  1647. # This is actually a requirement, an assumption we need to make about
  1648. # sane tzinfo classes.
  1649. #
  1650. # 3. The naive UTC time corresponding to x is x.n - x.o.
  1651. # This is again a requirement for a sane tzinfo class.
  1652. #
  1653. # 4. (x+k).s = x.s
  1654. # This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
  1655. #
  1656. # 5. (x+k).n = x.n + k
  1657. # Again follows from how arithmetic is defined.
  1658. #
  1659. # Now we can explain tz.fromutc(x). Let's assume it's an interesting case
  1660. # (meaning that the various tzinfo methods exist, and don't blow up or return
  1661. # None when called).
  1662. #
  1663. # The function wants to return a datetime y with timezone tz, equivalent to x.
  1664. # x is already in UTC.
  1665. #
  1666. # By #3, we want
  1667. #
  1668. # y.n - y.o = x.n [1]
  1669. #
  1670. # The algorithm starts by attaching tz to x.n, and calling that y. So
  1671. # x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
  1672. # becomes true; in effect, we want to solve [2] for k:
  1673. #
  1674. # (y+k).n - (y+k).o = x.n [2]
  1675. #
  1676. # By #1, this is the same as
  1677. #
  1678. # (y+k).n - ((y+k).s + (y+k).d) = x.n [3]
  1679. #
  1680. # By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
  1681. # Substituting that into [3],
  1682. #
  1683. # x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving
  1684. # k - (y+k).s - (y+k).d = 0; rearranging,
  1685. # k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so
  1686. # k = y.s - (y+k).d
  1687. #
  1688. # On the RHS, (y+k).d can't be computed directly, but y.s can be, and we
  1689. # approximate k by ignoring the (y+k).d term at first. Note that k can't be
  1690. # very large, since all offset-returning methods return a duration of magnitude
  1691. # less than 24 hours. For that reason, if y is firmly in std time, (y+k).d must
  1692. # be 0, so ignoring it has no consequence then.
  1693. #
  1694. # In any case, the new value is
  1695. #
  1696. # z = y + y.s [4]
  1697. #
  1698. # It's helpful to step back at look at [4] from a higher level: it's simply
  1699. # mapping from UTC to tz's standard time.
  1700. #
  1701. # At this point, if
  1702. #
  1703. # z.n - z.o = x.n [5]
  1704. #
  1705. # we have an equivalent time, and are almost done. The insecurity here is
  1706. # at the start of daylight time. Picture US Eastern for concreteness. The wall
  1707. # time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
  1708. # sense then. The docs ask that an Eastern tzinfo class consider such a time to
  1709. # be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST
  1710. # on the day DST starts. We want to return the 1:MM EST spelling because that's
  1711. # the only spelling that makes sense on the local wall clock.
  1712. #
  1713. # In fact, if [5] holds at this point, we do have the standard-time spelling,
  1714. # but that takes a bit of proof. We first prove a stronger result. What's the
  1715. # difference between the LHS and RHS of [5]? Let
  1716. #
  1717. # diff = x.n - (z.n - z.o) [6]
  1718. #
  1719. # Now
  1720. # z.n = by [4]
  1721. # (y + y.s).n = by #5
  1722. # y.n + y.s = since y.n = x.n
  1723. # x.n + y.s = since z and y are have the same tzinfo member,
  1724. # y.s = z.s by #2
  1725. # x.n + z.s
  1726. #
  1727. # Plugging that back into [6] gives
  1728. #
  1729. # diff =
  1730. # x.n - ((x.n + z.s) - z.o) = expanding
  1731. # x.n - x.n - z.s + z.o = cancelling
  1732. # - z.s + z.o = by #2
  1733. # z.d
  1734. #
  1735. # So diff = z.d.
  1736. #
  1737. # If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
  1738. # spelling we wanted in the endcase described above. We're done. Contrarily,
  1739. # if z.d = 0, then we have a UTC equivalent, and are also done.
  1740. #
  1741. # If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
  1742. # add to z (in effect, z is in tz's standard time, and we need to shift the
  1743. # local clock into tz's daylight time).
  1744. #
  1745. # Let
  1746. #
  1747. # z' = z + z.d = z + diff [7]
  1748. #
  1749. # and we can again ask whether
  1750. #
  1751. # z'.n - z'.o = x.n [8]
  1752. #
  1753. # If so, we're done. If not, the tzinfo class is insane, according to the
  1754. # assumptions we've made. This also requires a bit of proof. As before, let's
  1755. # compute the difference between the LHS and RHS of [8] (and skipping some of
  1756. # the justifications for the kinds of substitutions we've done several times
  1757. # already):
  1758. #
  1759. # diff' = x.n - (z'.n - z'.o) = replacing z'.n via [7]
  1760. # x.n - (z.n + diff - z'.o) = replacing diff via [6]
  1761. # x.n - (z.n + x.n - (z.n - z.o) - z'.o) =
  1762. # x.n - z.n - x.n + z.n - z.o + z'.o = cancel x.n
  1763. # - z.n + z.n - z.o + z'.o = cancel z.n
  1764. # - z.o + z'.o = #1 twice
  1765. # -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
  1766. # z'.d - z.d
  1767. #
  1768. # So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
  1769. # we've found the UTC-equivalent so are done. In fact, we stop with [7] and
  1770. # return z', not bothering to compute z'.d.
  1771. #
  1772. # How could z.d and z'd differ? z' = z + z.d [7], so merely moving z' by
  1773. # a dst() offset, and starting *from* a time already in DST (we know z.d != 0),
  1774. # would have to change the result dst() returns: we start in DST, and moving
  1775. # a little further into it takes us out of DST.
  1776. #
  1777. # There isn't a sane case where this can happen. The closest it gets is at
  1778. # the end of DST, where there's an hour in UTC with no spelling in a hybrid
  1779. # tzinfo class. In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT. During
  1780. # that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM
  1781. # UTC) because the docs insist on that, but 0:MM is taken as being in daylight
  1782. # time (4:MM UTC). There is no local time mapping to 5:MM UTC. The local
  1783. # clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in
  1784. # standard time. Since that's what the local clock *does*, we want to map both
  1785. # UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
  1786. # in local time, but so it goes -- it's the way the local clock works.
  1787. #
  1788. # When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
  1789. # so z=0:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
  1790. # z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
  1791. # (correctly) concludes that z' is not UTC-equivalent to x.
  1792. #
  1793. # Because we know z.d said z was in daylight time (else [5] would have held and
  1794. # we would have stopped then), and we know z.d != z'.d (else [8] would have held
  1795. # and we have stopped then), and there are only 2 possible values dst() can
  1796. # return in Eastern, it follows that z'.d must be 0 (which it is in the example,
  1797. # but the reasoning doesn't depend on the example -- it depends on there being
  1798. # two possible dst() outcomes, one zero and the other non-zero). Therefore
  1799. # z' must be in standard time, and is the spelling we want in this case.
  1800. #
  1801. # Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is
  1802. # concerned (because it takes z' as being in standard time rather than the
  1803. # daylight time we intend here), but returning it gives the real-life "local
  1804. # clock repeats an hour" behavior when mapping the "unspellable" UTC hour into
  1805. # tz.
  1806. #
  1807. # When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with
  1808. # the 1:MM standard time spelling we want.
  1809. #
  1810. # So how can this break? One of the assumptions must be violated. Two
  1811. # possibilities:
  1812. #
  1813. # 1) [2] effectively says that y.s is invariant across all y belong to a given
  1814. # time zone. This isn't true if, for political reasons or continental drift,
  1815. # a region decides to change its base offset from UTC.
  1816. #
  1817. # 2) There may be versions of "double daylight" time where the tail end of
  1818. # the analysis gives up a step too early. I haven't thought about that
  1819. # enough to say.
  1820. #
  1821. # In any case, it's clear that the default fromutc() is strong enough to handle
  1822. # "almost all" time zones: so long as the standard offset is invariant, it
  1823. # doesn't matter if daylight time transition points change from year to year, or
  1824. # if daylight time is skipped in some years; it doesn't matter how large or
  1825. # small dst() may get within its bounds; and it doesn't even matter if some
  1826. # perverse time zone returns a negative dst()). So a breaking case must be
  1827. # pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
  1828. try:
  1829. from _datetime import *
  1830. except ImportError:
  1831. pass
  1832. else:
  1833. # Clean up unused names
  1834. del (_DAYNAMES, _DAYS_BEFORE_MONTH, _DAYS_IN_MONTH, _DI100Y, _DI400Y,
  1835. _DI4Y, _EPOCH, _MAXORDINAL, _MONTHNAMES, _build_struct_time,
  1836. _check_date_fields, _check_int_field, _check_time_fields,
  1837. _check_tzinfo_arg, _check_tzname, _check_utc_offset, _cmp, _cmperror,
  1838. _date_class, _days_before_month, _days_before_year, _days_in_month,
  1839. _format_time, _is_leap, _isoweek1monday, _math, _ord2ymd,
  1840. _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord)
  1841. # XXX Since import * above excludes names that start with _,
  1842. # docstring does not get overwritten. In the future, it may be
  1843. # appropriate to maintain a single module level docstring and
  1844. # remove the following line.
  1845. from _datetime import __doc__