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.

2148 lines
74 KiB

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