blob: b734a743d0d19cc93a4868657f4cbb8e8c7c5010 [file] [log] [blame]
Ezio Melottif756f942013-04-13 20:12:38 +03001"""Concrete date/time and related types.
Alexander Belopolskycf86e362010-07-23 19:25:47 +00002
Ezio Melottif756f942013-04-13 20:12:38 +03003See http://www.iana.org/time-zones/repository/tz-link.html for
4time zone and DST data sources.
Alexander Belopolskycf86e362010-07-23 19:25:47 +00005"""
6
7import time as _time
8import math as _math
9
10def _cmp(x, y):
11 return 0 if x == y else 1 if x > y else -1
12
13MINYEAR = 1
14MAXYEAR = 9999
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -040015_MAXORDINAL = 3652059 # date.max.toordinal()
Alexander Belopolskycf86e362010-07-23 19:25:47 +000016
17# Utility functions, adapted from Python's Demo/classes/Dates.py, which
18# also assumes the current Gregorian calendar indefinitely extended in
19# both directions. Difference: Dates.py calls January 1 of year 0 day
20# number 1. The code here calls January 1 of year 1 day number 1. This is
21# to match the definition of the "proleptic Gregorian" calendar in Dershowitz
22# and Reingold's "Calendrical Calculations", where it's the base calendar
23# for all computations. See the book for algorithms for converting between
24# proleptic Gregorian ordinals and many other calendar systems.
25
Benjamin Petersonda0bea22013-08-29 17:29:30 -040026# -1 is a placeholder for indexing purposes.
Benjamin Petersonf908efb2013-08-29 17:27:57 -040027_DAYS_IN_MONTH = [-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
Alexander Belopolskycf86e362010-07-23 19:25:47 +000028
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -040029_DAYS_BEFORE_MONTH = [-1] # -1 is a placeholder for indexing purposes.
Alexander Belopolskycf86e362010-07-23 19:25:47 +000030dbm = 0
31for dim in _DAYS_IN_MONTH[1:]:
32 _DAYS_BEFORE_MONTH.append(dbm)
33 dbm += dim
34del dbm, dim
35
36def _is_leap(year):
37 "year -> 1 if leap year, else 0."
38 return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
39
40def _days_before_year(year):
41 "year -> number of days before January 1st of year."
42 y = year - 1
43 return y*365 + y//4 - y//100 + y//400
44
45def _days_in_month(year, month):
46 "year, month -> number of days in that month in that year."
47 assert 1 <= month <= 12, month
48 if month == 2 and _is_leap(year):
49 return 29
50 return _DAYS_IN_MONTH[month]
51
52def _days_before_month(year, month):
Ezio Melotti30b9d5d2013-08-17 15:50:46 +030053 "year, month -> number of days in year preceding first day of month."
Alexander Belopolskycf86e362010-07-23 19:25:47 +000054 assert 1 <= month <= 12, 'month must be in 1..12'
55 return _DAYS_BEFORE_MONTH[month] + (month > 2 and _is_leap(year))
56
57def _ymd2ord(year, month, day):
58 "year, month, day -> ordinal, considering 01-Jan-0001 as day 1."
59 assert 1 <= month <= 12, 'month must be in 1..12'
60 dim = _days_in_month(year, month)
61 assert 1 <= day <= dim, ('day must be in 1..%d' % dim)
62 return (_days_before_year(year) +
63 _days_before_month(year, month) +
64 day)
65
66_DI400Y = _days_before_year(401) # number of days in 400 years
67_DI100Y = _days_before_year(101) # " " " " 100 "
68_DI4Y = _days_before_year(5) # " " " " 4 "
69
70# A 4-year cycle has an extra leap day over what we'd get from pasting
71# together 4 single years.
72assert _DI4Y == 4 * 365 + 1
73
74# Similarly, a 400-year cycle has an extra leap day over what we'd get from
75# pasting together 4 100-year cycles.
76assert _DI400Y == 4 * _DI100Y + 1
77
78# OTOH, a 100-year cycle has one fewer leap day than we'd get from
79# pasting together 25 4-year cycles.
80assert _DI100Y == 25 * _DI4Y - 1
81
82def _ord2ymd(n):
83 "ordinal -> (year, month, day), considering 01-Jan-0001 as day 1."
84
85 # n is a 1-based index, starting at 1-Jan-1. The pattern of leap years
86 # repeats exactly every 400 years. The basic strategy is to find the
87 # closest 400-year boundary at or before n, then work with the offset
88 # from that boundary to n. Life is much clearer if we subtract 1 from
89 # n first -- then the values of n at 400-year boundaries are exactly
90 # those divisible by _DI400Y:
91 #
92 # D M Y n n-1
93 # -- --- ---- ---------- ----------------
94 # 31 Dec -400 -_DI400Y -_DI400Y -1
95 # 1 Jan -399 -_DI400Y +1 -_DI400Y 400-year boundary
96 # ...
97 # 30 Dec 000 -1 -2
98 # 31 Dec 000 0 -1
99 # 1 Jan 001 1 0 400-year boundary
100 # 2 Jan 001 2 1
101 # 3 Jan 001 3 2
102 # ...
103 # 31 Dec 400 _DI400Y _DI400Y -1
104 # 1 Jan 401 _DI400Y +1 _DI400Y 400-year boundary
105 n -= 1
106 n400, n = divmod(n, _DI400Y)
107 year = n400 * 400 + 1 # ..., -399, 1, 401, ...
108
109 # Now n is the (non-negative) offset, in days, from January 1 of year, to
110 # the desired date. Now compute how many 100-year cycles precede n.
111 # Note that it's possible for n100 to equal 4! In that case 4 full
112 # 100-year cycles precede the desired day, which implies the desired
113 # day is December 31 at the end of a 400-year cycle.
114 n100, n = divmod(n, _DI100Y)
115
116 # Now compute how many 4-year cycles precede it.
117 n4, n = divmod(n, _DI4Y)
118
119 # And now how many single years. Again n1 can be 4, and again meaning
120 # that the desired day is December 31 at the end of the 4-year cycle.
121 n1, n = divmod(n, 365)
122
123 year += n100 * 100 + n4 * 4 + n1
124 if n1 == 4 or n100 == 4:
125 assert n == 0
126 return year-1, 12, 31
127
128 # Now the year is correct, and n is the offset from January 1. We find
129 # the month via an estimate that's either exact or one too large.
130 leapyear = n1 == 3 and (n4 != 24 or n100 == 3)
131 assert leapyear == _is_leap(year)
132 month = (n + 50) >> 5
133 preceding = _DAYS_BEFORE_MONTH[month] + (month > 2 and leapyear)
134 if preceding > n: # estimate is too large
135 month -= 1
136 preceding -= _DAYS_IN_MONTH[month] + (month == 2 and leapyear)
137 n -= preceding
138 assert 0 <= n < _days_in_month(year, month)
139
140 # Now the year and month are correct, and n is the offset from the
141 # start of that month: we're done!
142 return year, month, n+1
143
144# Month and day names. For localized versions, see the calendar module.
145_MONTHNAMES = [None, "Jan", "Feb", "Mar", "Apr", "May", "Jun",
146 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
147_DAYNAMES = [None, "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
148
149
150def _build_struct_time(y, m, d, hh, mm, ss, dstflag):
151 wday = (_ymd2ord(y, m, d) + 6) % 7
152 dnum = _days_before_month(y, m) + d
153 return _time.struct_time((y, m, d, hh, mm, ss, wday, dnum, dstflag))
154
155def _format_time(hh, mm, ss, us):
156 # Skip trailing microseconds when us==0.
157 result = "%02d:%02d:%02d" % (hh, mm, ss)
158 if us:
159 result += ".%06d" % us
160 return result
161
162# Correctly substitute for %z and %Z escapes in strftime formats.
163def _wrap_strftime(object, format, timetuple):
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000164 # Don't call utcoffset() or tzname() unless actually needed.
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400165 freplace = None # the string to use for %f
166 zreplace = None # the string to use for %z
167 Zreplace = None # the string to use for %Z
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000168
169 # Scan format for %z and %Z escapes, replacing as needed.
170 newformat = []
171 push = newformat.append
172 i, n = 0, len(format)
173 while i < n:
174 ch = format[i]
175 i += 1
176 if ch == '%':
177 if i < n:
178 ch = format[i]
179 i += 1
180 if ch == 'f':
181 if freplace is None:
182 freplace = '%06d' % getattr(object,
183 'microsecond', 0)
184 newformat.append(freplace)
185 elif ch == 'z':
186 if zreplace is None:
187 zreplace = ""
188 if hasattr(object, "utcoffset"):
189 offset = object.utcoffset()
190 if offset is not None:
191 sign = '+'
192 if offset.days < 0:
193 offset = -offset
194 sign = '-'
195 h, m = divmod(offset, timedelta(hours=1))
196 assert not m % timedelta(minutes=1), "whole minute"
197 m //= timedelta(minutes=1)
198 zreplace = '%c%02d%02d' % (sign, h, m)
199 assert '%' not in zreplace
200 newformat.append(zreplace)
201 elif ch == 'Z':
202 if Zreplace is None:
203 Zreplace = ""
204 if hasattr(object, "tzname"):
205 s = object.tzname()
206 if s is not None:
207 # strftime is going to have at this: escape %
208 Zreplace = s.replace('%', '%%')
209 newformat.append(Zreplace)
210 else:
211 push('%')
212 push(ch)
213 else:
214 push('%')
215 else:
216 push(ch)
217 newformat = "".join(newformat)
218 return _time.strftime(newformat, timetuple)
219
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000220# Just raise TypeError if the arg isn't None or a string.
221def _check_tzname(name):
222 if name is not None and not isinstance(name, str):
223 raise TypeError("tzinfo.tzname() must return None or string, "
224 "not '%s'" % type(name))
225
226# name is the offset-producing method, "utcoffset" or "dst".
227# offset is what it returned.
228# If offset isn't None or timedelta, raises TypeError.
229# If offset is None, returns None.
230# Else offset is checked for being in range, and a whole # of minutes.
231# If it is, its integer value is returned. Else ValueError is raised.
232def _check_utc_offset(name, offset):
233 assert name in ("utcoffset", "dst")
234 if offset is None:
235 return
236 if not isinstance(offset, timedelta):
237 raise TypeError("tzinfo.%s() must return None "
238 "or timedelta, not '%s'" % (name, type(offset)))
239 if offset % timedelta(minutes=1) or offset.microseconds:
240 raise ValueError("tzinfo.%s() must return a whole number "
241 "of minutes, got %s" % (name, offset))
242 if not -timedelta(1) < offset < timedelta(1):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400243 raise ValueError("%s()=%s, must be must be strictly between "
244 "-timedelta(hours=24) and timedelta(hours=24)" %
245 (name, offset))
246
247def _check_int_field(value):
248 if isinstance(value, int):
249 return value
250 if not isinstance(value, float):
251 try:
252 value = value.__int__()
253 except AttributeError:
254 pass
255 else:
256 if isinstance(value, int):
257 return value
258 raise TypeError('__int__ returned non-int (type %s)' %
259 type(value).__name__)
260 raise TypeError('an integer is required (got type %s)' %
261 type(value).__name__)
262 raise TypeError('integer argument expected, got float')
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000263
264def _check_date_fields(year, month, day):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400265 year = _check_int_field(year)
266 month = _check_int_field(month)
267 day = _check_int_field(day)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000268 if not MINYEAR <= year <= MAXYEAR:
269 raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year)
270 if not 1 <= month <= 12:
271 raise ValueError('month must be in 1..12', month)
272 dim = _days_in_month(year, month)
273 if not 1 <= day <= dim:
274 raise ValueError('day must be in 1..%d' % dim, day)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400275 return year, month, day
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000276
277def _check_time_fields(hour, minute, second, microsecond):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400278 hour = _check_int_field(hour)
279 minute = _check_int_field(minute)
280 second = _check_int_field(second)
281 microsecond = _check_int_field(microsecond)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000282 if not 0 <= hour <= 23:
283 raise ValueError('hour must be in 0..23', hour)
284 if not 0 <= minute <= 59:
285 raise ValueError('minute must be in 0..59', minute)
286 if not 0 <= second <= 59:
287 raise ValueError('second must be in 0..59', second)
288 if not 0 <= microsecond <= 999999:
289 raise ValueError('microsecond must be in 0..999999', microsecond)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400290 return hour, minute, second, microsecond
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000291
292def _check_tzinfo_arg(tz):
293 if tz is not None and not isinstance(tz, tzinfo):
294 raise TypeError("tzinfo argument must be None or of a tzinfo subclass")
295
296def _cmperror(x, y):
297 raise TypeError("can't compare '%s' to '%s'" % (
298 type(x).__name__, type(y).__name__))
299
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500300def _divide_and_round(a, b):
301 """divide a by b and round result to the nearest integer
302
303 When the ratio is exactly half-way between two integers,
304 the even integer is returned.
305 """
306 # Based on the reference implementation for divmod_near
307 # in Objects/longobject.c.
308 q, r = divmod(a, b)
309 # round up if either r / b > 0.5, or r / b == 0.5 and q is odd.
310 # The expression r / b > 0.5 is equivalent to 2 * r > b if b is
311 # positive, 2 * r < b if b negative.
312 r *= 2
313 greater_than_half = r > b if b > 0 else r < b
314 if greater_than_half or r == b and q % 2 == 1:
315 q += 1
316
317 return q
318
Victor Stinner2ec55872015-09-02 19:16:07 +0200319
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000320class timedelta:
321 """Represent the difference between two datetime objects.
322
323 Supported operators:
324
325 - add, subtract timedelta
326 - unary plus, minus, abs
327 - compare to timedelta
Serhiy Storchaka95949422013-08-27 19:40:23 +0300328 - multiply, divide by int
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000329
330 In addition, datetime supports subtraction of two datetime objects
331 returning a timedelta, and addition or subtraction of a datetime
332 and a timedelta giving a datetime.
333
334 Representation: (days, seconds, microseconds). Why? Because I
335 felt like it.
336 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400337 __slots__ = '_days', '_seconds', '_microseconds', '_hashcode'
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000338
339 def __new__(cls, days=0, seconds=0, microseconds=0,
340 milliseconds=0, minutes=0, hours=0, weeks=0):
341 # Doing this efficiently and accurately in C is going to be difficult
342 # and error-prone, due to ubiquitous overflow possibilities, and that
343 # C double doesn't have enough bits of precision to represent
344 # microseconds over 10K years faithfully. The code here tries to make
345 # explicit where go-fast assumptions can be relied on, in order to
346 # guide the C implementation; it's way more convoluted than speed-
347 # ignoring auto-overflow-to-long idiomatic Python could be.
348
349 # XXX Check that all inputs are ints or floats.
350
351 # Final values, all integer.
352 # s and us fit in 32-bit signed ints; d isn't bounded.
353 d = s = us = 0
354
355 # Normalize everything to days, seconds, microseconds.
356 days += weeks*7
357 seconds += minutes*60 + hours*3600
358 microseconds += milliseconds*1000
359
360 # Get rid of all fractions, and normalize s and us.
361 # Take a deep breath <wink>.
362 if isinstance(days, float):
363 dayfrac, days = _math.modf(days)
364 daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.))
365 assert daysecondswhole == int(daysecondswhole) # can't overflow
366 s = int(daysecondswhole)
367 assert days == int(days)
368 d = int(days)
369 else:
370 daysecondsfrac = 0.0
371 d = days
372 assert isinstance(daysecondsfrac, float)
373 assert abs(daysecondsfrac) <= 1.0
374 assert isinstance(d, int)
375 assert abs(s) <= 24 * 3600
376 # days isn't referenced again before redefinition
377
378 if isinstance(seconds, float):
379 secondsfrac, seconds = _math.modf(seconds)
380 assert seconds == int(seconds)
381 seconds = int(seconds)
382 secondsfrac += daysecondsfrac
383 assert abs(secondsfrac) <= 2.0
384 else:
385 secondsfrac = daysecondsfrac
386 # daysecondsfrac isn't referenced again
387 assert isinstance(secondsfrac, float)
388 assert abs(secondsfrac) <= 2.0
389
390 assert isinstance(seconds, int)
391 days, seconds = divmod(seconds, 24*3600)
392 d += days
393 s += int(seconds) # can't overflow
394 assert isinstance(s, int)
395 assert abs(s) <= 2 * 24 * 3600
396 # seconds isn't referenced again before redefinition
397
398 usdouble = secondsfrac * 1e6
399 assert abs(usdouble) < 2.1e6 # exact value not critical
400 # secondsfrac isn't referenced again
401
402 if isinstance(microseconds, float):
Victor Stinner69cc4872015-09-08 23:58:54 +0200403 microseconds = round(microseconds + usdouble)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000404 seconds, microseconds = divmod(microseconds, 1000000)
405 days, seconds = divmod(seconds, 24*3600)
406 d += days
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400407 s += seconds
408 else:
409 microseconds = int(microseconds)
410 seconds, microseconds = divmod(microseconds, 1000000)
411 days, seconds = divmod(seconds, 24*3600)
412 d += days
413 s += seconds
Victor Stinner69cc4872015-09-08 23:58:54 +0200414 microseconds = round(microseconds + usdouble)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400415 assert isinstance(s, int)
416 assert isinstance(microseconds, int)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000417 assert abs(s) <= 3 * 24 * 3600
418 assert abs(microseconds) < 3.1e6
419
420 # Just a little bit of carrying possible for microseconds and seconds.
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400421 seconds, us = divmod(microseconds, 1000000)
422 s += seconds
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000423 days, s = divmod(s, 24*3600)
424 d += days
425
426 assert isinstance(d, int)
427 assert isinstance(s, int) and 0 <= s < 24*3600
428 assert isinstance(us, int) and 0 <= us < 1000000
429
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000430 if abs(d) > 999999999:
431 raise OverflowError("timedelta # of days is too large: %d" % d)
432
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400433 self = object.__new__(cls)
434 self._days = d
435 self._seconds = s
436 self._microseconds = us
437 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000438 return self
439
440 def __repr__(self):
441 if self._microseconds:
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300442 return "%s.%s(%d, %d, %d)" % (self.__class__.__module__,
443 self.__class__.__qualname__,
444 self._days,
445 self._seconds,
446 self._microseconds)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000447 if self._seconds:
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300448 return "%s.%s(%d, %d)" % (self.__class__.__module__,
449 self.__class__.__qualname__,
450 self._days,
451 self._seconds)
452 return "%s.%s(%d)" % (self.__class__.__module__,
453 self.__class__.__qualname__,
454 self._days)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000455
456 def __str__(self):
457 mm, ss = divmod(self._seconds, 60)
458 hh, mm = divmod(mm, 60)
459 s = "%d:%02d:%02d" % (hh, mm, ss)
460 if self._days:
461 def plural(n):
462 return n, abs(n) != 1 and "s" or ""
463 s = ("%d day%s, " % plural(self._days)) + s
464 if self._microseconds:
465 s = s + ".%06d" % self._microseconds
466 return s
467
468 def total_seconds(self):
469 """Total seconds in the duration."""
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400470 return ((self.days * 86400 + self.seconds) * 10**6 +
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000471 self.microseconds) / 10**6
472
473 # Read-only field accessors
474 @property
475 def days(self):
476 """days"""
477 return self._days
478
479 @property
480 def seconds(self):
481 """seconds"""
482 return self._seconds
483
484 @property
485 def microseconds(self):
486 """microseconds"""
487 return self._microseconds
488
489 def __add__(self, other):
490 if isinstance(other, timedelta):
491 # for CPython compatibility, we cannot use
492 # our __class__ here, but need a real timedelta
493 return timedelta(self._days + other._days,
494 self._seconds + other._seconds,
495 self._microseconds + other._microseconds)
496 return NotImplemented
497
498 __radd__ = __add__
499
500 def __sub__(self, other):
501 if isinstance(other, timedelta):
Alexander Belopolskyb6f5ec72011-04-05 20:07:38 -0400502 # for CPython compatibility, we cannot use
503 # our __class__ here, but need a real timedelta
504 return timedelta(self._days - other._days,
505 self._seconds - other._seconds,
506 self._microseconds - other._microseconds)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000507 return NotImplemented
508
509 def __rsub__(self, other):
510 if isinstance(other, timedelta):
511 return -self + other
512 return NotImplemented
513
514 def __neg__(self):
515 # for CPython compatibility, we cannot use
516 # our __class__ here, but need a real timedelta
517 return timedelta(-self._days,
518 -self._seconds,
519 -self._microseconds)
520
521 def __pos__(self):
522 return self
523
524 def __abs__(self):
525 if self._days < 0:
526 return -self
527 else:
528 return self
529
530 def __mul__(self, other):
531 if isinstance(other, int):
532 # for CPython compatibility, we cannot use
533 # our __class__ here, but need a real timedelta
534 return timedelta(self._days * other,
535 self._seconds * other,
536 self._microseconds * other)
537 if isinstance(other, float):
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500538 usec = self._to_microseconds()
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000539 a, b = other.as_integer_ratio()
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500540 return timedelta(0, 0, _divide_and_round(usec * a, b))
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000541 return NotImplemented
542
543 __rmul__ = __mul__
544
545 def _to_microseconds(self):
546 return ((self._days * (24*3600) + self._seconds) * 1000000 +
547 self._microseconds)
548
549 def __floordiv__(self, other):
550 if not isinstance(other, (int, timedelta)):
551 return NotImplemented
552 usec = self._to_microseconds()
553 if isinstance(other, timedelta):
554 return usec // other._to_microseconds()
555 if isinstance(other, int):
556 return timedelta(0, 0, usec // other)
557
558 def __truediv__(self, other):
559 if not isinstance(other, (int, float, timedelta)):
560 return NotImplemented
561 usec = self._to_microseconds()
562 if isinstance(other, timedelta):
563 return usec / other._to_microseconds()
564 if isinstance(other, int):
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500565 return timedelta(0, 0, _divide_and_round(usec, other))
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000566 if isinstance(other, float):
567 a, b = other.as_integer_ratio()
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500568 return timedelta(0, 0, _divide_and_round(b * usec, a))
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000569
570 def __mod__(self, other):
571 if isinstance(other, timedelta):
572 r = self._to_microseconds() % other._to_microseconds()
573 return timedelta(0, 0, r)
574 return NotImplemented
575
576 def __divmod__(self, other):
577 if isinstance(other, timedelta):
578 q, r = divmod(self._to_microseconds(),
579 other._to_microseconds())
580 return q, timedelta(0, 0, r)
581 return NotImplemented
582
583 # Comparisons of timedelta objects with other.
584
585 def __eq__(self, other):
586 if isinstance(other, timedelta):
587 return self._cmp(other) == 0
588 else:
589 return False
590
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000591 def __le__(self, other):
592 if isinstance(other, timedelta):
593 return self._cmp(other) <= 0
594 else:
595 _cmperror(self, other)
596
597 def __lt__(self, other):
598 if isinstance(other, timedelta):
599 return self._cmp(other) < 0
600 else:
601 _cmperror(self, other)
602
603 def __ge__(self, other):
604 if isinstance(other, timedelta):
605 return self._cmp(other) >= 0
606 else:
607 _cmperror(self, other)
608
609 def __gt__(self, other):
610 if isinstance(other, timedelta):
611 return self._cmp(other) > 0
612 else:
613 _cmperror(self, other)
614
615 def _cmp(self, other):
616 assert isinstance(other, timedelta)
617 return _cmp(self._getstate(), other._getstate())
618
619 def __hash__(self):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400620 if self._hashcode == -1:
621 self._hashcode = hash(self._getstate())
622 return self._hashcode
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000623
624 def __bool__(self):
625 return (self._days != 0 or
626 self._seconds != 0 or
627 self._microseconds != 0)
628
629 # Pickle support.
630
631 def _getstate(self):
632 return (self._days, self._seconds, self._microseconds)
633
634 def __reduce__(self):
635 return (self.__class__, self._getstate())
636
637timedelta.min = timedelta(-999999999)
638timedelta.max = timedelta(days=999999999, hours=23, minutes=59, seconds=59,
639 microseconds=999999)
640timedelta.resolution = timedelta(microseconds=1)
641
642class date:
643 """Concrete date type.
644
645 Constructors:
646
647 __new__()
648 fromtimestamp()
649 today()
650 fromordinal()
651
652 Operators:
653
654 __repr__, __str__
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200655 __eq__, __le__, __lt__, __ge__, __gt__, __hash__
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000656 __add__, __radd__, __sub__ (add/radd only with timedelta arg)
657
658 Methods:
659
660 timetuple()
661 toordinal()
662 weekday()
663 isoweekday(), isocalendar(), isoformat()
664 ctime()
665 strftime()
666
667 Properties (readonly):
668 year, month, day
669 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400670 __slots__ = '_year', '_month', '_day', '_hashcode'
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000671
672 def __new__(cls, year, month=None, day=None):
673 """Constructor.
674
675 Arguments:
676
677 year, month, day (required, base 1)
678 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400679 if month is None and isinstance(year, bytes) and len(year) == 4 and \
680 1 <= year[2] <= 12:
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000681 # Pickle support
682 self = object.__new__(cls)
683 self.__setstate(year)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400684 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000685 return self
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400686 year, month, day = _check_date_fields(year, month, day)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000687 self = object.__new__(cls)
688 self._year = year
689 self._month = month
690 self._day = day
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400691 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000692 return self
693
694 # Additional constructors
695
696 @classmethod
697 def fromtimestamp(cls, t):
698 "Construct a date from a POSIX timestamp (like time.time())."
699 y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
700 return cls(y, m, d)
701
702 @classmethod
703 def today(cls):
704 "Construct a date from time.time()."
705 t = _time.time()
706 return cls.fromtimestamp(t)
707
708 @classmethod
709 def fromordinal(cls, n):
710 """Contruct a date from a proleptic Gregorian ordinal.
711
712 January 1 of year 1 is day 1. Only the year, month and day are
713 non-zero in the result.
714 """
715 y, m, d = _ord2ymd(n)
716 return cls(y, m, d)
717
718 # Conversions to string
719
720 def __repr__(self):
721 """Convert to formal string, for repr().
722
723 >>> dt = datetime(2010, 1, 1)
724 >>> repr(dt)
725 'datetime.datetime(2010, 1, 1, 0, 0)'
726
727 >>> dt = datetime(2010, 1, 1, tzinfo=timezone.utc)
728 >>> repr(dt)
729 'datetime.datetime(2010, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)'
730 """
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300731 return "%s.%s(%d, %d, %d)" % (self.__class__.__module__,
732 self.__class__.__qualname__,
733 self._year,
734 self._month,
735 self._day)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000736 # XXX These shouldn't depend on time.localtime(), because that
737 # clips the usable dates to [1970 .. 2038). At least ctime() is
738 # easily done without using strftime() -- that's better too because
739 # strftime("%c", ...) is locale specific.
740
741
742 def ctime(self):
743 "Return ctime() style string."
744 weekday = self.toordinal() % 7 or 7
745 return "%s %s %2d 00:00:00 %04d" % (
746 _DAYNAMES[weekday],
747 _MONTHNAMES[self._month],
748 self._day, self._year)
749
750 def strftime(self, fmt):
751 "Format using strftime()."
752 return _wrap_strftime(self, fmt, self.timetuple())
753
754 def __format__(self, fmt):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400755 if not isinstance(fmt, str):
756 raise TypeError("must be str, not %s" % type(fmt).__name__)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000757 if len(fmt) != 0:
758 return self.strftime(fmt)
759 return str(self)
760
761 def isoformat(self):
762 """Return the date formatted according to ISO.
763
764 This is 'YYYY-MM-DD'.
765
766 References:
767 - http://www.w3.org/TR/NOTE-datetime
768 - http://www.cl.cam.ac.uk/~mgk25/iso-time.html
769 """
770 return "%04d-%02d-%02d" % (self._year, self._month, self._day)
771
772 __str__ = isoformat
773
774 # Read-only field accessors
775 @property
776 def year(self):
777 """year (1-9999)"""
778 return self._year
779
780 @property
781 def month(self):
782 """month (1-12)"""
783 return self._month
784
785 @property
786 def day(self):
787 """day (1-31)"""
788 return self._day
789
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200790 # Standard conversions, __eq__, __le__, __lt__, __ge__, __gt__,
791 # __hash__ (and helpers)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000792
793 def timetuple(self):
794 "Return local time tuple compatible with time.localtime()."
795 return _build_struct_time(self._year, self._month, self._day,
796 0, 0, 0, -1)
797
798 def toordinal(self):
799 """Return proleptic Gregorian ordinal for the year, month and day.
800
801 January 1 of year 1 is day 1. Only the year, month and day values
802 contribute to the result.
803 """
804 return _ymd2ord(self._year, self._month, self._day)
805
806 def replace(self, year=None, month=None, day=None):
807 """Return a new date with new values for the specified fields."""
808 if year is None:
809 year = self._year
810 if month is None:
811 month = self._month
812 if day is None:
813 day = self._day
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000814 return date(year, month, day)
815
816 # Comparisons of date objects with other.
817
818 def __eq__(self, other):
819 if isinstance(other, date):
820 return self._cmp(other) == 0
821 return NotImplemented
822
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000823 def __le__(self, other):
824 if isinstance(other, date):
825 return self._cmp(other) <= 0
826 return NotImplemented
827
828 def __lt__(self, other):
829 if isinstance(other, date):
830 return self._cmp(other) < 0
831 return NotImplemented
832
833 def __ge__(self, other):
834 if isinstance(other, date):
835 return self._cmp(other) >= 0
836 return NotImplemented
837
838 def __gt__(self, other):
839 if isinstance(other, date):
840 return self._cmp(other) > 0
841 return NotImplemented
842
843 def _cmp(self, other):
844 assert isinstance(other, date)
845 y, m, d = self._year, self._month, self._day
846 y2, m2, d2 = other._year, other._month, other._day
847 return _cmp((y, m, d), (y2, m2, d2))
848
849 def __hash__(self):
850 "Hash."
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400851 if self._hashcode == -1:
852 self._hashcode = hash(self._getstate())
853 return self._hashcode
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000854
855 # Computations
856
857 def __add__(self, other):
858 "Add a date to a timedelta."
859 if isinstance(other, timedelta):
860 o = self.toordinal() + other.days
861 if 0 < o <= _MAXORDINAL:
862 return date.fromordinal(o)
863 raise OverflowError("result out of range")
864 return NotImplemented
865
866 __radd__ = __add__
867
868 def __sub__(self, other):
869 """Subtract two dates, or a date and a timedelta."""
870 if isinstance(other, timedelta):
871 return self + timedelta(-other.days)
872 if isinstance(other, date):
873 days1 = self.toordinal()
874 days2 = other.toordinal()
875 return timedelta(days1 - days2)
876 return NotImplemented
877
878 def weekday(self):
879 "Return day of the week, where Monday == 0 ... Sunday == 6."
880 return (self.toordinal() + 6) % 7
881
882 # Day-of-the-week and week-of-the-year, according to ISO
883
884 def isoweekday(self):
885 "Return day of the week, where Monday == 1 ... Sunday == 7."
886 # 1-Jan-0001 is a Monday
887 return self.toordinal() % 7 or 7
888
889 def isocalendar(self):
890 """Return a 3-tuple containing ISO year, week number, and weekday.
891
892 The first ISO week of the year is the (Mon-Sun) week
893 containing the year's first Thursday; everything else derives
894 from that.
895
896 The first week is 1; Monday is 1 ... Sunday is 7.
897
898 ISO calendar algorithm taken from
899 http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
900 """
901 year = self._year
902 week1monday = _isoweek1monday(year)
903 today = _ymd2ord(self._year, self._month, self._day)
904 # Internally, week and day have origin 0
905 week, day = divmod(today - week1monday, 7)
906 if week < 0:
907 year -= 1
908 week1monday = _isoweek1monday(year)
909 week, day = divmod(today - week1monday, 7)
910 elif week >= 52:
911 if today >= _isoweek1monday(year+1):
912 year += 1
913 week = 0
914 return year, week+1, day+1
915
916 # Pickle support.
917
918 def _getstate(self):
919 yhi, ylo = divmod(self._year, 256)
920 return bytes([yhi, ylo, self._month, self._day]),
921
922 def __setstate(self, string):
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000923 yhi, ylo, self._month, self._day = string
924 self._year = yhi * 256 + ylo
925
926 def __reduce__(self):
927 return (self.__class__, self._getstate())
928
929_date_class = date # so functions w/ args named "date" can get at the class
930
931date.min = date(1, 1, 1)
932date.max = date(9999, 12, 31)
933date.resolution = timedelta(days=1)
934
935class tzinfo:
936 """Abstract base class for time zone info classes.
937
938 Subclasses must override the name(), utcoffset() and dst() methods.
939 """
940 __slots__ = ()
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400941
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000942 def tzname(self, dt):
943 "datetime -> string name of time zone."
944 raise NotImplementedError("tzinfo subclass must override tzname()")
945
946 def utcoffset(self, dt):
947 "datetime -> minutes east of UTC (negative for west of UTC)"
948 raise NotImplementedError("tzinfo subclass must override utcoffset()")
949
950 def dst(self, dt):
951 """datetime -> DST offset in minutes east of UTC.
952
953 Return 0 if DST not in effect. utcoffset() must include the DST
954 offset.
955 """
956 raise NotImplementedError("tzinfo subclass must override dst()")
957
958 def fromutc(self, dt):
959 "datetime in UTC -> datetime in local time."
960
961 if not isinstance(dt, datetime):
962 raise TypeError("fromutc() requires a datetime argument")
963 if dt.tzinfo is not self:
964 raise ValueError("dt.tzinfo is not self")
965
966 dtoff = dt.utcoffset()
967 if dtoff is None:
968 raise ValueError("fromutc() requires a non-None utcoffset() "
969 "result")
970
971 # See the long comment block at the end of this file for an
972 # explanation of this algorithm.
973 dtdst = dt.dst()
974 if dtdst is None:
975 raise ValueError("fromutc() requires a non-None dst() result")
976 delta = dtoff - dtdst
977 if delta:
978 dt += delta
979 dtdst = dt.dst()
980 if dtdst is None:
981 raise ValueError("fromutc(): dt.dst gave inconsistent "
982 "results; cannot convert")
983 return dt + dtdst
984
985 # Pickle support.
986
987 def __reduce__(self):
988 getinitargs = getattr(self, "__getinitargs__", None)
989 if getinitargs:
990 args = getinitargs()
991 else:
992 args = ()
993 getstate = getattr(self, "__getstate__", None)
994 if getstate:
995 state = getstate()
996 else:
997 state = getattr(self, "__dict__", None) or None
998 if state is None:
999 return (self.__class__, args)
1000 else:
1001 return (self.__class__, args, state)
1002
1003_tzinfo_class = tzinfo
1004
1005class time:
1006 """Time with time zone.
1007
1008 Constructors:
1009
1010 __new__()
1011
1012 Operators:
1013
1014 __repr__, __str__
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001015 __eq__, __le__, __lt__, __ge__, __gt__, __hash__
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001016
1017 Methods:
1018
1019 strftime()
1020 isoformat()
1021 utcoffset()
1022 tzname()
1023 dst()
1024
1025 Properties (readonly):
1026 hour, minute, second, microsecond, tzinfo
1027 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001028 __slots__ = '_hour', '_minute', '_second', '_microsecond', '_tzinfo', '_hashcode'
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001029
1030 def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None):
1031 """Constructor.
1032
1033 Arguments:
1034
1035 hour, minute (required)
1036 second, microsecond (default to zero)
1037 tzinfo (default to None)
1038 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001039 if isinstance(hour, bytes) and len(hour) == 6 and hour[0] < 24:
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001040 # Pickle support
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001041 self = object.__new__(cls)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001042 self.__setstate(hour, minute or None)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001043 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001044 return self
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001045 hour, minute, second, microsecond = _check_time_fields(
1046 hour, minute, second, microsecond)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001047 _check_tzinfo_arg(tzinfo)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001048 self = object.__new__(cls)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001049 self._hour = hour
1050 self._minute = minute
1051 self._second = second
1052 self._microsecond = microsecond
1053 self._tzinfo = tzinfo
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001054 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001055 return self
1056
1057 # Read-only field accessors
1058 @property
1059 def hour(self):
1060 """hour (0-23)"""
1061 return self._hour
1062
1063 @property
1064 def minute(self):
1065 """minute (0-59)"""
1066 return self._minute
1067
1068 @property
1069 def second(self):
1070 """second (0-59)"""
1071 return self._second
1072
1073 @property
1074 def microsecond(self):
1075 """microsecond (0-999999)"""
1076 return self._microsecond
1077
1078 @property
1079 def tzinfo(self):
1080 """timezone info object"""
1081 return self._tzinfo
1082
1083 # Standard conversions, __hash__ (and helpers)
1084
1085 # Comparisons of time objects with other.
1086
1087 def __eq__(self, other):
1088 if isinstance(other, time):
Alexander Belopolsky08313822012-06-15 20:19:47 -04001089 return self._cmp(other, allow_mixed=True) == 0
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001090 else:
1091 return False
1092
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001093 def __le__(self, other):
1094 if isinstance(other, time):
1095 return self._cmp(other) <= 0
1096 else:
1097 _cmperror(self, other)
1098
1099 def __lt__(self, other):
1100 if isinstance(other, time):
1101 return self._cmp(other) < 0
1102 else:
1103 _cmperror(self, other)
1104
1105 def __ge__(self, other):
1106 if isinstance(other, time):
1107 return self._cmp(other) >= 0
1108 else:
1109 _cmperror(self, other)
1110
1111 def __gt__(self, other):
1112 if isinstance(other, time):
1113 return self._cmp(other) > 0
1114 else:
1115 _cmperror(self, other)
1116
Alexander Belopolsky08313822012-06-15 20:19:47 -04001117 def _cmp(self, other, allow_mixed=False):
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001118 assert isinstance(other, time)
1119 mytz = self._tzinfo
1120 ottz = other._tzinfo
1121 myoff = otoff = None
1122
1123 if mytz is ottz:
1124 base_compare = True
1125 else:
1126 myoff = self.utcoffset()
1127 otoff = other.utcoffset()
1128 base_compare = myoff == otoff
1129
1130 if base_compare:
1131 return _cmp((self._hour, self._minute, self._second,
1132 self._microsecond),
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001133 (other._hour, other._minute, other._second,
1134 other._microsecond))
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001135 if myoff is None or otoff is None:
Alexander Belopolsky08313822012-06-15 20:19:47 -04001136 if allow_mixed:
1137 return 2 # arbitrary non-zero value
1138 else:
1139 raise TypeError("cannot compare naive and aware times")
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001140 myhhmm = self._hour * 60 + self._minute - myoff//timedelta(minutes=1)
1141 othhmm = other._hour * 60 + other._minute - otoff//timedelta(minutes=1)
1142 return _cmp((myhhmm, self._second, self._microsecond),
1143 (othhmm, other._second, other._microsecond))
1144
1145 def __hash__(self):
1146 """Hash."""
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001147 if self._hashcode == -1:
1148 tzoff = self.utcoffset()
1149 if not tzoff: # zero or None
1150 self._hashcode = hash(self._getstate()[0])
1151 else:
1152 h, m = divmod(timedelta(hours=self.hour, minutes=self.minute) - tzoff,
1153 timedelta(hours=1))
1154 assert not m % timedelta(minutes=1), "whole minute"
1155 m //= timedelta(minutes=1)
1156 if 0 <= h < 24:
1157 self._hashcode = hash(time(h, m, self.second, self.microsecond))
1158 else:
1159 self._hashcode = hash((h, m, self.second, self.microsecond))
1160 return self._hashcode
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001161
1162 # Conversion to string
1163
1164 def _tzstr(self, sep=":"):
1165 """Return formatted timezone offset (+xx:xx) or None."""
1166 off = self.utcoffset()
1167 if off is not None:
1168 if off.days < 0:
1169 sign = "-"
1170 off = -off
1171 else:
1172 sign = "+"
1173 hh, mm = divmod(off, timedelta(hours=1))
1174 assert not mm % timedelta(minutes=1), "whole minute"
1175 mm //= timedelta(minutes=1)
1176 assert 0 <= hh < 24
1177 off = "%s%02d%s%02d" % (sign, hh, sep, mm)
1178 return off
1179
1180 def __repr__(self):
1181 """Convert to formal string, for repr()."""
1182 if self._microsecond != 0:
1183 s = ", %d, %d" % (self._second, self._microsecond)
1184 elif self._second != 0:
1185 s = ", %d" % self._second
1186 else:
1187 s = ""
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001188 s= "%s.%s(%d, %d%s)" % (self.__class__.__module__,
1189 self.__class__.__qualname__,
1190 self._hour, self._minute, s)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001191 if self._tzinfo is not None:
1192 assert s[-1:] == ")"
1193 s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
1194 return s
1195
1196 def isoformat(self):
1197 """Return the time formatted according to ISO.
1198
1199 This is 'HH:MM:SS.mmmmmm+zz:zz', or 'HH:MM:SS+zz:zz' if
1200 self.microsecond == 0.
1201 """
1202 s = _format_time(self._hour, self._minute, self._second,
1203 self._microsecond)
1204 tz = self._tzstr()
1205 if tz:
1206 s += tz
1207 return s
1208
1209 __str__ = isoformat
1210
1211 def strftime(self, fmt):
1212 """Format using strftime(). The date part of the timestamp passed
1213 to underlying strftime should not be used.
1214 """
Alexander Belopolskyb8bb4662011-01-08 00:13:34 +00001215 # The year must be >= 1000 else Python's strftime implementation
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001216 # can raise a bogus exception.
1217 timetuple = (1900, 1, 1,
1218 self._hour, self._minute, self._second,
1219 0, 1, -1)
1220 return _wrap_strftime(self, fmt, timetuple)
1221
1222 def __format__(self, fmt):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001223 if not isinstance(fmt, str):
1224 raise TypeError("must be str, not %s" % type(fmt).__name__)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001225 if len(fmt) != 0:
1226 return self.strftime(fmt)
1227 return str(self)
1228
1229 # Timezone functions
1230
1231 def utcoffset(self):
1232 """Return the timezone offset in minutes east of UTC (negative west of
1233 UTC)."""
1234 if self._tzinfo is None:
1235 return None
1236 offset = self._tzinfo.utcoffset(None)
1237 _check_utc_offset("utcoffset", offset)
1238 return offset
1239
1240 def tzname(self):
1241 """Return the timezone name.
1242
1243 Note that the name is 100% informational -- there's no requirement that
1244 it mean anything in particular. For example, "GMT", "UTC", "-500",
1245 "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
1246 """
1247 if self._tzinfo is None:
1248 return None
1249 name = self._tzinfo.tzname(None)
1250 _check_tzname(name)
1251 return name
1252
1253 def dst(self):
1254 """Return 0 if DST is not in effect, or the DST offset (in minutes
1255 eastward) if DST is in effect.
1256
1257 This is purely informational; the DST offset has already been added to
1258 the UTC offset returned by utcoffset() if applicable, so there's no
1259 need to consult dst() unless you're interested in displaying the DST
1260 info.
1261 """
1262 if self._tzinfo is None:
1263 return None
1264 offset = self._tzinfo.dst(None)
1265 _check_utc_offset("dst", offset)
1266 return offset
1267
1268 def replace(self, hour=None, minute=None, second=None, microsecond=None,
1269 tzinfo=True):
1270 """Return a new time with new values for the specified fields."""
1271 if hour is None:
1272 hour = self.hour
1273 if minute is None:
1274 minute = self.minute
1275 if second is None:
1276 second = self.second
1277 if microsecond is None:
1278 microsecond = self.microsecond
1279 if tzinfo is True:
1280 tzinfo = self.tzinfo
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001281 return time(hour, minute, second, microsecond, tzinfo)
1282
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001283 # Pickle support.
1284
1285 def _getstate(self):
1286 us2, us3 = divmod(self._microsecond, 256)
1287 us1, us2 = divmod(us2, 256)
1288 basestate = bytes([self._hour, self._minute, self._second,
1289 us1, us2, us3])
1290 if self._tzinfo is None:
1291 return (basestate,)
1292 else:
1293 return (basestate, self._tzinfo)
1294
1295 def __setstate(self, string, tzinfo):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001296 if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
1297 raise TypeError("bad tzinfo state arg")
1298 self._hour, self._minute, self._second, us1, us2, us3 = string
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001299 self._microsecond = (((us1 << 8) | us2) << 8) | us3
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001300 self._tzinfo = tzinfo
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001301
1302 def __reduce__(self):
1303 return (time, self._getstate())
1304
1305_time_class = time # so functions w/ args named "time" can get at the class
1306
1307time.min = time(0, 0, 0)
1308time.max = time(23, 59, 59, 999999)
1309time.resolution = timedelta(microseconds=1)
1310
1311class datetime(date):
1312 """datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
1313
1314 The year, month and day arguments are required. tzinfo may be None, or an
Serhiy Storchaka95949422013-08-27 19:40:23 +03001315 instance of a tzinfo subclass. The remaining arguments may be ints.
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001316 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001317 __slots__ = date.__slots__ + time.__slots__
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001318
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001319 def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
1320 microsecond=0, tzinfo=None):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001321 if isinstance(year, bytes) and len(year) == 10 and 1 <= year[2] <= 12:
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001322 # Pickle support
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001323 self = object.__new__(cls)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001324 self.__setstate(year, month)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001325 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001326 return self
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001327 year, month, day = _check_date_fields(year, month, day)
1328 hour, minute, second, microsecond = _check_time_fields(
1329 hour, minute, second, microsecond)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001330 _check_tzinfo_arg(tzinfo)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001331 self = object.__new__(cls)
1332 self._year = year
1333 self._month = month
1334 self._day = day
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001335 self._hour = hour
1336 self._minute = minute
1337 self._second = second
1338 self._microsecond = microsecond
1339 self._tzinfo = tzinfo
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001340 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001341 return self
1342
1343 # Read-only field accessors
1344 @property
1345 def hour(self):
1346 """hour (0-23)"""
1347 return self._hour
1348
1349 @property
1350 def minute(self):
1351 """minute (0-59)"""
1352 return self._minute
1353
1354 @property
1355 def second(self):
1356 """second (0-59)"""
1357 return self._second
1358
1359 @property
1360 def microsecond(self):
1361 """microsecond (0-999999)"""
1362 return self._microsecond
1363
1364 @property
1365 def tzinfo(self):
1366 """timezone info object"""
1367 return self._tzinfo
1368
1369 @classmethod
Victor Stinneradfefa52015-09-04 23:57:25 +02001370 def _fromtimestamp(cls, t, utc, tz):
1371 """Construct a datetime from a POSIX timestamp (like time.time()).
1372
1373 A timezone info object may be passed in as well.
1374 """
1375 frac, t = _math.modf(t)
Victor Stinner7667f582015-09-09 01:02:23 +02001376 us = round(frac * 1e6)
Victor Stinneradfefa52015-09-04 23:57:25 +02001377 if us >= 1000000:
1378 t += 1
1379 us -= 1000000
1380 elif us < 0:
1381 t -= 1
1382 us += 1000000
1383
1384 converter = _time.gmtime if utc else _time.localtime
1385 y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
1386 ss = min(ss, 59) # clamp out leap seconds if the platform has them
1387 return cls(y, m, d, hh, mm, ss, us, tz)
1388
1389 @classmethod
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001390 def fromtimestamp(cls, t, tz=None):
1391 """Construct a datetime from a POSIX timestamp (like time.time()).
1392
1393 A timezone info object may be passed in as well.
1394 """
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001395 _check_tzinfo_arg(tz)
Alexander Belopolskyaeb03982010-07-26 02:36:41 +00001396
Victor Stinneradfefa52015-09-04 23:57:25 +02001397 result = cls._fromtimestamp(t, tz is not None, tz)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001398 if tz is not None:
1399 result = tz.fromutc(result)
1400 return result
1401
1402 @classmethod
1403 def utcfromtimestamp(cls, t):
Alexander Belopolskye2e178e2015-03-01 14:52:07 -05001404 """Construct a naive UTC datetime from a POSIX timestamp."""
Victor Stinneradfefa52015-09-04 23:57:25 +02001405 return cls._fromtimestamp(t, True, None)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001406
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001407 @classmethod
1408 def now(cls, tz=None):
1409 "Construct a datetime from time.time() and optional time zone info."
1410 t = _time.time()
1411 return cls.fromtimestamp(t, tz)
1412
1413 @classmethod
1414 def utcnow(cls):
1415 "Construct a UTC datetime from time.time()."
1416 t = _time.time()
1417 return cls.utcfromtimestamp(t)
1418
1419 @classmethod
1420 def combine(cls, date, time):
1421 "Construct a datetime from a given date and a given time."
1422 if not isinstance(date, _date_class):
1423 raise TypeError("date argument must be a date instance")
1424 if not isinstance(time, _time_class):
1425 raise TypeError("time argument must be a time instance")
1426 return cls(date.year, date.month, date.day,
1427 time.hour, time.minute, time.second, time.microsecond,
1428 time.tzinfo)
1429
1430 def timetuple(self):
1431 "Return local time tuple compatible with time.localtime()."
1432 dst = self.dst()
1433 if dst is None:
1434 dst = -1
1435 elif dst:
1436 dst = 1
1437 else:
1438 dst = 0
1439 return _build_struct_time(self.year, self.month, self.day,
1440 self.hour, self.minute, self.second,
1441 dst)
1442
Alexander Belopolskya4415142012-06-08 12:33:09 -04001443 def timestamp(self):
1444 "Return POSIX timestamp as float"
1445 if self._tzinfo is None:
1446 return _time.mktime((self.year, self.month, self.day,
1447 self.hour, self.minute, self.second,
1448 -1, -1, -1)) + self.microsecond / 1e6
1449 else:
1450 return (self - _EPOCH).total_seconds()
1451
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001452 def utctimetuple(self):
1453 "Return UTC time tuple compatible with time.gmtime()."
1454 offset = self.utcoffset()
1455 if offset:
1456 self -= offset
1457 y, m, d = self.year, self.month, self.day
1458 hh, mm, ss = self.hour, self.minute, self.second
1459 return _build_struct_time(y, m, d, hh, mm, ss, 0)
1460
1461 def date(self):
1462 "Return the date part."
1463 return date(self._year, self._month, self._day)
1464
1465 def time(self):
1466 "Return the time part, with tzinfo None."
1467 return time(self.hour, self.minute, self.second, self.microsecond)
1468
1469 def timetz(self):
1470 "Return the time part, with same tzinfo."
1471 return time(self.hour, self.minute, self.second, self.microsecond,
1472 self._tzinfo)
1473
1474 def replace(self, year=None, month=None, day=None, hour=None,
1475 minute=None, second=None, microsecond=None, tzinfo=True):
1476 """Return a new datetime with new values for the specified fields."""
1477 if year is None:
1478 year = self.year
1479 if month is None:
1480 month = self.month
1481 if day is None:
1482 day = self.day
1483 if hour is None:
1484 hour = self.hour
1485 if minute is None:
1486 minute = self.minute
1487 if second is None:
1488 second = self.second
1489 if microsecond is None:
1490 microsecond = self.microsecond
1491 if tzinfo is True:
1492 tzinfo = self.tzinfo
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001493 return datetime(year, month, day, hour, minute, second, microsecond,
1494 tzinfo)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001495
Alexander Belopolskyfdc860f2012-06-22 12:23:23 -04001496 def astimezone(self, tz=None):
1497 if tz is None:
1498 if self.tzinfo is None:
1499 raise ValueError("astimezone() requires an aware datetime")
1500 ts = (self - _EPOCH) // timedelta(seconds=1)
1501 localtm = _time.localtime(ts)
1502 local = datetime(*localtm[:6])
1503 try:
Alexander Belopolskyff493c92012-06-22 12:25:57 -04001504 # Extract TZ data if available
Alexander Belopolskyfdc860f2012-06-22 12:23:23 -04001505 gmtoff = localtm.tm_gmtoff
1506 zone = localtm.tm_zone
1507 except AttributeError:
1508 # Compute UTC offset and compare with the value implied
1509 # by tm_isdst. If the values match, use the zone name
1510 # implied by tm_isdst.
1511 delta = local - datetime(*_time.gmtime(ts)[:6])
1512 dst = _time.daylight and localtm.tm_isdst > 0
Alexander Belopolsky93c9cd02012-06-22 16:04:19 -04001513 gmtoff = -(_time.altzone if dst else _time.timezone)
1514 if delta == timedelta(seconds=gmtoff):
Alexander Belopolskyfdc860f2012-06-22 12:23:23 -04001515 tz = timezone(delta, _time.tzname[dst])
1516 else:
1517 tz = timezone(delta)
1518 else:
Alexander Belopolsky93c9cd02012-06-22 16:04:19 -04001519 tz = timezone(timedelta(seconds=gmtoff), zone)
Alexander Belopolskyff493c92012-06-22 12:25:57 -04001520
Alexander Belopolskyfdc860f2012-06-22 12:23:23 -04001521 elif not isinstance(tz, tzinfo):
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001522 raise TypeError("tz argument must be an instance of tzinfo")
1523
1524 mytz = self.tzinfo
1525 if mytz is None:
1526 raise ValueError("astimezone() requires an aware datetime")
1527
1528 if tz is mytz:
1529 return self
1530
1531 # Convert self to UTC, and attach the new time zone object.
1532 myoffset = self.utcoffset()
1533 if myoffset is None:
1534 raise ValueError("astimezone() requires an aware datetime")
1535 utc = (self - myoffset).replace(tzinfo=tz)
1536
1537 # Convert from UTC to tz's local time.
1538 return tz.fromutc(utc)
1539
1540 # Ways to produce a string.
1541
1542 def ctime(self):
1543 "Return ctime() style string."
1544 weekday = self.toordinal() % 7 or 7
1545 return "%s %s %2d %02d:%02d:%02d %04d" % (
1546 _DAYNAMES[weekday],
1547 _MONTHNAMES[self._month],
1548 self._day,
1549 self._hour, self._minute, self._second,
1550 self._year)
1551
1552 def isoformat(self, sep='T'):
1553 """Return the time formatted according to ISO.
1554
1555 This is 'YYYY-MM-DD HH:MM:SS.mmmmmm', or 'YYYY-MM-DD HH:MM:SS' if
1556 self.microsecond == 0.
1557
1558 If self.tzinfo is not None, the UTC offset is also attached, giving
1559 'YYYY-MM-DD HH:MM:SS.mmmmmm+HH:MM' or 'YYYY-MM-DD HH:MM:SS+HH:MM'.
1560
1561 Optional argument sep specifies the separator between date and
1562 time, default 'T'.
1563 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001564 s = ("%04d-%02d-%02d%c" % (self._year, self._month, self._day, sep) +
1565 _format_time(self._hour, self._minute, self._second,
1566 self._microsecond))
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001567 off = self.utcoffset()
1568 if off is not None:
1569 if off.days < 0:
1570 sign = "-"
1571 off = -off
1572 else:
1573 sign = "+"
1574 hh, mm = divmod(off, timedelta(hours=1))
1575 assert not mm % timedelta(minutes=1), "whole minute"
1576 mm //= timedelta(minutes=1)
1577 s += "%s%02d:%02d" % (sign, hh, mm)
1578 return s
1579
1580 def __repr__(self):
1581 """Convert to formal string, for repr()."""
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001582 L = [self._year, self._month, self._day, # These are never zero
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001583 self._hour, self._minute, self._second, self._microsecond]
1584 if L[-1] == 0:
1585 del L[-1]
1586 if L[-1] == 0:
1587 del L[-1]
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001588 s = "%s.%s(%s)" % (self.__class__.__module__,
1589 self.__class__.__qualname__,
1590 ", ".join(map(str, L)))
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001591 if self._tzinfo is not None:
1592 assert s[-1:] == ")"
1593 s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
1594 return s
1595
1596 def __str__(self):
1597 "Convert to string, for str()."
1598 return self.isoformat(sep=' ')
1599
1600 @classmethod
1601 def strptime(cls, date_string, format):
1602 'string, format -> new datetime parsed from a string (like time.strptime()).'
1603 import _strptime
1604 return _strptime._strptime_datetime(cls, date_string, format)
1605
1606 def utcoffset(self):
1607 """Return the timezone offset in minutes east of UTC (negative west of
1608 UTC)."""
1609 if self._tzinfo is None:
1610 return None
1611 offset = self._tzinfo.utcoffset(self)
1612 _check_utc_offset("utcoffset", offset)
1613 return offset
1614
1615 def tzname(self):
1616 """Return the timezone name.
1617
1618 Note that the name is 100% informational -- there's no requirement that
1619 it mean anything in particular. For example, "GMT", "UTC", "-500",
1620 "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
1621 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001622 if self._tzinfo is None:
1623 return None
1624 name = self._tzinfo.tzname(self)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001625 _check_tzname(name)
1626 return name
1627
1628 def dst(self):
1629 """Return 0 if DST is not in effect, or the DST offset (in minutes
1630 eastward) if DST is in effect.
1631
1632 This is purely informational; the DST offset has already been added to
1633 the UTC offset returned by utcoffset() if applicable, so there's no
1634 need to consult dst() unless you're interested in displaying the DST
1635 info.
1636 """
1637 if self._tzinfo is None:
1638 return None
1639 offset = self._tzinfo.dst(self)
1640 _check_utc_offset("dst", offset)
1641 return offset
1642
1643 # Comparisons of datetime objects with other.
1644
1645 def __eq__(self, other):
1646 if isinstance(other, datetime):
Alexander Belopolsky08313822012-06-15 20:19:47 -04001647 return self._cmp(other, allow_mixed=True) == 0
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001648 elif not isinstance(other, date):
1649 return NotImplemented
1650 else:
1651 return False
1652
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001653 def __le__(self, other):
1654 if isinstance(other, datetime):
1655 return self._cmp(other) <= 0
1656 elif not isinstance(other, date):
1657 return NotImplemented
1658 else:
1659 _cmperror(self, other)
1660
1661 def __lt__(self, other):
1662 if isinstance(other, datetime):
1663 return self._cmp(other) < 0
1664 elif not isinstance(other, date):
1665 return NotImplemented
1666 else:
1667 _cmperror(self, other)
1668
1669 def __ge__(self, other):
1670 if isinstance(other, datetime):
1671 return self._cmp(other) >= 0
1672 elif not isinstance(other, date):
1673 return NotImplemented
1674 else:
1675 _cmperror(self, other)
1676
1677 def __gt__(self, other):
1678 if isinstance(other, datetime):
1679 return self._cmp(other) > 0
1680 elif not isinstance(other, date):
1681 return NotImplemented
1682 else:
1683 _cmperror(self, other)
1684
Alexander Belopolsky08313822012-06-15 20:19:47 -04001685 def _cmp(self, other, allow_mixed=False):
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001686 assert isinstance(other, datetime)
1687 mytz = self._tzinfo
1688 ottz = other._tzinfo
1689 myoff = otoff = None
1690
1691 if mytz is ottz:
1692 base_compare = True
1693 else:
Alexander Belopolsky016ef552012-06-15 18:15:25 -04001694 myoff = self.utcoffset()
1695 otoff = other.utcoffset()
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001696 base_compare = myoff == otoff
1697
1698 if base_compare:
1699 return _cmp((self._year, self._month, self._day,
1700 self._hour, self._minute, self._second,
1701 self._microsecond),
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001702 (other._year, other._month, other._day,
1703 other._hour, other._minute, other._second,
1704 other._microsecond))
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001705 if myoff is None or otoff is None:
Alexander Belopolsky08313822012-06-15 20:19:47 -04001706 if allow_mixed:
1707 return 2 # arbitrary non-zero value
1708 else:
1709 raise TypeError("cannot compare naive and aware datetimes")
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001710 # XXX What follows could be done more efficiently...
1711 diff = self - other # this will take offsets into account
1712 if diff.days < 0:
1713 return -1
1714 return diff and 1 or 0
1715
1716 def __add__(self, other):
1717 "Add a datetime and a timedelta."
1718 if not isinstance(other, timedelta):
1719 return NotImplemented
1720 delta = timedelta(self.toordinal(),
1721 hours=self._hour,
1722 minutes=self._minute,
1723 seconds=self._second,
1724 microseconds=self._microsecond)
1725 delta += other
1726 hour, rem = divmod(delta.seconds, 3600)
1727 minute, second = divmod(rem, 60)
1728 if 0 < delta.days <= _MAXORDINAL:
1729 return datetime.combine(date.fromordinal(delta.days),
1730 time(hour, minute, second,
1731 delta.microseconds,
1732 tzinfo=self._tzinfo))
1733 raise OverflowError("result out of range")
1734
1735 __radd__ = __add__
1736
1737 def __sub__(self, other):
1738 "Subtract two datetimes, or a datetime and a timedelta."
1739 if not isinstance(other, datetime):
1740 if isinstance(other, timedelta):
1741 return self + -other
1742 return NotImplemented
1743
1744 days1 = self.toordinal()
1745 days2 = other.toordinal()
1746 secs1 = self._second + self._minute * 60 + self._hour * 3600
1747 secs2 = other._second + other._minute * 60 + other._hour * 3600
1748 base = timedelta(days1 - days2,
1749 secs1 - secs2,
1750 self._microsecond - other._microsecond)
1751 if self._tzinfo is other._tzinfo:
1752 return base
1753 myoff = self.utcoffset()
1754 otoff = other.utcoffset()
1755 if myoff == otoff:
1756 return base
1757 if myoff is None or otoff is None:
1758 raise TypeError("cannot mix naive and timezone-aware time")
1759 return base + otoff - myoff
1760
1761 def __hash__(self):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001762 if self._hashcode == -1:
1763 tzoff = self.utcoffset()
1764 if tzoff is None:
1765 self._hashcode = hash(self._getstate()[0])
1766 else:
1767 days = _ymd2ord(self.year, self.month, self.day)
1768 seconds = self.hour * 3600 + self.minute * 60 + self.second
1769 self._hashcode = hash(timedelta(days, seconds, self.microsecond) - tzoff)
1770 return self._hashcode
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001771
1772 # Pickle support.
1773
1774 def _getstate(self):
1775 yhi, ylo = divmod(self._year, 256)
1776 us2, us3 = divmod(self._microsecond, 256)
1777 us1, us2 = divmod(us2, 256)
1778 basestate = bytes([yhi, ylo, self._month, self._day,
1779 self._hour, self._minute, self._second,
1780 us1, us2, us3])
1781 if self._tzinfo is None:
1782 return (basestate,)
1783 else:
1784 return (basestate, self._tzinfo)
1785
1786 def __setstate(self, string, tzinfo):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001787 if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
1788 raise TypeError("bad tzinfo state arg")
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001789 (yhi, ylo, self._month, self._day, self._hour,
1790 self._minute, self._second, us1, us2, us3) = string
1791 self._year = yhi * 256 + ylo
1792 self._microsecond = (((us1 << 8) | us2) << 8) | us3
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001793 self._tzinfo = tzinfo
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001794
1795 def __reduce__(self):
1796 return (self.__class__, self._getstate())
1797
1798
1799datetime.min = datetime(1, 1, 1)
1800datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999)
1801datetime.resolution = timedelta(microseconds=1)
1802
1803
1804def _isoweek1monday(year):
1805 # Helper to calculate the day number of the Monday starting week 1
1806 # XXX This could be done more efficiently
1807 THURSDAY = 3
1808 firstday = _ymd2ord(year, 1, 1)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001809 firstweekday = (firstday + 6) % 7 # See weekday() above
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001810 week1monday = firstday - firstweekday
1811 if firstweekday > THURSDAY:
1812 week1monday += 7
1813 return week1monday
1814
1815class timezone(tzinfo):
1816 __slots__ = '_offset', '_name'
1817
1818 # Sentinel value to disallow None
1819 _Omitted = object()
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001820 def __new__(cls, offset, name=_Omitted):
1821 if not isinstance(offset, timedelta):
1822 raise TypeError("offset must be a timedelta")
1823 if name is cls._Omitted:
1824 if not offset:
1825 return cls.utc
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001826 name = None
1827 elif not isinstance(name, str):
1828 raise TypeError("name must be a string")
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001829 if not cls._minoffset <= offset <= cls._maxoffset:
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001830 raise ValueError("offset must be a timedelta "
1831 "strictly between -timedelta(hours=24) and "
1832 "timedelta(hours=24).")
1833 if (offset.microseconds != 0 or offset.seconds % 60 != 0):
1834 raise ValueError("offset must be a timedelta "
1835 "representing a whole number of minutes")
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001836 return cls._create(offset, name)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001837
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001838 @classmethod
1839 def _create(cls, offset, name=None):
1840 self = tzinfo.__new__(cls)
1841 self._offset = offset
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001842 self._name = name
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001843 return self
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001844
1845 def __getinitargs__(self):
1846 """pickle support"""
1847 if self._name is None:
1848 return (self._offset,)
1849 return (self._offset, self._name)
1850
1851 def __eq__(self, other):
Georg Brandl0085a242012-09-22 09:23:12 +02001852 if type(other) != timezone:
1853 return False
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001854 return self._offset == other._offset
1855
1856 def __hash__(self):
1857 return hash(self._offset)
1858
1859 def __repr__(self):
1860 """Convert to formal string, for repr().
1861
1862 >>> tz = timezone.utc
1863 >>> repr(tz)
1864 'datetime.timezone.utc'
1865 >>> tz = timezone(timedelta(hours=-5), 'EST')
1866 >>> repr(tz)
1867 "datetime.timezone(datetime.timedelta(-1, 68400), 'EST')"
1868 """
1869 if self is self.utc:
1870 return 'datetime.timezone.utc'
1871 if self._name is None:
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001872 return "%s.%s(%r)" % (self.__class__.__module__,
1873 self.__class__.__qualname__,
1874 self._offset)
1875 return "%s.%s(%r, %r)" % (self.__class__.__module__,
1876 self.__class__.__qualname__,
1877 self._offset, self._name)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001878
1879 def __str__(self):
1880 return self.tzname(None)
1881
1882 def utcoffset(self, dt):
1883 if isinstance(dt, datetime) or dt is None:
1884 return self._offset
1885 raise TypeError("utcoffset() argument must be a datetime instance"
1886 " or None")
1887
1888 def tzname(self, dt):
1889 if isinstance(dt, datetime) or dt is None:
1890 if self._name is None:
1891 return self._name_from_offset(self._offset)
1892 return self._name
1893 raise TypeError("tzname() argument must be a datetime instance"
1894 " or None")
1895
1896 def dst(self, dt):
1897 if isinstance(dt, datetime) or dt is None:
1898 return None
1899 raise TypeError("dst() argument must be a datetime instance"
1900 " or None")
1901
1902 def fromutc(self, dt):
1903 if isinstance(dt, datetime):
1904 if dt.tzinfo is not self:
1905 raise ValueError("fromutc: dt.tzinfo "
1906 "is not self")
1907 return dt + self._offset
1908 raise TypeError("fromutc() argument must be a datetime instance"
1909 " or None")
1910
1911 _maxoffset = timedelta(hours=23, minutes=59)
1912 _minoffset = -_maxoffset
1913
1914 @staticmethod
1915 def _name_from_offset(delta):
Alexander Belopolsky7827a5b2015-09-06 13:07:21 -04001916 if not delta:
1917 return 'UTC'
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001918 if delta < timedelta(0):
1919 sign = '-'
1920 delta = -delta
1921 else:
1922 sign = '+'
1923 hours, rest = divmod(delta, timedelta(hours=1))
1924 minutes = rest // timedelta(minutes=1)
1925 return 'UTC{}{:02d}:{:02d}'.format(sign, hours, minutes)
1926
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001927timezone.utc = timezone._create(timedelta(0))
1928timezone.min = timezone._create(timezone._minoffset)
1929timezone.max = timezone._create(timezone._maxoffset)
Alexander Belopolskya4415142012-06-08 12:33:09 -04001930_EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001931
Victor Stinner765531d2013-03-26 01:11:54 +01001932# Some time zone algebra. For a datetime x, let
1933# x.n = x stripped of its timezone -- its naive time.
1934# x.o = x.utcoffset(), and assuming that doesn't raise an exception or
1935# return None
1936# x.d = x.dst(), and assuming that doesn't raise an exception or
1937# return None
1938# x.s = x's standard offset, x.o - x.d
1939#
1940# Now some derived rules, where k is a duration (timedelta).
1941#
1942# 1. x.o = x.s + x.d
1943# This follows from the definition of x.s.
1944#
1945# 2. If x and y have the same tzinfo member, x.s = y.s.
1946# This is actually a requirement, an assumption we need to make about
1947# sane tzinfo classes.
1948#
1949# 3. The naive UTC time corresponding to x is x.n - x.o.
1950# This is again a requirement for a sane tzinfo class.
1951#
1952# 4. (x+k).s = x.s
1953# This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
1954#
1955# 5. (x+k).n = x.n + k
1956# Again follows from how arithmetic is defined.
1957#
1958# Now we can explain tz.fromutc(x). Let's assume it's an interesting case
1959# (meaning that the various tzinfo methods exist, and don't blow up or return
1960# None when called).
1961#
1962# The function wants to return a datetime y with timezone tz, equivalent to x.
1963# x is already in UTC.
1964#
1965# By #3, we want
1966#
1967# y.n - y.o = x.n [1]
1968#
1969# The algorithm starts by attaching tz to x.n, and calling that y. So
1970# x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
1971# becomes true; in effect, we want to solve [2] for k:
1972#
1973# (y+k).n - (y+k).o = x.n [2]
1974#
1975# By #1, this is the same as
1976#
1977# (y+k).n - ((y+k).s + (y+k).d) = x.n [3]
1978#
1979# By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
1980# Substituting that into [3],
1981#
1982# x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving
1983# k - (y+k).s - (y+k).d = 0; rearranging,
1984# k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so
1985# k = y.s - (y+k).d
1986#
1987# On the RHS, (y+k).d can't be computed directly, but y.s can be, and we
1988# approximate k by ignoring the (y+k).d term at first. Note that k can't be
1989# very large, since all offset-returning methods return a duration of magnitude
1990# less than 24 hours. For that reason, if y is firmly in std time, (y+k).d must
1991# be 0, so ignoring it has no consequence then.
1992#
1993# In any case, the new value is
1994#
1995# z = y + y.s [4]
1996#
1997# It's helpful to step back at look at [4] from a higher level: it's simply
1998# mapping from UTC to tz's standard time.
1999#
2000# At this point, if
2001#
2002# z.n - z.o = x.n [5]
2003#
2004# we have an equivalent time, and are almost done. The insecurity here is
2005# at the start of daylight time. Picture US Eastern for concreteness. The wall
2006# time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
2007# sense then. The docs ask that an Eastern tzinfo class consider such a time to
2008# be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST
2009# on the day DST starts. We want to return the 1:MM EST spelling because that's
2010# the only spelling that makes sense on the local wall clock.
2011#
2012# In fact, if [5] holds at this point, we do have the standard-time spelling,
2013# but that takes a bit of proof. We first prove a stronger result. What's the
2014# difference between the LHS and RHS of [5]? Let
2015#
2016# diff = x.n - (z.n - z.o) [6]
2017#
2018# Now
2019# z.n = by [4]
2020# (y + y.s).n = by #5
2021# y.n + y.s = since y.n = x.n
2022# x.n + y.s = since z and y are have the same tzinfo member,
2023# y.s = z.s by #2
2024# x.n + z.s
2025#
2026# Plugging that back into [6] gives
2027#
2028# diff =
2029# x.n - ((x.n + z.s) - z.o) = expanding
2030# x.n - x.n - z.s + z.o = cancelling
2031# - z.s + z.o = by #2
2032# z.d
2033#
2034# So diff = z.d.
2035#
2036# If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
2037# spelling we wanted in the endcase described above. We're done. Contrarily,
2038# if z.d = 0, then we have a UTC equivalent, and are also done.
2039#
2040# If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
2041# add to z (in effect, z is in tz's standard time, and we need to shift the
2042# local clock into tz's daylight time).
2043#
2044# Let
2045#
2046# z' = z + z.d = z + diff [7]
2047#
2048# and we can again ask whether
2049#
2050# z'.n - z'.o = x.n [8]
2051#
2052# If so, we're done. If not, the tzinfo class is insane, according to the
2053# assumptions we've made. This also requires a bit of proof. As before, let's
2054# compute the difference between the LHS and RHS of [8] (and skipping some of
2055# the justifications for the kinds of substitutions we've done several times
2056# already):
2057#
2058# diff' = x.n - (z'.n - z'.o) = replacing z'.n via [7]
2059# x.n - (z.n + diff - z'.o) = replacing diff via [6]
2060# x.n - (z.n + x.n - (z.n - z.o) - z'.o) =
2061# x.n - z.n - x.n + z.n - z.o + z'.o = cancel x.n
2062# - z.n + z.n - z.o + z'.o = cancel z.n
2063# - z.o + z'.o = #1 twice
2064# -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
2065# z'.d - z.d
2066#
2067# So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
2068# we've found the UTC-equivalent so are done. In fact, we stop with [7] and
2069# return z', not bothering to compute z'.d.
2070#
2071# How could z.d and z'd differ? z' = z + z.d [7], so merely moving z' by
2072# a dst() offset, and starting *from* a time already in DST (we know z.d != 0),
2073# would have to change the result dst() returns: we start in DST, and moving
2074# a little further into it takes us out of DST.
2075#
2076# There isn't a sane case where this can happen. The closest it gets is at
2077# the end of DST, where there's an hour in UTC with no spelling in a hybrid
2078# tzinfo class. In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT. During
2079# that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM
2080# UTC) because the docs insist on that, but 0:MM is taken as being in daylight
2081# time (4:MM UTC). There is no local time mapping to 5:MM UTC. The local
2082# clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in
2083# standard time. Since that's what the local clock *does*, we want to map both
2084# UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
2085# in local time, but so it goes -- it's the way the local clock works.
2086#
2087# When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
2088# so z=0:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
2089# z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
2090# (correctly) concludes that z' is not UTC-equivalent to x.
2091#
2092# Because we know z.d said z was in daylight time (else [5] would have held and
2093# we would have stopped then), and we know z.d != z'.d (else [8] would have held
2094# and we have stopped then), and there are only 2 possible values dst() can
2095# return in Eastern, it follows that z'.d must be 0 (which it is in the example,
2096# but the reasoning doesn't depend on the example -- it depends on there being
2097# two possible dst() outcomes, one zero and the other non-zero). Therefore
2098# z' must be in standard time, and is the spelling we want in this case.
2099#
2100# Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is
2101# concerned (because it takes z' as being in standard time rather than the
2102# daylight time we intend here), but returning it gives the real-life "local
2103# clock repeats an hour" behavior when mapping the "unspellable" UTC hour into
2104# tz.
2105#
2106# When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with
2107# the 1:MM standard time spelling we want.
2108#
2109# So how can this break? One of the assumptions must be violated. Two
2110# possibilities:
2111#
2112# 1) [2] effectively says that y.s is invariant across all y belong to a given
2113# time zone. This isn't true if, for political reasons or continental drift,
2114# a region decides to change its base offset from UTC.
2115#
2116# 2) There may be versions of "double daylight" time where the tail end of
2117# the analysis gives up a step too early. I haven't thought about that
2118# enough to say.
2119#
2120# In any case, it's clear that the default fromutc() is strong enough to handle
2121# "almost all" time zones: so long as the standard offset is invariant, it
2122# doesn't matter if daylight time transition points change from year to year, or
2123# if daylight time is skipped in some years; it doesn't matter how large or
2124# small dst() may get within its bounds; and it doesn't even matter if some
2125# perverse time zone returns a negative dst()). So a breaking case must be
2126# pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
Alexander Belopolskycf86e362010-07-23 19:25:47 +00002127
Alexander Belopolskycf86e362010-07-23 19:25:47 +00002128try:
2129 from _datetime import *
Brett Cannoncd171c82013-07-04 17:43:24 -04002130except ImportError:
Alexander Belopolskycf86e362010-07-23 19:25:47 +00002131 pass
2132else:
2133 # Clean up unused names
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04002134 del (_DAYNAMES, _DAYS_BEFORE_MONTH, _DAYS_IN_MONTH, _DI100Y, _DI400Y,
2135 _DI4Y, _EPOCH, _MAXORDINAL, _MONTHNAMES, _build_struct_time,
2136 _check_date_fields, _check_int_field, _check_time_fields,
2137 _check_tzinfo_arg, _check_tzname, _check_utc_offset, _cmp, _cmperror,
2138 _date_class, _days_before_month, _days_before_year, _days_in_month,
2139 _format_time, _is_leap, _isoweek1monday, _math, _ord2ymd,
2140 _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord)
Alexander Belopolskya5658742010-07-23 20:03:53 +00002141 # XXX Since import * above excludes names that start with _,
2142 # docstring does not get overwritten. In the future, it may be
2143 # appropriate to maintain a single module level docstring and
2144 # remove the following line.
2145 from _datetime import __doc__