You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2108 lines
72 KiB

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