blob: d4b7fc45d5bcc60a59ad49b87390cc3d22792e4c [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
Alexander Belopolskya2998a62016-03-06 14:58:43 -0500155def _format_time(hh, mm, ss, us, timespec='auto'):
156 specs = {
157 'hours': '{:02d}',
158 'minutes': '{:02d}:{:02d}',
159 'seconds': '{:02d}:{:02d}:{:02d}',
160 'milliseconds': '{:02d}:{:02d}:{:02d}.{:03d}',
161 'microseconds': '{:02d}:{:02d}:{:02d}.{:06d}'
162 }
163
164 if timespec == 'auto':
165 # Skip trailing microseconds when us==0.
166 timespec = 'microseconds' if us else 'seconds'
167 elif timespec == 'milliseconds':
168 us //= 1000
169 try:
170 fmt = specs[timespec]
171 except KeyError:
172 raise ValueError('Unknown timespec value')
173 else:
174 return fmt.format(hh, mm, ss, us)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000175
176# Correctly substitute for %z and %Z escapes in strftime formats.
177def _wrap_strftime(object, format, timetuple):
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000178 # Don't call utcoffset() or tzname() unless actually needed.
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400179 freplace = None # the string to use for %f
180 zreplace = None # the string to use for %z
181 Zreplace = None # the string to use for %Z
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000182
183 # Scan format for %z and %Z escapes, replacing as needed.
184 newformat = []
185 push = newformat.append
186 i, n = 0, len(format)
187 while i < n:
188 ch = format[i]
189 i += 1
190 if ch == '%':
191 if i < n:
192 ch = format[i]
193 i += 1
194 if ch == 'f':
195 if freplace is None:
196 freplace = '%06d' % getattr(object,
197 'microsecond', 0)
198 newformat.append(freplace)
199 elif ch == 'z':
200 if zreplace is None:
201 zreplace = ""
202 if hasattr(object, "utcoffset"):
203 offset = object.utcoffset()
204 if offset is not None:
205 sign = '+'
206 if offset.days < 0:
207 offset = -offset
208 sign = '-'
209 h, m = divmod(offset, timedelta(hours=1))
210 assert not m % timedelta(minutes=1), "whole minute"
211 m //= timedelta(minutes=1)
212 zreplace = '%c%02d%02d' % (sign, h, m)
213 assert '%' not in zreplace
214 newformat.append(zreplace)
215 elif ch == 'Z':
216 if Zreplace is None:
217 Zreplace = ""
218 if hasattr(object, "tzname"):
219 s = object.tzname()
220 if s is not None:
221 # strftime is going to have at this: escape %
222 Zreplace = s.replace('%', '%%')
223 newformat.append(Zreplace)
224 else:
225 push('%')
226 push(ch)
227 else:
228 push('%')
229 else:
230 push(ch)
231 newformat = "".join(newformat)
232 return _time.strftime(newformat, timetuple)
233
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000234# Just raise TypeError if the arg isn't None or a string.
235def _check_tzname(name):
236 if name is not None and not isinstance(name, str):
237 raise TypeError("tzinfo.tzname() must return None or string, "
238 "not '%s'" % type(name))
239
240# name is the offset-producing method, "utcoffset" or "dst".
241# offset is what it returned.
242# If offset isn't None or timedelta, raises TypeError.
243# If offset is None, returns None.
244# Else offset is checked for being in range, and a whole # of minutes.
245# If it is, its integer value is returned. Else ValueError is raised.
246def _check_utc_offset(name, offset):
247 assert name in ("utcoffset", "dst")
248 if offset is None:
249 return
250 if not isinstance(offset, timedelta):
251 raise TypeError("tzinfo.%s() must return None "
252 "or timedelta, not '%s'" % (name, type(offset)))
253 if offset % timedelta(minutes=1) or offset.microseconds:
254 raise ValueError("tzinfo.%s() must return a whole number "
255 "of minutes, got %s" % (name, offset))
256 if not -timedelta(1) < offset < timedelta(1):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400257 raise ValueError("%s()=%s, must be must be strictly between "
258 "-timedelta(hours=24) and timedelta(hours=24)" %
259 (name, offset))
260
261def _check_int_field(value):
262 if isinstance(value, int):
263 return value
264 if not isinstance(value, float):
265 try:
266 value = value.__int__()
267 except AttributeError:
268 pass
269 else:
270 if isinstance(value, int):
271 return value
272 raise TypeError('__int__ returned non-int (type %s)' %
273 type(value).__name__)
274 raise TypeError('an integer is required (got type %s)' %
275 type(value).__name__)
276 raise TypeError('integer argument expected, got float')
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000277
278def _check_date_fields(year, month, day):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400279 year = _check_int_field(year)
280 month = _check_int_field(month)
281 day = _check_int_field(day)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000282 if not MINYEAR <= year <= MAXYEAR:
283 raise ValueError('year must be in %d..%d' % (MINYEAR, MAXYEAR), year)
284 if not 1 <= month <= 12:
285 raise ValueError('month must be in 1..12', month)
286 dim = _days_in_month(year, month)
287 if not 1 <= day <= dim:
288 raise ValueError('day must be in 1..%d' % dim, day)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400289 return year, month, day
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000290
291def _check_time_fields(hour, minute, second, microsecond):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400292 hour = _check_int_field(hour)
293 minute = _check_int_field(minute)
294 second = _check_int_field(second)
295 microsecond = _check_int_field(microsecond)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000296 if not 0 <= hour <= 23:
297 raise ValueError('hour must be in 0..23', hour)
298 if not 0 <= minute <= 59:
299 raise ValueError('minute must be in 0..59', minute)
300 if not 0 <= second <= 59:
301 raise ValueError('second must be in 0..59', second)
302 if not 0 <= microsecond <= 999999:
303 raise ValueError('microsecond must be in 0..999999', microsecond)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400304 return hour, minute, second, microsecond
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000305
306def _check_tzinfo_arg(tz):
307 if tz is not None and not isinstance(tz, tzinfo):
308 raise TypeError("tzinfo argument must be None or of a tzinfo subclass")
309
310def _cmperror(x, y):
311 raise TypeError("can't compare '%s' to '%s'" % (
312 type(x).__name__, type(y).__name__))
313
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500314def _divide_and_round(a, b):
315 """divide a by b and round result to the nearest integer
316
317 When the ratio is exactly half-way between two integers,
318 the even integer is returned.
319 """
320 # Based on the reference implementation for divmod_near
321 # in Objects/longobject.c.
322 q, r = divmod(a, b)
323 # round up if either r / b > 0.5, or r / b == 0.5 and q is odd.
324 # The expression r / b > 0.5 is equivalent to 2 * r > b if b is
325 # positive, 2 * r < b if b negative.
326 r *= 2
327 greater_than_half = r > b if b > 0 else r < b
328 if greater_than_half or r == b and q % 2 == 1:
329 q += 1
330
331 return q
332
Victor Stinner2ec55872015-09-02 19:16:07 +0200333
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000334class timedelta:
335 """Represent the difference between two datetime objects.
336
337 Supported operators:
338
339 - add, subtract timedelta
340 - unary plus, minus, abs
341 - compare to timedelta
Serhiy Storchaka95949422013-08-27 19:40:23 +0300342 - multiply, divide by int
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000343
344 In addition, datetime supports subtraction of two datetime objects
345 returning a timedelta, and addition or subtraction of a datetime
346 and a timedelta giving a datetime.
347
348 Representation: (days, seconds, microseconds). Why? Because I
349 felt like it.
350 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400351 __slots__ = '_days', '_seconds', '_microseconds', '_hashcode'
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000352
353 def __new__(cls, days=0, seconds=0, microseconds=0,
354 milliseconds=0, minutes=0, hours=0, weeks=0):
355 # Doing this efficiently and accurately in C is going to be difficult
356 # and error-prone, due to ubiquitous overflow possibilities, and that
357 # C double doesn't have enough bits of precision to represent
358 # microseconds over 10K years faithfully. The code here tries to make
359 # explicit where go-fast assumptions can be relied on, in order to
360 # guide the C implementation; it's way more convoluted than speed-
361 # ignoring auto-overflow-to-long idiomatic Python could be.
362
363 # XXX Check that all inputs are ints or floats.
364
365 # Final values, all integer.
366 # s and us fit in 32-bit signed ints; d isn't bounded.
367 d = s = us = 0
368
369 # Normalize everything to days, seconds, microseconds.
370 days += weeks*7
371 seconds += minutes*60 + hours*3600
372 microseconds += milliseconds*1000
373
374 # Get rid of all fractions, and normalize s and us.
375 # Take a deep breath <wink>.
376 if isinstance(days, float):
377 dayfrac, days = _math.modf(days)
378 daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.))
379 assert daysecondswhole == int(daysecondswhole) # can't overflow
380 s = int(daysecondswhole)
381 assert days == int(days)
382 d = int(days)
383 else:
384 daysecondsfrac = 0.0
385 d = days
386 assert isinstance(daysecondsfrac, float)
387 assert abs(daysecondsfrac) <= 1.0
388 assert isinstance(d, int)
389 assert abs(s) <= 24 * 3600
390 # days isn't referenced again before redefinition
391
392 if isinstance(seconds, float):
393 secondsfrac, seconds = _math.modf(seconds)
394 assert seconds == int(seconds)
395 seconds = int(seconds)
396 secondsfrac += daysecondsfrac
397 assert abs(secondsfrac) <= 2.0
398 else:
399 secondsfrac = daysecondsfrac
400 # daysecondsfrac isn't referenced again
401 assert isinstance(secondsfrac, float)
402 assert abs(secondsfrac) <= 2.0
403
404 assert isinstance(seconds, int)
405 days, seconds = divmod(seconds, 24*3600)
406 d += days
407 s += int(seconds) # can't overflow
408 assert isinstance(s, int)
409 assert abs(s) <= 2 * 24 * 3600
410 # seconds isn't referenced again before redefinition
411
412 usdouble = secondsfrac * 1e6
413 assert abs(usdouble) < 2.1e6 # exact value not critical
414 # secondsfrac isn't referenced again
415
416 if isinstance(microseconds, float):
Victor Stinner69cc4872015-09-08 23:58:54 +0200417 microseconds = round(microseconds + usdouble)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000418 seconds, microseconds = divmod(microseconds, 1000000)
419 days, seconds = divmod(seconds, 24*3600)
420 d += days
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400421 s += seconds
422 else:
423 microseconds = int(microseconds)
424 seconds, microseconds = divmod(microseconds, 1000000)
425 days, seconds = divmod(seconds, 24*3600)
426 d += days
427 s += seconds
Victor Stinner69cc4872015-09-08 23:58:54 +0200428 microseconds = round(microseconds + usdouble)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400429 assert isinstance(s, int)
430 assert isinstance(microseconds, int)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000431 assert abs(s) <= 3 * 24 * 3600
432 assert abs(microseconds) < 3.1e6
433
434 # Just a little bit of carrying possible for microseconds and seconds.
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400435 seconds, us = divmod(microseconds, 1000000)
436 s += seconds
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000437 days, s = divmod(s, 24*3600)
438 d += days
439
440 assert isinstance(d, int)
441 assert isinstance(s, int) and 0 <= s < 24*3600
442 assert isinstance(us, int) and 0 <= us < 1000000
443
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000444 if abs(d) > 999999999:
445 raise OverflowError("timedelta # of days is too large: %d" % d)
446
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400447 self = object.__new__(cls)
448 self._days = d
449 self._seconds = s
450 self._microseconds = us
451 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000452 return self
453
454 def __repr__(self):
455 if self._microseconds:
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300456 return "%s.%s(%d, %d, %d)" % (self.__class__.__module__,
457 self.__class__.__qualname__,
458 self._days,
459 self._seconds,
460 self._microseconds)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000461 if self._seconds:
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300462 return "%s.%s(%d, %d)" % (self.__class__.__module__,
463 self.__class__.__qualname__,
464 self._days,
465 self._seconds)
466 return "%s.%s(%d)" % (self.__class__.__module__,
467 self.__class__.__qualname__,
468 self._days)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000469
470 def __str__(self):
471 mm, ss = divmod(self._seconds, 60)
472 hh, mm = divmod(mm, 60)
473 s = "%d:%02d:%02d" % (hh, mm, ss)
474 if self._days:
475 def plural(n):
476 return n, abs(n) != 1 and "s" or ""
477 s = ("%d day%s, " % plural(self._days)) + s
478 if self._microseconds:
479 s = s + ".%06d" % self._microseconds
480 return s
481
482 def total_seconds(self):
483 """Total seconds in the duration."""
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400484 return ((self.days * 86400 + self.seconds) * 10**6 +
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000485 self.microseconds) / 10**6
486
487 # Read-only field accessors
488 @property
489 def days(self):
490 """days"""
491 return self._days
492
493 @property
494 def seconds(self):
495 """seconds"""
496 return self._seconds
497
498 @property
499 def microseconds(self):
500 """microseconds"""
501 return self._microseconds
502
503 def __add__(self, other):
504 if isinstance(other, timedelta):
505 # for CPython compatibility, we cannot use
506 # our __class__ here, but need a real timedelta
507 return timedelta(self._days + other._days,
508 self._seconds + other._seconds,
509 self._microseconds + other._microseconds)
510 return NotImplemented
511
512 __radd__ = __add__
513
514 def __sub__(self, other):
515 if isinstance(other, timedelta):
Alexander Belopolskyb6f5ec72011-04-05 20:07:38 -0400516 # for CPython compatibility, we cannot use
517 # our __class__ here, but need a real timedelta
518 return timedelta(self._days - other._days,
519 self._seconds - other._seconds,
520 self._microseconds - other._microseconds)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000521 return NotImplemented
522
523 def __rsub__(self, other):
524 if isinstance(other, timedelta):
525 return -self + other
526 return NotImplemented
527
528 def __neg__(self):
529 # for CPython compatibility, we cannot use
530 # our __class__ here, but need a real timedelta
531 return timedelta(-self._days,
532 -self._seconds,
533 -self._microseconds)
534
535 def __pos__(self):
536 return self
537
538 def __abs__(self):
539 if self._days < 0:
540 return -self
541 else:
542 return self
543
544 def __mul__(self, other):
545 if isinstance(other, int):
546 # for CPython compatibility, we cannot use
547 # our __class__ here, but need a real timedelta
548 return timedelta(self._days * other,
549 self._seconds * other,
550 self._microseconds * other)
551 if isinstance(other, float):
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500552 usec = self._to_microseconds()
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000553 a, b = other.as_integer_ratio()
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500554 return timedelta(0, 0, _divide_and_round(usec * a, b))
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000555 return NotImplemented
556
557 __rmul__ = __mul__
558
559 def _to_microseconds(self):
560 return ((self._days * (24*3600) + self._seconds) * 1000000 +
561 self._microseconds)
562
563 def __floordiv__(self, other):
564 if not isinstance(other, (int, timedelta)):
565 return NotImplemented
566 usec = self._to_microseconds()
567 if isinstance(other, timedelta):
568 return usec // other._to_microseconds()
569 if isinstance(other, int):
570 return timedelta(0, 0, usec // other)
571
572 def __truediv__(self, other):
573 if not isinstance(other, (int, float, timedelta)):
574 return NotImplemented
575 usec = self._to_microseconds()
576 if isinstance(other, timedelta):
577 return usec / other._to_microseconds()
578 if isinstance(other, int):
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500579 return timedelta(0, 0, _divide_and_round(usec, other))
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000580 if isinstance(other, float):
581 a, b = other.as_integer_ratio()
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500582 return timedelta(0, 0, _divide_and_round(b * usec, a))
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000583
584 def __mod__(self, other):
585 if isinstance(other, timedelta):
586 r = self._to_microseconds() % other._to_microseconds()
587 return timedelta(0, 0, r)
588 return NotImplemented
589
590 def __divmod__(self, other):
591 if isinstance(other, timedelta):
592 q, r = divmod(self._to_microseconds(),
593 other._to_microseconds())
594 return q, timedelta(0, 0, r)
595 return NotImplemented
596
597 # Comparisons of timedelta objects with other.
598
599 def __eq__(self, other):
600 if isinstance(other, timedelta):
601 return self._cmp(other) == 0
602 else:
603 return False
604
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000605 def __le__(self, other):
606 if isinstance(other, timedelta):
607 return self._cmp(other) <= 0
608 else:
609 _cmperror(self, other)
610
611 def __lt__(self, other):
612 if isinstance(other, timedelta):
613 return self._cmp(other) < 0
614 else:
615 _cmperror(self, other)
616
617 def __ge__(self, other):
618 if isinstance(other, timedelta):
619 return self._cmp(other) >= 0
620 else:
621 _cmperror(self, other)
622
623 def __gt__(self, other):
624 if isinstance(other, timedelta):
625 return self._cmp(other) > 0
626 else:
627 _cmperror(self, other)
628
629 def _cmp(self, other):
630 assert isinstance(other, timedelta)
631 return _cmp(self._getstate(), other._getstate())
632
633 def __hash__(self):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400634 if self._hashcode == -1:
635 self._hashcode = hash(self._getstate())
636 return self._hashcode
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000637
638 def __bool__(self):
639 return (self._days != 0 or
640 self._seconds != 0 or
641 self._microseconds != 0)
642
643 # Pickle support.
644
645 def _getstate(self):
646 return (self._days, self._seconds, self._microseconds)
647
648 def __reduce__(self):
649 return (self.__class__, self._getstate())
650
651timedelta.min = timedelta(-999999999)
652timedelta.max = timedelta(days=999999999, hours=23, minutes=59, seconds=59,
653 microseconds=999999)
654timedelta.resolution = timedelta(microseconds=1)
655
656class date:
657 """Concrete date type.
658
659 Constructors:
660
661 __new__()
662 fromtimestamp()
663 today()
664 fromordinal()
665
666 Operators:
667
668 __repr__, __str__
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200669 __eq__, __le__, __lt__, __ge__, __gt__, __hash__
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000670 __add__, __radd__, __sub__ (add/radd only with timedelta arg)
671
672 Methods:
673
674 timetuple()
675 toordinal()
676 weekday()
677 isoweekday(), isocalendar(), isoformat()
678 ctime()
679 strftime()
680
681 Properties (readonly):
682 year, month, day
683 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400684 __slots__ = '_year', '_month', '_day', '_hashcode'
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000685
686 def __new__(cls, year, month=None, day=None):
687 """Constructor.
688
689 Arguments:
690
691 year, month, day (required, base 1)
692 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400693 if month is None and isinstance(year, bytes) and len(year) == 4 and \
694 1 <= year[2] <= 12:
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000695 # Pickle support
696 self = object.__new__(cls)
697 self.__setstate(year)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400698 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000699 return self
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400700 year, month, day = _check_date_fields(year, month, day)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000701 self = object.__new__(cls)
702 self._year = year
703 self._month = month
704 self._day = day
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400705 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000706 return self
707
708 # Additional constructors
709
710 @classmethod
711 def fromtimestamp(cls, t):
712 "Construct a date from a POSIX timestamp (like time.time())."
713 y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
714 return cls(y, m, d)
715
716 @classmethod
717 def today(cls):
718 "Construct a date from time.time()."
719 t = _time.time()
720 return cls.fromtimestamp(t)
721
722 @classmethod
723 def fromordinal(cls, n):
724 """Contruct a date from a proleptic Gregorian ordinal.
725
726 January 1 of year 1 is day 1. Only the year, month and day are
727 non-zero in the result.
728 """
729 y, m, d = _ord2ymd(n)
730 return cls(y, m, d)
731
732 # Conversions to string
733
734 def __repr__(self):
735 """Convert to formal string, for repr().
736
737 >>> dt = datetime(2010, 1, 1)
738 >>> repr(dt)
739 'datetime.datetime(2010, 1, 1, 0, 0)'
740
741 >>> dt = datetime(2010, 1, 1, tzinfo=timezone.utc)
742 >>> repr(dt)
743 'datetime.datetime(2010, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)'
744 """
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300745 return "%s.%s(%d, %d, %d)" % (self.__class__.__module__,
746 self.__class__.__qualname__,
747 self._year,
748 self._month,
749 self._day)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000750 # XXX These shouldn't depend on time.localtime(), because that
751 # clips the usable dates to [1970 .. 2038). At least ctime() is
752 # easily done without using strftime() -- that's better too because
753 # strftime("%c", ...) is locale specific.
754
755
756 def ctime(self):
757 "Return ctime() style string."
758 weekday = self.toordinal() % 7 or 7
759 return "%s %s %2d 00:00:00 %04d" % (
760 _DAYNAMES[weekday],
761 _MONTHNAMES[self._month],
762 self._day, self._year)
763
764 def strftime(self, fmt):
765 "Format using strftime()."
766 return _wrap_strftime(self, fmt, self.timetuple())
767
768 def __format__(self, fmt):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400769 if not isinstance(fmt, str):
770 raise TypeError("must be str, not %s" % type(fmt).__name__)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000771 if len(fmt) != 0:
772 return self.strftime(fmt)
773 return str(self)
774
775 def isoformat(self):
776 """Return the date formatted according to ISO.
777
778 This is 'YYYY-MM-DD'.
779
780 References:
781 - http://www.w3.org/TR/NOTE-datetime
782 - http://www.cl.cam.ac.uk/~mgk25/iso-time.html
783 """
784 return "%04d-%02d-%02d" % (self._year, self._month, self._day)
785
786 __str__ = isoformat
787
788 # Read-only field accessors
789 @property
790 def year(self):
791 """year (1-9999)"""
792 return self._year
793
794 @property
795 def month(self):
796 """month (1-12)"""
797 return self._month
798
799 @property
800 def day(self):
801 """day (1-31)"""
802 return self._day
803
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +0200804 # Standard conversions, __eq__, __le__, __lt__, __ge__, __gt__,
805 # __hash__ (and helpers)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000806
807 def timetuple(self):
808 "Return local time tuple compatible with time.localtime()."
809 return _build_struct_time(self._year, self._month, self._day,
810 0, 0, 0, -1)
811
812 def toordinal(self):
813 """Return proleptic Gregorian ordinal for the year, month and day.
814
815 January 1 of year 1 is day 1. Only the year, month and day values
816 contribute to the result.
817 """
818 return _ymd2ord(self._year, self._month, self._day)
819
820 def replace(self, year=None, month=None, day=None):
821 """Return a new date with new values for the specified fields."""
822 if year is None:
823 year = self._year
824 if month is None:
825 month = self._month
826 if day is None:
827 day = self._day
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000828 return date(year, month, day)
829
830 # Comparisons of date objects with other.
831
832 def __eq__(self, other):
833 if isinstance(other, date):
834 return self._cmp(other) == 0
835 return NotImplemented
836
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000837 def __le__(self, other):
838 if isinstance(other, date):
839 return self._cmp(other) <= 0
840 return NotImplemented
841
842 def __lt__(self, other):
843 if isinstance(other, date):
844 return self._cmp(other) < 0
845 return NotImplemented
846
847 def __ge__(self, other):
848 if isinstance(other, date):
849 return self._cmp(other) >= 0
850 return NotImplemented
851
852 def __gt__(self, other):
853 if isinstance(other, date):
854 return self._cmp(other) > 0
855 return NotImplemented
856
857 def _cmp(self, other):
858 assert isinstance(other, date)
859 y, m, d = self._year, self._month, self._day
860 y2, m2, d2 = other._year, other._month, other._day
861 return _cmp((y, m, d), (y2, m2, d2))
862
863 def __hash__(self):
864 "Hash."
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400865 if self._hashcode == -1:
866 self._hashcode = hash(self._getstate())
867 return self._hashcode
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000868
869 # Computations
870
871 def __add__(self, other):
872 "Add a date to a timedelta."
873 if isinstance(other, timedelta):
874 o = self.toordinal() + other.days
875 if 0 < o <= _MAXORDINAL:
876 return date.fromordinal(o)
877 raise OverflowError("result out of range")
878 return NotImplemented
879
880 __radd__ = __add__
881
882 def __sub__(self, other):
883 """Subtract two dates, or a date and a timedelta."""
884 if isinstance(other, timedelta):
885 return self + timedelta(-other.days)
886 if isinstance(other, date):
887 days1 = self.toordinal()
888 days2 = other.toordinal()
889 return timedelta(days1 - days2)
890 return NotImplemented
891
892 def weekday(self):
893 "Return day of the week, where Monday == 0 ... Sunday == 6."
894 return (self.toordinal() + 6) % 7
895
896 # Day-of-the-week and week-of-the-year, according to ISO
897
898 def isoweekday(self):
899 "Return day of the week, where Monday == 1 ... Sunday == 7."
900 # 1-Jan-0001 is a Monday
901 return self.toordinal() % 7 or 7
902
903 def isocalendar(self):
904 """Return a 3-tuple containing ISO year, week number, and weekday.
905
906 The first ISO week of the year is the (Mon-Sun) week
907 containing the year's first Thursday; everything else derives
908 from that.
909
910 The first week is 1; Monday is 1 ... Sunday is 7.
911
912 ISO calendar algorithm taken from
913 http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
Brett Cannon07b954d2016-01-15 09:53:51 -0800914 (used with permission)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000915 """
916 year = self._year
917 week1monday = _isoweek1monday(year)
918 today = _ymd2ord(self._year, self._month, self._day)
919 # Internally, week and day have origin 0
920 week, day = divmod(today - week1monday, 7)
921 if week < 0:
922 year -= 1
923 week1monday = _isoweek1monday(year)
924 week, day = divmod(today - week1monday, 7)
925 elif week >= 52:
926 if today >= _isoweek1monday(year+1):
927 year += 1
928 week = 0
929 return year, week+1, day+1
930
931 # Pickle support.
932
933 def _getstate(self):
934 yhi, ylo = divmod(self._year, 256)
935 return bytes([yhi, ylo, self._month, self._day]),
936
937 def __setstate(self, string):
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000938 yhi, ylo, self._month, self._day = string
939 self._year = yhi * 256 + ylo
940
941 def __reduce__(self):
942 return (self.__class__, self._getstate())
943
944_date_class = date # so functions w/ args named "date" can get at the class
945
946date.min = date(1, 1, 1)
947date.max = date(9999, 12, 31)
948date.resolution = timedelta(days=1)
949
950class tzinfo:
951 """Abstract base class for time zone info classes.
952
953 Subclasses must override the name(), utcoffset() and dst() methods.
954 """
955 __slots__ = ()
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400956
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000957 def tzname(self, dt):
958 "datetime -> string name of time zone."
959 raise NotImplementedError("tzinfo subclass must override tzname()")
960
961 def utcoffset(self, dt):
962 "datetime -> minutes east of UTC (negative for west of UTC)"
963 raise NotImplementedError("tzinfo subclass must override utcoffset()")
964
965 def dst(self, dt):
966 """datetime -> DST offset in minutes east of UTC.
967
968 Return 0 if DST not in effect. utcoffset() must include the DST
969 offset.
970 """
971 raise NotImplementedError("tzinfo subclass must override dst()")
972
973 def fromutc(self, dt):
974 "datetime in UTC -> datetime in local time."
975
976 if not isinstance(dt, datetime):
977 raise TypeError("fromutc() requires a datetime argument")
978 if dt.tzinfo is not self:
979 raise ValueError("dt.tzinfo is not self")
980
981 dtoff = dt.utcoffset()
982 if dtoff is None:
983 raise ValueError("fromutc() requires a non-None utcoffset() "
984 "result")
985
986 # See the long comment block at the end of this file for an
987 # explanation of this algorithm.
988 dtdst = dt.dst()
989 if dtdst is None:
990 raise ValueError("fromutc() requires a non-None dst() result")
991 delta = dtoff - dtdst
992 if delta:
993 dt += delta
994 dtdst = dt.dst()
995 if dtdst is None:
996 raise ValueError("fromutc(): dt.dst gave inconsistent "
997 "results; cannot convert")
998 return dt + dtdst
999
1000 # Pickle support.
1001
1002 def __reduce__(self):
1003 getinitargs = getattr(self, "__getinitargs__", None)
1004 if getinitargs:
1005 args = getinitargs()
1006 else:
1007 args = ()
1008 getstate = getattr(self, "__getstate__", None)
1009 if getstate:
1010 state = getstate()
1011 else:
1012 state = getattr(self, "__dict__", None) or None
1013 if state is None:
1014 return (self.__class__, args)
1015 else:
1016 return (self.__class__, args, state)
1017
1018_tzinfo_class = tzinfo
1019
1020class time:
1021 """Time with time zone.
1022
1023 Constructors:
1024
1025 __new__()
1026
1027 Operators:
1028
1029 __repr__, __str__
Serhiy Storchakaa60c2fe2015-03-12 21:56:08 +02001030 __eq__, __le__, __lt__, __ge__, __gt__, __hash__
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001031
1032 Methods:
1033
1034 strftime()
1035 isoformat()
1036 utcoffset()
1037 tzname()
1038 dst()
1039
1040 Properties (readonly):
1041 hour, minute, second, microsecond, tzinfo
1042 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001043 __slots__ = '_hour', '_minute', '_second', '_microsecond', '_tzinfo', '_hashcode'
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001044
1045 def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None):
1046 """Constructor.
1047
1048 Arguments:
1049
1050 hour, minute (required)
1051 second, microsecond (default to zero)
1052 tzinfo (default to None)
1053 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001054 if isinstance(hour, bytes) and len(hour) == 6 and hour[0] < 24:
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001055 # Pickle support
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001056 self = object.__new__(cls)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001057 self.__setstate(hour, minute or None)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001058 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001059 return self
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001060 hour, minute, second, microsecond = _check_time_fields(
1061 hour, minute, second, microsecond)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001062 _check_tzinfo_arg(tzinfo)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001063 self = object.__new__(cls)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001064 self._hour = hour
1065 self._minute = minute
1066 self._second = second
1067 self._microsecond = microsecond
1068 self._tzinfo = tzinfo
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001069 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001070 return self
1071
1072 # Read-only field accessors
1073 @property
1074 def hour(self):
1075 """hour (0-23)"""
1076 return self._hour
1077
1078 @property
1079 def minute(self):
1080 """minute (0-59)"""
1081 return self._minute
1082
1083 @property
1084 def second(self):
1085 """second (0-59)"""
1086 return self._second
1087
1088 @property
1089 def microsecond(self):
1090 """microsecond (0-999999)"""
1091 return self._microsecond
1092
1093 @property
1094 def tzinfo(self):
1095 """timezone info object"""
1096 return self._tzinfo
1097
1098 # Standard conversions, __hash__ (and helpers)
1099
1100 # Comparisons of time objects with other.
1101
1102 def __eq__(self, other):
1103 if isinstance(other, time):
Alexander Belopolsky08313822012-06-15 20:19:47 -04001104 return self._cmp(other, allow_mixed=True) == 0
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001105 else:
1106 return False
1107
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001108 def __le__(self, other):
1109 if isinstance(other, time):
1110 return self._cmp(other) <= 0
1111 else:
1112 _cmperror(self, other)
1113
1114 def __lt__(self, other):
1115 if isinstance(other, time):
1116 return self._cmp(other) < 0
1117 else:
1118 _cmperror(self, other)
1119
1120 def __ge__(self, other):
1121 if isinstance(other, time):
1122 return self._cmp(other) >= 0
1123 else:
1124 _cmperror(self, other)
1125
1126 def __gt__(self, other):
1127 if isinstance(other, time):
1128 return self._cmp(other) > 0
1129 else:
1130 _cmperror(self, other)
1131
Alexander Belopolsky08313822012-06-15 20:19:47 -04001132 def _cmp(self, other, allow_mixed=False):
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001133 assert isinstance(other, time)
1134 mytz = self._tzinfo
1135 ottz = other._tzinfo
1136 myoff = otoff = None
1137
1138 if mytz is ottz:
1139 base_compare = True
1140 else:
1141 myoff = self.utcoffset()
1142 otoff = other.utcoffset()
1143 base_compare = myoff == otoff
1144
1145 if base_compare:
1146 return _cmp((self._hour, self._minute, self._second,
1147 self._microsecond),
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001148 (other._hour, other._minute, other._second,
1149 other._microsecond))
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001150 if myoff is None or otoff is None:
Alexander Belopolsky08313822012-06-15 20:19:47 -04001151 if allow_mixed:
1152 return 2 # arbitrary non-zero value
1153 else:
1154 raise TypeError("cannot compare naive and aware times")
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001155 myhhmm = self._hour * 60 + self._minute - myoff//timedelta(minutes=1)
1156 othhmm = other._hour * 60 + other._minute - otoff//timedelta(minutes=1)
1157 return _cmp((myhhmm, self._second, self._microsecond),
1158 (othhmm, other._second, other._microsecond))
1159
1160 def __hash__(self):
1161 """Hash."""
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001162 if self._hashcode == -1:
1163 tzoff = self.utcoffset()
1164 if not tzoff: # zero or None
1165 self._hashcode = hash(self._getstate()[0])
1166 else:
1167 h, m = divmod(timedelta(hours=self.hour, minutes=self.minute) - tzoff,
1168 timedelta(hours=1))
1169 assert not m % timedelta(minutes=1), "whole minute"
1170 m //= timedelta(minutes=1)
1171 if 0 <= h < 24:
1172 self._hashcode = hash(time(h, m, self.second, self.microsecond))
1173 else:
1174 self._hashcode = hash((h, m, self.second, self.microsecond))
1175 return self._hashcode
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001176
1177 # Conversion to string
1178
1179 def _tzstr(self, sep=":"):
1180 """Return formatted timezone offset (+xx:xx) or None."""
1181 off = self.utcoffset()
1182 if off is not None:
1183 if off.days < 0:
1184 sign = "-"
1185 off = -off
1186 else:
1187 sign = "+"
1188 hh, mm = divmod(off, timedelta(hours=1))
1189 assert not mm % timedelta(minutes=1), "whole minute"
1190 mm //= timedelta(minutes=1)
1191 assert 0 <= hh < 24
1192 off = "%s%02d%s%02d" % (sign, hh, sep, mm)
1193 return off
1194
1195 def __repr__(self):
1196 """Convert to formal string, for repr()."""
1197 if self._microsecond != 0:
1198 s = ", %d, %d" % (self._second, self._microsecond)
1199 elif self._second != 0:
1200 s = ", %d" % self._second
1201 else:
1202 s = ""
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001203 s= "%s.%s(%d, %d%s)" % (self.__class__.__module__,
1204 self.__class__.__qualname__,
1205 self._hour, self._minute, s)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001206 if self._tzinfo is not None:
1207 assert s[-1:] == ")"
1208 s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
1209 return s
1210
Alexander Belopolskya2998a62016-03-06 14:58:43 -05001211 def isoformat(self, timespec='auto'):
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001212 """Return the time formatted according to ISO.
1213
Alexander Belopolskya2998a62016-03-06 14:58:43 -05001214 The full format is 'HH:MM:SS.mmmmmm+zz:zz'. By default, the fractional
1215 part is omitted if self.microsecond == 0.
1216
1217 The optional argument timespec specifies the number of additional
1218 terms of the time to include.
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001219 """
1220 s = _format_time(self._hour, self._minute, self._second,
Alexander Belopolskya2998a62016-03-06 14:58:43 -05001221 self._microsecond, timespec)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001222 tz = self._tzstr()
1223 if tz:
1224 s += tz
1225 return s
1226
1227 __str__ = isoformat
1228
1229 def strftime(self, fmt):
1230 """Format using strftime(). The date part of the timestamp passed
1231 to underlying strftime should not be used.
1232 """
Alexander Belopolskyb8bb4662011-01-08 00:13:34 +00001233 # The year must be >= 1000 else Python's strftime implementation
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001234 # can raise a bogus exception.
1235 timetuple = (1900, 1, 1,
1236 self._hour, self._minute, self._second,
1237 0, 1, -1)
1238 return _wrap_strftime(self, fmt, timetuple)
1239
1240 def __format__(self, fmt):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001241 if not isinstance(fmt, str):
1242 raise TypeError("must be str, not %s" % type(fmt).__name__)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001243 if len(fmt) != 0:
1244 return self.strftime(fmt)
1245 return str(self)
1246
1247 # Timezone functions
1248
1249 def utcoffset(self):
1250 """Return the timezone offset in minutes east of UTC (negative west of
1251 UTC)."""
1252 if self._tzinfo is None:
1253 return None
1254 offset = self._tzinfo.utcoffset(None)
1255 _check_utc_offset("utcoffset", offset)
1256 return offset
1257
1258 def tzname(self):
1259 """Return the timezone name.
1260
1261 Note that the name is 100% informational -- there's no requirement that
1262 it mean anything in particular. For example, "GMT", "UTC", "-500",
1263 "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
1264 """
1265 if self._tzinfo is None:
1266 return None
1267 name = self._tzinfo.tzname(None)
1268 _check_tzname(name)
1269 return name
1270
1271 def dst(self):
1272 """Return 0 if DST is not in effect, or the DST offset (in minutes
1273 eastward) if DST is in effect.
1274
1275 This is purely informational; the DST offset has already been added to
1276 the UTC offset returned by utcoffset() if applicable, so there's no
1277 need to consult dst() unless you're interested in displaying the DST
1278 info.
1279 """
1280 if self._tzinfo is None:
1281 return None
1282 offset = self._tzinfo.dst(None)
1283 _check_utc_offset("dst", offset)
1284 return offset
1285
1286 def replace(self, hour=None, minute=None, second=None, microsecond=None,
1287 tzinfo=True):
1288 """Return a new time with new values for the specified fields."""
1289 if hour is None:
1290 hour = self.hour
1291 if minute is None:
1292 minute = self.minute
1293 if second is None:
1294 second = self.second
1295 if microsecond is None:
1296 microsecond = self.microsecond
1297 if tzinfo is True:
1298 tzinfo = self.tzinfo
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001299 return time(hour, minute, second, microsecond, tzinfo)
1300
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001301 # Pickle support.
1302
1303 def _getstate(self):
1304 us2, us3 = divmod(self._microsecond, 256)
1305 us1, us2 = divmod(us2, 256)
1306 basestate = bytes([self._hour, self._minute, self._second,
1307 us1, us2, us3])
1308 if self._tzinfo is None:
1309 return (basestate,)
1310 else:
1311 return (basestate, self._tzinfo)
1312
1313 def __setstate(self, string, tzinfo):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001314 if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
1315 raise TypeError("bad tzinfo state arg")
1316 self._hour, self._minute, self._second, us1, us2, us3 = string
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001317 self._microsecond = (((us1 << 8) | us2) << 8) | us3
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001318 self._tzinfo = tzinfo
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001319
1320 def __reduce__(self):
1321 return (time, self._getstate())
1322
1323_time_class = time # so functions w/ args named "time" can get at the class
1324
1325time.min = time(0, 0, 0)
1326time.max = time(23, 59, 59, 999999)
1327time.resolution = timedelta(microseconds=1)
1328
1329class datetime(date):
1330 """datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
1331
1332 The year, month and day arguments are required. tzinfo may be None, or an
Serhiy Storchaka95949422013-08-27 19:40:23 +03001333 instance of a tzinfo subclass. The remaining arguments may be ints.
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001334 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001335 __slots__ = date.__slots__ + time.__slots__
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001336
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001337 def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
1338 microsecond=0, tzinfo=None):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001339 if isinstance(year, bytes) and len(year) == 10 and 1 <= year[2] <= 12:
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001340 # Pickle support
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001341 self = object.__new__(cls)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001342 self.__setstate(year, month)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001343 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001344 return self
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001345 year, month, day = _check_date_fields(year, month, day)
1346 hour, minute, second, microsecond = _check_time_fields(
1347 hour, minute, second, microsecond)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001348 _check_tzinfo_arg(tzinfo)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001349 self = object.__new__(cls)
1350 self._year = year
1351 self._month = month
1352 self._day = day
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001353 self._hour = hour
1354 self._minute = minute
1355 self._second = second
1356 self._microsecond = microsecond
1357 self._tzinfo = tzinfo
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001358 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001359 return self
1360
1361 # Read-only field accessors
1362 @property
1363 def hour(self):
1364 """hour (0-23)"""
1365 return self._hour
1366
1367 @property
1368 def minute(self):
1369 """minute (0-59)"""
1370 return self._minute
1371
1372 @property
1373 def second(self):
1374 """second (0-59)"""
1375 return self._second
1376
1377 @property
1378 def microsecond(self):
1379 """microsecond (0-999999)"""
1380 return self._microsecond
1381
1382 @property
1383 def tzinfo(self):
1384 """timezone info object"""
1385 return self._tzinfo
1386
1387 @classmethod
Victor Stinneradfefa52015-09-04 23:57:25 +02001388 def _fromtimestamp(cls, t, utc, tz):
1389 """Construct a datetime from a POSIX timestamp (like time.time()).
1390
1391 A timezone info object may be passed in as well.
1392 """
1393 frac, t = _math.modf(t)
Victor Stinner7667f582015-09-09 01:02:23 +02001394 us = round(frac * 1e6)
Victor Stinneradfefa52015-09-04 23:57:25 +02001395 if us >= 1000000:
1396 t += 1
1397 us -= 1000000
1398 elif us < 0:
1399 t -= 1
1400 us += 1000000
1401
1402 converter = _time.gmtime if utc else _time.localtime
1403 y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
1404 ss = min(ss, 59) # clamp out leap seconds if the platform has them
1405 return cls(y, m, d, hh, mm, ss, us, tz)
1406
1407 @classmethod
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001408 def fromtimestamp(cls, t, tz=None):
1409 """Construct a datetime from a POSIX timestamp (like time.time()).
1410
1411 A timezone info object may be passed in as well.
1412 """
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001413 _check_tzinfo_arg(tz)
Alexander Belopolskyaeb03982010-07-26 02:36:41 +00001414
Victor Stinneradfefa52015-09-04 23:57:25 +02001415 result = cls._fromtimestamp(t, tz is not None, tz)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001416 if tz is not None:
1417 result = tz.fromutc(result)
1418 return result
1419
1420 @classmethod
1421 def utcfromtimestamp(cls, t):
Alexander Belopolskye2e178e2015-03-01 14:52:07 -05001422 """Construct a naive UTC datetime from a POSIX timestamp."""
Victor Stinneradfefa52015-09-04 23:57:25 +02001423 return cls._fromtimestamp(t, True, None)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001424
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001425 @classmethod
1426 def now(cls, tz=None):
1427 "Construct a datetime from time.time() and optional time zone info."
1428 t = _time.time()
1429 return cls.fromtimestamp(t, tz)
1430
1431 @classmethod
1432 def utcnow(cls):
1433 "Construct a UTC datetime from time.time()."
1434 t = _time.time()
1435 return cls.utcfromtimestamp(t)
1436
1437 @classmethod
1438 def combine(cls, date, time):
1439 "Construct a datetime from a given date and a given time."
1440 if not isinstance(date, _date_class):
1441 raise TypeError("date argument must be a date instance")
1442 if not isinstance(time, _time_class):
1443 raise TypeError("time argument must be a time instance")
1444 return cls(date.year, date.month, date.day,
1445 time.hour, time.minute, time.second, time.microsecond,
1446 time.tzinfo)
1447
1448 def timetuple(self):
1449 "Return local time tuple compatible with time.localtime()."
1450 dst = self.dst()
1451 if dst is None:
1452 dst = -1
1453 elif dst:
1454 dst = 1
1455 else:
1456 dst = 0
1457 return _build_struct_time(self.year, self.month, self.day,
1458 self.hour, self.minute, self.second,
1459 dst)
1460
Alexander Belopolskya4415142012-06-08 12:33:09 -04001461 def timestamp(self):
1462 "Return POSIX timestamp as float"
1463 if self._tzinfo is None:
1464 return _time.mktime((self.year, self.month, self.day,
1465 self.hour, self.minute, self.second,
1466 -1, -1, -1)) + self.microsecond / 1e6
1467 else:
1468 return (self - _EPOCH).total_seconds()
1469
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001470 def utctimetuple(self):
1471 "Return UTC time tuple compatible with time.gmtime()."
1472 offset = self.utcoffset()
1473 if offset:
1474 self -= offset
1475 y, m, d = self.year, self.month, self.day
1476 hh, mm, ss = self.hour, self.minute, self.second
1477 return _build_struct_time(y, m, d, hh, mm, ss, 0)
1478
1479 def date(self):
1480 "Return the date part."
1481 return date(self._year, self._month, self._day)
1482
1483 def time(self):
1484 "Return the time part, with tzinfo None."
1485 return time(self.hour, self.minute, self.second, self.microsecond)
1486
1487 def timetz(self):
1488 "Return the time part, with same tzinfo."
1489 return time(self.hour, self.minute, self.second, self.microsecond,
1490 self._tzinfo)
1491
1492 def replace(self, year=None, month=None, day=None, hour=None,
1493 minute=None, second=None, microsecond=None, tzinfo=True):
1494 """Return a new datetime with new values for the specified fields."""
1495 if year is None:
1496 year = self.year
1497 if month is None:
1498 month = self.month
1499 if day is None:
1500 day = self.day
1501 if hour is None:
1502 hour = self.hour
1503 if minute is None:
1504 minute = self.minute
1505 if second is None:
1506 second = self.second
1507 if microsecond is None:
1508 microsecond = self.microsecond
1509 if tzinfo is True:
1510 tzinfo = self.tzinfo
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001511 return datetime(year, month, day, hour, minute, second, microsecond,
1512 tzinfo)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001513
Alexander Belopolskyfdc860f2012-06-22 12:23:23 -04001514 def astimezone(self, tz=None):
1515 if tz is None:
1516 if self.tzinfo is None:
1517 raise ValueError("astimezone() requires an aware datetime")
1518 ts = (self - _EPOCH) // timedelta(seconds=1)
1519 localtm = _time.localtime(ts)
1520 local = datetime(*localtm[:6])
1521 try:
Alexander Belopolskyff493c92012-06-22 12:25:57 -04001522 # Extract TZ data if available
Alexander Belopolskyfdc860f2012-06-22 12:23:23 -04001523 gmtoff = localtm.tm_gmtoff
1524 zone = localtm.tm_zone
1525 except AttributeError:
1526 # Compute UTC offset and compare with the value implied
1527 # by tm_isdst. If the values match, use the zone name
1528 # implied by tm_isdst.
1529 delta = local - datetime(*_time.gmtime(ts)[:6])
1530 dst = _time.daylight and localtm.tm_isdst > 0
Alexander Belopolsky93c9cd02012-06-22 16:04:19 -04001531 gmtoff = -(_time.altzone if dst else _time.timezone)
1532 if delta == timedelta(seconds=gmtoff):
Alexander Belopolskyfdc860f2012-06-22 12:23:23 -04001533 tz = timezone(delta, _time.tzname[dst])
1534 else:
1535 tz = timezone(delta)
1536 else:
Alexander Belopolsky93c9cd02012-06-22 16:04:19 -04001537 tz = timezone(timedelta(seconds=gmtoff), zone)
Alexander Belopolskyff493c92012-06-22 12:25:57 -04001538
Alexander Belopolskyfdc860f2012-06-22 12:23:23 -04001539 elif not isinstance(tz, tzinfo):
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001540 raise TypeError("tz argument must be an instance of tzinfo")
1541
1542 mytz = self.tzinfo
1543 if mytz is None:
1544 raise ValueError("astimezone() requires an aware datetime")
1545
1546 if tz is mytz:
1547 return self
1548
1549 # Convert self to UTC, and attach the new time zone object.
1550 myoffset = self.utcoffset()
1551 if myoffset is None:
1552 raise ValueError("astimezone() requires an aware datetime")
1553 utc = (self - myoffset).replace(tzinfo=tz)
1554
1555 # Convert from UTC to tz's local time.
1556 return tz.fromutc(utc)
1557
1558 # Ways to produce a string.
1559
1560 def ctime(self):
1561 "Return ctime() style string."
1562 weekday = self.toordinal() % 7 or 7
1563 return "%s %s %2d %02d:%02d:%02d %04d" % (
1564 _DAYNAMES[weekday],
1565 _MONTHNAMES[self._month],
1566 self._day,
1567 self._hour, self._minute, self._second,
1568 self._year)
1569
Alexander Belopolskya2998a62016-03-06 14:58:43 -05001570 def isoformat(self, sep='T', timespec='auto'):
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001571 """Return the time formatted according to ISO.
1572
Alexander Belopolskya2998a62016-03-06 14:58:43 -05001573 The full format looks like 'YYYY-MM-DD HH:MM:SS.mmmmmm'.
1574 By default, the fractional part is omitted if self.microsecond == 0.
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001575
1576 If self.tzinfo is not None, the UTC offset is also attached, giving
Alexander Belopolskya2998a62016-03-06 14:58:43 -05001577 giving a full format of 'YYYY-MM-DD HH:MM:SS.mmmmmm+HH:MM'.
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001578
1579 Optional argument sep specifies the separator between date and
1580 time, default 'T'.
Alexander Belopolskya2998a62016-03-06 14:58:43 -05001581
1582 The optional argument timespec specifies the number of additional
1583 terms of the time to include.
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001584 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001585 s = ("%04d-%02d-%02d%c" % (self._year, self._month, self._day, sep) +
1586 _format_time(self._hour, self._minute, self._second,
Alexander Belopolskya2998a62016-03-06 14:58:43 -05001587 self._microsecond, timespec))
1588
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001589 off = self.utcoffset()
1590 if off is not None:
1591 if off.days < 0:
1592 sign = "-"
1593 off = -off
1594 else:
1595 sign = "+"
1596 hh, mm = divmod(off, timedelta(hours=1))
1597 assert not mm % timedelta(minutes=1), "whole minute"
1598 mm //= timedelta(minutes=1)
1599 s += "%s%02d:%02d" % (sign, hh, mm)
1600 return s
1601
1602 def __repr__(self):
1603 """Convert to formal string, for repr()."""
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001604 L = [self._year, self._month, self._day, # These are never zero
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001605 self._hour, self._minute, self._second, self._microsecond]
1606 if L[-1] == 0:
1607 del L[-1]
1608 if L[-1] == 0:
1609 del L[-1]
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001610 s = "%s.%s(%s)" % (self.__class__.__module__,
1611 self.__class__.__qualname__,
1612 ", ".join(map(str, L)))
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001613 if self._tzinfo is not None:
1614 assert s[-1:] == ")"
1615 s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
1616 return s
1617
1618 def __str__(self):
1619 "Convert to string, for str()."
1620 return self.isoformat(sep=' ')
1621
1622 @classmethod
1623 def strptime(cls, date_string, format):
1624 'string, format -> new datetime parsed from a string (like time.strptime()).'
1625 import _strptime
1626 return _strptime._strptime_datetime(cls, date_string, format)
1627
1628 def utcoffset(self):
1629 """Return the timezone offset in minutes east of UTC (negative west of
1630 UTC)."""
1631 if self._tzinfo is None:
1632 return None
1633 offset = self._tzinfo.utcoffset(self)
1634 _check_utc_offset("utcoffset", offset)
1635 return offset
1636
1637 def tzname(self):
1638 """Return the timezone name.
1639
1640 Note that the name is 100% informational -- there's no requirement that
1641 it mean anything in particular. For example, "GMT", "UTC", "-500",
1642 "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
1643 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001644 if self._tzinfo is None:
1645 return None
1646 name = self._tzinfo.tzname(self)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001647 _check_tzname(name)
1648 return name
1649
1650 def dst(self):
1651 """Return 0 if DST is not in effect, or the DST offset (in minutes
1652 eastward) if DST is in effect.
1653
1654 This is purely informational; the DST offset has already been added to
1655 the UTC offset returned by utcoffset() if applicable, so there's no
1656 need to consult dst() unless you're interested in displaying the DST
1657 info.
1658 """
1659 if self._tzinfo is None:
1660 return None
1661 offset = self._tzinfo.dst(self)
1662 _check_utc_offset("dst", offset)
1663 return offset
1664
1665 # Comparisons of datetime objects with other.
1666
1667 def __eq__(self, other):
1668 if isinstance(other, datetime):
Alexander Belopolsky08313822012-06-15 20:19:47 -04001669 return self._cmp(other, allow_mixed=True) == 0
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001670 elif not isinstance(other, date):
1671 return NotImplemented
1672 else:
1673 return False
1674
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001675 def __le__(self, other):
1676 if isinstance(other, datetime):
1677 return self._cmp(other) <= 0
1678 elif not isinstance(other, date):
1679 return NotImplemented
1680 else:
1681 _cmperror(self, other)
1682
1683 def __lt__(self, other):
1684 if isinstance(other, datetime):
1685 return self._cmp(other) < 0
1686 elif not isinstance(other, date):
1687 return NotImplemented
1688 else:
1689 _cmperror(self, other)
1690
1691 def __ge__(self, other):
1692 if isinstance(other, datetime):
1693 return self._cmp(other) >= 0
1694 elif not isinstance(other, date):
1695 return NotImplemented
1696 else:
1697 _cmperror(self, other)
1698
1699 def __gt__(self, other):
1700 if isinstance(other, datetime):
1701 return self._cmp(other) > 0
1702 elif not isinstance(other, date):
1703 return NotImplemented
1704 else:
1705 _cmperror(self, other)
1706
Alexander Belopolsky08313822012-06-15 20:19:47 -04001707 def _cmp(self, other, allow_mixed=False):
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001708 assert isinstance(other, datetime)
1709 mytz = self._tzinfo
1710 ottz = other._tzinfo
1711 myoff = otoff = None
1712
1713 if mytz is ottz:
1714 base_compare = True
1715 else:
Alexander Belopolsky016ef552012-06-15 18:15:25 -04001716 myoff = self.utcoffset()
1717 otoff = other.utcoffset()
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001718 base_compare = myoff == otoff
1719
1720 if base_compare:
1721 return _cmp((self._year, self._month, self._day,
1722 self._hour, self._minute, self._second,
1723 self._microsecond),
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001724 (other._year, other._month, other._day,
1725 other._hour, other._minute, other._second,
1726 other._microsecond))
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001727 if myoff is None or otoff is None:
Alexander Belopolsky08313822012-06-15 20:19:47 -04001728 if allow_mixed:
1729 return 2 # arbitrary non-zero value
1730 else:
1731 raise TypeError("cannot compare naive and aware datetimes")
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001732 # XXX What follows could be done more efficiently...
1733 diff = self - other # this will take offsets into account
1734 if diff.days < 0:
1735 return -1
1736 return diff and 1 or 0
1737
1738 def __add__(self, other):
1739 "Add a datetime and a timedelta."
1740 if not isinstance(other, timedelta):
1741 return NotImplemented
1742 delta = timedelta(self.toordinal(),
1743 hours=self._hour,
1744 minutes=self._minute,
1745 seconds=self._second,
1746 microseconds=self._microsecond)
1747 delta += other
1748 hour, rem = divmod(delta.seconds, 3600)
1749 minute, second = divmod(rem, 60)
1750 if 0 < delta.days <= _MAXORDINAL:
1751 return datetime.combine(date.fromordinal(delta.days),
1752 time(hour, minute, second,
1753 delta.microseconds,
1754 tzinfo=self._tzinfo))
1755 raise OverflowError("result out of range")
1756
1757 __radd__ = __add__
1758
1759 def __sub__(self, other):
1760 "Subtract two datetimes, or a datetime and a timedelta."
1761 if not isinstance(other, datetime):
1762 if isinstance(other, timedelta):
1763 return self + -other
1764 return NotImplemented
1765
1766 days1 = self.toordinal()
1767 days2 = other.toordinal()
1768 secs1 = self._second + self._minute * 60 + self._hour * 3600
1769 secs2 = other._second + other._minute * 60 + other._hour * 3600
1770 base = timedelta(days1 - days2,
1771 secs1 - secs2,
1772 self._microsecond - other._microsecond)
1773 if self._tzinfo is other._tzinfo:
1774 return base
1775 myoff = self.utcoffset()
1776 otoff = other.utcoffset()
1777 if myoff == otoff:
1778 return base
1779 if myoff is None or otoff is None:
1780 raise TypeError("cannot mix naive and timezone-aware time")
1781 return base + otoff - myoff
1782
1783 def __hash__(self):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001784 if self._hashcode == -1:
1785 tzoff = self.utcoffset()
1786 if tzoff is None:
1787 self._hashcode = hash(self._getstate()[0])
1788 else:
1789 days = _ymd2ord(self.year, self.month, self.day)
1790 seconds = self.hour * 3600 + self.minute * 60 + self.second
1791 self._hashcode = hash(timedelta(days, seconds, self.microsecond) - tzoff)
1792 return self._hashcode
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001793
1794 # Pickle support.
1795
1796 def _getstate(self):
1797 yhi, ylo = divmod(self._year, 256)
1798 us2, us3 = divmod(self._microsecond, 256)
1799 us1, us2 = divmod(us2, 256)
1800 basestate = bytes([yhi, ylo, self._month, self._day,
1801 self._hour, self._minute, self._second,
1802 us1, us2, us3])
1803 if self._tzinfo is None:
1804 return (basestate,)
1805 else:
1806 return (basestate, self._tzinfo)
1807
1808 def __setstate(self, string, tzinfo):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001809 if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
1810 raise TypeError("bad tzinfo state arg")
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001811 (yhi, ylo, self._month, self._day, self._hour,
1812 self._minute, self._second, us1, us2, us3) = string
1813 self._year = yhi * 256 + ylo
1814 self._microsecond = (((us1 << 8) | us2) << 8) | us3
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001815 self._tzinfo = tzinfo
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001816
1817 def __reduce__(self):
1818 return (self.__class__, self._getstate())
1819
1820
1821datetime.min = datetime(1, 1, 1)
1822datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999)
1823datetime.resolution = timedelta(microseconds=1)
1824
1825
1826def _isoweek1monday(year):
1827 # Helper to calculate the day number of the Monday starting week 1
1828 # XXX This could be done more efficiently
1829 THURSDAY = 3
1830 firstday = _ymd2ord(year, 1, 1)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001831 firstweekday = (firstday + 6) % 7 # See weekday() above
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001832 week1monday = firstday - firstweekday
1833 if firstweekday > THURSDAY:
1834 week1monday += 7
1835 return week1monday
1836
1837class timezone(tzinfo):
1838 __slots__ = '_offset', '_name'
1839
1840 # Sentinel value to disallow None
1841 _Omitted = object()
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001842 def __new__(cls, offset, name=_Omitted):
1843 if not isinstance(offset, timedelta):
1844 raise TypeError("offset must be a timedelta")
1845 if name is cls._Omitted:
1846 if not offset:
1847 return cls.utc
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001848 name = None
1849 elif not isinstance(name, str):
1850 raise TypeError("name must be a string")
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001851 if not cls._minoffset <= offset <= cls._maxoffset:
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001852 raise ValueError("offset must be a timedelta "
1853 "strictly between -timedelta(hours=24) and "
1854 "timedelta(hours=24).")
1855 if (offset.microseconds != 0 or offset.seconds % 60 != 0):
1856 raise ValueError("offset must be a timedelta "
1857 "representing a whole number of minutes")
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001858 return cls._create(offset, name)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001859
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001860 @classmethod
1861 def _create(cls, offset, name=None):
1862 self = tzinfo.__new__(cls)
1863 self._offset = offset
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001864 self._name = name
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001865 return self
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001866
1867 def __getinitargs__(self):
1868 """pickle support"""
1869 if self._name is None:
1870 return (self._offset,)
1871 return (self._offset, self._name)
1872
1873 def __eq__(self, other):
Georg Brandl0085a242012-09-22 09:23:12 +02001874 if type(other) != timezone:
1875 return False
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001876 return self._offset == other._offset
1877
1878 def __hash__(self):
1879 return hash(self._offset)
1880
1881 def __repr__(self):
1882 """Convert to formal string, for repr().
1883
1884 >>> tz = timezone.utc
1885 >>> repr(tz)
1886 'datetime.timezone.utc'
1887 >>> tz = timezone(timedelta(hours=-5), 'EST')
1888 >>> repr(tz)
1889 "datetime.timezone(datetime.timedelta(-1, 68400), 'EST')"
1890 """
1891 if self is self.utc:
1892 return 'datetime.timezone.utc'
1893 if self._name is None:
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001894 return "%s.%s(%r)" % (self.__class__.__module__,
1895 self.__class__.__qualname__,
1896 self._offset)
1897 return "%s.%s(%r, %r)" % (self.__class__.__module__,
1898 self.__class__.__qualname__,
1899 self._offset, self._name)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001900
1901 def __str__(self):
1902 return self.tzname(None)
1903
1904 def utcoffset(self, dt):
1905 if isinstance(dt, datetime) or dt is None:
1906 return self._offset
1907 raise TypeError("utcoffset() argument must be a datetime instance"
1908 " or None")
1909
1910 def tzname(self, dt):
1911 if isinstance(dt, datetime) or dt is None:
1912 if self._name is None:
1913 return self._name_from_offset(self._offset)
1914 return self._name
1915 raise TypeError("tzname() argument must be a datetime instance"
1916 " or None")
1917
1918 def dst(self, dt):
1919 if isinstance(dt, datetime) or dt is None:
1920 return None
1921 raise TypeError("dst() argument must be a datetime instance"
1922 " or None")
1923
1924 def fromutc(self, dt):
1925 if isinstance(dt, datetime):
1926 if dt.tzinfo is not self:
1927 raise ValueError("fromutc: dt.tzinfo "
1928 "is not self")
1929 return dt + self._offset
1930 raise TypeError("fromutc() argument must be a datetime instance"
1931 " or None")
1932
1933 _maxoffset = timedelta(hours=23, minutes=59)
1934 _minoffset = -_maxoffset
1935
1936 @staticmethod
1937 def _name_from_offset(delta):
Alexander Belopolsky7827a5b2015-09-06 13:07:21 -04001938 if not delta:
1939 return 'UTC'
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001940 if delta < timedelta(0):
1941 sign = '-'
1942 delta = -delta
1943 else:
1944 sign = '+'
1945 hours, rest = divmod(delta, timedelta(hours=1))
1946 minutes = rest // timedelta(minutes=1)
1947 return 'UTC{}{:02d}:{:02d}'.format(sign, hours, minutes)
1948
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001949timezone.utc = timezone._create(timedelta(0))
1950timezone.min = timezone._create(timezone._minoffset)
1951timezone.max = timezone._create(timezone._maxoffset)
Alexander Belopolskya4415142012-06-08 12:33:09 -04001952_EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001953
Victor Stinner765531d2013-03-26 01:11:54 +01001954# Some time zone algebra. For a datetime x, let
1955# x.n = x stripped of its timezone -- its naive time.
1956# x.o = x.utcoffset(), and assuming that doesn't raise an exception or
1957# return None
1958# x.d = x.dst(), and assuming that doesn't raise an exception or
1959# return None
1960# x.s = x's standard offset, x.o - x.d
1961#
1962# Now some derived rules, where k is a duration (timedelta).
1963#
1964# 1. x.o = x.s + x.d
1965# This follows from the definition of x.s.
1966#
1967# 2. If x and y have the same tzinfo member, x.s = y.s.
1968# This is actually a requirement, an assumption we need to make about
1969# sane tzinfo classes.
1970#
1971# 3. The naive UTC time corresponding to x is x.n - x.o.
1972# This is again a requirement for a sane tzinfo class.
1973#
1974# 4. (x+k).s = x.s
1975# This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
1976#
1977# 5. (x+k).n = x.n + k
1978# Again follows from how arithmetic is defined.
1979#
1980# Now we can explain tz.fromutc(x). Let's assume it's an interesting case
1981# (meaning that the various tzinfo methods exist, and don't blow up or return
1982# None when called).
1983#
1984# The function wants to return a datetime y with timezone tz, equivalent to x.
1985# x is already in UTC.
1986#
1987# By #3, we want
1988#
1989# y.n - y.o = x.n [1]
1990#
1991# The algorithm starts by attaching tz to x.n, and calling that y. So
1992# x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
1993# becomes true; in effect, we want to solve [2] for k:
1994#
1995# (y+k).n - (y+k).o = x.n [2]
1996#
1997# By #1, this is the same as
1998#
1999# (y+k).n - ((y+k).s + (y+k).d) = x.n [3]
2000#
2001# By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
2002# Substituting that into [3],
2003#
2004# x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving
2005# k - (y+k).s - (y+k).d = 0; rearranging,
2006# k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so
2007# k = y.s - (y+k).d
2008#
2009# On the RHS, (y+k).d can't be computed directly, but y.s can be, and we
2010# approximate k by ignoring the (y+k).d term at first. Note that k can't be
2011# very large, since all offset-returning methods return a duration of magnitude
2012# less than 24 hours. For that reason, if y is firmly in std time, (y+k).d must
2013# be 0, so ignoring it has no consequence then.
2014#
2015# In any case, the new value is
2016#
2017# z = y + y.s [4]
2018#
2019# It's helpful to step back at look at [4] from a higher level: it's simply
2020# mapping from UTC to tz's standard time.
2021#
2022# At this point, if
2023#
2024# z.n - z.o = x.n [5]
2025#
2026# we have an equivalent time, and are almost done. The insecurity here is
2027# at the start of daylight time. Picture US Eastern for concreteness. The wall
2028# time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
2029# sense then. The docs ask that an Eastern tzinfo class consider such a time to
2030# be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST
2031# on the day DST starts. We want to return the 1:MM EST spelling because that's
2032# the only spelling that makes sense on the local wall clock.
2033#
2034# In fact, if [5] holds at this point, we do have the standard-time spelling,
2035# but that takes a bit of proof. We first prove a stronger result. What's the
2036# difference between the LHS and RHS of [5]? Let
2037#
2038# diff = x.n - (z.n - z.o) [6]
2039#
2040# Now
2041# z.n = by [4]
2042# (y + y.s).n = by #5
2043# y.n + y.s = since y.n = x.n
2044# x.n + y.s = since z and y are have the same tzinfo member,
2045# y.s = z.s by #2
2046# x.n + z.s
2047#
2048# Plugging that back into [6] gives
2049#
2050# diff =
2051# x.n - ((x.n + z.s) - z.o) = expanding
2052# x.n - x.n - z.s + z.o = cancelling
2053# - z.s + z.o = by #2
2054# z.d
2055#
2056# So diff = z.d.
2057#
2058# If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
2059# spelling we wanted in the endcase described above. We're done. Contrarily,
2060# if z.d = 0, then we have a UTC equivalent, and are also done.
2061#
2062# If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
2063# add to z (in effect, z is in tz's standard time, and we need to shift the
2064# local clock into tz's daylight time).
2065#
2066# Let
2067#
2068# z' = z + z.d = z + diff [7]
2069#
2070# and we can again ask whether
2071#
2072# z'.n - z'.o = x.n [8]
2073#
2074# If so, we're done. If not, the tzinfo class is insane, according to the
2075# assumptions we've made. This also requires a bit of proof. As before, let's
2076# compute the difference between the LHS and RHS of [8] (and skipping some of
2077# the justifications for the kinds of substitutions we've done several times
2078# already):
2079#
2080# diff' = x.n - (z'.n - z'.o) = replacing z'.n via [7]
2081# x.n - (z.n + diff - z'.o) = replacing diff via [6]
2082# x.n - (z.n + x.n - (z.n - z.o) - z'.o) =
2083# x.n - z.n - x.n + z.n - z.o + z'.o = cancel x.n
2084# - z.n + z.n - z.o + z'.o = cancel z.n
2085# - z.o + z'.o = #1 twice
2086# -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
2087# z'.d - z.d
2088#
2089# So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
2090# we've found the UTC-equivalent so are done. In fact, we stop with [7] and
2091# return z', not bothering to compute z'.d.
2092#
2093# How could z.d and z'd differ? z' = z + z.d [7], so merely moving z' by
2094# a dst() offset, and starting *from* a time already in DST (we know z.d != 0),
2095# would have to change the result dst() returns: we start in DST, and moving
2096# a little further into it takes us out of DST.
2097#
2098# There isn't a sane case where this can happen. The closest it gets is at
2099# the end of DST, where there's an hour in UTC with no spelling in a hybrid
2100# tzinfo class. In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT. During
2101# that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM
2102# UTC) because the docs insist on that, but 0:MM is taken as being in daylight
2103# time (4:MM UTC). There is no local time mapping to 5:MM UTC. The local
2104# clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in
2105# standard time. Since that's what the local clock *does*, we want to map both
2106# UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
2107# in local time, but so it goes -- it's the way the local clock works.
2108#
2109# When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
2110# so z=0:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
2111# z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
2112# (correctly) concludes that z' is not UTC-equivalent to x.
2113#
2114# Because we know z.d said z was in daylight time (else [5] would have held and
2115# we would have stopped then), and we know z.d != z'.d (else [8] would have held
2116# and we have stopped then), and there are only 2 possible values dst() can
2117# return in Eastern, it follows that z'.d must be 0 (which it is in the example,
2118# but the reasoning doesn't depend on the example -- it depends on there being
2119# two possible dst() outcomes, one zero and the other non-zero). Therefore
2120# z' must be in standard time, and is the spelling we want in this case.
2121#
2122# Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is
2123# concerned (because it takes z' as being in standard time rather than the
2124# daylight time we intend here), but returning it gives the real-life "local
2125# clock repeats an hour" behavior when mapping the "unspellable" UTC hour into
2126# tz.
2127#
2128# When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with
2129# the 1:MM standard time spelling we want.
2130#
2131# So how can this break? One of the assumptions must be violated. Two
2132# possibilities:
2133#
2134# 1) [2] effectively says that y.s is invariant across all y belong to a given
2135# time zone. This isn't true if, for political reasons or continental drift,
2136# a region decides to change its base offset from UTC.
2137#
2138# 2) There may be versions of "double daylight" time where the tail end of
2139# the analysis gives up a step too early. I haven't thought about that
2140# enough to say.
2141#
2142# In any case, it's clear that the default fromutc() is strong enough to handle
2143# "almost all" time zones: so long as the standard offset is invariant, it
2144# doesn't matter if daylight time transition points change from year to year, or
2145# if daylight time is skipped in some years; it doesn't matter how large or
2146# small dst() may get within its bounds; and it doesn't even matter if some
2147# perverse time zone returns a negative dst()). So a breaking case must be
2148# pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
Alexander Belopolskycf86e362010-07-23 19:25:47 +00002149
Alexander Belopolskycf86e362010-07-23 19:25:47 +00002150try:
2151 from _datetime import *
Brett Cannoncd171c82013-07-04 17:43:24 -04002152except ImportError:
Alexander Belopolskycf86e362010-07-23 19:25:47 +00002153 pass
2154else:
2155 # Clean up unused names
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04002156 del (_DAYNAMES, _DAYS_BEFORE_MONTH, _DAYS_IN_MONTH, _DI100Y, _DI400Y,
2157 _DI4Y, _EPOCH, _MAXORDINAL, _MONTHNAMES, _build_struct_time,
2158 _check_date_fields, _check_int_field, _check_time_fields,
2159 _check_tzinfo_arg, _check_tzname, _check_utc_offset, _cmp, _cmperror,
2160 _date_class, _days_before_month, _days_before_year, _days_in_month,
2161 _format_time, _is_leap, _isoweek1monday, _math, _ord2ymd,
2162 _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord)
Alexander Belopolskya5658742010-07-23 20:03:53 +00002163 # XXX Since import * above excludes names that start with _,
2164 # docstring does not get overwritten. In the future, it may be
2165 # appropriate to maintain a single module level docstring and
2166 # remove the following line.
2167 from _datetime import __doc__