blob: de574724b865de9e02b328fe16167ab2e3c74a23 [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
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000319class timedelta:
320 """Represent the difference between two datetime objects.
321
322 Supported operators:
323
324 - add, subtract timedelta
325 - unary plus, minus, abs
326 - compare to timedelta
Serhiy Storchaka95949422013-08-27 19:40:23 +0300327 - multiply, divide by int
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000328
329 In addition, datetime supports subtraction of two datetime objects
330 returning a timedelta, and addition or subtraction of a datetime
331 and a timedelta giving a datetime.
332
333 Representation: (days, seconds, microseconds). Why? Because I
334 felt like it.
335 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400336 __slots__ = '_days', '_seconds', '_microseconds', '_hashcode'
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000337
338 def __new__(cls, days=0, seconds=0, microseconds=0,
339 milliseconds=0, minutes=0, hours=0, weeks=0):
340 # Doing this efficiently and accurately in C is going to be difficult
341 # and error-prone, due to ubiquitous overflow possibilities, and that
342 # C double doesn't have enough bits of precision to represent
343 # microseconds over 10K years faithfully. The code here tries to make
344 # explicit where go-fast assumptions can be relied on, in order to
345 # guide the C implementation; it's way more convoluted than speed-
346 # ignoring auto-overflow-to-long idiomatic Python could be.
347
348 # XXX Check that all inputs are ints or floats.
349
350 # Final values, all integer.
351 # s and us fit in 32-bit signed ints; d isn't bounded.
352 d = s = us = 0
353
354 # Normalize everything to days, seconds, microseconds.
355 days += weeks*7
356 seconds += minutes*60 + hours*3600
357 microseconds += milliseconds*1000
358
359 # Get rid of all fractions, and normalize s and us.
360 # Take a deep breath <wink>.
361 if isinstance(days, float):
362 dayfrac, days = _math.modf(days)
363 daysecondsfrac, daysecondswhole = _math.modf(dayfrac * (24.*3600.))
364 assert daysecondswhole == int(daysecondswhole) # can't overflow
365 s = int(daysecondswhole)
366 assert days == int(days)
367 d = int(days)
368 else:
369 daysecondsfrac = 0.0
370 d = days
371 assert isinstance(daysecondsfrac, float)
372 assert abs(daysecondsfrac) <= 1.0
373 assert isinstance(d, int)
374 assert abs(s) <= 24 * 3600
375 # days isn't referenced again before redefinition
376
377 if isinstance(seconds, float):
378 secondsfrac, seconds = _math.modf(seconds)
379 assert seconds == int(seconds)
380 seconds = int(seconds)
381 secondsfrac += daysecondsfrac
382 assert abs(secondsfrac) <= 2.0
383 else:
384 secondsfrac = daysecondsfrac
385 # daysecondsfrac isn't referenced again
386 assert isinstance(secondsfrac, float)
387 assert abs(secondsfrac) <= 2.0
388
389 assert isinstance(seconds, int)
390 days, seconds = divmod(seconds, 24*3600)
391 d += days
392 s += int(seconds) # can't overflow
393 assert isinstance(s, int)
394 assert abs(s) <= 2 * 24 * 3600
395 # seconds isn't referenced again before redefinition
396
397 usdouble = secondsfrac * 1e6
398 assert abs(usdouble) < 2.1e6 # exact value not critical
399 # secondsfrac isn't referenced again
400
401 if isinstance(microseconds, float):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400402 microseconds = round(microseconds + usdouble)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000403 seconds, microseconds = divmod(microseconds, 1000000)
404 days, seconds = divmod(seconds, 24*3600)
405 d += days
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400406 s += seconds
407 else:
408 microseconds = int(microseconds)
409 seconds, microseconds = divmod(microseconds, 1000000)
410 days, seconds = divmod(seconds, 24*3600)
411 d += days
412 s += seconds
413 microseconds = round(microseconds + usdouble)
414 assert isinstance(s, int)
415 assert isinstance(microseconds, int)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000416 assert abs(s) <= 3 * 24 * 3600
417 assert abs(microseconds) < 3.1e6
418
419 # Just a little bit of carrying possible for microseconds and seconds.
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400420 seconds, us = divmod(microseconds, 1000000)
421 s += seconds
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000422 days, s = divmod(s, 24*3600)
423 d += days
424
425 assert isinstance(d, int)
426 assert isinstance(s, int) and 0 <= s < 24*3600
427 assert isinstance(us, int) and 0 <= us < 1000000
428
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000429 if abs(d) > 999999999:
430 raise OverflowError("timedelta # of days is too large: %d" % d)
431
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400432 self = object.__new__(cls)
433 self._days = d
434 self._seconds = s
435 self._microseconds = us
436 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000437 return self
438
439 def __repr__(self):
440 if self._microseconds:
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300441 return "%s.%s(%d, %d, %d)" % (self.__class__.__module__,
442 self.__class__.__qualname__,
443 self._days,
444 self._seconds,
445 self._microseconds)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000446 if self._seconds:
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300447 return "%s.%s(%d, %d)" % (self.__class__.__module__,
448 self.__class__.__qualname__,
449 self._days,
450 self._seconds)
451 return "%s.%s(%d)" % (self.__class__.__module__,
452 self.__class__.__qualname__,
453 self._days)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000454
455 def __str__(self):
456 mm, ss = divmod(self._seconds, 60)
457 hh, mm = divmod(mm, 60)
458 s = "%d:%02d:%02d" % (hh, mm, ss)
459 if self._days:
460 def plural(n):
461 return n, abs(n) != 1 and "s" or ""
462 s = ("%d day%s, " % plural(self._days)) + s
463 if self._microseconds:
464 s = s + ".%06d" % self._microseconds
465 return s
466
467 def total_seconds(self):
468 """Total seconds in the duration."""
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400469 return ((self.days * 86400 + self.seconds) * 10**6 +
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000470 self.microseconds) / 10**6
471
472 # Read-only field accessors
473 @property
474 def days(self):
475 """days"""
476 return self._days
477
478 @property
479 def seconds(self):
480 """seconds"""
481 return self._seconds
482
483 @property
484 def microseconds(self):
485 """microseconds"""
486 return self._microseconds
487
488 def __add__(self, other):
489 if isinstance(other, timedelta):
490 # for CPython compatibility, we cannot use
491 # our __class__ here, but need a real timedelta
492 return timedelta(self._days + other._days,
493 self._seconds + other._seconds,
494 self._microseconds + other._microseconds)
495 return NotImplemented
496
497 __radd__ = __add__
498
499 def __sub__(self, other):
500 if isinstance(other, timedelta):
Alexander Belopolskyb6f5ec72011-04-05 20:07:38 -0400501 # for CPython compatibility, we cannot use
502 # our __class__ here, but need a real timedelta
503 return timedelta(self._days - other._days,
504 self._seconds - other._seconds,
505 self._microseconds - other._microseconds)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000506 return NotImplemented
507
508 def __rsub__(self, other):
509 if isinstance(other, timedelta):
510 return -self + other
511 return NotImplemented
512
513 def __neg__(self):
514 # for CPython compatibility, we cannot use
515 # our __class__ here, but need a real timedelta
516 return timedelta(-self._days,
517 -self._seconds,
518 -self._microseconds)
519
520 def __pos__(self):
521 return self
522
523 def __abs__(self):
524 if self._days < 0:
525 return -self
526 else:
527 return self
528
529 def __mul__(self, other):
530 if isinstance(other, int):
531 # for CPython compatibility, we cannot use
532 # our __class__ here, but need a real timedelta
533 return timedelta(self._days * other,
534 self._seconds * other,
535 self._microseconds * other)
536 if isinstance(other, float):
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500537 usec = self._to_microseconds()
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000538 a, b = other.as_integer_ratio()
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500539 return timedelta(0, 0, _divide_and_round(usec * a, b))
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000540 return NotImplemented
541
542 __rmul__ = __mul__
543
544 def _to_microseconds(self):
545 return ((self._days * (24*3600) + self._seconds) * 1000000 +
546 self._microseconds)
547
548 def __floordiv__(self, other):
549 if not isinstance(other, (int, timedelta)):
550 return NotImplemented
551 usec = self._to_microseconds()
552 if isinstance(other, timedelta):
553 return usec // other._to_microseconds()
554 if isinstance(other, int):
555 return timedelta(0, 0, usec // other)
556
557 def __truediv__(self, other):
558 if not isinstance(other, (int, float, timedelta)):
559 return NotImplemented
560 usec = self._to_microseconds()
561 if isinstance(other, timedelta):
562 return usec / other._to_microseconds()
563 if isinstance(other, int):
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500564 return timedelta(0, 0, _divide_and_round(usec, other))
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000565 if isinstance(other, float):
566 a, b = other.as_integer_ratio()
Alexander Belopolsky24d3dee2015-02-28 10:41:57 -0500567 return timedelta(0, 0, _divide_and_round(b * usec, a))
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000568
569 def __mod__(self, other):
570 if isinstance(other, timedelta):
571 r = self._to_microseconds() % other._to_microseconds()
572 return timedelta(0, 0, r)
573 return NotImplemented
574
575 def __divmod__(self, other):
576 if isinstance(other, timedelta):
577 q, r = divmod(self._to_microseconds(),
578 other._to_microseconds())
579 return q, timedelta(0, 0, r)
580 return NotImplemented
581
582 # Comparisons of timedelta objects with other.
583
584 def __eq__(self, other):
585 if isinstance(other, timedelta):
586 return self._cmp(other) == 0
587 else:
588 return False
589
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000590 def __le__(self, other):
591 if isinstance(other, timedelta):
592 return self._cmp(other) <= 0
593 else:
594 _cmperror(self, other)
595
596 def __lt__(self, other):
597 if isinstance(other, timedelta):
598 return self._cmp(other) < 0
599 else:
600 _cmperror(self, other)
601
602 def __ge__(self, other):
603 if isinstance(other, timedelta):
604 return self._cmp(other) >= 0
605 else:
606 _cmperror(self, other)
607
608 def __gt__(self, other):
609 if isinstance(other, timedelta):
610 return self._cmp(other) > 0
611 else:
612 _cmperror(self, other)
613
614 def _cmp(self, other):
615 assert isinstance(other, timedelta)
616 return _cmp(self._getstate(), other._getstate())
617
618 def __hash__(self):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400619 if self._hashcode == -1:
620 self._hashcode = hash(self._getstate())
621 return self._hashcode
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000622
623 def __bool__(self):
624 return (self._days != 0 or
625 self._seconds != 0 or
626 self._microseconds != 0)
627
628 # Pickle support.
629
630 def _getstate(self):
631 return (self._days, self._seconds, self._microseconds)
632
633 def __reduce__(self):
634 return (self.__class__, self._getstate())
635
636timedelta.min = timedelta(-999999999)
637timedelta.max = timedelta(days=999999999, hours=23, minutes=59, seconds=59,
638 microseconds=999999)
639timedelta.resolution = timedelta(microseconds=1)
640
641class date:
642 """Concrete date type.
643
644 Constructors:
645
646 __new__()
647 fromtimestamp()
648 today()
649 fromordinal()
650
651 Operators:
652
653 __repr__, __str__
654 __cmp__, __hash__
655 __add__, __radd__, __sub__ (add/radd only with timedelta arg)
656
657 Methods:
658
659 timetuple()
660 toordinal()
661 weekday()
662 isoweekday(), isocalendar(), isoformat()
663 ctime()
664 strftime()
665
666 Properties (readonly):
667 year, month, day
668 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400669 __slots__ = '_year', '_month', '_day', '_hashcode'
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000670
671 def __new__(cls, year, month=None, day=None):
672 """Constructor.
673
674 Arguments:
675
676 year, month, day (required, base 1)
677 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400678 if month is None and isinstance(year, bytes) and len(year) == 4 and \
679 1 <= year[2] <= 12:
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000680 # Pickle support
681 self = object.__new__(cls)
682 self.__setstate(year)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400683 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000684 return self
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400685 year, month, day = _check_date_fields(year, month, day)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000686 self = object.__new__(cls)
687 self._year = year
688 self._month = month
689 self._day = day
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400690 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000691 return self
692
693 # Additional constructors
694
695 @classmethod
696 def fromtimestamp(cls, t):
697 "Construct a date from a POSIX timestamp (like time.time())."
698 y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
699 return cls(y, m, d)
700
701 @classmethod
702 def today(cls):
703 "Construct a date from time.time()."
704 t = _time.time()
705 return cls.fromtimestamp(t)
706
707 @classmethod
708 def fromordinal(cls, n):
709 """Contruct a date from a proleptic Gregorian ordinal.
710
711 January 1 of year 1 is day 1. Only the year, month and day are
712 non-zero in the result.
713 """
714 y, m, d = _ord2ymd(n)
715 return cls(y, m, d)
716
717 # Conversions to string
718
719 def __repr__(self):
720 """Convert to formal string, for repr().
721
722 >>> dt = datetime(2010, 1, 1)
723 >>> repr(dt)
724 'datetime.datetime(2010, 1, 1, 0, 0)'
725
726 >>> dt = datetime(2010, 1, 1, tzinfo=timezone.utc)
727 >>> repr(dt)
728 'datetime.datetime(2010, 1, 1, 0, 0, tzinfo=datetime.timezone.utc)'
729 """
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300730 return "%s.%s(%d, %d, %d)" % (self.__class__.__module__,
731 self.__class__.__qualname__,
732 self._year,
733 self._month,
734 self._day)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000735 # XXX These shouldn't depend on time.localtime(), because that
736 # clips the usable dates to [1970 .. 2038). At least ctime() is
737 # easily done without using strftime() -- that's better too because
738 # strftime("%c", ...) is locale specific.
739
740
741 def ctime(self):
742 "Return ctime() style string."
743 weekday = self.toordinal() % 7 or 7
744 return "%s %s %2d 00:00:00 %04d" % (
745 _DAYNAMES[weekday],
746 _MONTHNAMES[self._month],
747 self._day, self._year)
748
749 def strftime(self, fmt):
750 "Format using strftime()."
751 return _wrap_strftime(self, fmt, self.timetuple())
752
753 def __format__(self, fmt):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400754 if not isinstance(fmt, str):
755 raise TypeError("must be str, not %s" % type(fmt).__name__)
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000756 if len(fmt) != 0:
757 return self.strftime(fmt)
758 return str(self)
759
760 def isoformat(self):
761 """Return the date formatted according to ISO.
762
763 This is 'YYYY-MM-DD'.
764
765 References:
766 - http://www.w3.org/TR/NOTE-datetime
767 - http://www.cl.cam.ac.uk/~mgk25/iso-time.html
768 """
769 return "%04d-%02d-%02d" % (self._year, self._month, self._day)
770
771 __str__ = isoformat
772
773 # Read-only field accessors
774 @property
775 def year(self):
776 """year (1-9999)"""
777 return self._year
778
779 @property
780 def month(self):
781 """month (1-12)"""
782 return self._month
783
784 @property
785 def day(self):
786 """day (1-31)"""
787 return self._day
788
789 # Standard conversions, __cmp__, __hash__ (and helpers)
790
791 def timetuple(self):
792 "Return local time tuple compatible with time.localtime()."
793 return _build_struct_time(self._year, self._month, self._day,
794 0, 0, 0, -1)
795
796 def toordinal(self):
797 """Return proleptic Gregorian ordinal for the year, month and day.
798
799 January 1 of year 1 is day 1. Only the year, month and day values
800 contribute to the result.
801 """
802 return _ymd2ord(self._year, self._month, self._day)
803
804 def replace(self, year=None, month=None, day=None):
805 """Return a new date with new values for the specified fields."""
806 if year is None:
807 year = self._year
808 if month is None:
809 month = self._month
810 if day is None:
811 day = self._day
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000812 return date(year, month, day)
813
814 # Comparisons of date objects with other.
815
816 def __eq__(self, other):
817 if isinstance(other, date):
818 return self._cmp(other) == 0
819 return NotImplemented
820
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000821 def __le__(self, other):
822 if isinstance(other, date):
823 return self._cmp(other) <= 0
824 return NotImplemented
825
826 def __lt__(self, other):
827 if isinstance(other, date):
828 return self._cmp(other) < 0
829 return NotImplemented
830
831 def __ge__(self, other):
832 if isinstance(other, date):
833 return self._cmp(other) >= 0
834 return NotImplemented
835
836 def __gt__(self, other):
837 if isinstance(other, date):
838 return self._cmp(other) > 0
839 return NotImplemented
840
841 def _cmp(self, other):
842 assert isinstance(other, date)
843 y, m, d = self._year, self._month, self._day
844 y2, m2, d2 = other._year, other._month, other._day
845 return _cmp((y, m, d), (y2, m2, d2))
846
847 def __hash__(self):
848 "Hash."
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400849 if self._hashcode == -1:
850 self._hashcode = hash(self._getstate())
851 return self._hashcode
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000852
853 # Computations
854
855 def __add__(self, other):
856 "Add a date to a timedelta."
857 if isinstance(other, timedelta):
858 o = self.toordinal() + other.days
859 if 0 < o <= _MAXORDINAL:
860 return date.fromordinal(o)
861 raise OverflowError("result out of range")
862 return NotImplemented
863
864 __radd__ = __add__
865
866 def __sub__(self, other):
867 """Subtract two dates, or a date and a timedelta."""
868 if isinstance(other, timedelta):
869 return self + timedelta(-other.days)
870 if isinstance(other, date):
871 days1 = self.toordinal()
872 days2 = other.toordinal()
873 return timedelta(days1 - days2)
874 return NotImplemented
875
876 def weekday(self):
877 "Return day of the week, where Monday == 0 ... Sunday == 6."
878 return (self.toordinal() + 6) % 7
879
880 # Day-of-the-week and week-of-the-year, according to ISO
881
882 def isoweekday(self):
883 "Return day of the week, where Monday == 1 ... Sunday == 7."
884 # 1-Jan-0001 is a Monday
885 return self.toordinal() % 7 or 7
886
887 def isocalendar(self):
888 """Return a 3-tuple containing ISO year, week number, and weekday.
889
890 The first ISO week of the year is the (Mon-Sun) week
891 containing the year's first Thursday; everything else derives
892 from that.
893
894 The first week is 1; Monday is 1 ... Sunday is 7.
895
896 ISO calendar algorithm taken from
897 http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
898 """
899 year = self._year
900 week1monday = _isoweek1monday(year)
901 today = _ymd2ord(self._year, self._month, self._day)
902 # Internally, week and day have origin 0
903 week, day = divmod(today - week1monday, 7)
904 if week < 0:
905 year -= 1
906 week1monday = _isoweek1monday(year)
907 week, day = divmod(today - week1monday, 7)
908 elif week >= 52:
909 if today >= _isoweek1monday(year+1):
910 year += 1
911 week = 0
912 return year, week+1, day+1
913
914 # Pickle support.
915
916 def _getstate(self):
917 yhi, ylo = divmod(self._year, 256)
918 return bytes([yhi, ylo, self._month, self._day]),
919
920 def __setstate(self, string):
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000921 yhi, ylo, self._month, self._day = string
922 self._year = yhi * 256 + ylo
923
924 def __reduce__(self):
925 return (self.__class__, self._getstate())
926
927_date_class = date # so functions w/ args named "date" can get at the class
928
929date.min = date(1, 1, 1)
930date.max = date(9999, 12, 31)
931date.resolution = timedelta(days=1)
932
933class tzinfo:
934 """Abstract base class for time zone info classes.
935
936 Subclasses must override the name(), utcoffset() and dst() methods.
937 """
938 __slots__ = ()
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -0400939
Alexander Belopolskycf86e362010-07-23 19:25:47 +0000940 def tzname(self, dt):
941 "datetime -> string name of time zone."
942 raise NotImplementedError("tzinfo subclass must override tzname()")
943
944 def utcoffset(self, dt):
945 "datetime -> minutes east of UTC (negative for west of UTC)"
946 raise NotImplementedError("tzinfo subclass must override utcoffset()")
947
948 def dst(self, dt):
949 """datetime -> DST offset in minutes east of UTC.
950
951 Return 0 if DST not in effect. utcoffset() must include the DST
952 offset.
953 """
954 raise NotImplementedError("tzinfo subclass must override dst()")
955
956 def fromutc(self, dt):
957 "datetime in UTC -> datetime in local time."
958
959 if not isinstance(dt, datetime):
960 raise TypeError("fromutc() requires a datetime argument")
961 if dt.tzinfo is not self:
962 raise ValueError("dt.tzinfo is not self")
963
964 dtoff = dt.utcoffset()
965 if dtoff is None:
966 raise ValueError("fromutc() requires a non-None utcoffset() "
967 "result")
968
969 # See the long comment block at the end of this file for an
970 # explanation of this algorithm.
971 dtdst = dt.dst()
972 if dtdst is None:
973 raise ValueError("fromutc() requires a non-None dst() result")
974 delta = dtoff - dtdst
975 if delta:
976 dt += delta
977 dtdst = dt.dst()
978 if dtdst is None:
979 raise ValueError("fromutc(): dt.dst gave inconsistent "
980 "results; cannot convert")
981 return dt + dtdst
982
983 # Pickle support.
984
985 def __reduce__(self):
986 getinitargs = getattr(self, "__getinitargs__", None)
987 if getinitargs:
988 args = getinitargs()
989 else:
990 args = ()
991 getstate = getattr(self, "__getstate__", None)
992 if getstate:
993 state = getstate()
994 else:
995 state = getattr(self, "__dict__", None) or None
996 if state is None:
997 return (self.__class__, args)
998 else:
999 return (self.__class__, args, state)
1000
1001_tzinfo_class = tzinfo
1002
1003class time:
1004 """Time with time zone.
1005
1006 Constructors:
1007
1008 __new__()
1009
1010 Operators:
1011
1012 __repr__, __str__
1013 __cmp__, __hash__
1014
1015 Methods:
1016
1017 strftime()
1018 isoformat()
1019 utcoffset()
1020 tzname()
1021 dst()
1022
1023 Properties (readonly):
1024 hour, minute, second, microsecond, tzinfo
1025 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001026 __slots__ = '_hour', '_minute', '_second', '_microsecond', '_tzinfo', '_hashcode'
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001027
1028 def __new__(cls, hour=0, minute=0, second=0, microsecond=0, tzinfo=None):
1029 """Constructor.
1030
1031 Arguments:
1032
1033 hour, minute (required)
1034 second, microsecond (default to zero)
1035 tzinfo (default to None)
1036 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001037 if isinstance(hour, bytes) and len(hour) == 6 and hour[0] < 24:
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001038 # Pickle support
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001039 self = object.__new__(cls)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001040 self.__setstate(hour, minute or None)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001041 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001042 return self
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001043 hour, minute, second, microsecond = _check_time_fields(
1044 hour, minute, second, microsecond)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001045 _check_tzinfo_arg(tzinfo)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001046 self = object.__new__(cls)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001047 self._hour = hour
1048 self._minute = minute
1049 self._second = second
1050 self._microsecond = microsecond
1051 self._tzinfo = tzinfo
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001052 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001053 return self
1054
1055 # Read-only field accessors
1056 @property
1057 def hour(self):
1058 """hour (0-23)"""
1059 return self._hour
1060
1061 @property
1062 def minute(self):
1063 """minute (0-59)"""
1064 return self._minute
1065
1066 @property
1067 def second(self):
1068 """second (0-59)"""
1069 return self._second
1070
1071 @property
1072 def microsecond(self):
1073 """microsecond (0-999999)"""
1074 return self._microsecond
1075
1076 @property
1077 def tzinfo(self):
1078 """timezone info object"""
1079 return self._tzinfo
1080
1081 # Standard conversions, __hash__ (and helpers)
1082
1083 # Comparisons of time objects with other.
1084
1085 def __eq__(self, other):
1086 if isinstance(other, time):
Alexander Belopolsky08313822012-06-15 20:19:47 -04001087 return self._cmp(other, allow_mixed=True) == 0
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001088 else:
1089 return False
1090
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001091 def __le__(self, other):
1092 if isinstance(other, time):
1093 return self._cmp(other) <= 0
1094 else:
1095 _cmperror(self, other)
1096
1097 def __lt__(self, other):
1098 if isinstance(other, time):
1099 return self._cmp(other) < 0
1100 else:
1101 _cmperror(self, other)
1102
1103 def __ge__(self, other):
1104 if isinstance(other, time):
1105 return self._cmp(other) >= 0
1106 else:
1107 _cmperror(self, other)
1108
1109 def __gt__(self, other):
1110 if isinstance(other, time):
1111 return self._cmp(other) > 0
1112 else:
1113 _cmperror(self, other)
1114
Alexander Belopolsky08313822012-06-15 20:19:47 -04001115 def _cmp(self, other, allow_mixed=False):
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001116 assert isinstance(other, time)
1117 mytz = self._tzinfo
1118 ottz = other._tzinfo
1119 myoff = otoff = None
1120
1121 if mytz is ottz:
1122 base_compare = True
1123 else:
1124 myoff = self.utcoffset()
1125 otoff = other.utcoffset()
1126 base_compare = myoff == otoff
1127
1128 if base_compare:
1129 return _cmp((self._hour, self._minute, self._second,
1130 self._microsecond),
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001131 (other._hour, other._minute, other._second,
1132 other._microsecond))
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001133 if myoff is None or otoff is None:
Alexander Belopolsky08313822012-06-15 20:19:47 -04001134 if allow_mixed:
1135 return 2 # arbitrary non-zero value
1136 else:
1137 raise TypeError("cannot compare naive and aware times")
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001138 myhhmm = self._hour * 60 + self._minute - myoff//timedelta(minutes=1)
1139 othhmm = other._hour * 60 + other._minute - otoff//timedelta(minutes=1)
1140 return _cmp((myhhmm, self._second, self._microsecond),
1141 (othhmm, other._second, other._microsecond))
1142
1143 def __hash__(self):
1144 """Hash."""
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001145 if self._hashcode == -1:
1146 tzoff = self.utcoffset()
1147 if not tzoff: # zero or None
1148 self._hashcode = hash(self._getstate()[0])
1149 else:
1150 h, m = divmod(timedelta(hours=self.hour, minutes=self.minute) - tzoff,
1151 timedelta(hours=1))
1152 assert not m % timedelta(minutes=1), "whole minute"
1153 m //= timedelta(minutes=1)
1154 if 0 <= h < 24:
1155 self._hashcode = hash(time(h, m, self.second, self.microsecond))
1156 else:
1157 self._hashcode = hash((h, m, self.second, self.microsecond))
1158 return self._hashcode
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001159
1160 # Conversion to string
1161
1162 def _tzstr(self, sep=":"):
1163 """Return formatted timezone offset (+xx:xx) or None."""
1164 off = self.utcoffset()
1165 if off is not None:
1166 if off.days < 0:
1167 sign = "-"
1168 off = -off
1169 else:
1170 sign = "+"
1171 hh, mm = divmod(off, timedelta(hours=1))
1172 assert not mm % timedelta(minutes=1), "whole minute"
1173 mm //= timedelta(minutes=1)
1174 assert 0 <= hh < 24
1175 off = "%s%02d%s%02d" % (sign, hh, sep, mm)
1176 return off
1177
1178 def __repr__(self):
1179 """Convert to formal string, for repr()."""
1180 if self._microsecond != 0:
1181 s = ", %d, %d" % (self._second, self._microsecond)
1182 elif self._second != 0:
1183 s = ", %d" % self._second
1184 else:
1185 s = ""
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001186 s= "%s.%s(%d, %d%s)" % (self.__class__.__module__,
1187 self.__class__.__qualname__,
1188 self._hour, self._minute, s)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001189 if self._tzinfo is not None:
1190 assert s[-1:] == ")"
1191 s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
1192 return s
1193
1194 def isoformat(self):
1195 """Return the time formatted according to ISO.
1196
1197 This is 'HH:MM:SS.mmmmmm+zz:zz', or 'HH:MM:SS+zz:zz' if
1198 self.microsecond == 0.
1199 """
1200 s = _format_time(self._hour, self._minute, self._second,
1201 self._microsecond)
1202 tz = self._tzstr()
1203 if tz:
1204 s += tz
1205 return s
1206
1207 __str__ = isoformat
1208
1209 def strftime(self, fmt):
1210 """Format using strftime(). The date part of the timestamp passed
1211 to underlying strftime should not be used.
1212 """
Alexander Belopolskyb8bb4662011-01-08 00:13:34 +00001213 # The year must be >= 1000 else Python's strftime implementation
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001214 # can raise a bogus exception.
1215 timetuple = (1900, 1, 1,
1216 self._hour, self._minute, self._second,
1217 0, 1, -1)
1218 return _wrap_strftime(self, fmt, timetuple)
1219
1220 def __format__(self, fmt):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001221 if not isinstance(fmt, str):
1222 raise TypeError("must be str, not %s" % type(fmt).__name__)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001223 if len(fmt) != 0:
1224 return self.strftime(fmt)
1225 return str(self)
1226
1227 # Timezone functions
1228
1229 def utcoffset(self):
1230 """Return the timezone offset in minutes east of UTC (negative west of
1231 UTC)."""
1232 if self._tzinfo is None:
1233 return None
1234 offset = self._tzinfo.utcoffset(None)
1235 _check_utc_offset("utcoffset", offset)
1236 return offset
1237
1238 def tzname(self):
1239 """Return the timezone name.
1240
1241 Note that the name is 100% informational -- there's no requirement that
1242 it mean anything in particular. For example, "GMT", "UTC", "-500",
1243 "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
1244 """
1245 if self._tzinfo is None:
1246 return None
1247 name = self._tzinfo.tzname(None)
1248 _check_tzname(name)
1249 return name
1250
1251 def dst(self):
1252 """Return 0 if DST is not in effect, or the DST offset (in minutes
1253 eastward) if DST is in effect.
1254
1255 This is purely informational; the DST offset has already been added to
1256 the UTC offset returned by utcoffset() if applicable, so there's no
1257 need to consult dst() unless you're interested in displaying the DST
1258 info.
1259 """
1260 if self._tzinfo is None:
1261 return None
1262 offset = self._tzinfo.dst(None)
1263 _check_utc_offset("dst", offset)
1264 return offset
1265
1266 def replace(self, hour=None, minute=None, second=None, microsecond=None,
1267 tzinfo=True):
1268 """Return a new time with new values for the specified fields."""
1269 if hour is None:
1270 hour = self.hour
1271 if minute is None:
1272 minute = self.minute
1273 if second is None:
1274 second = self.second
1275 if microsecond is None:
1276 microsecond = self.microsecond
1277 if tzinfo is True:
1278 tzinfo = self.tzinfo
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001279 return time(hour, minute, second, microsecond, tzinfo)
1280
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001281 # Pickle support.
1282
1283 def _getstate(self):
1284 us2, us3 = divmod(self._microsecond, 256)
1285 us1, us2 = divmod(us2, 256)
1286 basestate = bytes([self._hour, self._minute, self._second,
1287 us1, us2, us3])
1288 if self._tzinfo is None:
1289 return (basestate,)
1290 else:
1291 return (basestate, self._tzinfo)
1292
1293 def __setstate(self, string, tzinfo):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001294 if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
1295 raise TypeError("bad tzinfo state arg")
1296 self._hour, self._minute, self._second, us1, us2, us3 = string
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001297 self._microsecond = (((us1 << 8) | us2) << 8) | us3
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001298 self._tzinfo = tzinfo
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001299
1300 def __reduce__(self):
1301 return (time, self._getstate())
1302
1303_time_class = time # so functions w/ args named "time" can get at the class
1304
1305time.min = time(0, 0, 0)
1306time.max = time(23, 59, 59, 999999)
1307time.resolution = timedelta(microseconds=1)
1308
1309class datetime(date):
1310 """datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
1311
1312 The year, month and day arguments are required. tzinfo may be None, or an
Serhiy Storchaka95949422013-08-27 19:40:23 +03001313 instance of a tzinfo subclass. The remaining arguments may be ints.
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001314 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001315 __slots__ = date.__slots__ + time.__slots__
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001316
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001317 def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
1318 microsecond=0, tzinfo=None):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001319 if isinstance(year, bytes) and len(year) == 10 and 1 <= year[2] <= 12:
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001320 # Pickle support
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001321 self = object.__new__(cls)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001322 self.__setstate(year, month)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001323 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001324 return self
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001325 year, month, day = _check_date_fields(year, month, day)
1326 hour, minute, second, microsecond = _check_time_fields(
1327 hour, minute, second, microsecond)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001328 _check_tzinfo_arg(tzinfo)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001329 self = object.__new__(cls)
1330 self._year = year
1331 self._month = month
1332 self._day = day
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001333 self._hour = hour
1334 self._minute = minute
1335 self._second = second
1336 self._microsecond = microsecond
1337 self._tzinfo = tzinfo
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001338 self._hashcode = -1
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001339 return self
1340
1341 # Read-only field accessors
1342 @property
1343 def hour(self):
1344 """hour (0-23)"""
1345 return self._hour
1346
1347 @property
1348 def minute(self):
1349 """minute (0-59)"""
1350 return self._minute
1351
1352 @property
1353 def second(self):
1354 """second (0-59)"""
1355 return self._second
1356
1357 @property
1358 def microsecond(self):
1359 """microsecond (0-999999)"""
1360 return self._microsecond
1361
1362 @property
1363 def tzinfo(self):
1364 """timezone info object"""
1365 return self._tzinfo
1366
1367 @classmethod
1368 def fromtimestamp(cls, t, tz=None):
1369 """Construct a datetime from a POSIX timestamp (like time.time()).
1370
1371 A timezone info object may be passed in as well.
1372 """
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001373 _check_tzinfo_arg(tz)
Alexander Belopolskyaeb03982010-07-26 02:36:41 +00001374
1375 converter = _time.localtime if tz is None else _time.gmtime
1376
1377 t, frac = divmod(t, 1.0)
Victor Stinner5d272cc2012-03-13 13:35:55 +01001378 us = int(frac * 1e6)
Alexander Belopolskyaeb03982010-07-26 02:36:41 +00001379
1380 # If timestamp is less than one microsecond smaller than a
1381 # full second, us can be rounded up to 1000000. In this case,
1382 # roll over to seconds, otherwise, ValueError is raised
1383 # by the constructor.
1384 if us == 1000000:
1385 t += 1
1386 us = 0
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001387 y, m, d, hh, mm, ss, weekday, jday, dst = converter(t)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001388 ss = min(ss, 59) # clamp out leap seconds if the platform has them
1389 result = cls(y, m, d, hh, mm, ss, us, tz)
1390 if tz is not None:
1391 result = tz.fromutc(result)
1392 return result
1393
1394 @classmethod
1395 def utcfromtimestamp(cls, t):
Alexander Belopolskye2e178e2015-03-01 14:52:07 -05001396 """Construct a naive UTC datetime from a POSIX timestamp."""
Alexander Belopolsky3e62f782010-09-21 16:30:56 +00001397 t, frac = divmod(t, 1.0)
Victor Stinner5d272cc2012-03-13 13:35:55 +01001398 us = int(frac * 1e6)
Alexander Belopolsky3e62f782010-09-21 16:30:56 +00001399
1400 # If timestamp is less than one microsecond smaller than a
1401 # full second, us can be rounded up to 1000000. In this case,
1402 # roll over to seconds, otherwise, ValueError is raised
1403 # by the constructor.
1404 if us == 1000000:
1405 t += 1
1406 us = 0
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001407 y, m, d, hh, mm, ss, weekday, jday, dst = _time.gmtime(t)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001408 ss = min(ss, 59) # clamp out leap seconds if the platform has them
1409 return cls(y, m, d, hh, mm, ss, us)
1410
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001411 @classmethod
1412 def now(cls, tz=None):
1413 "Construct a datetime from time.time() and optional time zone info."
1414 t = _time.time()
1415 return cls.fromtimestamp(t, tz)
1416
1417 @classmethod
1418 def utcnow(cls):
1419 "Construct a UTC datetime from time.time()."
1420 t = _time.time()
1421 return cls.utcfromtimestamp(t)
1422
1423 @classmethod
1424 def combine(cls, date, time):
1425 "Construct a datetime from a given date and a given time."
1426 if not isinstance(date, _date_class):
1427 raise TypeError("date argument must be a date instance")
1428 if not isinstance(time, _time_class):
1429 raise TypeError("time argument must be a time instance")
1430 return cls(date.year, date.month, date.day,
1431 time.hour, time.minute, time.second, time.microsecond,
1432 time.tzinfo)
1433
1434 def timetuple(self):
1435 "Return local time tuple compatible with time.localtime()."
1436 dst = self.dst()
1437 if dst is None:
1438 dst = -1
1439 elif dst:
1440 dst = 1
1441 else:
1442 dst = 0
1443 return _build_struct_time(self.year, self.month, self.day,
1444 self.hour, self.minute, self.second,
1445 dst)
1446
Alexander Belopolskya4415142012-06-08 12:33:09 -04001447 def timestamp(self):
1448 "Return POSIX timestamp as float"
1449 if self._tzinfo is None:
1450 return _time.mktime((self.year, self.month, self.day,
1451 self.hour, self.minute, self.second,
1452 -1, -1, -1)) + self.microsecond / 1e6
1453 else:
1454 return (self - _EPOCH).total_seconds()
1455
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001456 def utctimetuple(self):
1457 "Return UTC time tuple compatible with time.gmtime()."
1458 offset = self.utcoffset()
1459 if offset:
1460 self -= offset
1461 y, m, d = self.year, self.month, self.day
1462 hh, mm, ss = self.hour, self.minute, self.second
1463 return _build_struct_time(y, m, d, hh, mm, ss, 0)
1464
1465 def date(self):
1466 "Return the date part."
1467 return date(self._year, self._month, self._day)
1468
1469 def time(self):
1470 "Return the time part, with tzinfo None."
1471 return time(self.hour, self.minute, self.second, self.microsecond)
1472
1473 def timetz(self):
1474 "Return the time part, with same tzinfo."
1475 return time(self.hour, self.minute, self.second, self.microsecond,
1476 self._tzinfo)
1477
1478 def replace(self, year=None, month=None, day=None, hour=None,
1479 minute=None, second=None, microsecond=None, tzinfo=True):
1480 """Return a new datetime with new values for the specified fields."""
1481 if year is None:
1482 year = self.year
1483 if month is None:
1484 month = self.month
1485 if day is None:
1486 day = self.day
1487 if hour is None:
1488 hour = self.hour
1489 if minute is None:
1490 minute = self.minute
1491 if second is None:
1492 second = self.second
1493 if microsecond is None:
1494 microsecond = self.microsecond
1495 if tzinfo is True:
1496 tzinfo = self.tzinfo
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001497 return datetime(year, month, day, hour, minute, second, microsecond,
1498 tzinfo)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001499
Alexander Belopolskyfdc860f2012-06-22 12:23:23 -04001500 def astimezone(self, tz=None):
1501 if tz is None:
1502 if self.tzinfo is None:
1503 raise ValueError("astimezone() requires an aware datetime")
1504 ts = (self - _EPOCH) // timedelta(seconds=1)
1505 localtm = _time.localtime(ts)
1506 local = datetime(*localtm[:6])
1507 try:
Alexander Belopolskyff493c92012-06-22 12:25:57 -04001508 # Extract TZ data if available
Alexander Belopolskyfdc860f2012-06-22 12:23:23 -04001509 gmtoff = localtm.tm_gmtoff
1510 zone = localtm.tm_zone
1511 except AttributeError:
1512 # Compute UTC offset and compare with the value implied
1513 # by tm_isdst. If the values match, use the zone name
1514 # implied by tm_isdst.
1515 delta = local - datetime(*_time.gmtime(ts)[:6])
1516 dst = _time.daylight and localtm.tm_isdst > 0
Alexander Belopolsky93c9cd02012-06-22 16:04:19 -04001517 gmtoff = -(_time.altzone if dst else _time.timezone)
1518 if delta == timedelta(seconds=gmtoff):
Alexander Belopolskyfdc860f2012-06-22 12:23:23 -04001519 tz = timezone(delta, _time.tzname[dst])
1520 else:
1521 tz = timezone(delta)
1522 else:
Alexander Belopolsky93c9cd02012-06-22 16:04:19 -04001523 tz = timezone(timedelta(seconds=gmtoff), zone)
Alexander Belopolskyff493c92012-06-22 12:25:57 -04001524
Alexander Belopolskyfdc860f2012-06-22 12:23:23 -04001525 elif not isinstance(tz, tzinfo):
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001526 raise TypeError("tz argument must be an instance of tzinfo")
1527
1528 mytz = self.tzinfo
1529 if mytz is None:
1530 raise ValueError("astimezone() requires an aware datetime")
1531
1532 if tz is mytz:
1533 return self
1534
1535 # Convert self to UTC, and attach the new time zone object.
1536 myoffset = self.utcoffset()
1537 if myoffset is None:
1538 raise ValueError("astimezone() requires an aware datetime")
1539 utc = (self - myoffset).replace(tzinfo=tz)
1540
1541 # Convert from UTC to tz's local time.
1542 return tz.fromutc(utc)
1543
1544 # Ways to produce a string.
1545
1546 def ctime(self):
1547 "Return ctime() style string."
1548 weekday = self.toordinal() % 7 or 7
1549 return "%s %s %2d %02d:%02d:%02d %04d" % (
1550 _DAYNAMES[weekday],
1551 _MONTHNAMES[self._month],
1552 self._day,
1553 self._hour, self._minute, self._second,
1554 self._year)
1555
1556 def isoformat(self, sep='T'):
1557 """Return the time formatted according to ISO.
1558
1559 This is 'YYYY-MM-DD HH:MM:SS.mmmmmm', or 'YYYY-MM-DD HH:MM:SS' if
1560 self.microsecond == 0.
1561
1562 If self.tzinfo is not None, the UTC offset is also attached, giving
1563 'YYYY-MM-DD HH:MM:SS.mmmmmm+HH:MM' or 'YYYY-MM-DD HH:MM:SS+HH:MM'.
1564
1565 Optional argument sep specifies the separator between date and
1566 time, default 'T'.
1567 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001568 s = ("%04d-%02d-%02d%c" % (self._year, self._month, self._day, sep) +
1569 _format_time(self._hour, self._minute, self._second,
1570 self._microsecond))
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001571 off = self.utcoffset()
1572 if off is not None:
1573 if off.days < 0:
1574 sign = "-"
1575 off = -off
1576 else:
1577 sign = "+"
1578 hh, mm = divmod(off, timedelta(hours=1))
1579 assert not mm % timedelta(minutes=1), "whole minute"
1580 mm //= timedelta(minutes=1)
1581 s += "%s%02d:%02d" % (sign, hh, mm)
1582 return s
1583
1584 def __repr__(self):
1585 """Convert to formal string, for repr()."""
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001586 L = [self._year, self._month, self._day, # These are never zero
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001587 self._hour, self._minute, self._second, self._microsecond]
1588 if L[-1] == 0:
1589 del L[-1]
1590 if L[-1] == 0:
1591 del L[-1]
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001592 s = "%s.%s(%s)" % (self.__class__.__module__,
1593 self.__class__.__qualname__,
1594 ", ".join(map(str, L)))
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001595 if self._tzinfo is not None:
1596 assert s[-1:] == ")"
1597 s = s[:-1] + ", tzinfo=%r" % self._tzinfo + ")"
1598 return s
1599
1600 def __str__(self):
1601 "Convert to string, for str()."
1602 return self.isoformat(sep=' ')
1603
1604 @classmethod
1605 def strptime(cls, date_string, format):
1606 'string, format -> new datetime parsed from a string (like time.strptime()).'
1607 import _strptime
1608 return _strptime._strptime_datetime(cls, date_string, format)
1609
1610 def utcoffset(self):
1611 """Return the timezone offset in minutes east of UTC (negative west of
1612 UTC)."""
1613 if self._tzinfo is None:
1614 return None
1615 offset = self._tzinfo.utcoffset(self)
1616 _check_utc_offset("utcoffset", offset)
1617 return offset
1618
1619 def tzname(self):
1620 """Return the timezone name.
1621
1622 Note that the name is 100% informational -- there's no requirement that
1623 it mean anything in particular. For example, "GMT", "UTC", "-500",
1624 "-5:00", "EDT", "US/Eastern", "America/New York" are all valid replies.
1625 """
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001626 if self._tzinfo is None:
1627 return None
1628 name = self._tzinfo.tzname(self)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001629 _check_tzname(name)
1630 return name
1631
1632 def dst(self):
1633 """Return 0 if DST is not in effect, or the DST offset (in minutes
1634 eastward) if DST is in effect.
1635
1636 This is purely informational; the DST offset has already been added to
1637 the UTC offset returned by utcoffset() if applicable, so there's no
1638 need to consult dst() unless you're interested in displaying the DST
1639 info.
1640 """
1641 if self._tzinfo is None:
1642 return None
1643 offset = self._tzinfo.dst(self)
1644 _check_utc_offset("dst", offset)
1645 return offset
1646
1647 # Comparisons of datetime objects with other.
1648
1649 def __eq__(self, other):
1650 if isinstance(other, datetime):
Alexander Belopolsky08313822012-06-15 20:19:47 -04001651 return self._cmp(other, allow_mixed=True) == 0
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001652 elif not isinstance(other, date):
1653 return NotImplemented
1654 else:
1655 return False
1656
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001657 def __le__(self, other):
1658 if isinstance(other, datetime):
1659 return self._cmp(other) <= 0
1660 elif not isinstance(other, date):
1661 return NotImplemented
1662 else:
1663 _cmperror(self, other)
1664
1665 def __lt__(self, other):
1666 if isinstance(other, datetime):
1667 return self._cmp(other) < 0
1668 elif not isinstance(other, date):
1669 return NotImplemented
1670 else:
1671 _cmperror(self, other)
1672
1673 def __ge__(self, other):
1674 if isinstance(other, datetime):
1675 return self._cmp(other) >= 0
1676 elif not isinstance(other, date):
1677 return NotImplemented
1678 else:
1679 _cmperror(self, other)
1680
1681 def __gt__(self, other):
1682 if isinstance(other, datetime):
1683 return self._cmp(other) > 0
1684 elif not isinstance(other, date):
1685 return NotImplemented
1686 else:
1687 _cmperror(self, other)
1688
Alexander Belopolsky08313822012-06-15 20:19:47 -04001689 def _cmp(self, other, allow_mixed=False):
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001690 assert isinstance(other, datetime)
1691 mytz = self._tzinfo
1692 ottz = other._tzinfo
1693 myoff = otoff = None
1694
1695 if mytz is ottz:
1696 base_compare = True
1697 else:
Alexander Belopolsky016ef552012-06-15 18:15:25 -04001698 myoff = self.utcoffset()
1699 otoff = other.utcoffset()
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001700 base_compare = myoff == otoff
1701
1702 if base_compare:
1703 return _cmp((self._year, self._month, self._day,
1704 self._hour, self._minute, self._second,
1705 self._microsecond),
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001706 (other._year, other._month, other._day,
1707 other._hour, other._minute, other._second,
1708 other._microsecond))
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001709 if myoff is None or otoff is None:
Alexander Belopolsky08313822012-06-15 20:19:47 -04001710 if allow_mixed:
1711 return 2 # arbitrary non-zero value
1712 else:
1713 raise TypeError("cannot compare naive and aware datetimes")
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001714 # XXX What follows could be done more efficiently...
1715 diff = self - other # this will take offsets into account
1716 if diff.days < 0:
1717 return -1
1718 return diff and 1 or 0
1719
1720 def __add__(self, other):
1721 "Add a datetime and a timedelta."
1722 if not isinstance(other, timedelta):
1723 return NotImplemented
1724 delta = timedelta(self.toordinal(),
1725 hours=self._hour,
1726 minutes=self._minute,
1727 seconds=self._second,
1728 microseconds=self._microsecond)
1729 delta += other
1730 hour, rem = divmod(delta.seconds, 3600)
1731 minute, second = divmod(rem, 60)
1732 if 0 < delta.days <= _MAXORDINAL:
1733 return datetime.combine(date.fromordinal(delta.days),
1734 time(hour, minute, second,
1735 delta.microseconds,
1736 tzinfo=self._tzinfo))
1737 raise OverflowError("result out of range")
1738
1739 __radd__ = __add__
1740
1741 def __sub__(self, other):
1742 "Subtract two datetimes, or a datetime and a timedelta."
1743 if not isinstance(other, datetime):
1744 if isinstance(other, timedelta):
1745 return self + -other
1746 return NotImplemented
1747
1748 days1 = self.toordinal()
1749 days2 = other.toordinal()
1750 secs1 = self._second + self._minute * 60 + self._hour * 3600
1751 secs2 = other._second + other._minute * 60 + other._hour * 3600
1752 base = timedelta(days1 - days2,
1753 secs1 - secs2,
1754 self._microsecond - other._microsecond)
1755 if self._tzinfo is other._tzinfo:
1756 return base
1757 myoff = self.utcoffset()
1758 otoff = other.utcoffset()
1759 if myoff == otoff:
1760 return base
1761 if myoff is None or otoff is None:
1762 raise TypeError("cannot mix naive and timezone-aware time")
1763 return base + otoff - myoff
1764
1765 def __hash__(self):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001766 if self._hashcode == -1:
1767 tzoff = self.utcoffset()
1768 if tzoff is None:
1769 self._hashcode = hash(self._getstate()[0])
1770 else:
1771 days = _ymd2ord(self.year, self.month, self.day)
1772 seconds = self.hour * 3600 + self.minute * 60 + self.second
1773 self._hashcode = hash(timedelta(days, seconds, self.microsecond) - tzoff)
1774 return self._hashcode
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001775
1776 # Pickle support.
1777
1778 def _getstate(self):
1779 yhi, ylo = divmod(self._year, 256)
1780 us2, us3 = divmod(self._microsecond, 256)
1781 us1, us2 = divmod(us2, 256)
1782 basestate = bytes([yhi, ylo, self._month, self._day,
1783 self._hour, self._minute, self._second,
1784 us1, us2, us3])
1785 if self._tzinfo is None:
1786 return (basestate,)
1787 else:
1788 return (basestate, self._tzinfo)
1789
1790 def __setstate(self, string, tzinfo):
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001791 if tzinfo is not None and not isinstance(tzinfo, _tzinfo_class):
1792 raise TypeError("bad tzinfo state arg")
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001793 (yhi, ylo, self._month, self._day, self._hour,
1794 self._minute, self._second, us1, us2, us3) = string
1795 self._year = yhi * 256 + ylo
1796 self._microsecond = (((us1 << 8) | us2) << 8) | us3
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001797 self._tzinfo = tzinfo
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001798
1799 def __reduce__(self):
1800 return (self.__class__, self._getstate())
1801
1802
1803datetime.min = datetime(1, 1, 1)
1804datetime.max = datetime(9999, 12, 31, 23, 59, 59, 999999)
1805datetime.resolution = timedelta(microseconds=1)
1806
1807
1808def _isoweek1monday(year):
1809 # Helper to calculate the day number of the Monday starting week 1
1810 # XXX This could be done more efficiently
1811 THURSDAY = 3
1812 firstday = _ymd2ord(year, 1, 1)
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001813 firstweekday = (firstday + 6) % 7 # See weekday() above
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001814 week1monday = firstday - firstweekday
1815 if firstweekday > THURSDAY:
1816 week1monday += 7
1817 return week1monday
1818
1819class timezone(tzinfo):
1820 __slots__ = '_offset', '_name'
1821
1822 # Sentinel value to disallow None
1823 _Omitted = object()
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001824 def __new__(cls, offset, name=_Omitted):
1825 if not isinstance(offset, timedelta):
1826 raise TypeError("offset must be a timedelta")
1827 if name is cls._Omitted:
1828 if not offset:
1829 return cls.utc
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001830 name = None
1831 elif not isinstance(name, str):
1832 raise TypeError("name must be a string")
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001833 if not cls._minoffset <= offset <= cls._maxoffset:
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04001834 raise ValueError("offset must be a timedelta "
1835 "strictly between -timedelta(hours=24) and "
1836 "timedelta(hours=24).")
1837 if (offset.microseconds != 0 or offset.seconds % 60 != 0):
1838 raise ValueError("offset must be a timedelta "
1839 "representing a whole number of minutes")
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001840 return cls._create(offset, name)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001841
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001842 @classmethod
1843 def _create(cls, offset, name=None):
1844 self = tzinfo.__new__(cls)
1845 self._offset = offset
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001846 self._name = name
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001847 return self
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001848
1849 def __getinitargs__(self):
1850 """pickle support"""
1851 if self._name is None:
1852 return (self._offset,)
1853 return (self._offset, self._name)
1854
1855 def __eq__(self, other):
Georg Brandl0085a242012-09-22 09:23:12 +02001856 if type(other) != timezone:
1857 return False
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001858 return self._offset == other._offset
1859
1860 def __hash__(self):
1861 return hash(self._offset)
1862
1863 def __repr__(self):
1864 """Convert to formal string, for repr().
1865
1866 >>> tz = timezone.utc
1867 >>> repr(tz)
1868 'datetime.timezone.utc'
1869 >>> tz = timezone(timedelta(hours=-5), 'EST')
1870 >>> repr(tz)
1871 "datetime.timezone(datetime.timedelta(-1, 68400), 'EST')"
1872 """
1873 if self is self.utc:
1874 return 'datetime.timezone.utc'
1875 if self._name is None:
Serhiy Storchaka465e60e2014-07-25 23:36:00 +03001876 return "%s.%s(%r)" % (self.__class__.__module__,
1877 self.__class__.__qualname__,
1878 self._offset)
1879 return "%s.%s(%r, %r)" % (self.__class__.__module__,
1880 self.__class__.__qualname__,
1881 self._offset, self._name)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001882
1883 def __str__(self):
1884 return self.tzname(None)
1885
1886 def utcoffset(self, dt):
1887 if isinstance(dt, datetime) or dt is None:
1888 return self._offset
1889 raise TypeError("utcoffset() argument must be a datetime instance"
1890 " or None")
1891
1892 def tzname(self, dt):
1893 if isinstance(dt, datetime) or dt is None:
1894 if self._name is None:
1895 return self._name_from_offset(self._offset)
1896 return self._name
1897 raise TypeError("tzname() argument must be a datetime instance"
1898 " or None")
1899
1900 def dst(self, dt):
1901 if isinstance(dt, datetime) or dt is None:
1902 return None
1903 raise TypeError("dst() argument must be a datetime instance"
1904 " or None")
1905
1906 def fromutc(self, dt):
1907 if isinstance(dt, datetime):
1908 if dt.tzinfo is not self:
1909 raise ValueError("fromutc: dt.tzinfo "
1910 "is not self")
1911 return dt + self._offset
1912 raise TypeError("fromutc() argument must be a datetime instance"
1913 " or None")
1914
1915 _maxoffset = timedelta(hours=23, minutes=59)
1916 _minoffset = -_maxoffset
1917
1918 @staticmethod
1919 def _name_from_offset(delta):
1920 if delta < timedelta(0):
1921 sign = '-'
1922 delta = -delta
1923 else:
1924 sign = '+'
1925 hours, rest = divmod(delta, timedelta(hours=1))
1926 minutes = rest // timedelta(minutes=1)
1927 return 'UTC{}{:02d}:{:02d}'.format(sign, hours, minutes)
1928
Alexander Belopolsky1bcbaab2010-10-14 17:03:51 +00001929timezone.utc = timezone._create(timedelta(0))
1930timezone.min = timezone._create(timezone._minoffset)
1931timezone.max = timezone._create(timezone._maxoffset)
Alexander Belopolskya4415142012-06-08 12:33:09 -04001932_EPOCH = datetime(1970, 1, 1, tzinfo=timezone.utc)
Alexander Belopolskycf86e362010-07-23 19:25:47 +00001933
Victor Stinner765531d2013-03-26 01:11:54 +01001934# Some time zone algebra. For a datetime x, let
1935# x.n = x stripped of its timezone -- its naive time.
1936# x.o = x.utcoffset(), and assuming that doesn't raise an exception or
1937# return None
1938# x.d = x.dst(), and assuming that doesn't raise an exception or
1939# return None
1940# x.s = x's standard offset, x.o - x.d
1941#
1942# Now some derived rules, where k is a duration (timedelta).
1943#
1944# 1. x.o = x.s + x.d
1945# This follows from the definition of x.s.
1946#
1947# 2. If x and y have the same tzinfo member, x.s = y.s.
1948# This is actually a requirement, an assumption we need to make about
1949# sane tzinfo classes.
1950#
1951# 3. The naive UTC time corresponding to x is x.n - x.o.
1952# This is again a requirement for a sane tzinfo class.
1953#
1954# 4. (x+k).s = x.s
1955# This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
1956#
1957# 5. (x+k).n = x.n + k
1958# Again follows from how arithmetic is defined.
1959#
1960# Now we can explain tz.fromutc(x). Let's assume it's an interesting case
1961# (meaning that the various tzinfo methods exist, and don't blow up or return
1962# None when called).
1963#
1964# The function wants to return a datetime y with timezone tz, equivalent to x.
1965# x is already in UTC.
1966#
1967# By #3, we want
1968#
1969# y.n - y.o = x.n [1]
1970#
1971# The algorithm starts by attaching tz to x.n, and calling that y. So
1972# x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
1973# becomes true; in effect, we want to solve [2] for k:
1974#
1975# (y+k).n - (y+k).o = x.n [2]
1976#
1977# By #1, this is the same as
1978#
1979# (y+k).n - ((y+k).s + (y+k).d) = x.n [3]
1980#
1981# By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
1982# Substituting that into [3],
1983#
1984# x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving
1985# k - (y+k).s - (y+k).d = 0; rearranging,
1986# k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so
1987# k = y.s - (y+k).d
1988#
1989# On the RHS, (y+k).d can't be computed directly, but y.s can be, and we
1990# approximate k by ignoring the (y+k).d term at first. Note that k can't be
1991# very large, since all offset-returning methods return a duration of magnitude
1992# less than 24 hours. For that reason, if y is firmly in std time, (y+k).d must
1993# be 0, so ignoring it has no consequence then.
1994#
1995# In any case, the new value is
1996#
1997# z = y + y.s [4]
1998#
1999# It's helpful to step back at look at [4] from a higher level: it's simply
2000# mapping from UTC to tz's standard time.
2001#
2002# At this point, if
2003#
2004# z.n - z.o = x.n [5]
2005#
2006# we have an equivalent time, and are almost done. The insecurity here is
2007# at the start of daylight time. Picture US Eastern for concreteness. The wall
2008# time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
2009# sense then. The docs ask that an Eastern tzinfo class consider such a time to
2010# be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST
2011# on the day DST starts. We want to return the 1:MM EST spelling because that's
2012# the only spelling that makes sense on the local wall clock.
2013#
2014# In fact, if [5] holds at this point, we do have the standard-time spelling,
2015# but that takes a bit of proof. We first prove a stronger result. What's the
2016# difference between the LHS and RHS of [5]? Let
2017#
2018# diff = x.n - (z.n - z.o) [6]
2019#
2020# Now
2021# z.n = by [4]
2022# (y + y.s).n = by #5
2023# y.n + y.s = since y.n = x.n
2024# x.n + y.s = since z and y are have the same tzinfo member,
2025# y.s = z.s by #2
2026# x.n + z.s
2027#
2028# Plugging that back into [6] gives
2029#
2030# diff =
2031# x.n - ((x.n + z.s) - z.o) = expanding
2032# x.n - x.n - z.s + z.o = cancelling
2033# - z.s + z.o = by #2
2034# z.d
2035#
2036# So diff = z.d.
2037#
2038# If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
2039# spelling we wanted in the endcase described above. We're done. Contrarily,
2040# if z.d = 0, then we have a UTC equivalent, and are also done.
2041#
2042# If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
2043# add to z (in effect, z is in tz's standard time, and we need to shift the
2044# local clock into tz's daylight time).
2045#
2046# Let
2047#
2048# z' = z + z.d = z + diff [7]
2049#
2050# and we can again ask whether
2051#
2052# z'.n - z'.o = x.n [8]
2053#
2054# If so, we're done. If not, the tzinfo class is insane, according to the
2055# assumptions we've made. This also requires a bit of proof. As before, let's
2056# compute the difference between the LHS and RHS of [8] (and skipping some of
2057# the justifications for the kinds of substitutions we've done several times
2058# already):
2059#
2060# diff' = x.n - (z'.n - z'.o) = replacing z'.n via [7]
2061# x.n - (z.n + diff - z'.o) = replacing diff via [6]
2062# x.n - (z.n + x.n - (z.n - z.o) - z'.o) =
2063# x.n - z.n - x.n + z.n - z.o + z'.o = cancel x.n
2064# - z.n + z.n - z.o + z'.o = cancel z.n
2065# - z.o + z'.o = #1 twice
2066# -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
2067# z'.d - z.d
2068#
2069# So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
2070# we've found the UTC-equivalent so are done. In fact, we stop with [7] and
2071# return z', not bothering to compute z'.d.
2072#
2073# How could z.d and z'd differ? z' = z + z.d [7], so merely moving z' by
2074# a dst() offset, and starting *from* a time already in DST (we know z.d != 0),
2075# would have to change the result dst() returns: we start in DST, and moving
2076# a little further into it takes us out of DST.
2077#
2078# There isn't a sane case where this can happen. The closest it gets is at
2079# the end of DST, where there's an hour in UTC with no spelling in a hybrid
2080# tzinfo class. In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT. During
2081# that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM
2082# UTC) because the docs insist on that, but 0:MM is taken as being in daylight
2083# time (4:MM UTC). There is no local time mapping to 5:MM UTC. The local
2084# clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in
2085# standard time. Since that's what the local clock *does*, we want to map both
2086# UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
2087# in local time, but so it goes -- it's the way the local clock works.
2088#
2089# When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
2090# so z=0:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
2091# z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
2092# (correctly) concludes that z' is not UTC-equivalent to x.
2093#
2094# Because we know z.d said z was in daylight time (else [5] would have held and
2095# we would have stopped then), and we know z.d != z'.d (else [8] would have held
2096# and we have stopped then), and there are only 2 possible values dst() can
2097# return in Eastern, it follows that z'.d must be 0 (which it is in the example,
2098# but the reasoning doesn't depend on the example -- it depends on there being
2099# two possible dst() outcomes, one zero and the other non-zero). Therefore
2100# z' must be in standard time, and is the spelling we want in this case.
2101#
2102# Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is
2103# concerned (because it takes z' as being in standard time rather than the
2104# daylight time we intend here), but returning it gives the real-life "local
2105# clock repeats an hour" behavior when mapping the "unspellable" UTC hour into
2106# tz.
2107#
2108# When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with
2109# the 1:MM standard time spelling we want.
2110#
2111# So how can this break? One of the assumptions must be violated. Two
2112# possibilities:
2113#
2114# 1) [2] effectively says that y.s is invariant across all y belong to a given
2115# time zone. This isn't true if, for political reasons or continental drift,
2116# a region decides to change its base offset from UTC.
2117#
2118# 2) There may be versions of "double daylight" time where the tail end of
2119# the analysis gives up a step too early. I haven't thought about that
2120# enough to say.
2121#
2122# In any case, it's clear that the default fromutc() is strong enough to handle
2123# "almost all" time zones: so long as the standard offset is invariant, it
2124# doesn't matter if daylight time transition points change from year to year, or
2125# if daylight time is skipped in some years; it doesn't matter how large or
2126# small dst() may get within its bounds; and it doesn't even matter if some
2127# perverse time zone returns a negative dst()). So a breaking case must be
2128# pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
Alexander Belopolskycf86e362010-07-23 19:25:47 +00002129
Alexander Belopolskycf86e362010-07-23 19:25:47 +00002130try:
2131 from _datetime import *
Brett Cannoncd171c82013-07-04 17:43:24 -04002132except ImportError:
Alexander Belopolskycf86e362010-07-23 19:25:47 +00002133 pass
2134else:
2135 # Clean up unused names
Alexander Belopolsky6c7a4182014-09-28 19:11:56 -04002136 del (_DAYNAMES, _DAYS_BEFORE_MONTH, _DAYS_IN_MONTH, _DI100Y, _DI400Y,
2137 _DI4Y, _EPOCH, _MAXORDINAL, _MONTHNAMES, _build_struct_time,
2138 _check_date_fields, _check_int_field, _check_time_fields,
2139 _check_tzinfo_arg, _check_tzname, _check_utc_offset, _cmp, _cmperror,
2140 _date_class, _days_before_month, _days_before_year, _days_in_month,
2141 _format_time, _is_leap, _isoweek1monday, _math, _ord2ymd,
2142 _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord)
Alexander Belopolskya5658742010-07-23 20:03:53 +00002143 # XXX Since import * above excludes names that start with _,
2144 # docstring does not get overwritten. In the future, it may be
2145 # appropriate to maintain a single module level docstring and
2146 # remove the following line.
2147 from _datetime import __doc__