datetime.py 74 KB

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