1 /* C implementation for the date/time type documented at
2 * http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage
3 */
4
5 /* bpo-35081: Defining this prevents including the C API capsule;
6 * internal versions of the Py*_Check macros which do not require
7 * the capsule are defined below */
8 #define _PY_DATETIME_IMPL
9
10 #include "Python.h"
11 #include "datetime.h"
12 #include "structmember.h" // PyMemberDef
13
14 #include <time.h>
15
16 #ifdef MS_WINDOWS
17 # include <winsock2.h> /* struct timeval */
18 #endif
19
20 #define PyDate_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateType)
21 #define PyDate_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_DateType)
22
23 #define PyDateTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateTimeType)
24 #define PyDateTime_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_DateTimeType)
25
26 #define PyTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeType)
27 #define PyTime_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_TimeType)
28
29 #define PyDelta_Check(op) PyObject_TypeCheck(op, &PyDateTime_DeltaType)
30 #define PyDelta_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_DeltaType)
31
32 #define PyTZInfo_Check(op) PyObject_TypeCheck(op, &PyDateTime_TZInfoType)
33 #define PyTZInfo_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_TZInfoType)
34
35 #define PyTimezone_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeZoneType)
36
37 /*[clinic input]
38 module datetime
39 class datetime.datetime "PyDateTime_DateTime *" "&PyDateTime_DateTimeType"
40 class datetime.date "PyDateTime_Date *" "&PyDateTime_DateType"
41 class datetime.IsoCalendarDate "PyDateTime_IsoCalendarDate *" "&PyDateTime_IsoCalendarDateType"
42 [clinic start generated code]*/
43 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=81bec0fa19837f63]*/
44
45 #include "clinic/_datetimemodule.c.h"
46
47 /* We require that C int be at least 32 bits, and use int virtually
48 * everywhere. In just a few cases we use a temp long, where a Python
49 * API returns a C long. In such cases, we have to ensure that the
50 * final result fits in a C int (this can be an issue on 64-bit boxes).
51 */
52 #if SIZEOF_INT < 4
53 # error "_datetime.c requires that C int have at least 32 bits"
54 #endif
55
56 #define MINYEAR 1
57 #define MAXYEAR 9999
58 #define MAXORDINAL 3652059 /* date(9999,12,31).toordinal() */
59
60 /* Nine decimal digits is easy to communicate, and leaves enough room
61 * so that two delta days can be added w/o fear of overflowing a signed
62 * 32-bit int, and with plenty of room left over to absorb any possible
63 * carries from adding seconds.
64 */
65 #define MAX_DELTA_DAYS 999999999
66
67 /* Rename the long macros in datetime.h to more reasonable short names. */
68 #define GET_YEAR PyDateTime_GET_YEAR
69 #define GET_MONTH PyDateTime_GET_MONTH
70 #define GET_DAY PyDateTime_GET_DAY
71 #define DATE_GET_HOUR PyDateTime_DATE_GET_HOUR
72 #define DATE_GET_MINUTE PyDateTime_DATE_GET_MINUTE
73 #define DATE_GET_SECOND PyDateTime_DATE_GET_SECOND
74 #define DATE_GET_MICROSECOND PyDateTime_DATE_GET_MICROSECOND
75 #define DATE_GET_FOLD PyDateTime_DATE_GET_FOLD
76
77 /* Date accessors for date and datetime. */
78 #define SET_YEAR(o, v) (((o)->data[0] = ((v) & 0xff00) >> 8), \
79 ((o)->data[1] = ((v) & 0x00ff)))
80 #define SET_MONTH(o, v) (PyDateTime_GET_MONTH(o) = (v))
81 #define SET_DAY(o, v) (PyDateTime_GET_DAY(o) = (v))
82
83 /* Date/Time accessors for datetime. */
84 #define DATE_SET_HOUR(o, v) (PyDateTime_DATE_GET_HOUR(o) = (v))
85 #define DATE_SET_MINUTE(o, v) (PyDateTime_DATE_GET_MINUTE(o) = (v))
86 #define DATE_SET_SECOND(o, v) (PyDateTime_DATE_GET_SECOND(o) = (v))
87 #define DATE_SET_MICROSECOND(o, v) \
88 (((o)->data[7] = ((v) & 0xff0000) >> 16), \
89 ((o)->data[8] = ((v) & 0x00ff00) >> 8), \
90 ((o)->data[9] = ((v) & 0x0000ff)))
91 #define DATE_SET_FOLD(o, v) (PyDateTime_DATE_GET_FOLD(o) = (v))
92
93 /* Time accessors for time. */
94 #define TIME_GET_HOUR PyDateTime_TIME_GET_HOUR
95 #define TIME_GET_MINUTE PyDateTime_TIME_GET_MINUTE
96 #define TIME_GET_SECOND PyDateTime_TIME_GET_SECOND
97 #define TIME_GET_MICROSECOND PyDateTime_TIME_GET_MICROSECOND
98 #define TIME_GET_FOLD PyDateTime_TIME_GET_FOLD
99 #define TIME_SET_HOUR(o, v) (PyDateTime_TIME_GET_HOUR(o) = (v))
100 #define TIME_SET_MINUTE(o, v) (PyDateTime_TIME_GET_MINUTE(o) = (v))
101 #define TIME_SET_SECOND(o, v) (PyDateTime_TIME_GET_SECOND(o) = (v))
102 #define TIME_SET_MICROSECOND(o, v) \
103 (((o)->data[3] = ((v) & 0xff0000) >> 16), \
104 ((o)->data[4] = ((v) & 0x00ff00) >> 8), \
105 ((o)->data[5] = ((v) & 0x0000ff)))
106 #define TIME_SET_FOLD(o, v) (PyDateTime_TIME_GET_FOLD(o) = (v))
107
108 /* Delta accessors for timedelta. */
109 #define GET_TD_DAYS(o) (((PyDateTime_Delta *)(o))->days)
110 #define GET_TD_SECONDS(o) (((PyDateTime_Delta *)(o))->seconds)
111 #define GET_TD_MICROSECONDS(o) (((PyDateTime_Delta *)(o))->microseconds)
112
113 #define SET_TD_DAYS(o, v) ((o)->days = (v))
114 #define SET_TD_SECONDS(o, v) ((o)->seconds = (v))
115 #define SET_TD_MICROSECONDS(o, v) ((o)->microseconds = (v))
116
117 /* p is a pointer to a time or a datetime object; HASTZINFO(p) returns
118 * p->hastzinfo.
119 */
120 #define HASTZINFO(p) (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo)
121 #define GET_TIME_TZINFO(p) (HASTZINFO(p) ? \
122 ((PyDateTime_Time *)(p))->tzinfo : Py_None)
123 #define GET_DT_TZINFO(p) (HASTZINFO(p) ? \
124 ((PyDateTime_DateTime *)(p))->tzinfo : Py_None)
125 /* M is a char or int claiming to be a valid month. The macro is equivalent
126 * to the two-sided Python test
127 * 1 <= M <= 12
128 */
129 #define MONTH_IS_SANE(M) ((unsigned int)(M) - 1 < 12)
130
131 /* Forward declarations. */
132 static PyTypeObject PyDateTime_DateType;
133 static PyTypeObject PyDateTime_DateTimeType;
134 static PyTypeObject PyDateTime_DeltaType;
135 static PyTypeObject PyDateTime_IsoCalendarDateType;
136 static PyTypeObject PyDateTime_TimeType;
137 static PyTypeObject PyDateTime_TZInfoType;
138 static PyTypeObject PyDateTime_TimeZoneType;
139
140 static int check_tzinfo_subclass(PyObject *p);
141
142 _Py_IDENTIFIER(as_integer_ratio);
143 _Py_IDENTIFIER(fromutc);
144 _Py_IDENTIFIER(isoformat);
145 _Py_IDENTIFIER(strftime);
146
147 /* ---------------------------------------------------------------------------
148 * Math utilities.
149 */
150
151 /* k = i+j overflows iff k differs in sign from both inputs,
152 * iff k^i has sign bit set and k^j has sign bit set,
153 * iff (k^i)&(k^j) has sign bit set.
154 */
155 #define SIGNED_ADD_OVERFLOWED(RESULT, I, J) \
156 ((((RESULT) ^ (I)) & ((RESULT) ^ (J))) < 0)
157
158 /* Compute Python divmod(x, y), returning the quotient and storing the
159 * remainder into *r. The quotient is the floor of x/y, and that's
160 * the real point of this. C will probably truncate instead (C99
161 * requires truncation; C89 left it implementation-defined).
162 * Simplification: we *require* that y > 0 here. That's appropriate
163 * for all the uses made of it. This simplifies the code and makes
164 * the overflow case impossible (divmod(LONG_MIN, -1) is the only
165 * overflow case).
166 */
167 static int
divmod(int x,int y,int * r)168 divmod(int x, int y, int *r)
169 {
170 int quo;
171
172 assert(y > 0);
173 quo = x / y;
174 *r = x - quo * y;
175 if (*r < 0) {
176 --quo;
177 *r += y;
178 }
179 assert(0 <= *r && *r < y);
180 return quo;
181 }
182
183 /* Nearest integer to m / n for integers m and n. Half-integer results
184 * are rounded to even.
185 */
186 static PyObject *
divide_nearest(PyObject * m,PyObject * n)187 divide_nearest(PyObject *m, PyObject *n)
188 {
189 PyObject *result;
190 PyObject *temp;
191
192 temp = _PyLong_DivmodNear(m, n);
193 if (temp == NULL)
194 return NULL;
195 result = PyTuple_GET_ITEM(temp, 0);
196 Py_INCREF(result);
197 Py_DECREF(temp);
198
199 return result;
200 }
201
202 /* ---------------------------------------------------------------------------
203 * General calendrical helper functions
204 */
205
206 /* For each month ordinal in 1..12, the number of days in that month,
207 * and the number of days before that month in the same year. These
208 * are correct for non-leap years only.
209 */
210 static const int _days_in_month[] = {
211 0, /* unused; this vector uses 1-based indexing */
212 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
213 };
214
215 static const int _days_before_month[] = {
216 0, /* unused; this vector uses 1-based indexing */
217 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
218 };
219
220 /* year -> 1 if leap year, else 0. */
221 static int
is_leap(int year)222 is_leap(int year)
223 {
224 /* Cast year to unsigned. The result is the same either way, but
225 * C can generate faster code for unsigned mod than for signed
226 * mod (especially for % 4 -- a good compiler should just grab
227 * the last 2 bits when the LHS is unsigned).
228 */
229 const unsigned int ayear = (unsigned int)year;
230 return ayear % 4 == 0 && (ayear % 100 != 0 || ayear % 400 == 0);
231 }
232
233 /* year, month -> number of days in that month in that year */
234 static int
days_in_month(int year,int month)235 days_in_month(int year, int month)
236 {
237 assert(month >= 1);
238 assert(month <= 12);
239 if (month == 2 && is_leap(year))
240 return 29;
241 else
242 return _days_in_month[month];
243 }
244
245 /* year, month -> number of days in year preceding first day of month */
246 static int
days_before_month(int year,int month)247 days_before_month(int year, int month)
248 {
249 int days;
250
251 assert(month >= 1);
252 assert(month <= 12);
253 days = _days_before_month[month];
254 if (month > 2 && is_leap(year))
255 ++days;
256 return days;
257 }
258
259 /* year -> number of days before January 1st of year. Remember that we
260 * start with year 1, so days_before_year(1) == 0.
261 */
262 static int
days_before_year(int year)263 days_before_year(int year)
264 {
265 int y = year - 1;
266 /* This is incorrect if year <= 0; we really want the floor
267 * here. But so long as MINYEAR is 1, the smallest year this
268 * can see is 1.
269 */
270 assert (year >= 1);
271 return y*365 + y/4 - y/100 + y/400;
272 }
273
274 /* Number of days in 4, 100, and 400 year cycles. That these have
275 * the correct values is asserted in the module init function.
276 */
277 #define DI4Y 1461 /* days_before_year(5); days in 4 years */
278 #define DI100Y 36524 /* days_before_year(101); days in 100 years */
279 #define DI400Y 146097 /* days_before_year(401); days in 400 years */
280
281 /* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */
282 static void
ord_to_ymd(int ordinal,int * year,int * month,int * day)283 ord_to_ymd(int ordinal, int *year, int *month, int *day)
284 {
285 int n, n1, n4, n100, n400, leapyear, preceding;
286
287 /* ordinal is a 1-based index, starting at 1-Jan-1. The pattern of
288 * leap years repeats exactly every 400 years. The basic strategy is
289 * to find the closest 400-year boundary at or before ordinal, then
290 * work with the offset from that boundary to ordinal. Life is much
291 * clearer if we subtract 1 from ordinal first -- then the values
292 * of ordinal at 400-year boundaries are exactly those divisible
293 * by DI400Y:
294 *
295 * D M Y n n-1
296 * -- --- ---- ---------- ----------------
297 * 31 Dec -400 -DI400Y -DI400Y -1
298 * 1 Jan -399 -DI400Y +1 -DI400Y 400-year boundary
299 * ...
300 * 30 Dec 000 -1 -2
301 * 31 Dec 000 0 -1
302 * 1 Jan 001 1 0 400-year boundary
303 * 2 Jan 001 2 1
304 * 3 Jan 001 3 2
305 * ...
306 * 31 Dec 400 DI400Y DI400Y -1
307 * 1 Jan 401 DI400Y +1 DI400Y 400-year boundary
308 */
309 assert(ordinal >= 1);
310 --ordinal;
311 n400 = ordinal / DI400Y;
312 n = ordinal % DI400Y;
313 *year = n400 * 400 + 1;
314
315 /* Now n is the (non-negative) offset, in days, from January 1 of
316 * year, to the desired date. Now compute how many 100-year cycles
317 * precede n.
318 * Note that it's possible for n100 to equal 4! In that case 4 full
319 * 100-year cycles precede the desired day, which implies the
320 * desired day is December 31 at the end of a 400-year cycle.
321 */
322 n100 = n / DI100Y;
323 n = n % DI100Y;
324
325 /* Now compute how many 4-year cycles precede it. */
326 n4 = n / DI4Y;
327 n = n % DI4Y;
328
329 /* And now how many single years. Again n1 can be 4, and again
330 * meaning that the desired day is December 31 at the end of the
331 * 4-year cycle.
332 */
333 n1 = n / 365;
334 n = n % 365;
335
336 *year += n100 * 100 + n4 * 4 + n1;
337 if (n1 == 4 || n100 == 4) {
338 assert(n == 0);
339 *year -= 1;
340 *month = 12;
341 *day = 31;
342 return;
343 }
344
345 /* Now the year is correct, and n is the offset from January 1. We
346 * find the month via an estimate that's either exact or one too
347 * large.
348 */
349 leapyear = n1 == 3 && (n4 != 24 || n100 == 3);
350 assert(leapyear == is_leap(*year));
351 *month = (n + 50) >> 5;
352 preceding = (_days_before_month[*month] + (*month > 2 && leapyear));
353 if (preceding > n) {
354 /* estimate is too large */
355 *month -= 1;
356 preceding -= days_in_month(*year, *month);
357 }
358 n -= preceding;
359 assert(0 <= n);
360 assert(n < days_in_month(*year, *month));
361
362 *day = n + 1;
363 }
364
365 /* year, month, day -> ordinal, considering 01-Jan-0001 as day 1. */
366 static int
ymd_to_ord(int year,int month,int day)367 ymd_to_ord(int year, int month, int day)
368 {
369 return days_before_year(year) + days_before_month(year, month) + day;
370 }
371
372 /* Day of week, where Monday==0, ..., Sunday==6. 1/1/1 was a Monday. */
373 static int
weekday(int year,int month,int day)374 weekday(int year, int month, int day)
375 {
376 return (ymd_to_ord(year, month, day) + 6) % 7;
377 }
378
379 /* Ordinal of the Monday starting week 1 of the ISO year. Week 1 is the
380 * first calendar week containing a Thursday.
381 */
382 static int
iso_week1_monday(int year)383 iso_week1_monday(int year)
384 {
385 int first_day = ymd_to_ord(year, 1, 1); /* ord of 1/1 */
386 /* 0 if 1/1 is a Monday, 1 if a Tue, etc. */
387 int first_weekday = (first_day + 6) % 7;
388 /* ordinal of closest Monday at or before 1/1 */
389 int week1_monday = first_day - first_weekday;
390
391 if (first_weekday > 3) /* if 1/1 was Fri, Sat, Sun */
392 week1_monday += 7;
393 return week1_monday;
394 }
395
396 /* ---------------------------------------------------------------------------
397 * Range checkers.
398 */
399
400 /* Check that -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS. If so, return 0.
401 * If not, raise OverflowError and return -1.
402 */
403 static int
check_delta_day_range(int days)404 check_delta_day_range(int days)
405 {
406 if (-MAX_DELTA_DAYS <= days && days <= MAX_DELTA_DAYS)
407 return 0;
408 PyErr_Format(PyExc_OverflowError,
409 "days=%d; must have magnitude <= %d",
410 days, MAX_DELTA_DAYS);
411 return -1;
412 }
413
414 /* Check that date arguments are in range. Return 0 if they are. If they
415 * aren't, raise ValueError and return -1.
416 */
417 static int
check_date_args(int year,int month,int day)418 check_date_args(int year, int month, int day)
419 {
420
421 if (year < MINYEAR || year > MAXYEAR) {
422 PyErr_Format(PyExc_ValueError, "year %i is out of range", year);
423 return -1;
424 }
425 if (month < 1 || month > 12) {
426 PyErr_SetString(PyExc_ValueError,
427 "month must be in 1..12");
428 return -1;
429 }
430 if (day < 1 || day > days_in_month(year, month)) {
431 PyErr_SetString(PyExc_ValueError,
432 "day is out of range for month");
433 return -1;
434 }
435 return 0;
436 }
437
438 /* Check that time arguments are in range. Return 0 if they are. If they
439 * aren't, raise ValueError and return -1.
440 */
441 static int
check_time_args(int h,int m,int s,int us,int fold)442 check_time_args(int h, int m, int s, int us, int fold)
443 {
444 if (h < 0 || h > 23) {
445 PyErr_SetString(PyExc_ValueError,
446 "hour must be in 0..23");
447 return -1;
448 }
449 if (m < 0 || m > 59) {
450 PyErr_SetString(PyExc_ValueError,
451 "minute must be in 0..59");
452 return -1;
453 }
454 if (s < 0 || s > 59) {
455 PyErr_SetString(PyExc_ValueError,
456 "second must be in 0..59");
457 return -1;
458 }
459 if (us < 0 || us > 999999) {
460 PyErr_SetString(PyExc_ValueError,
461 "microsecond must be in 0..999999");
462 return -1;
463 }
464 if (fold != 0 && fold != 1) {
465 PyErr_SetString(PyExc_ValueError,
466 "fold must be either 0 or 1");
467 return -1;
468 }
469 return 0;
470 }
471
472 /* ---------------------------------------------------------------------------
473 * Normalization utilities.
474 */
475
476 /* One step of a mixed-radix conversion. A "hi" unit is equivalent to
477 * factor "lo" units. factor must be > 0. If *lo is less than 0, or
478 * at least factor, enough of *lo is converted into "hi" units so that
479 * 0 <= *lo < factor. The input values must be such that int overflow
480 * is impossible.
481 */
482 static void
normalize_pair(int * hi,int * lo,int factor)483 normalize_pair(int *hi, int *lo, int factor)
484 {
485 assert(factor > 0);
486 assert(lo != hi);
487 if (*lo < 0 || *lo >= factor) {
488 const int num_hi = divmod(*lo, factor, lo);
489 const int new_hi = *hi + num_hi;
490 assert(! SIGNED_ADD_OVERFLOWED(new_hi, *hi, num_hi));
491 *hi = new_hi;
492 }
493 assert(0 <= *lo && *lo < factor);
494 }
495
496 /* Fiddle days (d), seconds (s), and microseconds (us) so that
497 * 0 <= *s < 24*3600
498 * 0 <= *us < 1000000
499 * The input values must be such that the internals don't overflow.
500 * The way this routine is used, we don't get close.
501 */
502 static void
normalize_d_s_us(int * d,int * s,int * us)503 normalize_d_s_us(int *d, int *s, int *us)
504 {
505 if (*us < 0 || *us >= 1000000) {
506 normalize_pair(s, us, 1000000);
507 /* |s| can't be bigger than about
508 * |original s| + |original us|/1000000 now.
509 */
510
511 }
512 if (*s < 0 || *s >= 24*3600) {
513 normalize_pair(d, s, 24*3600);
514 /* |d| can't be bigger than about
515 * |original d| +
516 * (|original s| + |original us|/1000000) / (24*3600) now.
517 */
518 }
519 assert(0 <= *s && *s < 24*3600);
520 assert(0 <= *us && *us < 1000000);
521 }
522
523 /* Fiddle years (y), months (m), and days (d) so that
524 * 1 <= *m <= 12
525 * 1 <= *d <= days_in_month(*y, *m)
526 * The input values must be such that the internals don't overflow.
527 * The way this routine is used, we don't get close.
528 */
529 static int
normalize_y_m_d(int * y,int * m,int * d)530 normalize_y_m_d(int *y, int *m, int *d)
531 {
532 int dim; /* # of days in month */
533
534 /* In actual use, m is always the month component extracted from a
535 * date/datetime object. Therefore it is always in [1, 12] range.
536 */
537
538 assert(1 <= *m && *m <= 12);
539
540 /* Now only day can be out of bounds (year may also be out of bounds
541 * for a datetime object, but we don't care about that here).
542 * If day is out of bounds, what to do is arguable, but at least the
543 * method here is principled and explainable.
544 */
545 dim = days_in_month(*y, *m);
546 if (*d < 1 || *d > dim) {
547 /* Move day-1 days from the first of the month. First try to
548 * get off cheap if we're only one day out of range
549 * (adjustments for timezone alone can't be worse than that).
550 */
551 if (*d == 0) {
552 --*m;
553 if (*m > 0)
554 *d = days_in_month(*y, *m);
555 else {
556 --*y;
557 *m = 12;
558 *d = 31;
559 }
560 }
561 else if (*d == dim + 1) {
562 /* move forward a day */
563 ++*m;
564 *d = 1;
565 if (*m > 12) {
566 *m = 1;
567 ++*y;
568 }
569 }
570 else {
571 int ordinal = ymd_to_ord(*y, *m, 1) +
572 *d - 1;
573 if (ordinal < 1 || ordinal > MAXORDINAL) {
574 goto error;
575 } else {
576 ord_to_ymd(ordinal, y, m, d);
577 return 0;
578 }
579 }
580 }
581 assert(*m > 0);
582 assert(*d > 0);
583 if (MINYEAR <= *y && *y <= MAXYEAR)
584 return 0;
585 error:
586 PyErr_SetString(PyExc_OverflowError,
587 "date value out of range");
588 return -1;
589
590 }
591
592 /* Fiddle out-of-bounds months and days so that the result makes some kind
593 * of sense. The parameters are both inputs and outputs. Returns < 0 on
594 * failure, where failure means the adjusted year is out of bounds.
595 */
596 static int
normalize_date(int * year,int * month,int * day)597 normalize_date(int *year, int *month, int *day)
598 {
599 return normalize_y_m_d(year, month, day);
600 }
601
602 /* Force all the datetime fields into range. The parameters are both
603 * inputs and outputs. Returns < 0 on error.
604 */
605 static int
normalize_datetime(int * year,int * month,int * day,int * hour,int * minute,int * second,int * microsecond)606 normalize_datetime(int *year, int *month, int *day,
607 int *hour, int *minute, int *second,
608 int *microsecond)
609 {
610 normalize_pair(second, microsecond, 1000000);
611 normalize_pair(minute, second, 60);
612 normalize_pair(hour, minute, 60);
613 normalize_pair(day, hour, 24);
614 return normalize_date(year, month, day);
615 }
616
617 /* ---------------------------------------------------------------------------
618 * Basic object allocation: tp_alloc implementations. These allocate
619 * Python objects of the right size and type, and do the Python object-
620 * initialization bit. If there's not enough memory, they return NULL after
621 * setting MemoryError. All data members remain uninitialized trash.
622 *
623 * We abuse the tp_alloc "nitems" argument to communicate whether a tzinfo
624 * member is needed. This is ugly, imprecise, and possibly insecure.
625 * tp_basicsize for the time and datetime types is set to the size of the
626 * struct that has room for the tzinfo member, so subclasses in Python will
627 * allocate enough space for a tzinfo member whether or not one is actually
628 * needed. That's the "ugly and imprecise" parts. The "possibly insecure"
629 * part is that PyType_GenericAlloc() (which subclasses in Python end up
630 * using) just happens today to effectively ignore the nitems argument
631 * when tp_itemsize is 0, which it is for these type objects. If that
632 * changes, perhaps the callers of tp_alloc slots in this file should
633 * be changed to force a 0 nitems argument unless the type being allocated
634 * is a base type implemented in this file (so that tp_alloc is time_alloc
635 * or datetime_alloc below, which know about the nitems abuse).
636 */
637
638 static PyObject *
time_alloc(PyTypeObject * type,Py_ssize_t aware)639 time_alloc(PyTypeObject *type, Py_ssize_t aware)
640 {
641 PyObject *self;
642
643 self = (PyObject *)
644 PyObject_MALLOC(aware ?
645 sizeof(PyDateTime_Time) :
646 sizeof(_PyDateTime_BaseTime));
647 if (self == NULL)
648 return (PyObject *)PyErr_NoMemory();
649 (void)PyObject_INIT(self, type);
650 return self;
651 }
652
653 static PyObject *
datetime_alloc(PyTypeObject * type,Py_ssize_t aware)654 datetime_alloc(PyTypeObject *type, Py_ssize_t aware)
655 {
656 PyObject *self;
657
658 self = (PyObject *)
659 PyObject_MALLOC(aware ?
660 sizeof(PyDateTime_DateTime) :
661 sizeof(_PyDateTime_BaseDateTime));
662 if (self == NULL)
663 return (PyObject *)PyErr_NoMemory();
664 (void)PyObject_INIT(self, type);
665 return self;
666 }
667
668 /* ---------------------------------------------------------------------------
669 * Helpers for setting object fields. These work on pointers to the
670 * appropriate base class.
671 */
672
673 /* For date and datetime. */
674 static void
set_date_fields(PyDateTime_Date * self,int y,int m,int d)675 set_date_fields(PyDateTime_Date *self, int y, int m, int d)
676 {
677 self->hashcode = -1;
678 SET_YEAR(self, y);
679 SET_MONTH(self, m);
680 SET_DAY(self, d);
681 }
682
683 /* ---------------------------------------------------------------------------
684 * String parsing utilities and helper functions
685 */
686
687 static const char *
parse_digits(const char * ptr,int * var,size_t num_digits)688 parse_digits(const char *ptr, int *var, size_t num_digits)
689 {
690 for (size_t i = 0; i < num_digits; ++i) {
691 unsigned int tmp = (unsigned int)(*(ptr++) - '0');
692 if (tmp > 9) {
693 return NULL;
694 }
695 *var *= 10;
696 *var += (signed int)tmp;
697 }
698
699 return ptr;
700 }
701
702 static int
parse_isoformat_date(const char * dtstr,int * year,int * month,int * day)703 parse_isoformat_date(const char *dtstr, int *year, int *month, int *day)
704 {
705 /* Parse the date components of the result of date.isoformat()
706 *
707 * Return codes:
708 * 0: Success
709 * -1: Failed to parse date component
710 * -2: Failed to parse dateseparator
711 */
712 const char *p = dtstr;
713 p = parse_digits(p, year, 4);
714 if (NULL == p) {
715 return -1;
716 }
717
718 if (*(p++) != '-') {
719 return -2;
720 }
721
722 p = parse_digits(p, month, 2);
723 if (NULL == p) {
724 return -1;
725 }
726
727 if (*(p++) != '-') {
728 return -2;
729 }
730
731 p = parse_digits(p, day, 2);
732 if (p == NULL) {
733 return -1;
734 }
735
736 return 0;
737 }
738
739 static int
parse_hh_mm_ss_ff(const char * tstr,const char * tstr_end,int * hour,int * minute,int * second,int * microsecond)740 parse_hh_mm_ss_ff(const char *tstr, const char *tstr_end, int *hour,
741 int *minute, int *second, int *microsecond)
742 {
743 const char *p = tstr;
744 const char *p_end = tstr_end;
745 int *vals[3] = {hour, minute, second};
746
747 // Parse [HH[:MM[:SS]]]
748 for (size_t i = 0; i < 3; ++i) {
749 p = parse_digits(p, vals[i], 2);
750 if (NULL == p) {
751 return -3;
752 }
753
754 char c = *(p++);
755 if (p >= p_end) {
756 return c != '\0';
757 }
758 else if (c == ':') {
759 continue;
760 }
761 else if (c == '.') {
762 break;
763 }
764 else {
765 return -4; // Malformed time separator
766 }
767 }
768
769 // Parse .fff[fff]
770 size_t len_remains = p_end - p;
771 if (!(len_remains == 6 || len_remains == 3)) {
772 return -3;
773 }
774
775 p = parse_digits(p, microsecond, len_remains);
776 if (NULL == p) {
777 return -3;
778 }
779
780 if (len_remains == 3) {
781 *microsecond *= 1000;
782 }
783
784 // Return 1 if it's not the end of the string
785 return *p != '\0';
786 }
787
788 static int
parse_isoformat_time(const char * dtstr,size_t dtlen,int * hour,int * minute,int * second,int * microsecond,int * tzoffset,int * tzmicrosecond)789 parse_isoformat_time(const char *dtstr, size_t dtlen, int *hour, int *minute,
790 int *second, int *microsecond, int *tzoffset,
791 int *tzmicrosecond)
792 {
793 // Parse the time portion of a datetime.isoformat() string
794 //
795 // Return codes:
796 // 0: Success (no tzoffset)
797 // 1: Success (with tzoffset)
798 // -3: Failed to parse time component
799 // -4: Failed to parse time separator
800 // -5: Malformed timezone string
801
802 const char *p = dtstr;
803 const char *p_end = dtstr + dtlen;
804
805 const char *tzinfo_pos = p;
806 do {
807 if (*tzinfo_pos == '+' || *tzinfo_pos == '-') {
808 break;
809 }
810 } while (++tzinfo_pos < p_end);
811
812 int rv = parse_hh_mm_ss_ff(dtstr, tzinfo_pos, hour, minute, second,
813 microsecond);
814
815 if (rv < 0) {
816 return rv;
817 }
818 else if (tzinfo_pos == p_end) {
819 // We know that there's no time zone, so if there's stuff at the
820 // end of the string it's an error.
821 if (rv == 1) {
822 return -5;
823 }
824 else {
825 return 0;
826 }
827 }
828
829 // Parse time zone component
830 // Valid formats are:
831 // - +HH:MM (len 6)
832 // - +HH:MM:SS (len 9)
833 // - +HH:MM:SS.ffffff (len 16)
834 size_t tzlen = p_end - tzinfo_pos;
835 if (!(tzlen == 6 || tzlen == 9 || tzlen == 16)) {
836 return -5;
837 }
838
839 int tzsign = (*tzinfo_pos == '-') ? -1 : 1;
840 tzinfo_pos++;
841 int tzhour = 0, tzminute = 0, tzsecond = 0;
842 rv = parse_hh_mm_ss_ff(tzinfo_pos, p_end, &tzhour, &tzminute, &tzsecond,
843 tzmicrosecond);
844
845 *tzoffset = tzsign * ((tzhour * 3600) + (tzminute * 60) + tzsecond);
846 *tzmicrosecond *= tzsign;
847
848 return rv ? -5 : 1;
849 }
850
851 /* ---------------------------------------------------------------------------
852 * Create various objects, mostly without range checking.
853 */
854
855 /* Create a date instance with no range checking. */
856 static PyObject *
new_date_ex(int year,int month,int day,PyTypeObject * type)857 new_date_ex(int year, int month, int day, PyTypeObject *type)
858 {
859 PyDateTime_Date *self;
860
861 if (check_date_args(year, month, day) < 0) {
862 return NULL;
863 }
864
865 self = (PyDateTime_Date *)(type->tp_alloc(type, 0));
866 if (self != NULL)
867 set_date_fields(self, year, month, day);
868 return (PyObject *)self;
869 }
870
871 #define new_date(year, month, day) \
872 new_date_ex(year, month, day, &PyDateTime_DateType)
873
874 // Forward declaration
875 static PyObject *
876 new_datetime_ex(int, int, int, int, int, int, int, PyObject *, PyTypeObject *);
877
878 /* Create date instance with no range checking, or call subclass constructor */
879 static PyObject *
new_date_subclass_ex(int year,int month,int day,PyObject * cls)880 new_date_subclass_ex(int year, int month, int day, PyObject *cls)
881 {
882 PyObject *result;
883 // We have "fast path" constructors for two subclasses: date and datetime
884 if ((PyTypeObject *)cls == &PyDateTime_DateType) {
885 result = new_date_ex(year, month, day, (PyTypeObject *)cls);
886 }
887 else if ((PyTypeObject *)cls == &PyDateTime_DateTimeType) {
888 result = new_datetime_ex(year, month, day, 0, 0, 0, 0, Py_None,
889 (PyTypeObject *)cls);
890 }
891 else {
892 result = PyObject_CallFunction(cls, "iii", year, month, day);
893 }
894
895 return result;
896 }
897
898 /* Create a datetime instance with no range checking. */
899 static PyObject *
new_datetime_ex2(int year,int month,int day,int hour,int minute,int second,int usecond,PyObject * tzinfo,int fold,PyTypeObject * type)900 new_datetime_ex2(int year, int month, int day, int hour, int minute,
901 int second, int usecond, PyObject *tzinfo, int fold, PyTypeObject *type)
902 {
903 PyDateTime_DateTime *self;
904 char aware = tzinfo != Py_None;
905
906 if (check_date_args(year, month, day) < 0) {
907 return NULL;
908 }
909 if (check_time_args(hour, minute, second, usecond, fold) < 0) {
910 return NULL;
911 }
912 if (check_tzinfo_subclass(tzinfo) < 0) {
913 return NULL;
914 }
915
916 self = (PyDateTime_DateTime *) (type->tp_alloc(type, aware));
917 if (self != NULL) {
918 self->hastzinfo = aware;
919 set_date_fields((PyDateTime_Date *)self, year, month, day);
920 DATE_SET_HOUR(self, hour);
921 DATE_SET_MINUTE(self, minute);
922 DATE_SET_SECOND(self, second);
923 DATE_SET_MICROSECOND(self, usecond);
924 if (aware) {
925 Py_INCREF(tzinfo);
926 self->tzinfo = tzinfo;
927 }
928 DATE_SET_FOLD(self, fold);
929 }
930 return (PyObject *)self;
931 }
932
933 static PyObject *
new_datetime_ex(int year,int month,int day,int hour,int minute,int second,int usecond,PyObject * tzinfo,PyTypeObject * type)934 new_datetime_ex(int year, int month, int day, int hour, int minute,
935 int second, int usecond, PyObject *tzinfo, PyTypeObject *type)
936 {
937 return new_datetime_ex2(year, month, day, hour, minute, second, usecond,
938 tzinfo, 0, type);
939 }
940
941 #define new_datetime(y, m, d, hh, mm, ss, us, tzinfo, fold) \
942 new_datetime_ex2(y, m, d, hh, mm, ss, us, tzinfo, fold, \
943 &PyDateTime_DateTimeType)
944
945 static PyObject *
new_datetime_subclass_fold_ex(int year,int month,int day,int hour,int minute,int second,int usecond,PyObject * tzinfo,int fold,PyObject * cls)946 new_datetime_subclass_fold_ex(int year, int month, int day, int hour, int minute,
947 int second, int usecond, PyObject *tzinfo,
948 int fold, PyObject *cls) {
949 PyObject* dt;
950 if ((PyTypeObject*)cls == &PyDateTime_DateTimeType) {
951 // Use the fast path constructor
952 dt = new_datetime(year, month, day, hour, minute, second, usecond,
953 tzinfo, fold);
954 } else {
955 // Subclass
956 dt = PyObject_CallFunction(cls, "iiiiiiiO",
957 year,
958 month,
959 day,
960 hour,
961 minute,
962 second,
963 usecond,
964 tzinfo);
965 }
966
967 return dt;
968 }
969
970 static PyObject *
new_datetime_subclass_ex(int year,int month,int day,int hour,int minute,int second,int usecond,PyObject * tzinfo,PyObject * cls)971 new_datetime_subclass_ex(int year, int month, int day, int hour, int minute,
972 int second, int usecond, PyObject *tzinfo,
973 PyObject *cls) {
974 return new_datetime_subclass_fold_ex(year, month, day, hour, minute,
975 second, usecond, tzinfo, 0,
976 cls);
977 }
978
979 /* Create a time instance with no range checking. */
980 static PyObject *
new_time_ex2(int hour,int minute,int second,int usecond,PyObject * tzinfo,int fold,PyTypeObject * type)981 new_time_ex2(int hour, int minute, int second, int usecond,
982 PyObject *tzinfo, int fold, PyTypeObject *type)
983 {
984 PyDateTime_Time *self;
985 char aware = tzinfo != Py_None;
986
987 if (check_time_args(hour, minute, second, usecond, fold) < 0) {
988 return NULL;
989 }
990 if (check_tzinfo_subclass(tzinfo) < 0) {
991 return NULL;
992 }
993
994 self = (PyDateTime_Time *) (type->tp_alloc(type, aware));
995 if (self != NULL) {
996 self->hastzinfo = aware;
997 self->hashcode = -1;
998 TIME_SET_HOUR(self, hour);
999 TIME_SET_MINUTE(self, minute);
1000 TIME_SET_SECOND(self, second);
1001 TIME_SET_MICROSECOND(self, usecond);
1002 if (aware) {
1003 Py_INCREF(tzinfo);
1004 self->tzinfo = tzinfo;
1005 }
1006 TIME_SET_FOLD(self, fold);
1007 }
1008 return (PyObject *)self;
1009 }
1010
1011 static PyObject *
new_time_ex(int hour,int minute,int second,int usecond,PyObject * tzinfo,PyTypeObject * type)1012 new_time_ex(int hour, int minute, int second, int usecond,
1013 PyObject *tzinfo, PyTypeObject *type)
1014 {
1015 return new_time_ex2(hour, minute, second, usecond, tzinfo, 0, type);
1016 }
1017
1018 #define new_time(hh, mm, ss, us, tzinfo, fold) \
1019 new_time_ex2(hh, mm, ss, us, tzinfo, fold, &PyDateTime_TimeType)
1020
1021 /* Create a timedelta instance. Normalize the members iff normalize is
1022 * true. Passing false is a speed optimization, if you know for sure
1023 * that seconds and microseconds are already in their proper ranges. In any
1024 * case, raises OverflowError and returns NULL if the normalized days is out
1025 * of range).
1026 */
1027 static PyObject *
new_delta_ex(int days,int seconds,int microseconds,int normalize,PyTypeObject * type)1028 new_delta_ex(int days, int seconds, int microseconds, int normalize,
1029 PyTypeObject *type)
1030 {
1031 PyDateTime_Delta *self;
1032
1033 if (normalize)
1034 normalize_d_s_us(&days, &seconds, µseconds);
1035 assert(0 <= seconds && seconds < 24*3600);
1036 assert(0 <= microseconds && microseconds < 1000000);
1037
1038 if (check_delta_day_range(days) < 0)
1039 return NULL;
1040
1041 self = (PyDateTime_Delta *) (type->tp_alloc(type, 0));
1042 if (self != NULL) {
1043 self->hashcode = -1;
1044 SET_TD_DAYS(self, days);
1045 SET_TD_SECONDS(self, seconds);
1046 SET_TD_MICROSECONDS(self, microseconds);
1047 }
1048 return (PyObject *) self;
1049 }
1050
1051 #define new_delta(d, s, us, normalize) \
1052 new_delta_ex(d, s, us, normalize, &PyDateTime_DeltaType)
1053
1054
1055 typedef struct
1056 {
1057 PyObject_HEAD
1058 PyObject *offset;
1059 PyObject *name;
1060 } PyDateTime_TimeZone;
1061
1062 /* The interned UTC timezone instance */
1063 static PyObject *PyDateTime_TimeZone_UTC;
1064 /* The interned Epoch datetime instance */
1065 static PyObject *PyDateTime_Epoch;
1066
1067 /* Create new timezone instance checking offset range. This
1068 function does not check the name argument. Caller must assure
1069 that offset is a timedelta instance and name is either NULL
1070 or a unicode object. */
1071 static PyObject *
create_timezone(PyObject * offset,PyObject * name)1072 create_timezone(PyObject *offset, PyObject *name)
1073 {
1074 PyDateTime_TimeZone *self;
1075 PyTypeObject *type = &PyDateTime_TimeZoneType;
1076
1077 assert(offset != NULL);
1078 assert(PyDelta_Check(offset));
1079 assert(name == NULL || PyUnicode_Check(name));
1080
1081 self = (PyDateTime_TimeZone *)(type->tp_alloc(type, 0));
1082 if (self == NULL) {
1083 return NULL;
1084 }
1085 Py_INCREF(offset);
1086 self->offset = offset;
1087 Py_XINCREF(name);
1088 self->name = name;
1089 return (PyObject *)self;
1090 }
1091
1092 static int delta_bool(PyDateTime_Delta *self);
1093
1094 static PyObject *
new_timezone(PyObject * offset,PyObject * name)1095 new_timezone(PyObject *offset, PyObject *name)
1096 {
1097 assert(offset != NULL);
1098 assert(PyDelta_Check(offset));
1099 assert(name == NULL || PyUnicode_Check(name));
1100
1101 if (name == NULL && delta_bool((PyDateTime_Delta *)offset) == 0) {
1102 Py_INCREF(PyDateTime_TimeZone_UTC);
1103 return PyDateTime_TimeZone_UTC;
1104 }
1105 if ((GET_TD_DAYS(offset) == -1 &&
1106 GET_TD_SECONDS(offset) == 0 &&
1107 GET_TD_MICROSECONDS(offset) < 1) ||
1108 GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) {
1109 PyErr_Format(PyExc_ValueError, "offset must be a timedelta"
1110 " strictly between -timedelta(hours=24) and"
1111 " timedelta(hours=24),"
1112 " not %R.", offset);
1113 return NULL;
1114 }
1115
1116 return create_timezone(offset, name);
1117 }
1118
1119 /* ---------------------------------------------------------------------------
1120 * tzinfo helpers.
1121 */
1122
1123 /* Ensure that p is None or of a tzinfo subclass. Return 0 if OK; if not
1124 * raise TypeError and return -1.
1125 */
1126 static int
check_tzinfo_subclass(PyObject * p)1127 check_tzinfo_subclass(PyObject *p)
1128 {
1129 if (p == Py_None || PyTZInfo_Check(p))
1130 return 0;
1131 PyErr_Format(PyExc_TypeError,
1132 "tzinfo argument must be None or of a tzinfo subclass, "
1133 "not type '%s'",
1134 Py_TYPE(p)->tp_name);
1135 return -1;
1136 }
1137
1138 /* If self has a tzinfo member, return a BORROWED reference to it. Else
1139 * return NULL, which is NOT AN ERROR. There are no error returns here,
1140 * and the caller must not decref the result.
1141 */
1142 static PyObject *
get_tzinfo_member(PyObject * self)1143 get_tzinfo_member(PyObject *self)
1144 {
1145 PyObject *tzinfo = NULL;
1146
1147 if (PyDateTime_Check(self) && HASTZINFO(self))
1148 tzinfo = ((PyDateTime_DateTime *)self)->tzinfo;
1149 else if (PyTime_Check(self) && HASTZINFO(self))
1150 tzinfo = ((PyDateTime_Time *)self)->tzinfo;
1151
1152 return tzinfo;
1153 }
1154
1155 /* Call getattr(tzinfo, name)(tzinfoarg), and check the result. tzinfo must
1156 * be an instance of the tzinfo class. If the method returns None, this
1157 * returns None. If the method doesn't return None or timedelta, TypeError is
1158 * raised and this returns NULL. If it returns a timedelta and the value is
1159 * out of range or isn't a whole number of minutes, ValueError is raised and
1160 * this returns NULL. Else result is returned.
1161 */
1162 static PyObject *
call_tzinfo_method(PyObject * tzinfo,const char * name,PyObject * tzinfoarg)1163 call_tzinfo_method(PyObject *tzinfo, const char *name, PyObject *tzinfoarg)
1164 {
1165 PyObject *offset;
1166
1167 assert(tzinfo != NULL);
1168 assert(PyTZInfo_Check(tzinfo) || tzinfo == Py_None);
1169 assert(tzinfoarg != NULL);
1170
1171 if (tzinfo == Py_None)
1172 Py_RETURN_NONE;
1173 offset = PyObject_CallMethod(tzinfo, name, "O", tzinfoarg);
1174 if (offset == Py_None || offset == NULL)
1175 return offset;
1176 if (PyDelta_Check(offset)) {
1177 if ((GET_TD_DAYS(offset) == -1 &&
1178 GET_TD_SECONDS(offset) == 0 &&
1179 GET_TD_MICROSECONDS(offset) < 1) ||
1180 GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) {
1181 Py_DECREF(offset);
1182 PyErr_Format(PyExc_ValueError, "offset must be a timedelta"
1183 " strictly between -timedelta(hours=24) and"
1184 " timedelta(hours=24).");
1185 return NULL;
1186 }
1187 }
1188 else {
1189 PyErr_Format(PyExc_TypeError,
1190 "tzinfo.%s() must return None or "
1191 "timedelta, not '%.200s'",
1192 name, Py_TYPE(offset)->tp_name);
1193 Py_DECREF(offset);
1194 return NULL;
1195 }
1196
1197 return offset;
1198 }
1199
1200 /* Call tzinfo.utcoffset(tzinfoarg), and extract an integer from the
1201 * result. tzinfo must be an instance of the tzinfo class. If utcoffset()
1202 * returns None, call_utcoffset returns 0 and sets *none to 1. If uctoffset()
1203 * doesn't return None or timedelta, TypeError is raised and this returns -1.
1204 * If utcoffset() returns an out of range timedelta,
1205 * ValueError is raised and this returns -1. Else *none is
1206 * set to 0 and the offset is returned (as timedelta, positive east of UTC).
1207 */
1208 static PyObject *
call_utcoffset(PyObject * tzinfo,PyObject * tzinfoarg)1209 call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg)
1210 {
1211 return call_tzinfo_method(tzinfo, "utcoffset", tzinfoarg);
1212 }
1213
1214 /* Call tzinfo.dst(tzinfoarg), and extract an integer from the
1215 * result. tzinfo must be an instance of the tzinfo class. If dst()
1216 * returns None, call_dst returns 0 and sets *none to 1. If dst()
1217 * doesn't return None or timedelta, TypeError is raised and this
1218 * returns -1. If dst() returns an invalid timedelta for a UTC offset,
1219 * ValueError is raised and this returns -1. Else *none is set to 0 and
1220 * the offset is returned (as timedelta, positive east of UTC).
1221 */
1222 static PyObject *
call_dst(PyObject * tzinfo,PyObject * tzinfoarg)1223 call_dst(PyObject *tzinfo, PyObject *tzinfoarg)
1224 {
1225 return call_tzinfo_method(tzinfo, "dst", tzinfoarg);
1226 }
1227
1228 /* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be
1229 * an instance of the tzinfo class or None. If tzinfo isn't None, and
1230 * tzname() doesn't return None or a string, TypeError is raised and this
1231 * returns NULL. If the result is a string, we ensure it is a Unicode
1232 * string.
1233 */
1234 static PyObject *
call_tzname(PyObject * tzinfo,PyObject * tzinfoarg)1235 call_tzname(PyObject *tzinfo, PyObject *tzinfoarg)
1236 {
1237 PyObject *result;
1238 _Py_IDENTIFIER(tzname);
1239
1240 assert(tzinfo != NULL);
1241 assert(check_tzinfo_subclass(tzinfo) >= 0);
1242 assert(tzinfoarg != NULL);
1243
1244 if (tzinfo == Py_None)
1245 Py_RETURN_NONE;
1246
1247 result = _PyObject_CallMethodIdOneArg(tzinfo, &PyId_tzname, tzinfoarg);
1248
1249 if (result == NULL || result == Py_None)
1250 return result;
1251
1252 if (!PyUnicode_Check(result)) {
1253 PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must "
1254 "return None or a string, not '%s'",
1255 Py_TYPE(result)->tp_name);
1256 Py_DECREF(result);
1257 result = NULL;
1258 }
1259
1260 return result;
1261 }
1262
1263 /* repr is like "someclass(arg1, arg2)". If tzinfo isn't None,
1264 * stuff
1265 * ", tzinfo=" + repr(tzinfo)
1266 * before the closing ")".
1267 */
1268 static PyObject *
append_keyword_tzinfo(PyObject * repr,PyObject * tzinfo)1269 append_keyword_tzinfo(PyObject *repr, PyObject *tzinfo)
1270 {
1271 PyObject *temp;
1272
1273 assert(PyUnicode_Check(repr));
1274 assert(tzinfo);
1275 if (tzinfo == Py_None)
1276 return repr;
1277 /* Get rid of the trailing ')'. */
1278 assert(PyUnicode_READ_CHAR(repr, PyUnicode_GET_LENGTH(repr)-1) == ')');
1279 temp = PyUnicode_Substring(repr, 0, PyUnicode_GET_LENGTH(repr) - 1);
1280 Py_DECREF(repr);
1281 if (temp == NULL)
1282 return NULL;
1283 repr = PyUnicode_FromFormat("%U, tzinfo=%R)", temp, tzinfo);
1284 Py_DECREF(temp);
1285 return repr;
1286 }
1287
1288 /* repr is like "someclass(arg1, arg2)". If fold isn't 0,
1289 * stuff
1290 * ", fold=" + repr(tzinfo)
1291 * before the closing ")".
1292 */
1293 static PyObject *
append_keyword_fold(PyObject * repr,int fold)1294 append_keyword_fold(PyObject *repr, int fold)
1295 {
1296 PyObject *temp;
1297
1298 assert(PyUnicode_Check(repr));
1299 if (fold == 0)
1300 return repr;
1301 /* Get rid of the trailing ')'. */
1302 assert(PyUnicode_READ_CHAR(repr, PyUnicode_GET_LENGTH(repr)-1) == ')');
1303 temp = PyUnicode_Substring(repr, 0, PyUnicode_GET_LENGTH(repr) - 1);
1304 Py_DECREF(repr);
1305 if (temp == NULL)
1306 return NULL;
1307 repr = PyUnicode_FromFormat("%U, fold=%d)", temp, fold);
1308 Py_DECREF(temp);
1309 return repr;
1310 }
1311
1312 static inline PyObject *
tzinfo_from_isoformat_results(int rv,int tzoffset,int tz_useconds)1313 tzinfo_from_isoformat_results(int rv, int tzoffset, int tz_useconds)
1314 {
1315 PyObject *tzinfo;
1316 if (rv == 1) {
1317 // Create a timezone from offset in seconds (0 returns UTC)
1318 if (tzoffset == 0) {
1319 Py_INCREF(PyDateTime_TimeZone_UTC);
1320 return PyDateTime_TimeZone_UTC;
1321 }
1322
1323 PyObject *delta = new_delta(0, tzoffset, tz_useconds, 1);
1324 if (delta == NULL) {
1325 return NULL;
1326 }
1327 tzinfo = new_timezone(delta, NULL);
1328 Py_DECREF(delta);
1329 }
1330 else {
1331 tzinfo = Py_None;
1332 Py_INCREF(Py_None);
1333 }
1334
1335 return tzinfo;
1336 }
1337
1338 /* ---------------------------------------------------------------------------
1339 * String format helpers.
1340 */
1341
1342 static PyObject *
format_ctime(PyDateTime_Date * date,int hours,int minutes,int seconds)1343 format_ctime(PyDateTime_Date *date, int hours, int minutes, int seconds)
1344 {
1345 static const char * const DayNames[] = {
1346 "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
1347 };
1348 static const char * const MonthNames[] = {
1349 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1350 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1351 };
1352
1353 int wday = weekday(GET_YEAR(date), GET_MONTH(date), GET_DAY(date));
1354
1355 return PyUnicode_FromFormat("%s %s %2d %02d:%02d:%02d %04d",
1356 DayNames[wday], MonthNames[GET_MONTH(date)-1],
1357 GET_DAY(date), hours, minutes, seconds,
1358 GET_YEAR(date));
1359 }
1360
1361 static PyObject *delta_negative(PyDateTime_Delta *self);
1362
1363 /* Add formatted UTC offset string to buf. buf has no more than
1364 * buflen bytes remaining. The UTC offset is gotten by calling
1365 * tzinfo.uctoffset(tzinfoarg). If that returns None, \0 is stored into
1366 * *buf, and that's all. Else the returned value is checked for sanity (an
1367 * integer in range), and if that's OK it's converted to an hours & minutes
1368 * string of the form
1369 * sign HH sep MM [sep SS [. UUUUUU]]
1370 * Returns 0 if everything is OK. If the return value from utcoffset() is
1371 * bogus, an appropriate exception is set and -1 is returned.
1372 */
1373 static int
format_utcoffset(char * buf,size_t buflen,const char * sep,PyObject * tzinfo,PyObject * tzinfoarg)1374 format_utcoffset(char *buf, size_t buflen, const char *sep,
1375 PyObject *tzinfo, PyObject *tzinfoarg)
1376 {
1377 PyObject *offset;
1378 int hours, minutes, seconds, microseconds;
1379 char sign;
1380
1381 assert(buflen >= 1);
1382
1383 offset = call_utcoffset(tzinfo, tzinfoarg);
1384 if (offset == NULL)
1385 return -1;
1386 if (offset == Py_None) {
1387 Py_DECREF(offset);
1388 *buf = '\0';
1389 return 0;
1390 }
1391 /* Offset is normalized, so it is negative if days < 0 */
1392 if (GET_TD_DAYS(offset) < 0) {
1393 sign = '-';
1394 Py_SETREF(offset, delta_negative((PyDateTime_Delta *)offset));
1395 if (offset == NULL)
1396 return -1;
1397 }
1398 else {
1399 sign = '+';
1400 }
1401 /* Offset is not negative here. */
1402 microseconds = GET_TD_MICROSECONDS(offset);
1403 seconds = GET_TD_SECONDS(offset);
1404 Py_DECREF(offset);
1405 minutes = divmod(seconds, 60, &seconds);
1406 hours = divmod(minutes, 60, &minutes);
1407 if (microseconds) {
1408 PyOS_snprintf(buf, buflen, "%c%02d%s%02d%s%02d.%06d", sign,
1409 hours, sep, minutes, sep, seconds, microseconds);
1410 return 0;
1411 }
1412 if (seconds) {
1413 PyOS_snprintf(buf, buflen, "%c%02d%s%02d%s%02d", sign, hours,
1414 sep, minutes, sep, seconds);
1415 return 0;
1416 }
1417 PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes);
1418 return 0;
1419 }
1420
1421 static PyObject *
make_Zreplacement(PyObject * object,PyObject * tzinfoarg)1422 make_Zreplacement(PyObject *object, PyObject *tzinfoarg)
1423 {
1424 PyObject *temp;
1425 PyObject *tzinfo = get_tzinfo_member(object);
1426 PyObject *Zreplacement = PyUnicode_FromStringAndSize(NULL, 0);
1427 _Py_IDENTIFIER(replace);
1428
1429 if (Zreplacement == NULL)
1430 return NULL;
1431 if (tzinfo == Py_None || tzinfo == NULL)
1432 return Zreplacement;
1433
1434 assert(tzinfoarg != NULL);
1435 temp = call_tzname(tzinfo, tzinfoarg);
1436 if (temp == NULL)
1437 goto Error;
1438 if (temp == Py_None) {
1439 Py_DECREF(temp);
1440 return Zreplacement;
1441 }
1442
1443 assert(PyUnicode_Check(temp));
1444 /* Since the tzname is getting stuffed into the
1445 * format, we have to double any % signs so that
1446 * strftime doesn't treat them as format codes.
1447 */
1448 Py_DECREF(Zreplacement);
1449 Zreplacement = _PyObject_CallMethodId(temp, &PyId_replace, "ss", "%", "%%");
1450 Py_DECREF(temp);
1451 if (Zreplacement == NULL)
1452 return NULL;
1453 if (!PyUnicode_Check(Zreplacement)) {
1454 PyErr_SetString(PyExc_TypeError,
1455 "tzname.replace() did not return a string");
1456 goto Error;
1457 }
1458 return Zreplacement;
1459
1460 Error:
1461 Py_DECREF(Zreplacement);
1462 return NULL;
1463 }
1464
1465 static PyObject *
make_freplacement(PyObject * object)1466 make_freplacement(PyObject *object)
1467 {
1468 char freplacement[64];
1469 if (PyTime_Check(object))
1470 sprintf(freplacement, "%06d", TIME_GET_MICROSECOND(object));
1471 else if (PyDateTime_Check(object))
1472 sprintf(freplacement, "%06d", DATE_GET_MICROSECOND(object));
1473 else
1474 sprintf(freplacement, "%06d", 0);
1475
1476 return PyBytes_FromStringAndSize(freplacement, strlen(freplacement));
1477 }
1478
1479 /* I sure don't want to reproduce the strftime code from the time module,
1480 * so this imports the module and calls it. All the hair is due to
1481 * giving special meanings to the %z, %Z and %f format codes via a
1482 * preprocessing step on the format string.
1483 * tzinfoarg is the argument to pass to the object's tzinfo method, if
1484 * needed.
1485 */
1486 static PyObject *
wrap_strftime(PyObject * object,PyObject * format,PyObject * timetuple,PyObject * tzinfoarg)1487 wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
1488 PyObject *tzinfoarg)
1489 {
1490 PyObject *result = NULL; /* guilty until proved innocent */
1491
1492 PyObject *zreplacement = NULL; /* py string, replacement for %z */
1493 PyObject *Zreplacement = NULL; /* py string, replacement for %Z */
1494 PyObject *freplacement = NULL; /* py string, replacement for %f */
1495
1496 const char *pin; /* pointer to next char in input format */
1497 Py_ssize_t flen; /* length of input format */
1498 char ch; /* next char in input format */
1499
1500 PyObject *newfmt = NULL; /* py string, the output format */
1501 char *pnew; /* pointer to available byte in output format */
1502 size_t totalnew; /* number bytes total in output format buffer,
1503 exclusive of trailing \0 */
1504 size_t usednew; /* number bytes used so far in output format buffer */
1505
1506 const char *ptoappend; /* ptr to string to append to output buffer */
1507 Py_ssize_t ntoappend; /* # of bytes to append to output buffer */
1508
1509 assert(object && format && timetuple);
1510 assert(PyUnicode_Check(format));
1511 /* Convert the input format to a C string and size */
1512 pin = PyUnicode_AsUTF8AndSize(format, &flen);
1513 if (!pin)
1514 return NULL;
1515
1516 /* Scan the input format, looking for %z/%Z/%f escapes, building
1517 * a new format. Since computing the replacements for those codes
1518 * is expensive, don't unless they're actually used.
1519 */
1520 if (flen > INT_MAX - 1) {
1521 PyErr_NoMemory();
1522 goto Done;
1523 }
1524
1525 totalnew = flen + 1; /* realistic if no %z/%Z */
1526 newfmt = PyBytes_FromStringAndSize(NULL, totalnew);
1527 if (newfmt == NULL) goto Done;
1528 pnew = PyBytes_AsString(newfmt);
1529 usednew = 0;
1530
1531 while ((ch = *pin++) != '\0') {
1532 if (ch != '%') {
1533 ptoappend = pin - 1;
1534 ntoappend = 1;
1535 }
1536 else if ((ch = *pin++) == '\0') {
1537 /* Null byte follows %, copy only '%'.
1538 *
1539 * Back the pin up one char so that we catch the null check
1540 * the next time through the loop.*/
1541 pin--;
1542 ptoappend = pin - 1;
1543 ntoappend = 1;
1544 }
1545 /* A % has been seen and ch is the character after it. */
1546 else if (ch == 'z') {
1547 if (zreplacement == NULL) {
1548 /* format utcoffset */
1549 char buf[100];
1550 PyObject *tzinfo = get_tzinfo_member(object);
1551 zreplacement = PyBytes_FromStringAndSize("", 0);
1552 if (zreplacement == NULL) goto Done;
1553 if (tzinfo != Py_None && tzinfo != NULL) {
1554 assert(tzinfoarg != NULL);
1555 if (format_utcoffset(buf,
1556 sizeof(buf),
1557 "",
1558 tzinfo,
1559 tzinfoarg) < 0)
1560 goto Done;
1561 Py_DECREF(zreplacement);
1562 zreplacement =
1563 PyBytes_FromStringAndSize(buf,
1564 strlen(buf));
1565 if (zreplacement == NULL)
1566 goto Done;
1567 }
1568 }
1569 assert(zreplacement != NULL);
1570 ptoappend = PyBytes_AS_STRING(zreplacement);
1571 ntoappend = PyBytes_GET_SIZE(zreplacement);
1572 }
1573 else if (ch == 'Z') {
1574 /* format tzname */
1575 if (Zreplacement == NULL) {
1576 Zreplacement = make_Zreplacement(object,
1577 tzinfoarg);
1578 if (Zreplacement == NULL)
1579 goto Done;
1580 }
1581 assert(Zreplacement != NULL);
1582 assert(PyUnicode_Check(Zreplacement));
1583 ptoappend = PyUnicode_AsUTF8AndSize(Zreplacement,
1584 &ntoappend);
1585 if (ptoappend == NULL)
1586 goto Done;
1587 }
1588 else if (ch == 'f') {
1589 /* format microseconds */
1590 if (freplacement == NULL) {
1591 freplacement = make_freplacement(object);
1592 if (freplacement == NULL)
1593 goto Done;
1594 }
1595 assert(freplacement != NULL);
1596 assert(PyBytes_Check(freplacement));
1597 ptoappend = PyBytes_AS_STRING(freplacement);
1598 ntoappend = PyBytes_GET_SIZE(freplacement);
1599 }
1600 else {
1601 /* percent followed by neither z nor Z */
1602 ptoappend = pin - 2;
1603 ntoappend = 2;
1604 }
1605
1606 /* Append the ntoappend chars starting at ptoappend to
1607 * the new format.
1608 */
1609 if (ntoappend == 0)
1610 continue;
1611 assert(ptoappend != NULL);
1612 assert(ntoappend > 0);
1613 while (usednew + ntoappend > totalnew) {
1614 if (totalnew > (PY_SSIZE_T_MAX >> 1)) { /* overflow */
1615 PyErr_NoMemory();
1616 goto Done;
1617 }
1618 totalnew <<= 1;
1619 if (_PyBytes_Resize(&newfmt, totalnew) < 0)
1620 goto Done;
1621 pnew = PyBytes_AsString(newfmt) + usednew;
1622 }
1623 memcpy(pnew, ptoappend, ntoappend);
1624 pnew += ntoappend;
1625 usednew += ntoappend;
1626 assert(usednew <= totalnew);
1627 } /* end while() */
1628
1629 if (_PyBytes_Resize(&newfmt, usednew) < 0)
1630 goto Done;
1631 {
1632 PyObject *format;
1633 PyObject *time = PyImport_ImportModuleNoBlock("time");
1634
1635 if (time == NULL)
1636 goto Done;
1637 format = PyUnicode_FromString(PyBytes_AS_STRING(newfmt));
1638 if (format != NULL) {
1639 result = _PyObject_CallMethodIdObjArgs(time, &PyId_strftime,
1640 format, timetuple, NULL);
1641 Py_DECREF(format);
1642 }
1643 Py_DECREF(time);
1644 }
1645 Done:
1646 Py_XDECREF(freplacement);
1647 Py_XDECREF(zreplacement);
1648 Py_XDECREF(Zreplacement);
1649 Py_XDECREF(newfmt);
1650 return result;
1651 }
1652
1653 /* ---------------------------------------------------------------------------
1654 * Wrap functions from the time module. These aren't directly available
1655 * from C. Perhaps they should be.
1656 */
1657
1658 /* Call time.time() and return its result (a Python float). */
1659 static PyObject *
time_time(void)1660 time_time(void)
1661 {
1662 PyObject *result = NULL;
1663 PyObject *time = PyImport_ImportModuleNoBlock("time");
1664
1665 if (time != NULL) {
1666 _Py_IDENTIFIER(time);
1667
1668 result = _PyObject_CallMethodIdNoArgs(time, &PyId_time);
1669 Py_DECREF(time);
1670 }
1671 return result;
1672 }
1673
1674 /* Build a time.struct_time. The weekday and day number are automatically
1675 * computed from the y,m,d args.
1676 */
1677 static PyObject *
build_struct_time(int y,int m,int d,int hh,int mm,int ss,int dstflag)1678 build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
1679 {
1680 PyObject *time;
1681 PyObject *result;
1682 _Py_IDENTIFIER(struct_time);
1683 PyObject *args;
1684
1685
1686 time = PyImport_ImportModuleNoBlock("time");
1687 if (time == NULL) {
1688 return NULL;
1689 }
1690
1691 args = Py_BuildValue("iiiiiiiii",
1692 y, m, d,
1693 hh, mm, ss,
1694 weekday(y, m, d),
1695 days_before_month(y, m) + d,
1696 dstflag);
1697 if (args == NULL) {
1698 Py_DECREF(time);
1699 return NULL;
1700 }
1701
1702 result = _PyObject_CallMethodIdOneArg(time, &PyId_struct_time, args);
1703 Py_DECREF(time);
1704 Py_DECREF(args);
1705 return result;
1706 }
1707
1708 /* ---------------------------------------------------------------------------
1709 * Miscellaneous helpers.
1710 */
1711
1712 /* The comparisons here all most naturally compute a cmp()-like result.
1713 * This little helper turns that into a bool result for rich comparisons.
1714 */
1715 static PyObject *
diff_to_bool(int diff,int op)1716 diff_to_bool(int diff, int op)
1717 {
1718 Py_RETURN_RICHCOMPARE(diff, 0, op);
1719 }
1720
1721 /* Raises a "can't compare" TypeError and returns NULL. */
1722 static PyObject *
cmperror(PyObject * a,PyObject * b)1723 cmperror(PyObject *a, PyObject *b)
1724 {
1725 PyErr_Format(PyExc_TypeError,
1726 "can't compare %s to %s",
1727 Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name);
1728 return NULL;
1729 }
1730
1731 /* ---------------------------------------------------------------------------
1732 * Cached Python objects; these are set by the module init function.
1733 */
1734
1735 /* Conversion factors. */
1736 static PyObject *us_per_ms = NULL; /* 1000 */
1737 static PyObject *us_per_second = NULL; /* 1000000 */
1738 static PyObject *us_per_minute = NULL; /* 1e6 * 60 as Python int */
1739 static PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python int */
1740 static PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python int */
1741 static PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python int */
1742 static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */
1743
1744 /* ---------------------------------------------------------------------------
1745 * Class implementations.
1746 */
1747
1748 /*
1749 * PyDateTime_Delta implementation.
1750 */
1751
1752 /* Convert a timedelta to a number of us,
1753 * (24*3600*self.days + self.seconds)*1000000 + self.microseconds
1754 * as a Python int.
1755 * Doing mixed-radix arithmetic by hand instead is excruciating in C,
1756 * due to ubiquitous overflow possibilities.
1757 */
1758 static PyObject *
delta_to_microseconds(PyDateTime_Delta * self)1759 delta_to_microseconds(PyDateTime_Delta *self)
1760 {
1761 PyObject *x1 = NULL;
1762 PyObject *x2 = NULL;
1763 PyObject *x3 = NULL;
1764 PyObject *result = NULL;
1765
1766 x1 = PyLong_FromLong(GET_TD_DAYS(self));
1767 if (x1 == NULL)
1768 goto Done;
1769 x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */
1770 if (x2 == NULL)
1771 goto Done;
1772 Py_DECREF(x1);
1773 x1 = NULL;
1774
1775 /* x2 has days in seconds */
1776 x1 = PyLong_FromLong(GET_TD_SECONDS(self)); /* seconds */
1777 if (x1 == NULL)
1778 goto Done;
1779 x3 = PyNumber_Add(x1, x2); /* days and seconds in seconds */
1780 if (x3 == NULL)
1781 goto Done;
1782 Py_DECREF(x1);
1783 Py_DECREF(x2);
1784 /* x1 = */ x2 = NULL;
1785
1786 /* x3 has days+seconds in seconds */
1787 x1 = PyNumber_Multiply(x3, us_per_second); /* us */
1788 if (x1 == NULL)
1789 goto Done;
1790 Py_DECREF(x3);
1791 x3 = NULL;
1792
1793 /* x1 has days+seconds in us */
1794 x2 = PyLong_FromLong(GET_TD_MICROSECONDS(self));
1795 if (x2 == NULL)
1796 goto Done;
1797 result = PyNumber_Add(x1, x2);
1798 assert(result == NULL || PyLong_CheckExact(result));
1799
1800 Done:
1801 Py_XDECREF(x1);
1802 Py_XDECREF(x2);
1803 Py_XDECREF(x3);
1804 return result;
1805 }
1806
1807 static PyObject *
checked_divmod(PyObject * a,PyObject * b)1808 checked_divmod(PyObject *a, PyObject *b)
1809 {
1810 PyObject *result = PyNumber_Divmod(a, b);
1811 if (result != NULL) {
1812 if (!PyTuple_Check(result)) {
1813 PyErr_Format(PyExc_TypeError,
1814 "divmod() returned non-tuple (type %.200s)",
1815 Py_TYPE(result)->tp_name);
1816 Py_DECREF(result);
1817 return NULL;
1818 }
1819 if (PyTuple_GET_SIZE(result) != 2) {
1820 PyErr_Format(PyExc_TypeError,
1821 "divmod() returned a tuple of size %zd",
1822 PyTuple_GET_SIZE(result));
1823 Py_DECREF(result);
1824 return NULL;
1825 }
1826 }
1827 return result;
1828 }
1829
1830 /* Convert a number of us (as a Python int) to a timedelta.
1831 */
1832 static PyObject *
microseconds_to_delta_ex(PyObject * pyus,PyTypeObject * type)1833 microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
1834 {
1835 int us;
1836 int s;
1837 int d;
1838
1839 PyObject *tuple = NULL;
1840 PyObject *num = NULL;
1841 PyObject *result = NULL;
1842
1843 tuple = checked_divmod(pyus, us_per_second);
1844 if (tuple == NULL) {
1845 goto Done;
1846 }
1847
1848 num = PyTuple_GET_ITEM(tuple, 1); /* us */
1849 us = _PyLong_AsInt(num);
1850 num = NULL;
1851 if (us == -1 && PyErr_Occurred()) {
1852 goto Done;
1853 }
1854 if (!(0 <= us && us < 1000000)) {
1855 goto BadDivmod;
1856 }
1857
1858 num = PyTuple_GET_ITEM(tuple, 0); /* leftover seconds */
1859 Py_INCREF(num);
1860 Py_DECREF(tuple);
1861
1862 tuple = checked_divmod(num, seconds_per_day);
1863 if (tuple == NULL)
1864 goto Done;
1865 Py_DECREF(num);
1866
1867 num = PyTuple_GET_ITEM(tuple, 1); /* seconds */
1868 s = _PyLong_AsInt(num);
1869 num = NULL;
1870 if (s == -1 && PyErr_Occurred()) {
1871 goto Done;
1872 }
1873 if (!(0 <= s && s < 24*3600)) {
1874 goto BadDivmod;
1875 }
1876
1877 num = PyTuple_GET_ITEM(tuple, 0); /* leftover days */
1878 Py_INCREF(num);
1879 d = _PyLong_AsInt(num);
1880 if (d == -1 && PyErr_Occurred()) {
1881 goto Done;
1882 }
1883 result = new_delta_ex(d, s, us, 0, type);
1884
1885 Done:
1886 Py_XDECREF(tuple);
1887 Py_XDECREF(num);
1888 return result;
1889
1890 BadDivmod:
1891 PyErr_SetString(PyExc_TypeError,
1892 "divmod() returned a value out of range");
1893 goto Done;
1894 }
1895
1896 #define microseconds_to_delta(pymicros) \
1897 microseconds_to_delta_ex(pymicros, &PyDateTime_DeltaType)
1898
1899 static PyObject *
multiply_int_timedelta(PyObject * intobj,PyDateTime_Delta * delta)1900 multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
1901 {
1902 PyObject *pyus_in;
1903 PyObject *pyus_out;
1904 PyObject *result;
1905
1906 pyus_in = delta_to_microseconds(delta);
1907 if (pyus_in == NULL)
1908 return NULL;
1909
1910 pyus_out = PyNumber_Multiply(intobj, pyus_in);
1911 Py_DECREF(pyus_in);
1912 if (pyus_out == NULL)
1913 return NULL;
1914
1915 result = microseconds_to_delta(pyus_out);
1916 Py_DECREF(pyus_out);
1917 return result;
1918 }
1919
1920 static PyObject *
get_float_as_integer_ratio(PyObject * floatobj)1921 get_float_as_integer_ratio(PyObject *floatobj)
1922 {
1923 PyObject *ratio;
1924
1925 assert(floatobj && PyFloat_Check(floatobj));
1926 ratio = _PyObject_CallMethodIdNoArgs(floatobj, &PyId_as_integer_ratio);
1927 if (ratio == NULL) {
1928 return NULL;
1929 }
1930 if (!PyTuple_Check(ratio)) {
1931 PyErr_Format(PyExc_TypeError,
1932 "unexpected return type from as_integer_ratio(): "
1933 "expected tuple, got '%.200s'",
1934 Py_TYPE(ratio)->tp_name);
1935 Py_DECREF(ratio);
1936 return NULL;
1937 }
1938 if (PyTuple_Size(ratio) != 2) {
1939 PyErr_SetString(PyExc_ValueError,
1940 "as_integer_ratio() must return a 2-tuple");
1941 Py_DECREF(ratio);
1942 return NULL;
1943 }
1944 return ratio;
1945 }
1946
1947 /* op is 0 for multiplication, 1 for division */
1948 static PyObject *
multiply_truedivide_timedelta_float(PyDateTime_Delta * delta,PyObject * floatobj,int op)1949 multiply_truedivide_timedelta_float(PyDateTime_Delta *delta, PyObject *floatobj, int op)
1950 {
1951 PyObject *result = NULL;
1952 PyObject *pyus_in = NULL, *temp, *pyus_out;
1953 PyObject *ratio = NULL;
1954
1955 pyus_in = delta_to_microseconds(delta);
1956 if (pyus_in == NULL)
1957 return NULL;
1958 ratio = get_float_as_integer_ratio(floatobj);
1959 if (ratio == NULL) {
1960 goto error;
1961 }
1962 temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, op));
1963 Py_DECREF(pyus_in);
1964 pyus_in = NULL;
1965 if (temp == NULL)
1966 goto error;
1967 pyus_out = divide_nearest(temp, PyTuple_GET_ITEM(ratio, !op));
1968 Py_DECREF(temp);
1969 if (pyus_out == NULL)
1970 goto error;
1971 result = microseconds_to_delta(pyus_out);
1972 Py_DECREF(pyus_out);
1973 error:
1974 Py_XDECREF(pyus_in);
1975 Py_XDECREF(ratio);
1976
1977 return result;
1978 }
1979
1980 static PyObject *
divide_timedelta_int(PyDateTime_Delta * delta,PyObject * intobj)1981 divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj)
1982 {
1983 PyObject *pyus_in;
1984 PyObject *pyus_out;
1985 PyObject *result;
1986
1987 pyus_in = delta_to_microseconds(delta);
1988 if (pyus_in == NULL)
1989 return NULL;
1990
1991 pyus_out = PyNumber_FloorDivide(pyus_in, intobj);
1992 Py_DECREF(pyus_in);
1993 if (pyus_out == NULL)
1994 return NULL;
1995
1996 result = microseconds_to_delta(pyus_out);
1997 Py_DECREF(pyus_out);
1998 return result;
1999 }
2000
2001 static PyObject *
divide_timedelta_timedelta(PyDateTime_Delta * left,PyDateTime_Delta * right)2002 divide_timedelta_timedelta(PyDateTime_Delta *left, PyDateTime_Delta *right)
2003 {
2004 PyObject *pyus_left;
2005 PyObject *pyus_right;
2006 PyObject *result;
2007
2008 pyus_left = delta_to_microseconds(left);
2009 if (pyus_left == NULL)
2010 return NULL;
2011
2012 pyus_right = delta_to_microseconds(right);
2013 if (pyus_right == NULL) {
2014 Py_DECREF(pyus_left);
2015 return NULL;
2016 }
2017
2018 result = PyNumber_FloorDivide(pyus_left, pyus_right);
2019 Py_DECREF(pyus_left);
2020 Py_DECREF(pyus_right);
2021 return result;
2022 }
2023
2024 static PyObject *
truedivide_timedelta_timedelta(PyDateTime_Delta * left,PyDateTime_Delta * right)2025 truedivide_timedelta_timedelta(PyDateTime_Delta *left, PyDateTime_Delta *right)
2026 {
2027 PyObject *pyus_left;
2028 PyObject *pyus_right;
2029 PyObject *result;
2030
2031 pyus_left = delta_to_microseconds(left);
2032 if (pyus_left == NULL)
2033 return NULL;
2034
2035 pyus_right = delta_to_microseconds(right);
2036 if (pyus_right == NULL) {
2037 Py_DECREF(pyus_left);
2038 return NULL;
2039 }
2040
2041 result = PyNumber_TrueDivide(pyus_left, pyus_right);
2042 Py_DECREF(pyus_left);
2043 Py_DECREF(pyus_right);
2044 return result;
2045 }
2046
2047 static PyObject *
truedivide_timedelta_int(PyDateTime_Delta * delta,PyObject * i)2048 truedivide_timedelta_int(PyDateTime_Delta *delta, PyObject *i)
2049 {
2050 PyObject *result;
2051 PyObject *pyus_in, *pyus_out;
2052 pyus_in = delta_to_microseconds(delta);
2053 if (pyus_in == NULL)
2054 return NULL;
2055 pyus_out = divide_nearest(pyus_in, i);
2056 Py_DECREF(pyus_in);
2057 if (pyus_out == NULL)
2058 return NULL;
2059 result = microseconds_to_delta(pyus_out);
2060 Py_DECREF(pyus_out);
2061
2062 return result;
2063 }
2064
2065 static PyObject *
delta_add(PyObject * left,PyObject * right)2066 delta_add(PyObject *left, PyObject *right)
2067 {
2068 PyObject *result = Py_NotImplemented;
2069
2070 if (PyDelta_Check(left) && PyDelta_Check(right)) {
2071 /* delta + delta */
2072 /* The C-level additions can't overflow because of the
2073 * invariant bounds.
2074 */
2075 int days = GET_TD_DAYS(left) + GET_TD_DAYS(right);
2076 int seconds = GET_TD_SECONDS(left) + GET_TD_SECONDS(right);
2077 int microseconds = GET_TD_MICROSECONDS(left) +
2078 GET_TD_MICROSECONDS(right);
2079 result = new_delta(days, seconds, microseconds, 1);
2080 }
2081
2082 if (result == Py_NotImplemented)
2083 Py_INCREF(result);
2084 return result;
2085 }
2086
2087 static PyObject *
delta_negative(PyDateTime_Delta * self)2088 delta_negative(PyDateTime_Delta *self)
2089 {
2090 return new_delta(-GET_TD_DAYS(self),
2091 -GET_TD_SECONDS(self),
2092 -GET_TD_MICROSECONDS(self),
2093 1);
2094 }
2095
2096 static PyObject *
delta_positive(PyDateTime_Delta * self)2097 delta_positive(PyDateTime_Delta *self)
2098 {
2099 /* Could optimize this (by returning self) if this isn't a
2100 * subclass -- but who uses unary + ? Approximately nobody.
2101 */
2102 return new_delta(GET_TD_DAYS(self),
2103 GET_TD_SECONDS(self),
2104 GET_TD_MICROSECONDS(self),
2105 0);
2106 }
2107
2108 static PyObject *
delta_abs(PyDateTime_Delta * self)2109 delta_abs(PyDateTime_Delta *self)
2110 {
2111 PyObject *result;
2112
2113 assert(GET_TD_MICROSECONDS(self) >= 0);
2114 assert(GET_TD_SECONDS(self) >= 0);
2115
2116 if (GET_TD_DAYS(self) < 0)
2117 result = delta_negative(self);
2118 else
2119 result = delta_positive(self);
2120
2121 return result;
2122 }
2123
2124 static PyObject *
delta_subtract(PyObject * left,PyObject * right)2125 delta_subtract(PyObject *left, PyObject *right)
2126 {
2127 PyObject *result = Py_NotImplemented;
2128
2129 if (PyDelta_Check(left) && PyDelta_Check(right)) {
2130 /* delta - delta */
2131 /* The C-level additions can't overflow because of the
2132 * invariant bounds.
2133 */
2134 int days = GET_TD_DAYS(left) - GET_TD_DAYS(right);
2135 int seconds = GET_TD_SECONDS(left) - GET_TD_SECONDS(right);
2136 int microseconds = GET_TD_MICROSECONDS(left) -
2137 GET_TD_MICROSECONDS(right);
2138 result = new_delta(days, seconds, microseconds, 1);
2139 }
2140
2141 if (result == Py_NotImplemented)
2142 Py_INCREF(result);
2143 return result;
2144 }
2145
2146 static int
delta_cmp(PyObject * self,PyObject * other)2147 delta_cmp(PyObject *self, PyObject *other)
2148 {
2149 int diff = GET_TD_DAYS(self) - GET_TD_DAYS(other);
2150 if (diff == 0) {
2151 diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other);
2152 if (diff == 0)
2153 diff = GET_TD_MICROSECONDS(self) -
2154 GET_TD_MICROSECONDS(other);
2155 }
2156 return diff;
2157 }
2158
2159 static PyObject *
delta_richcompare(PyObject * self,PyObject * other,int op)2160 delta_richcompare(PyObject *self, PyObject *other, int op)
2161 {
2162 if (PyDelta_Check(other)) {
2163 int diff = delta_cmp(self, other);
2164 return diff_to_bool(diff, op);
2165 }
2166 else {
2167 Py_RETURN_NOTIMPLEMENTED;
2168 }
2169 }
2170
2171 static PyObject *delta_getstate(PyDateTime_Delta *self);
2172
2173 static Py_hash_t
delta_hash(PyDateTime_Delta * self)2174 delta_hash(PyDateTime_Delta *self)
2175 {
2176 if (self->hashcode == -1) {
2177 PyObject *temp = delta_getstate(self);
2178 if (temp != NULL) {
2179 self->hashcode = PyObject_Hash(temp);
2180 Py_DECREF(temp);
2181 }
2182 }
2183 return self->hashcode;
2184 }
2185
2186 static PyObject *
delta_multiply(PyObject * left,PyObject * right)2187 delta_multiply(PyObject *left, PyObject *right)
2188 {
2189 PyObject *result = Py_NotImplemented;
2190
2191 if (PyDelta_Check(left)) {
2192 /* delta * ??? */
2193 if (PyLong_Check(right))
2194 result = multiply_int_timedelta(right,
2195 (PyDateTime_Delta *) left);
2196 else if (PyFloat_Check(right))
2197 result = multiply_truedivide_timedelta_float(
2198 (PyDateTime_Delta *) left, right, 0);
2199 }
2200 else if (PyLong_Check(left))
2201 result = multiply_int_timedelta(left,
2202 (PyDateTime_Delta *) right);
2203 else if (PyFloat_Check(left))
2204 result = multiply_truedivide_timedelta_float(
2205 (PyDateTime_Delta *) right, left, 0);
2206
2207 if (result == Py_NotImplemented)
2208 Py_INCREF(result);
2209 return result;
2210 }
2211
2212 static PyObject *
delta_divide(PyObject * left,PyObject * right)2213 delta_divide(PyObject *left, PyObject *right)
2214 {
2215 PyObject *result = Py_NotImplemented;
2216
2217 if (PyDelta_Check(left)) {
2218 /* delta * ??? */
2219 if (PyLong_Check(right))
2220 result = divide_timedelta_int(
2221 (PyDateTime_Delta *)left,
2222 right);
2223 else if (PyDelta_Check(right))
2224 result = divide_timedelta_timedelta(
2225 (PyDateTime_Delta *)left,
2226 (PyDateTime_Delta *)right);
2227 }
2228
2229 if (result == Py_NotImplemented)
2230 Py_INCREF(result);
2231 return result;
2232 }
2233
2234 static PyObject *
delta_truedivide(PyObject * left,PyObject * right)2235 delta_truedivide(PyObject *left, PyObject *right)
2236 {
2237 PyObject *result = Py_NotImplemented;
2238
2239 if (PyDelta_Check(left)) {
2240 if (PyDelta_Check(right))
2241 result = truedivide_timedelta_timedelta(
2242 (PyDateTime_Delta *)left,
2243 (PyDateTime_Delta *)right);
2244 else if (PyFloat_Check(right))
2245 result = multiply_truedivide_timedelta_float(
2246 (PyDateTime_Delta *)left, right, 1);
2247 else if (PyLong_Check(right))
2248 result = truedivide_timedelta_int(
2249 (PyDateTime_Delta *)left, right);
2250 }
2251
2252 if (result == Py_NotImplemented)
2253 Py_INCREF(result);
2254 return result;
2255 }
2256
2257 static PyObject *
delta_remainder(PyObject * left,PyObject * right)2258 delta_remainder(PyObject *left, PyObject *right)
2259 {
2260 PyObject *pyus_left;
2261 PyObject *pyus_right;
2262 PyObject *pyus_remainder;
2263 PyObject *remainder;
2264
2265 if (!PyDelta_Check(left) || !PyDelta_Check(right))
2266 Py_RETURN_NOTIMPLEMENTED;
2267
2268 pyus_left = delta_to_microseconds((PyDateTime_Delta *)left);
2269 if (pyus_left == NULL)
2270 return NULL;
2271
2272 pyus_right = delta_to_microseconds((PyDateTime_Delta *)right);
2273 if (pyus_right == NULL) {
2274 Py_DECREF(pyus_left);
2275 return NULL;
2276 }
2277
2278 pyus_remainder = PyNumber_Remainder(pyus_left, pyus_right);
2279 Py_DECREF(pyus_left);
2280 Py_DECREF(pyus_right);
2281 if (pyus_remainder == NULL)
2282 return NULL;
2283
2284 remainder = microseconds_to_delta(pyus_remainder);
2285 Py_DECREF(pyus_remainder);
2286 if (remainder == NULL)
2287 return NULL;
2288
2289 return remainder;
2290 }
2291
2292 static PyObject *
delta_divmod(PyObject * left,PyObject * right)2293 delta_divmod(PyObject *left, PyObject *right)
2294 {
2295 PyObject *pyus_left;
2296 PyObject *pyus_right;
2297 PyObject *divmod;
2298 PyObject *delta;
2299 PyObject *result;
2300
2301 if (!PyDelta_Check(left) || !PyDelta_Check(right))
2302 Py_RETURN_NOTIMPLEMENTED;
2303
2304 pyus_left = delta_to_microseconds((PyDateTime_Delta *)left);
2305 if (pyus_left == NULL)
2306 return NULL;
2307
2308 pyus_right = delta_to_microseconds((PyDateTime_Delta *)right);
2309 if (pyus_right == NULL) {
2310 Py_DECREF(pyus_left);
2311 return NULL;
2312 }
2313
2314 divmod = checked_divmod(pyus_left, pyus_right);
2315 Py_DECREF(pyus_left);
2316 Py_DECREF(pyus_right);
2317 if (divmod == NULL)
2318 return NULL;
2319
2320 delta = microseconds_to_delta(PyTuple_GET_ITEM(divmod, 1));
2321 if (delta == NULL) {
2322 Py_DECREF(divmod);
2323 return NULL;
2324 }
2325 result = PyTuple_Pack(2, PyTuple_GET_ITEM(divmod, 0), delta);
2326 Py_DECREF(delta);
2327 Py_DECREF(divmod);
2328 return result;
2329 }
2330
2331 /* Fold in the value of the tag ("seconds", "weeks", etc) component of a
2332 * timedelta constructor. sofar is the # of microseconds accounted for
2333 * so far, and there are factor microseconds per current unit, the number
2334 * of which is given by num. num * factor is added to sofar in a
2335 * numerically careful way, and that's the result. Any fractional
2336 * microseconds left over (this can happen if num is a float type) are
2337 * added into *leftover.
2338 * Note that there are many ways this can give an error (NULL) return.
2339 */
2340 static PyObject *
accum(const char * tag,PyObject * sofar,PyObject * num,PyObject * factor,double * leftover)2341 accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
2342 double *leftover)
2343 {
2344 PyObject *prod;
2345 PyObject *sum;
2346
2347 assert(num != NULL);
2348
2349 if (PyLong_Check(num)) {
2350 prod = PyNumber_Multiply(num, factor);
2351 if (prod == NULL)
2352 return NULL;
2353 sum = PyNumber_Add(sofar, prod);
2354 Py_DECREF(prod);
2355 return sum;
2356 }
2357
2358 if (PyFloat_Check(num)) {
2359 double dnum;
2360 double fracpart;
2361 double intpart;
2362 PyObject *x;
2363 PyObject *y;
2364
2365 /* The Plan: decompose num into an integer part and a
2366 * fractional part, num = intpart + fracpart.
2367 * Then num * factor ==
2368 * intpart * factor + fracpart * factor
2369 * and the LHS can be computed exactly in long arithmetic.
2370 * The RHS is again broken into an int part and frac part.
2371 * and the frac part is added into *leftover.
2372 */
2373 dnum = PyFloat_AsDouble(num);
2374 if (dnum == -1.0 && PyErr_Occurred())
2375 return NULL;
2376 fracpart = modf(dnum, &intpart);
2377 x = PyLong_FromDouble(intpart);
2378 if (x == NULL)
2379 return NULL;
2380
2381 prod = PyNumber_Multiply(x, factor);
2382 Py_DECREF(x);
2383 if (prod == NULL)
2384 return NULL;
2385
2386 sum = PyNumber_Add(sofar, prod);
2387 Py_DECREF(prod);
2388 if (sum == NULL)
2389 return NULL;
2390
2391 if (fracpart == 0.0)
2392 return sum;
2393 /* So far we've lost no information. Dealing with the
2394 * fractional part requires float arithmetic, and may
2395 * lose a little info.
2396 */
2397 assert(PyLong_CheckExact(factor));
2398 dnum = PyLong_AsDouble(factor);
2399
2400 dnum *= fracpart;
2401 fracpart = modf(dnum, &intpart);
2402 x = PyLong_FromDouble(intpart);
2403 if (x == NULL) {
2404 Py_DECREF(sum);
2405 return NULL;
2406 }
2407
2408 y = PyNumber_Add(sum, x);
2409 Py_DECREF(sum);
2410 Py_DECREF(x);
2411 *leftover += fracpart;
2412 return y;
2413 }
2414
2415 PyErr_Format(PyExc_TypeError,
2416 "unsupported type for timedelta %s component: %s",
2417 tag, Py_TYPE(num)->tp_name);
2418 return NULL;
2419 }
2420
2421 static PyObject *
delta_new(PyTypeObject * type,PyObject * args,PyObject * kw)2422 delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2423 {
2424 PyObject *self = NULL;
2425
2426 /* Argument objects. */
2427 PyObject *day = NULL;
2428 PyObject *second = NULL;
2429 PyObject *us = NULL;
2430 PyObject *ms = NULL;
2431 PyObject *minute = NULL;
2432 PyObject *hour = NULL;
2433 PyObject *week = NULL;
2434
2435 PyObject *x = NULL; /* running sum of microseconds */
2436 PyObject *y = NULL; /* temp sum of microseconds */
2437 double leftover_us = 0.0;
2438
2439 static char *keywords[] = {
2440 "days", "seconds", "microseconds", "milliseconds",
2441 "minutes", "hours", "weeks", NULL
2442 };
2443
2444 if (PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOO:__new__",
2445 keywords,
2446 &day, &second, &us,
2447 &ms, &minute, &hour, &week) == 0)
2448 goto Done;
2449
2450 x = PyLong_FromLong(0);
2451 if (x == NULL)
2452 goto Done;
2453
2454 #define CLEANUP \
2455 Py_DECREF(x); \
2456 x = y; \
2457 if (x == NULL) \
2458 goto Done
2459
2460 if (us) {
2461 y = accum("microseconds", x, us, _PyLong_One, &leftover_us);
2462 CLEANUP;
2463 }
2464 if (ms) {
2465 y = accum("milliseconds", x, ms, us_per_ms, &leftover_us);
2466 CLEANUP;
2467 }
2468 if (second) {
2469 y = accum("seconds", x, second, us_per_second, &leftover_us);
2470 CLEANUP;
2471 }
2472 if (minute) {
2473 y = accum("minutes", x, minute, us_per_minute, &leftover_us);
2474 CLEANUP;
2475 }
2476 if (hour) {
2477 y = accum("hours", x, hour, us_per_hour, &leftover_us);
2478 CLEANUP;
2479 }
2480 if (day) {
2481 y = accum("days", x, day, us_per_day, &leftover_us);
2482 CLEANUP;
2483 }
2484 if (week) {
2485 y = accum("weeks", x, week, us_per_week, &leftover_us);
2486 CLEANUP;
2487 }
2488 if (leftover_us) {
2489 /* Round to nearest whole # of us, and add into x. */
2490 double whole_us = round(leftover_us);
2491 int x_is_odd;
2492 PyObject *temp;
2493
2494 if (fabs(whole_us - leftover_us) == 0.5) {
2495 /* We're exactly halfway between two integers. In order
2496 * to do round-half-to-even, we must determine whether x
2497 * is odd. Note that x is odd when it's last bit is 1. The
2498 * code below uses bitwise and operation to check the last
2499 * bit. */
2500 temp = PyNumber_And(x, _PyLong_One); /* temp <- x & 1 */
2501 if (temp == NULL) {
2502 Py_DECREF(x);
2503 goto Done;
2504 }
2505 x_is_odd = PyObject_IsTrue(temp);
2506 Py_DECREF(temp);
2507 if (x_is_odd == -1) {
2508 Py_DECREF(x);
2509 goto Done;
2510 }
2511 whole_us = 2.0 * round((leftover_us + x_is_odd) * 0.5) - x_is_odd;
2512 }
2513
2514 temp = PyLong_FromLong((long)whole_us);
2515
2516 if (temp == NULL) {
2517 Py_DECREF(x);
2518 goto Done;
2519 }
2520 y = PyNumber_Add(x, temp);
2521 Py_DECREF(temp);
2522 CLEANUP;
2523 }
2524
2525 self = microseconds_to_delta_ex(x, type);
2526 Py_DECREF(x);
2527 Done:
2528 return self;
2529
2530 #undef CLEANUP
2531 }
2532
2533 static int
delta_bool(PyDateTime_Delta * self)2534 delta_bool(PyDateTime_Delta *self)
2535 {
2536 return (GET_TD_DAYS(self) != 0
2537 || GET_TD_SECONDS(self) != 0
2538 || GET_TD_MICROSECONDS(self) != 0);
2539 }
2540
2541 static PyObject *
delta_repr(PyDateTime_Delta * self)2542 delta_repr(PyDateTime_Delta *self)
2543 {
2544 PyObject *args = PyUnicode_FromString("");
2545
2546 if (args == NULL) {
2547 return NULL;
2548 }
2549
2550 const char *sep = "";
2551
2552 if (GET_TD_DAYS(self) != 0) {
2553 Py_SETREF(args, PyUnicode_FromFormat("days=%d", GET_TD_DAYS(self)));
2554 if (args == NULL) {
2555 return NULL;
2556 }
2557 sep = ", ";
2558 }
2559
2560 if (GET_TD_SECONDS(self) != 0) {
2561 Py_SETREF(args, PyUnicode_FromFormat("%U%sseconds=%d", args, sep,
2562 GET_TD_SECONDS(self)));
2563 if (args == NULL) {
2564 return NULL;
2565 }
2566 sep = ", ";
2567 }
2568
2569 if (GET_TD_MICROSECONDS(self) != 0) {
2570 Py_SETREF(args, PyUnicode_FromFormat("%U%smicroseconds=%d", args, sep,
2571 GET_TD_MICROSECONDS(self)));
2572 if (args == NULL) {
2573 return NULL;
2574 }
2575 }
2576
2577 if (PyUnicode_GET_LENGTH(args) == 0) {
2578 Py_SETREF(args, PyUnicode_FromString("0"));
2579 if (args == NULL) {
2580 return NULL;
2581 }
2582 }
2583
2584 PyObject *repr = PyUnicode_FromFormat("%s(%S)", Py_TYPE(self)->tp_name,
2585 args);
2586 Py_DECREF(args);
2587 return repr;
2588 }
2589
2590 static PyObject *
delta_str(PyDateTime_Delta * self)2591 delta_str(PyDateTime_Delta *self)
2592 {
2593 int us = GET_TD_MICROSECONDS(self);
2594 int seconds = GET_TD_SECONDS(self);
2595 int minutes = divmod(seconds, 60, &seconds);
2596 int hours = divmod(minutes, 60, &minutes);
2597 int days = GET_TD_DAYS(self);
2598
2599 if (days) {
2600 if (us)
2601 return PyUnicode_FromFormat("%d day%s, %d:%02d:%02d.%06d",
2602 days, (days == 1 || days == -1) ? "" : "s",
2603 hours, minutes, seconds, us);
2604 else
2605 return PyUnicode_FromFormat("%d day%s, %d:%02d:%02d",
2606 days, (days == 1 || days == -1) ? "" : "s",
2607 hours, minutes, seconds);
2608 } else {
2609 if (us)
2610 return PyUnicode_FromFormat("%d:%02d:%02d.%06d",
2611 hours, minutes, seconds, us);
2612 else
2613 return PyUnicode_FromFormat("%d:%02d:%02d",
2614 hours, minutes, seconds);
2615 }
2616
2617 }
2618
2619 /* Pickle support, a simple use of __reduce__. */
2620
2621 /* __getstate__ isn't exposed */
2622 static PyObject *
delta_getstate(PyDateTime_Delta * self)2623 delta_getstate(PyDateTime_Delta *self)
2624 {
2625 return Py_BuildValue("iii", GET_TD_DAYS(self),
2626 GET_TD_SECONDS(self),
2627 GET_TD_MICROSECONDS(self));
2628 }
2629
2630 static PyObject *
delta_total_seconds(PyObject * self,PyObject * Py_UNUSED (ignored))2631 delta_total_seconds(PyObject *self, PyObject *Py_UNUSED(ignored))
2632 {
2633 PyObject *total_seconds;
2634 PyObject *total_microseconds;
2635
2636 total_microseconds = delta_to_microseconds((PyDateTime_Delta *)self);
2637 if (total_microseconds == NULL)
2638 return NULL;
2639
2640 total_seconds = PyNumber_TrueDivide(total_microseconds, us_per_second);
2641
2642 Py_DECREF(total_microseconds);
2643 return total_seconds;
2644 }
2645
2646 static PyObject *
delta_reduce(PyDateTime_Delta * self,PyObject * Py_UNUSED (ignored))2647 delta_reduce(PyDateTime_Delta* self, PyObject *Py_UNUSED(ignored))
2648 {
2649 return Py_BuildValue("ON", Py_TYPE(self), delta_getstate(self));
2650 }
2651
2652 #define OFFSET(field) offsetof(PyDateTime_Delta, field)
2653
2654 static PyMemberDef delta_members[] = {
2655
2656 {"days", T_INT, OFFSET(days), READONLY,
2657 PyDoc_STR("Number of days.")},
2658
2659 {"seconds", T_INT, OFFSET(seconds), READONLY,
2660 PyDoc_STR("Number of seconds (>= 0 and less than 1 day).")},
2661
2662 {"microseconds", T_INT, OFFSET(microseconds), READONLY,
2663 PyDoc_STR("Number of microseconds (>= 0 and less than 1 second).")},
2664 {NULL}
2665 };
2666
2667 static PyMethodDef delta_methods[] = {
2668 {"total_seconds", delta_total_seconds, METH_NOARGS,
2669 PyDoc_STR("Total seconds in the duration.")},
2670
2671 {"__reduce__", (PyCFunction)delta_reduce, METH_NOARGS,
2672 PyDoc_STR("__reduce__() -> (cls, state)")},
2673
2674 {NULL, NULL},
2675 };
2676
2677 static const char delta_doc[] =
2678 PyDoc_STR("Difference between two datetime values.\n\n"
2679 "timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, "
2680 "minutes=0, hours=0, weeks=0)\n\n"
2681 "All arguments are optional and default to 0.\n"
2682 "Arguments may be integers or floats, and may be positive or negative.");
2683
2684 static PyNumberMethods delta_as_number = {
2685 delta_add, /* nb_add */
2686 delta_subtract, /* nb_subtract */
2687 delta_multiply, /* nb_multiply */
2688 delta_remainder, /* nb_remainder */
2689 delta_divmod, /* nb_divmod */
2690 0, /* nb_power */
2691 (unaryfunc)delta_negative, /* nb_negative */
2692 (unaryfunc)delta_positive, /* nb_positive */
2693 (unaryfunc)delta_abs, /* nb_absolute */
2694 (inquiry)delta_bool, /* nb_bool */
2695 0, /*nb_invert*/
2696 0, /*nb_lshift*/
2697 0, /*nb_rshift*/
2698 0, /*nb_and*/
2699 0, /*nb_xor*/
2700 0, /*nb_or*/
2701 0, /*nb_int*/
2702 0, /*nb_reserved*/
2703 0, /*nb_float*/
2704 0, /*nb_inplace_add*/
2705 0, /*nb_inplace_subtract*/
2706 0, /*nb_inplace_multiply*/
2707 0, /*nb_inplace_remainder*/
2708 0, /*nb_inplace_power*/
2709 0, /*nb_inplace_lshift*/
2710 0, /*nb_inplace_rshift*/
2711 0, /*nb_inplace_and*/
2712 0, /*nb_inplace_xor*/
2713 0, /*nb_inplace_or*/
2714 delta_divide, /* nb_floor_divide */
2715 delta_truedivide, /* nb_true_divide */
2716 0, /* nb_inplace_floor_divide */
2717 0, /* nb_inplace_true_divide */
2718 };
2719
2720 static PyTypeObject PyDateTime_DeltaType = {
2721 PyVarObject_HEAD_INIT(NULL, 0)
2722 "datetime.timedelta", /* tp_name */
2723 sizeof(PyDateTime_Delta), /* tp_basicsize */
2724 0, /* tp_itemsize */
2725 0, /* tp_dealloc */
2726 0, /* tp_vectorcall_offset */
2727 0, /* tp_getattr */
2728 0, /* tp_setattr */
2729 0, /* tp_as_async */
2730 (reprfunc)delta_repr, /* tp_repr */
2731 &delta_as_number, /* tp_as_number */
2732 0, /* tp_as_sequence */
2733 0, /* tp_as_mapping */
2734 (hashfunc)delta_hash, /* tp_hash */
2735 0, /* tp_call */
2736 (reprfunc)delta_str, /* tp_str */
2737 PyObject_GenericGetAttr, /* tp_getattro */
2738 0, /* tp_setattro */
2739 0, /* tp_as_buffer */
2740 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
2741 delta_doc, /* tp_doc */
2742 0, /* tp_traverse */
2743 0, /* tp_clear */
2744 delta_richcompare, /* tp_richcompare */
2745 0, /* tp_weaklistoffset */
2746 0, /* tp_iter */
2747 0, /* tp_iternext */
2748 delta_methods, /* tp_methods */
2749 delta_members, /* tp_members */
2750 0, /* tp_getset */
2751 0, /* tp_base */
2752 0, /* tp_dict */
2753 0, /* tp_descr_get */
2754 0, /* tp_descr_set */
2755 0, /* tp_dictoffset */
2756 0, /* tp_init */
2757 0, /* tp_alloc */
2758 delta_new, /* tp_new */
2759 0, /* tp_free */
2760 };
2761
2762 /*
2763 * PyDateTime_Date implementation.
2764 */
2765
2766 /* Accessor properties. */
2767
2768 static PyObject *
date_year(PyDateTime_Date * self,void * unused)2769 date_year(PyDateTime_Date *self, void *unused)
2770 {
2771 return PyLong_FromLong(GET_YEAR(self));
2772 }
2773
2774 static PyObject *
date_month(PyDateTime_Date * self,void * unused)2775 date_month(PyDateTime_Date *self, void *unused)
2776 {
2777 return PyLong_FromLong(GET_MONTH(self));
2778 }
2779
2780 static PyObject *
date_day(PyDateTime_Date * self,void * unused)2781 date_day(PyDateTime_Date *self, void *unused)
2782 {
2783 return PyLong_FromLong(GET_DAY(self));
2784 }
2785
2786 static PyGetSetDef date_getset[] = {
2787 {"year", (getter)date_year},
2788 {"month", (getter)date_month},
2789 {"day", (getter)date_day},
2790 {NULL}
2791 };
2792
2793 /* Constructors. */
2794
2795 static char *date_kws[] = {"year", "month", "day", NULL};
2796
2797 static PyObject *
date_from_pickle(PyTypeObject * type,PyObject * state)2798 date_from_pickle(PyTypeObject *type, PyObject *state)
2799 {
2800 PyDateTime_Date *me;
2801
2802 me = (PyDateTime_Date *) (type->tp_alloc(type, 0));
2803 if (me != NULL) {
2804 const char *pdata = PyBytes_AS_STRING(state);
2805 memcpy(me->data, pdata, _PyDateTime_DATE_DATASIZE);
2806 me->hashcode = -1;
2807 }
2808 return (PyObject *)me;
2809 }
2810
2811 static PyObject *
date_new(PyTypeObject * type,PyObject * args,PyObject * kw)2812 date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2813 {
2814 PyObject *self = NULL;
2815 int year;
2816 int month;
2817 int day;
2818
2819 /* Check for invocation from pickle with __getstate__ state */
2820 if (PyTuple_GET_SIZE(args) == 1) {
2821 PyObject *state = PyTuple_GET_ITEM(args, 0);
2822 if (PyBytes_Check(state)) {
2823 if (PyBytes_GET_SIZE(state) == _PyDateTime_DATE_DATASIZE &&
2824 MONTH_IS_SANE(PyBytes_AS_STRING(state)[2]))
2825 {
2826 return date_from_pickle(type, state);
2827 }
2828 }
2829 else if (PyUnicode_Check(state)) {
2830 if (PyUnicode_READY(state)) {
2831 return NULL;
2832 }
2833 if (PyUnicode_GET_LENGTH(state) == _PyDateTime_DATE_DATASIZE &&
2834 MONTH_IS_SANE(PyUnicode_READ_CHAR(state, 2)))
2835 {
2836 state = PyUnicode_AsLatin1String(state);
2837 if (state == NULL) {
2838 if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) {
2839 /* More informative error message. */
2840 PyErr_SetString(PyExc_ValueError,
2841 "Failed to encode latin1 string when unpickling "
2842 "a date object. "
2843 "pickle.load(data, encoding='latin1') is assumed.");
2844 }
2845 return NULL;
2846 }
2847 self = date_from_pickle(type, state);
2848 Py_DECREF(state);
2849 return self;
2850 }
2851 }
2852 }
2853
2854 if (PyArg_ParseTupleAndKeywords(args, kw, "iii", date_kws,
2855 &year, &month, &day)) {
2856 self = new_date_ex(year, month, day, type);
2857 }
2858 return self;
2859 }
2860
2861 static PyObject *
date_fromtimestamp(PyObject * cls,PyObject * obj)2862 date_fromtimestamp(PyObject *cls, PyObject *obj)
2863 {
2864 struct tm tm;
2865 time_t t;
2866
2867 if (_PyTime_ObjectToTime_t(obj, &t, _PyTime_ROUND_FLOOR) == -1)
2868 return NULL;
2869
2870 if (_PyTime_localtime(t, &tm) != 0)
2871 return NULL;
2872
2873 return new_date_subclass_ex(tm.tm_year + 1900,
2874 tm.tm_mon + 1,
2875 tm.tm_mday,
2876 cls);
2877 }
2878
2879 /* Return new date from current time.
2880 * We say this is equivalent to fromtimestamp(time.time()), and the
2881 * only way to be sure of that is to *call* time.time(). That's not
2882 * generally the same as calling C's time.
2883 */
2884 static PyObject *
date_today(PyObject * cls,PyObject * dummy)2885 date_today(PyObject *cls, PyObject *dummy)
2886 {
2887 PyObject *time;
2888 PyObject *result;
2889 _Py_IDENTIFIER(fromtimestamp);
2890
2891 time = time_time();
2892 if (time == NULL)
2893 return NULL;
2894
2895 /* Note well: today() is a class method, so this may not call
2896 * date.fromtimestamp. For example, it may call
2897 * datetime.fromtimestamp. That's why we need all the accuracy
2898 * time.time() delivers; if someone were gonzo about optimization,
2899 * date.today() could get away with plain C time().
2900 */
2901 result = _PyObject_CallMethodIdOneArg(cls, &PyId_fromtimestamp, time);
2902 Py_DECREF(time);
2903 return result;
2904 }
2905
2906 /*[clinic input]
2907 @classmethod
2908 datetime.date.fromtimestamp
2909
2910 timestamp: object
2911 /
2912
2913 Create a date from a POSIX timestamp.
2914
2915 The timestamp is a number, e.g. created via time.time(), that is interpreted
2916 as local time.
2917 [clinic start generated code]*/
2918
2919 static PyObject *
datetime_date_fromtimestamp(PyTypeObject * type,PyObject * timestamp)2920 datetime_date_fromtimestamp(PyTypeObject *type, PyObject *timestamp)
2921 /*[clinic end generated code: output=fd045fda58168869 input=eabb3fe7f40491fe]*/
2922 {
2923 return date_fromtimestamp((PyObject *) type, timestamp);
2924 }
2925
2926 /* bpo-36025: This is a wrapper for API compatibility with the public C API,
2927 * which expects a function that takes an *args tuple, whereas the argument
2928 * clinic generates code that takes METH_O.
2929 */
2930 static PyObject *
datetime_date_fromtimestamp_capi(PyObject * cls,PyObject * args)2931 datetime_date_fromtimestamp_capi(PyObject *cls, PyObject *args)
2932 {
2933 PyObject *timestamp;
2934 PyObject *result = NULL;
2935
2936 if (PyArg_UnpackTuple(args, "fromtimestamp", 1, 1, ×tamp)) {
2937 result = date_fromtimestamp(cls, timestamp);
2938 }
2939
2940 return result;
2941 }
2942
2943 /* Return new date from proleptic Gregorian ordinal. Raises ValueError if
2944 * the ordinal is out of range.
2945 */
2946 static PyObject *
date_fromordinal(PyObject * cls,PyObject * args)2947 date_fromordinal(PyObject *cls, PyObject *args)
2948 {
2949 PyObject *result = NULL;
2950 int ordinal;
2951
2952 if (PyArg_ParseTuple(args, "i:fromordinal", &ordinal)) {
2953 int year;
2954 int month;
2955 int day;
2956
2957 if (ordinal < 1)
2958 PyErr_SetString(PyExc_ValueError, "ordinal must be "
2959 ">= 1");
2960 else {
2961 ord_to_ymd(ordinal, &year, &month, &day);
2962 result = new_date_subclass_ex(year, month, day, cls);
2963 }
2964 }
2965 return result;
2966 }
2967
2968 /* Return the new date from a string as generated by date.isoformat() */
2969 static PyObject *
date_fromisoformat(PyObject * cls,PyObject * dtstr)2970 date_fromisoformat(PyObject *cls, PyObject *dtstr)
2971 {
2972 assert(dtstr != NULL);
2973
2974 if (!PyUnicode_Check(dtstr)) {
2975 PyErr_SetString(PyExc_TypeError,
2976 "fromisoformat: argument must be str");
2977 return NULL;
2978 }
2979
2980 Py_ssize_t len;
2981
2982 const char *dt_ptr = PyUnicode_AsUTF8AndSize(dtstr, &len);
2983 if (dt_ptr == NULL) {
2984 goto invalid_string_error;
2985 }
2986
2987 int year = 0, month = 0, day = 0;
2988
2989 int rv;
2990 if (len == 10) {
2991 rv = parse_isoformat_date(dt_ptr, &year, &month, &day);
2992 }
2993 else {
2994 rv = -1;
2995 }
2996
2997 if (rv < 0) {
2998 goto invalid_string_error;
2999 }
3000
3001 return new_date_subclass_ex(year, month, day, cls);
3002
3003 invalid_string_error:
3004 PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %R", dtstr);
3005 return NULL;
3006 }
3007
3008
3009 static PyObject *
date_fromisocalendar(PyObject * cls,PyObject * args,PyObject * kw)3010 date_fromisocalendar(PyObject *cls, PyObject *args, PyObject *kw)
3011 {
3012 static char *keywords[] = {
3013 "year", "week", "day", NULL
3014 };
3015
3016 int year, week, day;
3017 if (PyArg_ParseTupleAndKeywords(args, kw, "iii:fromisocalendar",
3018 keywords,
3019 &year, &week, &day) == 0) {
3020 if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
3021 PyErr_Format(PyExc_ValueError,
3022 "ISO calendar component out of range");
3023
3024 }
3025 return NULL;
3026 }
3027
3028 // Year is bounded to 0 < year < 10000 because 9999-12-31 is (9999, 52, 5)
3029 if (year < MINYEAR || year > MAXYEAR) {
3030 PyErr_Format(PyExc_ValueError, "Year is out of range: %d", year);
3031 return NULL;
3032 }
3033
3034 if (week <= 0 || week >= 53) {
3035 int out_of_range = 1;
3036 if (week == 53) {
3037 // ISO years have 53 weeks in it on years starting with a Thursday
3038 // and on leap years starting on Wednesday
3039 int first_weekday = weekday(year, 1, 1);
3040 if (first_weekday == 3 || (first_weekday == 2 && is_leap(year))) {
3041 out_of_range = 0;
3042 }
3043 }
3044
3045 if (out_of_range) {
3046 PyErr_Format(PyExc_ValueError, "Invalid week: %d", week);
3047 return NULL;
3048 }
3049 }
3050
3051 if (day <= 0 || day >= 8) {
3052 PyErr_Format(PyExc_ValueError, "Invalid day: %d (range is [1, 7])",
3053 day);
3054 return NULL;
3055 }
3056
3057 // Convert (Y, W, D) to (Y, M, D) in-place
3058 int day_1 = iso_week1_monday(year);
3059
3060 int month = week;
3061 int day_offset = (month - 1)*7 + day - 1;
3062
3063 ord_to_ymd(day_1 + day_offset, &year, &month, &day);
3064
3065 return new_date_subclass_ex(year, month, day, cls);
3066 }
3067
3068
3069 /*
3070 * Date arithmetic.
3071 */
3072
3073 /* date + timedelta -> date. If arg negate is true, subtract the timedelta
3074 * instead.
3075 */
3076 static PyObject *
add_date_timedelta(PyDateTime_Date * date,PyDateTime_Delta * delta,int negate)3077 add_date_timedelta(PyDateTime_Date *date, PyDateTime_Delta *delta, int negate)
3078 {
3079 PyObject *result = NULL;
3080 int year = GET_YEAR(date);
3081 int month = GET_MONTH(date);
3082 int deltadays = GET_TD_DAYS(delta);
3083 /* C-level overflow is impossible because |deltadays| < 1e9. */
3084 int day = GET_DAY(date) + (negate ? -deltadays : deltadays);
3085
3086 if (normalize_date(&year, &month, &day) >= 0)
3087 result = new_date_subclass_ex(year, month, day,
3088 (PyObject* )Py_TYPE(date));
3089 return result;
3090 }
3091
3092 static PyObject *
date_add(PyObject * left,PyObject * right)3093 date_add(PyObject *left, PyObject *right)
3094 {
3095 if (PyDateTime_Check(left) || PyDateTime_Check(right))
3096 Py_RETURN_NOTIMPLEMENTED;
3097
3098 if (PyDate_Check(left)) {
3099 /* date + ??? */
3100 if (PyDelta_Check(right))
3101 /* date + delta */
3102 return add_date_timedelta((PyDateTime_Date *) left,
3103 (PyDateTime_Delta *) right,
3104 0);
3105 }
3106 else {
3107 /* ??? + date
3108 * 'right' must be one of us, or we wouldn't have been called
3109 */
3110 if (PyDelta_Check(left))
3111 /* delta + date */
3112 return add_date_timedelta((PyDateTime_Date *) right,
3113 (PyDateTime_Delta *) left,
3114 0);
3115 }
3116 Py_RETURN_NOTIMPLEMENTED;
3117 }
3118
3119 static PyObject *
date_subtract(PyObject * left,PyObject * right)3120 date_subtract(PyObject *left, PyObject *right)
3121 {
3122 if (PyDateTime_Check(left) || PyDateTime_Check(right))
3123 Py_RETURN_NOTIMPLEMENTED;
3124
3125 if (PyDate_Check(left)) {
3126 if (PyDate_Check(right)) {
3127 /* date - date */
3128 int left_ord = ymd_to_ord(GET_YEAR(left),
3129 GET_MONTH(left),
3130 GET_DAY(left));
3131 int right_ord = ymd_to_ord(GET_YEAR(right),
3132 GET_MONTH(right),
3133 GET_DAY(right));
3134 return new_delta(left_ord - right_ord, 0, 0, 0);
3135 }
3136 if (PyDelta_Check(right)) {
3137 /* date - delta */
3138 return add_date_timedelta((PyDateTime_Date *) left,
3139 (PyDateTime_Delta *) right,
3140 1);
3141 }
3142 }
3143 Py_RETURN_NOTIMPLEMENTED;
3144 }
3145
3146
3147 /* Various ways to turn a date into a string. */
3148
3149 static PyObject *
date_repr(PyDateTime_Date * self)3150 date_repr(PyDateTime_Date *self)
3151 {
3152 return PyUnicode_FromFormat("%s(%d, %d, %d)",
3153 Py_TYPE(self)->tp_name,
3154 GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
3155 }
3156
3157 static PyObject *
date_isoformat(PyDateTime_Date * self,PyObject * Py_UNUSED (ignored))3158 date_isoformat(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
3159 {
3160 return PyUnicode_FromFormat("%04d-%02d-%02d",
3161 GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
3162 }
3163
3164 /* str() calls the appropriate isoformat() method. */
3165 static PyObject *
date_str(PyDateTime_Date * self)3166 date_str(PyDateTime_Date *self)
3167 {
3168 return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat);
3169 }
3170
3171
3172 static PyObject *
date_ctime(PyDateTime_Date * self,PyObject * Py_UNUSED (ignored))3173 date_ctime(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
3174 {
3175 return format_ctime(self, 0, 0, 0);
3176 }
3177
3178 static PyObject *
date_strftime(PyDateTime_Date * self,PyObject * args,PyObject * kw)3179 date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw)
3180 {
3181 /* This method can be inherited, and needs to call the
3182 * timetuple() method appropriate to self's class.
3183 */
3184 PyObject *result;
3185 PyObject *tuple;
3186 PyObject *format;
3187 _Py_IDENTIFIER(timetuple);
3188 static char *keywords[] = {"format", NULL};
3189
3190 if (! PyArg_ParseTupleAndKeywords(args, kw, "U:strftime", keywords,
3191 &format))
3192 return NULL;
3193
3194 tuple = _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_timetuple);
3195 if (tuple == NULL)
3196 return NULL;
3197 result = wrap_strftime((PyObject *)self, format, tuple,
3198 (PyObject *)self);
3199 Py_DECREF(tuple);
3200 return result;
3201 }
3202
3203 static PyObject *
date_format(PyDateTime_Date * self,PyObject * args)3204 date_format(PyDateTime_Date *self, PyObject *args)
3205 {
3206 PyObject *format;
3207
3208 if (!PyArg_ParseTuple(args, "U:__format__", &format))
3209 return NULL;
3210
3211 /* if the format is zero length, return str(self) */
3212 if (PyUnicode_GetLength(format) == 0)
3213 return PyObject_Str((PyObject *)self);
3214
3215 return _PyObject_CallMethodIdOneArg((PyObject *)self, &PyId_strftime,
3216 format);
3217 }
3218
3219 /* ISO methods. */
3220
3221 static PyObject *
date_isoweekday(PyDateTime_Date * self,PyObject * Py_UNUSED (ignored))3222 date_isoweekday(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
3223 {
3224 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
3225
3226 return PyLong_FromLong(dow + 1);
3227 }
3228
3229 PyDoc_STRVAR(iso_calendar_date__doc__,
3230 "The result of date.isocalendar() or datetime.isocalendar()\n\n\
3231 This object may be accessed either as a tuple of\n\
3232 ((year, week, weekday)\n\
3233 or via the object attributes as named in the above tuple.");
3234
3235 typedef struct {
3236 PyTupleObject tuple;
3237 } PyDateTime_IsoCalendarDate;
3238
3239 static PyObject *
iso_calendar_date_repr(PyDateTime_IsoCalendarDate * self)3240 iso_calendar_date_repr(PyDateTime_IsoCalendarDate *self)
3241 {
3242 PyObject* year = PyTuple_GetItem((PyObject *)self, 0);
3243 if (year == NULL) {
3244 return NULL;
3245 }
3246 PyObject* week = PyTuple_GetItem((PyObject *)self, 1);
3247 if (week == NULL) {
3248 return NULL;
3249 }
3250 PyObject* weekday = PyTuple_GetItem((PyObject *)self, 2);
3251 if (weekday == NULL) {
3252 return NULL;
3253 }
3254
3255 return PyUnicode_FromFormat("%.200s(year=%S, week=%S, weekday=%S)",
3256 Py_TYPE(self)->tp_name, year, week, weekday);
3257 }
3258
3259 static PyObject *
iso_calendar_date_reduce(PyObject * self,PyObject * Py_UNUSED (ignored))3260 iso_calendar_date_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
3261 {
3262 // Construct the tuple that this reduces to
3263 PyObject * reduce_tuple = Py_BuildValue(
3264 "O((OOO))", &PyTuple_Type,
3265 PyTuple_GET_ITEM(self, 0),
3266 PyTuple_GET_ITEM(self, 1),
3267 PyTuple_GET_ITEM(self, 2)
3268 );
3269
3270 return reduce_tuple;
3271 }
3272
3273 static PyObject *
iso_calendar_date_year(PyDateTime_IsoCalendarDate * self,void * unused)3274 iso_calendar_date_year(PyDateTime_IsoCalendarDate *self, void *unused)
3275 {
3276 PyObject *year = PyTuple_GetItem((PyObject *)self, 0);
3277 if (year == NULL) {
3278 return NULL;
3279 }
3280 Py_INCREF(year);
3281 return year;
3282 }
3283
3284 static PyObject *
iso_calendar_date_week(PyDateTime_IsoCalendarDate * self,void * unused)3285 iso_calendar_date_week(PyDateTime_IsoCalendarDate *self, void *unused)
3286 {
3287 PyObject *week = PyTuple_GetItem((PyObject *)self, 1);
3288 if (week == NULL) {
3289 return NULL;
3290 }
3291 Py_INCREF(week);
3292 return week;
3293 }
3294
3295 static PyObject *
iso_calendar_date_weekday(PyDateTime_IsoCalendarDate * self,void * unused)3296 iso_calendar_date_weekday(PyDateTime_IsoCalendarDate *self, void *unused)
3297 {
3298 PyObject *weekday = PyTuple_GetItem((PyObject *)self, 2);
3299 if (weekday == NULL) {
3300 return NULL;
3301 }
3302 Py_INCREF(weekday);
3303 return weekday;
3304 }
3305
3306 static PyGetSetDef iso_calendar_date_getset[] = {
3307 {"year", (getter)iso_calendar_date_year},
3308 {"week", (getter)iso_calendar_date_week},
3309 {"weekday", (getter)iso_calendar_date_weekday},
3310 {NULL}
3311 };
3312
3313 static PyMethodDef iso_calendar_date_methods[] = {
3314 {"__reduce__", (PyCFunction)iso_calendar_date_reduce, METH_NOARGS,
3315 PyDoc_STR("__reduce__() -> (cls, state)")},
3316 {NULL, NULL},
3317 };
3318
3319 static PyTypeObject PyDateTime_IsoCalendarDateType = {
3320 PyVarObject_HEAD_INIT(NULL, 0)
3321 .tp_name = "datetime.IsoCalendarDate",
3322 .tp_basicsize = sizeof(PyDateTime_IsoCalendarDate),
3323 .tp_repr = (reprfunc) iso_calendar_date_repr,
3324 .tp_flags = Py_TPFLAGS_DEFAULT,
3325 .tp_doc = iso_calendar_date__doc__,
3326 .tp_methods = iso_calendar_date_methods,
3327 .tp_getset = iso_calendar_date_getset,
3328 // .tp_base = &PyTuple_Type, // filled in PyInit__datetime
3329 .tp_new = iso_calendar_date_new,
3330 };
3331
3332 /*[clinic input]
3333 @classmethod
3334 datetime.IsoCalendarDate.__new__ as iso_calendar_date_new
3335 year: int
3336 week: int
3337 weekday: int
3338 [clinic start generated code]*/
3339
3340 static PyObject *
iso_calendar_date_new_impl(PyTypeObject * type,int year,int week,int weekday)3341 iso_calendar_date_new_impl(PyTypeObject *type, int year, int week,
3342 int weekday)
3343 /*[clinic end generated code: output=383d33d8dc7183a2 input=4f2c663c9d19c4ee]*/
3344
3345 {
3346 PyDateTime_IsoCalendarDate *self;
3347 self = (PyDateTime_IsoCalendarDate *) type->tp_alloc(type, 3);
3348 if (self == NULL) {
3349 return NULL;
3350 }
3351
3352 PyTuple_SET_ITEM(self, 0, PyLong_FromLong(year));
3353 PyTuple_SET_ITEM(self, 1, PyLong_FromLong(week));
3354 PyTuple_SET_ITEM(self, 2, PyLong_FromLong(weekday));
3355
3356 return (PyObject *)self;
3357 }
3358
3359 static PyObject *
date_isocalendar(PyDateTime_Date * self,PyObject * Py_UNUSED (ignored))3360 date_isocalendar(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
3361 {
3362 int year = GET_YEAR(self);
3363 int week1_monday = iso_week1_monday(year);
3364 int today = ymd_to_ord(year, GET_MONTH(self), GET_DAY(self));
3365 int week;
3366 int day;
3367
3368 week = divmod(today - week1_monday, 7, &day);
3369 if (week < 0) {
3370 --year;
3371 week1_monday = iso_week1_monday(year);
3372 week = divmod(today - week1_monday, 7, &day);
3373 }
3374 else if (week >= 52 && today >= iso_week1_monday(year + 1)) {
3375 ++year;
3376 week = 0;
3377 }
3378
3379 PyObject* v = iso_calendar_date_new_impl(&PyDateTime_IsoCalendarDateType,
3380 year, week + 1, day + 1);
3381 if (v == NULL) {
3382 return NULL;
3383 }
3384 return v;
3385 }
3386
3387 /* Miscellaneous methods. */
3388
3389 static PyObject *
date_richcompare(PyObject * self,PyObject * other,int op)3390 date_richcompare(PyObject *self, PyObject *other, int op)
3391 {
3392 if (PyDate_Check(other)) {
3393 int diff = memcmp(((PyDateTime_Date *)self)->data,
3394 ((PyDateTime_Date *)other)->data,
3395 _PyDateTime_DATE_DATASIZE);
3396 return diff_to_bool(diff, op);
3397 }
3398 else
3399 Py_RETURN_NOTIMPLEMENTED;
3400 }
3401
3402 static PyObject *
date_timetuple(PyDateTime_Date * self,PyObject * Py_UNUSED (ignored))3403 date_timetuple(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
3404 {
3405 return build_struct_time(GET_YEAR(self),
3406 GET_MONTH(self),
3407 GET_DAY(self),
3408 0, 0, 0, -1);
3409 }
3410
3411 static PyObject *
date_replace(PyDateTime_Date * self,PyObject * args,PyObject * kw)3412 date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw)
3413 {
3414 PyObject *clone;
3415 PyObject *tuple;
3416 int year = GET_YEAR(self);
3417 int month = GET_MONTH(self);
3418 int day = GET_DAY(self);
3419
3420 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iii:replace", date_kws,
3421 &year, &month, &day))
3422 return NULL;
3423 tuple = Py_BuildValue("iii", year, month, day);
3424 if (tuple == NULL)
3425 return NULL;
3426 clone = date_new(Py_TYPE(self), tuple, NULL);
3427 Py_DECREF(tuple);
3428 return clone;
3429 }
3430
3431 static Py_hash_t
generic_hash(unsigned char * data,int len)3432 generic_hash(unsigned char *data, int len)
3433 {
3434 return _Py_HashBytes(data, len);
3435 }
3436
3437
3438 static PyObject *date_getstate(PyDateTime_Date *self);
3439
3440 static Py_hash_t
date_hash(PyDateTime_Date * self)3441 date_hash(PyDateTime_Date *self)
3442 {
3443 if (self->hashcode == -1) {
3444 self->hashcode = generic_hash(
3445 (unsigned char *)self->data, _PyDateTime_DATE_DATASIZE);
3446 }
3447
3448 return self->hashcode;
3449 }
3450
3451 static PyObject *
date_toordinal(PyDateTime_Date * self,PyObject * Py_UNUSED (ignored))3452 date_toordinal(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
3453 {
3454 return PyLong_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self),
3455 GET_DAY(self)));
3456 }
3457
3458 static PyObject *
date_weekday(PyDateTime_Date * self,PyObject * Py_UNUSED (ignored))3459 date_weekday(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored))
3460 {
3461 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
3462
3463 return PyLong_FromLong(dow);
3464 }
3465
3466 /* Pickle support, a simple use of __reduce__. */
3467
3468 /* __getstate__ isn't exposed */
3469 static PyObject *
date_getstate(PyDateTime_Date * self)3470 date_getstate(PyDateTime_Date *self)
3471 {
3472 PyObject* field;
3473 field = PyBytes_FromStringAndSize((char*)self->data,
3474 _PyDateTime_DATE_DATASIZE);
3475 return Py_BuildValue("(N)", field);
3476 }
3477
3478 static PyObject *
date_reduce(PyDateTime_Date * self,PyObject * arg)3479 date_reduce(PyDateTime_Date *self, PyObject *arg)
3480 {
3481 return Py_BuildValue("(ON)", Py_TYPE(self), date_getstate(self));
3482 }
3483
3484 static PyMethodDef date_methods[] = {
3485
3486 /* Class methods: */
3487 DATETIME_DATE_FROMTIMESTAMP_METHODDEF
3488
3489 {"fromordinal", (PyCFunction)date_fromordinal, METH_VARARGS |
3490 METH_CLASS,
3491 PyDoc_STR("int -> date corresponding to a proleptic Gregorian "
3492 "ordinal.")},
3493
3494 {"fromisoformat", (PyCFunction)date_fromisoformat, METH_O |
3495 METH_CLASS,
3496 PyDoc_STR("str -> Construct a date from the output of date.isoformat()")},
3497
3498 {"fromisocalendar", (PyCFunction)(void(*)(void))date_fromisocalendar,
3499 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
3500 PyDoc_STR("int, int, int -> Construct a date from the ISO year, week "
3501 "number and weekday.\n\n"
3502 "This is the inverse of the date.isocalendar() function")},
3503
3504 {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS,
3505 PyDoc_STR("Current date or datetime: same as "
3506 "self.__class__.fromtimestamp(time.time()).")},
3507
3508 /* Instance methods: */
3509
3510 {"ctime", (PyCFunction)date_ctime, METH_NOARGS,
3511 PyDoc_STR("Return ctime() style string.")},
3512
3513 {"strftime", (PyCFunction)(void(*)(void))date_strftime, METH_VARARGS | METH_KEYWORDS,
3514 PyDoc_STR("format -> strftime() style string.")},
3515
3516 {"__format__", (PyCFunction)date_format, METH_VARARGS,
3517 PyDoc_STR("Formats self with strftime.")},
3518
3519 {"timetuple", (PyCFunction)date_timetuple, METH_NOARGS,
3520 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
3521
3522 {"isocalendar", (PyCFunction)date_isocalendar, METH_NOARGS,
3523 PyDoc_STR("Return a named tuple containing ISO year, week number, and "
3524 "weekday.")},
3525
3526 {"isoformat", (PyCFunction)date_isoformat, METH_NOARGS,
3527 PyDoc_STR("Return string in ISO 8601 format, YYYY-MM-DD.")},
3528
3529 {"isoweekday", (PyCFunction)date_isoweekday, METH_NOARGS,
3530 PyDoc_STR("Return the day of the week represented by the date.\n"
3531 "Monday == 1 ... Sunday == 7")},
3532
3533 {"toordinal", (PyCFunction)date_toordinal, METH_NOARGS,
3534 PyDoc_STR("Return proleptic Gregorian ordinal. January 1 of year "
3535 "1 is day 1.")},
3536
3537 {"weekday", (PyCFunction)date_weekday, METH_NOARGS,
3538 PyDoc_STR("Return the day of the week represented by the date.\n"
3539 "Monday == 0 ... Sunday == 6")},
3540
3541 {"replace", (PyCFunction)(void(*)(void))date_replace, METH_VARARGS | METH_KEYWORDS,
3542 PyDoc_STR("Return date with new specified fields.")},
3543
3544 {"__reduce__", (PyCFunction)date_reduce, METH_NOARGS,
3545 PyDoc_STR("__reduce__() -> (cls, state)")},
3546
3547 {NULL, NULL}
3548 };
3549
3550 static const char date_doc[] =
3551 PyDoc_STR("date(year, month, day) --> date object");
3552
3553 static PyNumberMethods date_as_number = {
3554 date_add, /* nb_add */
3555 date_subtract, /* nb_subtract */
3556 0, /* nb_multiply */
3557 0, /* nb_remainder */
3558 0, /* nb_divmod */
3559 0, /* nb_power */
3560 0, /* nb_negative */
3561 0, /* nb_positive */
3562 0, /* nb_absolute */
3563 0, /* nb_bool */
3564 };
3565
3566 static PyTypeObject PyDateTime_DateType = {
3567 PyVarObject_HEAD_INIT(NULL, 0)
3568 "datetime.date", /* tp_name */
3569 sizeof(PyDateTime_Date), /* tp_basicsize */
3570 0, /* tp_itemsize */
3571 0, /* tp_dealloc */
3572 0, /* tp_vectorcall_offset */
3573 0, /* tp_getattr */
3574 0, /* tp_setattr */
3575 0, /* tp_as_async */
3576 (reprfunc)date_repr, /* tp_repr */
3577 &date_as_number, /* tp_as_number */
3578 0, /* tp_as_sequence */
3579 0, /* tp_as_mapping */
3580 (hashfunc)date_hash, /* tp_hash */
3581 0, /* tp_call */
3582 (reprfunc)date_str, /* tp_str */
3583 PyObject_GenericGetAttr, /* tp_getattro */
3584 0, /* tp_setattro */
3585 0, /* tp_as_buffer */
3586 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
3587 date_doc, /* tp_doc */
3588 0, /* tp_traverse */
3589 0, /* tp_clear */
3590 date_richcompare, /* tp_richcompare */
3591 0, /* tp_weaklistoffset */
3592 0, /* tp_iter */
3593 0, /* tp_iternext */
3594 date_methods, /* tp_methods */
3595 0, /* tp_members */
3596 date_getset, /* tp_getset */
3597 0, /* tp_base */
3598 0, /* tp_dict */
3599 0, /* tp_descr_get */
3600 0, /* tp_descr_set */
3601 0, /* tp_dictoffset */
3602 0, /* tp_init */
3603 0, /* tp_alloc */
3604 date_new, /* tp_new */
3605 0, /* tp_free */
3606 };
3607
3608 /*
3609 * PyDateTime_TZInfo implementation.
3610 */
3611
3612 /* This is a pure abstract base class, so doesn't do anything beyond
3613 * raising NotImplemented exceptions. Real tzinfo classes need
3614 * to derive from this. This is mostly for clarity, and for efficiency in
3615 * datetime and time constructors (their tzinfo arguments need to
3616 * be subclasses of this tzinfo class, which is easy and quick to check).
3617 *
3618 * Note: For reasons having to do with pickling of subclasses, we have
3619 * to allow tzinfo objects to be instantiated. This wasn't an issue
3620 * in the Python implementation (__init__() could raise NotImplementedError
3621 * there without ill effect), but doing so in the C implementation hit a
3622 * brick wall.
3623 */
3624
3625 static PyObject *
tzinfo_nogo(const char * methodname)3626 tzinfo_nogo(const char* methodname)
3627 {
3628 PyErr_Format(PyExc_NotImplementedError,
3629 "a tzinfo subclass must implement %s()",
3630 methodname);
3631 return NULL;
3632 }
3633
3634 /* Methods. A subclass must implement these. */
3635
3636 static PyObject *
tzinfo_tzname(PyDateTime_TZInfo * self,PyObject * dt)3637 tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt)
3638 {
3639 return tzinfo_nogo("tzname");
3640 }
3641
3642 static PyObject *
tzinfo_utcoffset(PyDateTime_TZInfo * self,PyObject * dt)3643 tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt)
3644 {
3645 return tzinfo_nogo("utcoffset");
3646 }
3647
3648 static PyObject *
tzinfo_dst(PyDateTime_TZInfo * self,PyObject * dt)3649 tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
3650 {
3651 return tzinfo_nogo("dst");
3652 }
3653
3654
3655 static PyObject *add_datetime_timedelta(PyDateTime_DateTime *date,
3656 PyDateTime_Delta *delta,
3657 int factor);
3658 static PyObject *datetime_utcoffset(PyObject *self, PyObject *);
3659 static PyObject *datetime_dst(PyObject *self, PyObject *);
3660
3661 static PyObject *
tzinfo_fromutc(PyDateTime_TZInfo * self,PyObject * dt)3662 tzinfo_fromutc(PyDateTime_TZInfo *self, PyObject *dt)
3663 {
3664 PyObject *result = NULL;
3665 PyObject *off = NULL, *dst = NULL;
3666 PyDateTime_Delta *delta = NULL;
3667
3668 if (!PyDateTime_Check(dt)) {
3669 PyErr_SetString(PyExc_TypeError,
3670 "fromutc: argument must be a datetime");
3671 return NULL;
3672 }
3673 if (GET_DT_TZINFO(dt) != (PyObject *)self) {
3674 PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo "
3675 "is not self");
3676 return NULL;
3677 }
3678
3679 off = datetime_utcoffset(dt, NULL);
3680 if (off == NULL)
3681 return NULL;
3682 if (off == Py_None) {
3683 PyErr_SetString(PyExc_ValueError, "fromutc: non-None "
3684 "utcoffset() result required");
3685 goto Fail;
3686 }
3687
3688 dst = datetime_dst(dt, NULL);
3689 if (dst == NULL)
3690 goto Fail;
3691 if (dst == Py_None) {
3692 PyErr_SetString(PyExc_ValueError, "fromutc: non-None "
3693 "dst() result required");
3694 goto Fail;
3695 }
3696
3697 delta = (PyDateTime_Delta *)delta_subtract(off, dst);
3698 if (delta == NULL)
3699 goto Fail;
3700 result = add_datetime_timedelta((PyDateTime_DateTime *)dt, delta, 1);
3701 if (result == NULL)
3702 goto Fail;
3703
3704 Py_DECREF(dst);
3705 dst = call_dst(GET_DT_TZINFO(dt), result);
3706 if (dst == NULL)
3707 goto Fail;
3708 if (dst == Py_None)
3709 goto Inconsistent;
3710 if (delta_bool((PyDateTime_Delta *)dst) != 0) {
3711 Py_SETREF(result, add_datetime_timedelta((PyDateTime_DateTime *)result,
3712 (PyDateTime_Delta *)dst, 1));
3713 if (result == NULL)
3714 goto Fail;
3715 }
3716 Py_DECREF(delta);
3717 Py_DECREF(dst);
3718 Py_DECREF(off);
3719 return result;
3720
3721 Inconsistent:
3722 PyErr_SetString(PyExc_ValueError, "fromutc: tz.dst() gave "
3723 "inconsistent results; cannot convert");
3724
3725 /* fall through to failure */
3726 Fail:
3727 Py_XDECREF(off);
3728 Py_XDECREF(dst);
3729 Py_XDECREF(delta);
3730 Py_XDECREF(result);
3731 return NULL;
3732 }
3733
3734 /*
3735 * Pickle support. This is solely so that tzinfo subclasses can use
3736 * pickling -- tzinfo itself is supposed to be uninstantiable.
3737 */
3738
3739 static PyObject *
tzinfo_reduce(PyObject * self,PyObject * Py_UNUSED (ignored))3740 tzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
3741 {
3742 PyObject *args, *state;
3743 PyObject *getinitargs, *getstate;
3744 _Py_IDENTIFIER(__getinitargs__);
3745 _Py_IDENTIFIER(__getstate__);
3746
3747 if (_PyObject_LookupAttrId(self, &PyId___getinitargs__, &getinitargs) < 0) {
3748 return NULL;
3749 }
3750 if (getinitargs != NULL) {
3751 args = PyObject_CallNoArgs(getinitargs);
3752 Py_DECREF(getinitargs);
3753 }
3754 else {
3755 args = PyTuple_New(0);
3756 }
3757 if (args == NULL) {
3758 return NULL;
3759 }
3760
3761 if (_PyObject_LookupAttrId(self, &PyId___getstate__, &getstate) < 0) {
3762 Py_DECREF(args);
3763 return NULL;
3764 }
3765 if (getstate != NULL) {
3766 state = PyObject_CallNoArgs(getstate);
3767 Py_DECREF(getstate);
3768 if (state == NULL) {
3769 Py_DECREF(args);
3770 return NULL;
3771 }
3772 }
3773 else {
3774 PyObject **dictptr;
3775 state = Py_None;
3776 dictptr = _PyObject_GetDictPtr(self);
3777 if (dictptr && *dictptr && PyDict_GET_SIZE(*dictptr)) {
3778 state = *dictptr;
3779 }
3780 Py_INCREF(state);
3781 }
3782
3783 if (state == Py_None) {
3784 Py_DECREF(state);
3785 return Py_BuildValue("(ON)", Py_TYPE(self), args);
3786 }
3787 else
3788 return Py_BuildValue("(ONN)", Py_TYPE(self), args, state);
3789 }
3790
3791 static PyMethodDef tzinfo_methods[] = {
3792
3793 {"tzname", (PyCFunction)tzinfo_tzname, METH_O,
3794 PyDoc_STR("datetime -> string name of time zone.")},
3795
3796 {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
3797 PyDoc_STR("datetime -> timedelta showing offset from UTC, negative "
3798 "values indicating West of UTC")},
3799
3800 {"dst", (PyCFunction)tzinfo_dst, METH_O,
3801 PyDoc_STR("datetime -> DST offset as timedelta positive east of UTC.")},
3802
3803 {"fromutc", (PyCFunction)tzinfo_fromutc, METH_O,
3804 PyDoc_STR("datetime in UTC -> datetime in local time.")},
3805
3806 {"__reduce__", tzinfo_reduce, METH_NOARGS,
3807 PyDoc_STR("-> (cls, state)")},
3808
3809 {NULL, NULL}
3810 };
3811
3812 static const char tzinfo_doc[] =
3813 PyDoc_STR("Abstract base class for time zone info objects.");
3814
3815 static PyTypeObject PyDateTime_TZInfoType = {
3816 PyVarObject_HEAD_INIT(NULL, 0)
3817 "datetime.tzinfo", /* tp_name */
3818 sizeof(PyDateTime_TZInfo), /* tp_basicsize */
3819 0, /* tp_itemsize */
3820 0, /* tp_dealloc */
3821 0, /* tp_vectorcall_offset */
3822 0, /* tp_getattr */
3823 0, /* tp_setattr */
3824 0, /* tp_as_async */
3825 0, /* tp_repr */
3826 0, /* tp_as_number */
3827 0, /* tp_as_sequence */
3828 0, /* tp_as_mapping */
3829 0, /* tp_hash */
3830 0, /* tp_call */
3831 0, /* tp_str */
3832 PyObject_GenericGetAttr, /* tp_getattro */
3833 0, /* tp_setattro */
3834 0, /* tp_as_buffer */
3835 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
3836 tzinfo_doc, /* tp_doc */
3837 0, /* tp_traverse */
3838 0, /* tp_clear */
3839 0, /* tp_richcompare */
3840 0, /* tp_weaklistoffset */
3841 0, /* tp_iter */
3842 0, /* tp_iternext */
3843 tzinfo_methods, /* tp_methods */
3844 0, /* tp_members */
3845 0, /* tp_getset */
3846 0, /* tp_base */
3847 0, /* tp_dict */
3848 0, /* tp_descr_get */
3849 0, /* tp_descr_set */
3850 0, /* tp_dictoffset */
3851 0, /* tp_init */
3852 0, /* tp_alloc */
3853 PyType_GenericNew, /* tp_new */
3854 0, /* tp_free */
3855 };
3856
3857 static char *timezone_kws[] = {"offset", "name", NULL};
3858
3859 static PyObject *
timezone_new(PyTypeObject * type,PyObject * args,PyObject * kw)3860 timezone_new(PyTypeObject *type, PyObject *args, PyObject *kw)
3861 {
3862 PyObject *offset;
3863 PyObject *name = NULL;
3864 if (PyArg_ParseTupleAndKeywords(args, kw, "O!|U:timezone", timezone_kws,
3865 &PyDateTime_DeltaType, &offset, &name))
3866 return new_timezone(offset, name);
3867
3868 return NULL;
3869 }
3870
3871 static void
timezone_dealloc(PyDateTime_TimeZone * self)3872 timezone_dealloc(PyDateTime_TimeZone *self)
3873 {
3874 Py_CLEAR(self->offset);
3875 Py_CLEAR(self->name);
3876 Py_TYPE(self)->tp_free((PyObject *)self);
3877 }
3878
3879 static PyObject *
timezone_richcompare(PyDateTime_TimeZone * self,PyDateTime_TimeZone * other,int op)3880 timezone_richcompare(PyDateTime_TimeZone *self,
3881 PyDateTime_TimeZone *other, int op)
3882 {
3883 if (op != Py_EQ && op != Py_NE)
3884 Py_RETURN_NOTIMPLEMENTED;
3885 if (!PyTimezone_Check(other)) {
3886 Py_RETURN_NOTIMPLEMENTED;
3887 }
3888 return delta_richcompare(self->offset, other->offset, op);
3889 }
3890
3891 static Py_hash_t
timezone_hash(PyDateTime_TimeZone * self)3892 timezone_hash(PyDateTime_TimeZone *self)
3893 {
3894 return delta_hash((PyDateTime_Delta *)self->offset);
3895 }
3896
3897 /* Check argument type passed to tzname, utcoffset, or dst methods.
3898 Returns 0 for good argument. Returns -1 and sets exception info
3899 otherwise.
3900 */
3901 static int
_timezone_check_argument(PyObject * dt,const char * meth)3902 _timezone_check_argument(PyObject *dt, const char *meth)
3903 {
3904 if (dt == Py_None || PyDateTime_Check(dt))
3905 return 0;
3906 PyErr_Format(PyExc_TypeError, "%s(dt) argument must be a datetime instance"
3907 " or None, not %.200s", meth, Py_TYPE(dt)->tp_name);
3908 return -1;
3909 }
3910
3911 static PyObject *
timezone_repr(PyDateTime_TimeZone * self)3912 timezone_repr(PyDateTime_TimeZone *self)
3913 {
3914 /* Note that although timezone is not subclassable, it is convenient
3915 to use Py_TYPE(self)->tp_name here. */
3916 const char *type_name = Py_TYPE(self)->tp_name;
3917
3918 if (((PyObject *)self) == PyDateTime_TimeZone_UTC)
3919 return PyUnicode_FromFormat("%s.utc", type_name);
3920
3921 if (self->name == NULL)
3922 return PyUnicode_FromFormat("%s(%R)", type_name, self->offset);
3923
3924 return PyUnicode_FromFormat("%s(%R, %R)", type_name, self->offset,
3925 self->name);
3926 }
3927
3928
3929 static PyObject *
timezone_str(PyDateTime_TimeZone * self)3930 timezone_str(PyDateTime_TimeZone *self)
3931 {
3932 int hours, minutes, seconds, microseconds;
3933 PyObject *offset;
3934 char sign;
3935
3936 if (self->name != NULL) {
3937 Py_INCREF(self->name);
3938 return self->name;
3939 }
3940 if ((PyObject *)self == PyDateTime_TimeZone_UTC ||
3941 (GET_TD_DAYS(self->offset) == 0 &&
3942 GET_TD_SECONDS(self->offset) == 0 &&
3943 GET_TD_MICROSECONDS(self->offset) == 0))
3944 return PyUnicode_FromString("UTC");
3945 /* Offset is normalized, so it is negative if days < 0 */
3946 if (GET_TD_DAYS(self->offset) < 0) {
3947 sign = '-';
3948 offset = delta_negative((PyDateTime_Delta *)self->offset);
3949 if (offset == NULL)
3950 return NULL;
3951 }
3952 else {
3953 sign = '+';
3954 offset = self->offset;
3955 Py_INCREF(offset);
3956 }
3957 /* Offset is not negative here. */
3958 microseconds = GET_TD_MICROSECONDS(offset);
3959 seconds = GET_TD_SECONDS(offset);
3960 Py_DECREF(offset);
3961 minutes = divmod(seconds, 60, &seconds);
3962 hours = divmod(minutes, 60, &minutes);
3963 if (microseconds != 0) {
3964 return PyUnicode_FromFormat("UTC%c%02d:%02d:%02d.%06d",
3965 sign, hours, minutes,
3966 seconds, microseconds);
3967 }
3968 if (seconds != 0) {
3969 return PyUnicode_FromFormat("UTC%c%02d:%02d:%02d",
3970 sign, hours, minutes, seconds);
3971 }
3972 return PyUnicode_FromFormat("UTC%c%02d:%02d", sign, hours, minutes);
3973 }
3974
3975 static PyObject *
timezone_tzname(PyDateTime_TimeZone * self,PyObject * dt)3976 timezone_tzname(PyDateTime_TimeZone *self, PyObject *dt)
3977 {
3978 if (_timezone_check_argument(dt, "tzname") == -1)
3979 return NULL;
3980
3981 return timezone_str(self);
3982 }
3983
3984 static PyObject *
timezone_utcoffset(PyDateTime_TimeZone * self,PyObject * dt)3985 timezone_utcoffset(PyDateTime_TimeZone *self, PyObject *dt)
3986 {
3987 if (_timezone_check_argument(dt, "utcoffset") == -1)
3988 return NULL;
3989
3990 Py_INCREF(self->offset);
3991 return self->offset;
3992 }
3993
3994 static PyObject *
timezone_dst(PyObject * self,PyObject * dt)3995 timezone_dst(PyObject *self, PyObject *dt)
3996 {
3997 if (_timezone_check_argument(dt, "dst") == -1)
3998 return NULL;
3999
4000 Py_RETURN_NONE;
4001 }
4002
4003 static PyObject *
timezone_fromutc(PyDateTime_TimeZone * self,PyDateTime_DateTime * dt)4004 timezone_fromutc(PyDateTime_TimeZone *self, PyDateTime_DateTime *dt)
4005 {
4006 if (!PyDateTime_Check(dt)) {
4007 PyErr_SetString(PyExc_TypeError,
4008 "fromutc: argument must be a datetime");
4009 return NULL;
4010 }
4011 if (!HASTZINFO(dt) || dt->tzinfo != (PyObject *)self) {
4012 PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo "
4013 "is not self");
4014 return NULL;
4015 }
4016
4017 return add_datetime_timedelta(dt, (PyDateTime_Delta *)self->offset, 1);
4018 }
4019
4020 static PyObject *
timezone_getinitargs(PyDateTime_TimeZone * self,PyObject * Py_UNUSED (ignored))4021 timezone_getinitargs(PyDateTime_TimeZone *self, PyObject *Py_UNUSED(ignored))
4022 {
4023 if (self->name == NULL)
4024 return Py_BuildValue("(O)", self->offset);
4025 return Py_BuildValue("(OO)", self->offset, self->name);
4026 }
4027
4028 static PyMethodDef timezone_methods[] = {
4029 {"tzname", (PyCFunction)timezone_tzname, METH_O,
4030 PyDoc_STR("If name is specified when timezone is created, returns the name."
4031 " Otherwise returns offset as 'UTC(+|-)HH:MM'.")},
4032
4033 {"utcoffset", (PyCFunction)timezone_utcoffset, METH_O,
4034 PyDoc_STR("Return fixed offset.")},
4035
4036 {"dst", (PyCFunction)timezone_dst, METH_O,
4037 PyDoc_STR("Return None.")},
4038
4039 {"fromutc", (PyCFunction)timezone_fromutc, METH_O,
4040 PyDoc_STR("datetime in UTC -> datetime in local time.")},
4041
4042 {"__getinitargs__", (PyCFunction)timezone_getinitargs, METH_NOARGS,
4043 PyDoc_STR("pickle support")},
4044
4045 {NULL, NULL}
4046 };
4047
4048 static const char timezone_doc[] =
4049 PyDoc_STR("Fixed offset from UTC implementation of tzinfo.");
4050
4051 static PyTypeObject PyDateTime_TimeZoneType = {
4052 PyVarObject_HEAD_INIT(NULL, 0)
4053 "datetime.timezone", /* tp_name */
4054 sizeof(PyDateTime_TimeZone), /* tp_basicsize */
4055 0, /* tp_itemsize */
4056 (destructor)timezone_dealloc, /* tp_dealloc */
4057 0, /* tp_vectorcall_offset */
4058 0, /* tp_getattr */
4059 0, /* tp_setattr */
4060 0, /* tp_as_async */
4061 (reprfunc)timezone_repr, /* tp_repr */
4062 0, /* tp_as_number */
4063 0, /* tp_as_sequence */
4064 0, /* tp_as_mapping */
4065 (hashfunc)timezone_hash, /* tp_hash */
4066 0, /* tp_call */
4067 (reprfunc)timezone_str, /* tp_str */
4068 0, /* tp_getattro */
4069 0, /* tp_setattro */
4070 0, /* tp_as_buffer */
4071 Py_TPFLAGS_DEFAULT, /* tp_flags */
4072 timezone_doc, /* tp_doc */
4073 0, /* tp_traverse */
4074 0, /* tp_clear */
4075 (richcmpfunc)timezone_richcompare,/* tp_richcompare */
4076 0, /* tp_weaklistoffset */
4077 0, /* tp_iter */
4078 0, /* tp_iternext */
4079 timezone_methods, /* tp_methods */
4080 0, /* tp_members */
4081 0, /* tp_getset */
4082 0, /* tp_base; filled in PyInit__datetime */
4083 0, /* tp_dict */
4084 0, /* tp_descr_get */
4085 0, /* tp_descr_set */
4086 0, /* tp_dictoffset */
4087 0, /* tp_init */
4088 0, /* tp_alloc */
4089 timezone_new, /* tp_new */
4090 };
4091
4092 /*
4093 * PyDateTime_Time implementation.
4094 */
4095
4096 /* Accessor properties.
4097 */
4098
4099 static PyObject *
time_hour(PyDateTime_Time * self,void * unused)4100 time_hour(PyDateTime_Time *self, void *unused)
4101 {
4102 return PyLong_FromLong(TIME_GET_HOUR(self));
4103 }
4104
4105 static PyObject *
time_minute(PyDateTime_Time * self,void * unused)4106 time_minute(PyDateTime_Time *self, void *unused)
4107 {
4108 return PyLong_FromLong(TIME_GET_MINUTE(self));
4109 }
4110
4111 /* The name time_second conflicted with some platform header file. */
4112 static PyObject *
py_time_second(PyDateTime_Time * self,void * unused)4113 py_time_second(PyDateTime_Time *self, void *unused)
4114 {
4115 return PyLong_FromLong(TIME_GET_SECOND(self));
4116 }
4117
4118 static PyObject *
time_microsecond(PyDateTime_Time * self,void * unused)4119 time_microsecond(PyDateTime_Time *self, void *unused)
4120 {
4121 return PyLong_FromLong(TIME_GET_MICROSECOND(self));
4122 }
4123
4124 static PyObject *
time_tzinfo(PyDateTime_Time * self,void * unused)4125 time_tzinfo(PyDateTime_Time *self, void *unused)
4126 {
4127 PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
4128 Py_INCREF(result);
4129 return result;
4130 }
4131
4132 static PyObject *
time_fold(PyDateTime_Time * self,void * unused)4133 time_fold(PyDateTime_Time *self, void *unused)
4134 {
4135 return PyLong_FromLong(TIME_GET_FOLD(self));
4136 }
4137
4138 static PyGetSetDef time_getset[] = {
4139 {"hour", (getter)time_hour},
4140 {"minute", (getter)time_minute},
4141 {"second", (getter)py_time_second},
4142 {"microsecond", (getter)time_microsecond},
4143 {"tzinfo", (getter)time_tzinfo},
4144 {"fold", (getter)time_fold},
4145 {NULL}
4146 };
4147
4148 /*
4149 * Constructors.
4150 */
4151
4152 static char *time_kws[] = {"hour", "minute", "second", "microsecond",
4153 "tzinfo", "fold", NULL};
4154
4155 static PyObject *
time_from_pickle(PyTypeObject * type,PyObject * state,PyObject * tzinfo)4156 time_from_pickle(PyTypeObject *type, PyObject *state, PyObject *tzinfo)
4157 {
4158 PyDateTime_Time *me;
4159 char aware = (char)(tzinfo != Py_None);
4160
4161 if (aware && check_tzinfo_subclass(tzinfo) < 0) {
4162 PyErr_SetString(PyExc_TypeError, "bad tzinfo state arg");
4163 return NULL;
4164 }
4165
4166 me = (PyDateTime_Time *) (type->tp_alloc(type, aware));
4167 if (me != NULL) {
4168 const char *pdata = PyBytes_AS_STRING(state);
4169
4170 memcpy(me->data, pdata, _PyDateTime_TIME_DATASIZE);
4171 me->hashcode = -1;
4172 me->hastzinfo = aware;
4173 if (aware) {
4174 Py_INCREF(tzinfo);
4175 me->tzinfo = tzinfo;
4176 }
4177 if (pdata[0] & (1 << 7)) {
4178 me->data[0] -= 128;
4179 me->fold = 1;
4180 }
4181 else {
4182 me->fold = 0;
4183 }
4184 }
4185 return (PyObject *)me;
4186 }
4187
4188 static PyObject *
time_new(PyTypeObject * type,PyObject * args,PyObject * kw)4189 time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4190 {
4191 PyObject *self = NULL;
4192 int hour = 0;
4193 int minute = 0;
4194 int second = 0;
4195 int usecond = 0;
4196 PyObject *tzinfo = Py_None;
4197 int fold = 0;
4198
4199 /* Check for invocation from pickle with __getstate__ state */
4200 if (PyTuple_GET_SIZE(args) >= 1 && PyTuple_GET_SIZE(args) <= 2) {
4201 PyObject *state = PyTuple_GET_ITEM(args, 0);
4202 if (PyTuple_GET_SIZE(args) == 2) {
4203 tzinfo = PyTuple_GET_ITEM(args, 1);
4204 }
4205 if (PyBytes_Check(state)) {
4206 if (PyBytes_GET_SIZE(state) == _PyDateTime_TIME_DATASIZE &&
4207 (0x7F & ((unsigned char) (PyBytes_AS_STRING(state)[0]))) < 24)
4208 {
4209 return time_from_pickle(type, state, tzinfo);
4210 }
4211 }
4212 else if (PyUnicode_Check(state)) {
4213 if (PyUnicode_READY(state)) {
4214 return NULL;
4215 }
4216 if (PyUnicode_GET_LENGTH(state) == _PyDateTime_TIME_DATASIZE &&
4217 (0x7F & PyUnicode_READ_CHAR(state, 0)) < 24)
4218 {
4219 state = PyUnicode_AsLatin1String(state);
4220 if (state == NULL) {
4221 if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) {
4222 /* More informative error message. */
4223 PyErr_SetString(PyExc_ValueError,
4224 "Failed to encode latin1 string when unpickling "
4225 "a time object. "
4226 "pickle.load(data, encoding='latin1') is assumed.");
4227 }
4228 return NULL;
4229 }
4230 self = time_from_pickle(type, state, tzinfo);
4231 Py_DECREF(state);
4232 return self;
4233 }
4234 }
4235 tzinfo = Py_None;
4236 }
4237
4238 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO$i", time_kws,
4239 &hour, &minute, &second, &usecond,
4240 &tzinfo, &fold)) {
4241 self = new_time_ex2(hour, minute, second, usecond, tzinfo, fold,
4242 type);
4243 }
4244 return self;
4245 }
4246
4247 /*
4248 * Destructor.
4249 */
4250
4251 static void
time_dealloc(PyDateTime_Time * self)4252 time_dealloc(PyDateTime_Time *self)
4253 {
4254 if (HASTZINFO(self)) {
4255 Py_XDECREF(self->tzinfo);
4256 }
4257 Py_TYPE(self)->tp_free((PyObject *)self);
4258 }
4259
4260 /*
4261 * Indirect access to tzinfo methods.
4262 */
4263
4264 /* These are all METH_NOARGS, so don't need to check the arglist. */
4265 static PyObject *
time_utcoffset(PyObject * self,PyObject * unused)4266 time_utcoffset(PyObject *self, PyObject *unused) {
4267 return call_utcoffset(GET_TIME_TZINFO(self), Py_None);
4268 }
4269
4270 static PyObject *
time_dst(PyObject * self,PyObject * unused)4271 time_dst(PyObject *self, PyObject *unused) {
4272 return call_dst(GET_TIME_TZINFO(self), Py_None);
4273 }
4274
4275 static PyObject *
time_tzname(PyDateTime_Time * self,PyObject * unused)4276 time_tzname(PyDateTime_Time *self, PyObject *unused) {
4277 return call_tzname(GET_TIME_TZINFO(self), Py_None);
4278 }
4279
4280 /*
4281 * Various ways to turn a time into a string.
4282 */
4283
4284 static PyObject *
time_repr(PyDateTime_Time * self)4285 time_repr(PyDateTime_Time *self)
4286 {
4287 const char *type_name = Py_TYPE(self)->tp_name;
4288 int h = TIME_GET_HOUR(self);
4289 int m = TIME_GET_MINUTE(self);
4290 int s = TIME_GET_SECOND(self);
4291 int us = TIME_GET_MICROSECOND(self);
4292 int fold = TIME_GET_FOLD(self);
4293 PyObject *result = NULL;
4294
4295 if (us)
4296 result = PyUnicode_FromFormat("%s(%d, %d, %d, %d)",
4297 type_name, h, m, s, us);
4298 else if (s)
4299 result = PyUnicode_FromFormat("%s(%d, %d, %d)",
4300 type_name, h, m, s);
4301 else
4302 result = PyUnicode_FromFormat("%s(%d, %d)", type_name, h, m);
4303 if (result != NULL && HASTZINFO(self))
4304 result = append_keyword_tzinfo(result, self->tzinfo);
4305 if (result != NULL && fold)
4306 result = append_keyword_fold(result, fold);
4307 return result;
4308 }
4309
4310 static PyObject *
time_str(PyDateTime_Time * self)4311 time_str(PyDateTime_Time *self)
4312 {
4313 return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat);
4314 }
4315
4316 static PyObject *
time_isoformat(PyDateTime_Time * self,PyObject * args,PyObject * kw)4317 time_isoformat(PyDateTime_Time *self, PyObject *args, PyObject *kw)
4318 {
4319 char buf[100];
4320 const char *timespec = NULL;
4321 static char *keywords[] = {"timespec", NULL};
4322 PyObject *result;
4323 int us = TIME_GET_MICROSECOND(self);
4324 static const char *specs[][2] = {
4325 {"hours", "%02d"},
4326 {"minutes", "%02d:%02d"},
4327 {"seconds", "%02d:%02d:%02d"},
4328 {"milliseconds", "%02d:%02d:%02d.%03d"},
4329 {"microseconds", "%02d:%02d:%02d.%06d"},
4330 };
4331 size_t given_spec;
4332
4333 if (!PyArg_ParseTupleAndKeywords(args, kw, "|s:isoformat", keywords, ×pec))
4334 return NULL;
4335
4336 if (timespec == NULL || strcmp(timespec, "auto") == 0) {
4337 if (us == 0) {
4338 /* seconds */
4339 given_spec = 2;
4340 }
4341 else {
4342 /* microseconds */
4343 given_spec = 4;
4344 }
4345 }
4346 else {
4347 for (given_spec = 0; given_spec < Py_ARRAY_LENGTH(specs); given_spec++) {
4348 if (strcmp(timespec, specs[given_spec][0]) == 0) {
4349 if (given_spec == 3) {
4350 /* milliseconds */
4351 us = us / 1000;
4352 }
4353 break;
4354 }
4355 }
4356 }
4357
4358 if (given_spec == Py_ARRAY_LENGTH(specs)) {
4359 PyErr_Format(PyExc_ValueError, "Unknown timespec value");
4360 return NULL;
4361 }
4362 else {
4363 result = PyUnicode_FromFormat(specs[given_spec][1],
4364 TIME_GET_HOUR(self), TIME_GET_MINUTE(self),
4365 TIME_GET_SECOND(self), us);
4366 }
4367
4368 if (result == NULL || !HASTZINFO(self) || self->tzinfo == Py_None)
4369 return result;
4370
4371 /* We need to append the UTC offset. */
4372 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
4373 Py_None) < 0) {
4374 Py_DECREF(result);
4375 return NULL;
4376 }
4377 PyUnicode_AppendAndDel(&result, PyUnicode_FromString(buf));
4378 return result;
4379 }
4380
4381 static PyObject *
time_strftime(PyDateTime_Time * self,PyObject * args,PyObject * kw)4382 time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
4383 {
4384 PyObject *result;
4385 PyObject *tuple;
4386 PyObject *format;
4387 static char *keywords[] = {"format", NULL};
4388
4389 if (! PyArg_ParseTupleAndKeywords(args, kw, "U:strftime", keywords,
4390 &format))
4391 return NULL;
4392
4393 /* Python's strftime does insane things with the year part of the
4394 * timetuple. The year is forced to (the otherwise nonsensical)
4395 * 1900 to work around that.
4396 */
4397 tuple = Py_BuildValue("iiiiiiiii",
4398 1900, 1, 1, /* year, month, day */
4399 TIME_GET_HOUR(self),
4400 TIME_GET_MINUTE(self),
4401 TIME_GET_SECOND(self),
4402 0, 1, -1); /* weekday, daynum, dst */
4403 if (tuple == NULL)
4404 return NULL;
4405 assert(PyTuple_Size(tuple) == 9);
4406 result = wrap_strftime((PyObject *)self, format, tuple,
4407 Py_None);
4408 Py_DECREF(tuple);
4409 return result;
4410 }
4411
4412 /*
4413 * Miscellaneous methods.
4414 */
4415
4416 static PyObject *
time_richcompare(PyObject * self,PyObject * other,int op)4417 time_richcompare(PyObject *self, PyObject *other, int op)
4418 {
4419 PyObject *result = NULL;
4420 PyObject *offset1, *offset2;
4421 int diff;
4422
4423 if (! PyTime_Check(other))
4424 Py_RETURN_NOTIMPLEMENTED;
4425
4426 if (GET_TIME_TZINFO(self) == GET_TIME_TZINFO(other)) {
4427 diff = memcmp(((PyDateTime_Time *)self)->data,
4428 ((PyDateTime_Time *)other)->data,
4429 _PyDateTime_TIME_DATASIZE);
4430 return diff_to_bool(diff, op);
4431 }
4432 offset1 = time_utcoffset(self, NULL);
4433 if (offset1 == NULL)
4434 return NULL;
4435 offset2 = time_utcoffset(other, NULL);
4436 if (offset2 == NULL)
4437 goto done;
4438 /* If they're both naive, or both aware and have the same offsets,
4439 * we get off cheap. Note that if they're both naive, offset1 ==
4440 * offset2 == Py_None at this point.
4441 */
4442 if ((offset1 == offset2) ||
4443 (PyDelta_Check(offset1) && PyDelta_Check(offset2) &&
4444 delta_cmp(offset1, offset2) == 0)) {
4445 diff = memcmp(((PyDateTime_Time *)self)->data,
4446 ((PyDateTime_Time *)other)->data,
4447 _PyDateTime_TIME_DATASIZE);
4448 result = diff_to_bool(diff, op);
4449 }
4450 /* The hard case: both aware with different UTC offsets */
4451 else if (offset1 != Py_None && offset2 != Py_None) {
4452 int offsecs1, offsecs2;
4453 assert(offset1 != offset2); /* else last "if" handled it */
4454 offsecs1 = TIME_GET_HOUR(self) * 3600 +
4455 TIME_GET_MINUTE(self) * 60 +
4456 TIME_GET_SECOND(self) -
4457 GET_TD_DAYS(offset1) * 86400 -
4458 GET_TD_SECONDS(offset1);
4459 offsecs2 = TIME_GET_HOUR(other) * 3600 +
4460 TIME_GET_MINUTE(other) * 60 +
4461 TIME_GET_SECOND(other) -
4462 GET_TD_DAYS(offset2) * 86400 -
4463 GET_TD_SECONDS(offset2);
4464 diff = offsecs1 - offsecs2;
4465 if (diff == 0)
4466 diff = TIME_GET_MICROSECOND(self) -
4467 TIME_GET_MICROSECOND(other);
4468 result = diff_to_bool(diff, op);
4469 }
4470 else if (op == Py_EQ) {
4471 result = Py_False;
4472 Py_INCREF(result);
4473 }
4474 else if (op == Py_NE) {
4475 result = Py_True;
4476 Py_INCREF(result);
4477 }
4478 else {
4479 PyErr_SetString(PyExc_TypeError,
4480 "can't compare offset-naive and "
4481 "offset-aware times");
4482 }
4483 done:
4484 Py_DECREF(offset1);
4485 Py_XDECREF(offset2);
4486 return result;
4487 }
4488
4489 static Py_hash_t
time_hash(PyDateTime_Time * self)4490 time_hash(PyDateTime_Time *self)
4491 {
4492 if (self->hashcode == -1) {
4493 PyObject *offset, *self0;
4494 if (TIME_GET_FOLD(self)) {
4495 self0 = new_time_ex2(TIME_GET_HOUR(self),
4496 TIME_GET_MINUTE(self),
4497 TIME_GET_SECOND(self),
4498 TIME_GET_MICROSECOND(self),
4499 HASTZINFO(self) ? self->tzinfo : Py_None,
4500 0, Py_TYPE(self));
4501 if (self0 == NULL)
4502 return -1;
4503 }
4504 else {
4505 self0 = (PyObject *)self;
4506 Py_INCREF(self0);
4507 }
4508 offset = time_utcoffset(self0, NULL);
4509 Py_DECREF(self0);
4510
4511 if (offset == NULL)
4512 return -1;
4513
4514 /* Reduce this to a hash of another object. */
4515 if (offset == Py_None)
4516 self->hashcode = generic_hash(
4517 (unsigned char *)self->data, _PyDateTime_TIME_DATASIZE);
4518 else {
4519 PyObject *temp1, *temp2;
4520 int seconds, microseconds;
4521 assert(HASTZINFO(self));
4522 seconds = TIME_GET_HOUR(self) * 3600 +
4523 TIME_GET_MINUTE(self) * 60 +
4524 TIME_GET_SECOND(self);
4525 microseconds = TIME_GET_MICROSECOND(self);
4526 temp1 = new_delta(0, seconds, microseconds, 1);
4527 if (temp1 == NULL) {
4528 Py_DECREF(offset);
4529 return -1;
4530 }
4531 temp2 = delta_subtract(temp1, offset);
4532 Py_DECREF(temp1);
4533 if (temp2 == NULL) {
4534 Py_DECREF(offset);
4535 return -1;
4536 }
4537 self->hashcode = PyObject_Hash(temp2);
4538 Py_DECREF(temp2);
4539 }
4540 Py_DECREF(offset);
4541 }
4542 return self->hashcode;
4543 }
4544
4545 static PyObject *
time_replace(PyDateTime_Time * self,PyObject * args,PyObject * kw)4546 time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
4547 {
4548 PyObject *clone;
4549 PyObject *tuple;
4550 int hh = TIME_GET_HOUR(self);
4551 int mm = TIME_GET_MINUTE(self);
4552 int ss = TIME_GET_SECOND(self);
4553 int us = TIME_GET_MICROSECOND(self);
4554 PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
4555 int fold = TIME_GET_FOLD(self);
4556
4557 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO$i:replace",
4558 time_kws,
4559 &hh, &mm, &ss, &us, &tzinfo, &fold))
4560 return NULL;
4561 if (fold != 0 && fold != 1) {
4562 PyErr_SetString(PyExc_ValueError,
4563 "fold must be either 0 or 1");
4564 return NULL;
4565 }
4566 tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
4567 if (tuple == NULL)
4568 return NULL;
4569 clone = time_new(Py_TYPE(self), tuple, NULL);
4570 if (clone != NULL) {
4571 TIME_SET_FOLD(clone, fold);
4572 }
4573 Py_DECREF(tuple);
4574 return clone;
4575 }
4576
4577 static PyObject *
time_fromisoformat(PyObject * cls,PyObject * tstr)4578 time_fromisoformat(PyObject *cls, PyObject *tstr) {
4579 assert(tstr != NULL);
4580
4581 if (!PyUnicode_Check(tstr)) {
4582 PyErr_SetString(PyExc_TypeError, "fromisoformat: argument must be str");
4583 return NULL;
4584 }
4585
4586 Py_ssize_t len;
4587 const char *p = PyUnicode_AsUTF8AndSize(tstr, &len);
4588
4589 if (p == NULL) {
4590 goto invalid_string_error;
4591 }
4592
4593 int hour = 0, minute = 0, second = 0, microsecond = 0;
4594 int tzoffset, tzimicrosecond = 0;
4595 int rv = parse_isoformat_time(p, len,
4596 &hour, &minute, &second, µsecond,
4597 &tzoffset, &tzimicrosecond);
4598
4599 if (rv < 0) {
4600 goto invalid_string_error;
4601 }
4602
4603 PyObject *tzinfo = tzinfo_from_isoformat_results(rv, tzoffset,
4604 tzimicrosecond);
4605
4606 if (tzinfo == NULL) {
4607 return NULL;
4608 }
4609
4610 PyObject *t;
4611 if ( (PyTypeObject *)cls == &PyDateTime_TimeType ) {
4612 t = new_time(hour, minute, second, microsecond, tzinfo, 0);
4613 } else {
4614 t = PyObject_CallFunction(cls, "iiiiO",
4615 hour, minute, second, microsecond, tzinfo);
4616 }
4617
4618 Py_DECREF(tzinfo);
4619 return t;
4620
4621 invalid_string_error:
4622 PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %R", tstr);
4623 return NULL;
4624 }
4625
4626
4627 /* Pickle support, a simple use of __reduce__. */
4628
4629 /* Let basestate be the non-tzinfo data string.
4630 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4631 * So it's a tuple in any (non-error) case.
4632 * __getstate__ isn't exposed.
4633 */
4634 static PyObject *
time_getstate(PyDateTime_Time * self,int proto)4635 time_getstate(PyDateTime_Time *self, int proto)
4636 {
4637 PyObject *basestate;
4638 PyObject *result = NULL;
4639
4640 basestate = PyBytes_FromStringAndSize((char *)self->data,
4641 _PyDateTime_TIME_DATASIZE);
4642 if (basestate != NULL) {
4643 if (proto > 3 && TIME_GET_FOLD(self))
4644 /* Set the first bit of the first byte */
4645 PyBytes_AS_STRING(basestate)[0] |= (1 << 7);
4646 if (! HASTZINFO(self) || self->tzinfo == Py_None)
4647 result = PyTuple_Pack(1, basestate);
4648 else
4649 result = PyTuple_Pack(2, basestate, self->tzinfo);
4650 Py_DECREF(basestate);
4651 }
4652 return result;
4653 }
4654
4655 static PyObject *
time_reduce_ex(PyDateTime_Time * self,PyObject * args)4656 time_reduce_ex(PyDateTime_Time *self, PyObject *args)
4657 {
4658 int proto;
4659 if (!PyArg_ParseTuple(args, "i:__reduce_ex__", &proto))
4660 return NULL;
4661
4662 return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self, proto));
4663 }
4664
4665 static PyObject *
time_reduce(PyDateTime_Time * self,PyObject * arg)4666 time_reduce(PyDateTime_Time *self, PyObject *arg)
4667 {
4668 return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self, 2));
4669 }
4670
4671 static PyMethodDef time_methods[] = {
4672
4673 {"isoformat", (PyCFunction)(void(*)(void))time_isoformat, METH_VARARGS | METH_KEYWORDS,
4674 PyDoc_STR("Return string in ISO 8601 format, [HH[:MM[:SS[.mmm[uuu]]]]]"
4675 "[+HH:MM].\n\n"
4676 "The optional argument timespec specifies the number "
4677 "of additional terms\nof the time to include. Valid "
4678 "options are 'auto', 'hours', 'minutes',\n'seconds', "
4679 "'milliseconds' and 'microseconds'.\n")},
4680
4681 {"strftime", (PyCFunction)(void(*)(void))time_strftime, METH_VARARGS | METH_KEYWORDS,
4682 PyDoc_STR("format -> strftime() style string.")},
4683
4684 {"__format__", (PyCFunction)date_format, METH_VARARGS,
4685 PyDoc_STR("Formats self with strftime.")},
4686
4687 {"utcoffset", (PyCFunction)time_utcoffset, METH_NOARGS,
4688 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
4689
4690 {"tzname", (PyCFunction)time_tzname, METH_NOARGS,
4691 PyDoc_STR("Return self.tzinfo.tzname(self).")},
4692
4693 {"dst", (PyCFunction)time_dst, METH_NOARGS,
4694 PyDoc_STR("Return self.tzinfo.dst(self).")},
4695
4696 {"replace", (PyCFunction)(void(*)(void))time_replace, METH_VARARGS | METH_KEYWORDS,
4697 PyDoc_STR("Return time with new specified fields.")},
4698
4699 {"fromisoformat", (PyCFunction)time_fromisoformat, METH_O | METH_CLASS,
4700 PyDoc_STR("string -> time from time.isoformat() output")},
4701
4702 {"__reduce_ex__", (PyCFunction)time_reduce_ex, METH_VARARGS,
4703 PyDoc_STR("__reduce_ex__(proto) -> (cls, state)")},
4704
4705 {"__reduce__", (PyCFunction)time_reduce, METH_NOARGS,
4706 PyDoc_STR("__reduce__() -> (cls, state)")},
4707
4708 {NULL, NULL}
4709 };
4710
4711 static const char time_doc[] =
4712 PyDoc_STR("time([hour[, minute[, second[, microsecond[, tzinfo]]]]]) --> a time object\n\
4713 \n\
4714 All arguments are optional. tzinfo may be None, or an instance of\n\
4715 a tzinfo subclass. The remaining arguments may be ints.\n");
4716
4717 static PyTypeObject PyDateTime_TimeType = {
4718 PyVarObject_HEAD_INIT(NULL, 0)
4719 "datetime.time", /* tp_name */
4720 sizeof(PyDateTime_Time), /* tp_basicsize */
4721 0, /* tp_itemsize */
4722 (destructor)time_dealloc, /* tp_dealloc */
4723 0, /* tp_vectorcall_offset */
4724 0, /* tp_getattr */
4725 0, /* tp_setattr */
4726 0, /* tp_as_async */
4727 (reprfunc)time_repr, /* tp_repr */
4728 0, /* tp_as_number */
4729 0, /* tp_as_sequence */
4730 0, /* tp_as_mapping */
4731 (hashfunc)time_hash, /* tp_hash */
4732 0, /* tp_call */
4733 (reprfunc)time_str, /* tp_str */
4734 PyObject_GenericGetAttr, /* tp_getattro */
4735 0, /* tp_setattro */
4736 0, /* tp_as_buffer */
4737 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
4738 time_doc, /* tp_doc */
4739 0, /* tp_traverse */
4740 0, /* tp_clear */
4741 time_richcompare, /* tp_richcompare */
4742 0, /* tp_weaklistoffset */
4743 0, /* tp_iter */
4744 0, /* tp_iternext */
4745 time_methods, /* tp_methods */
4746 0, /* tp_members */
4747 time_getset, /* tp_getset */
4748 0, /* tp_base */
4749 0, /* tp_dict */
4750 0, /* tp_descr_get */
4751 0, /* tp_descr_set */
4752 0, /* tp_dictoffset */
4753 0, /* tp_init */
4754 time_alloc, /* tp_alloc */
4755 time_new, /* tp_new */
4756 0, /* tp_free */
4757 };
4758
4759 /*
4760 * PyDateTime_DateTime implementation.
4761 */
4762
4763 /* Accessor properties. Properties for day, month, and year are inherited
4764 * from date.
4765 */
4766
4767 static PyObject *
datetime_hour(PyDateTime_DateTime * self,void * unused)4768 datetime_hour(PyDateTime_DateTime *self, void *unused)
4769 {
4770 return PyLong_FromLong(DATE_GET_HOUR(self));
4771 }
4772
4773 static PyObject *
datetime_minute(PyDateTime_DateTime * self,void * unused)4774 datetime_minute(PyDateTime_DateTime *self, void *unused)
4775 {
4776 return PyLong_FromLong(DATE_GET_MINUTE(self));
4777 }
4778
4779 static PyObject *
datetime_second(PyDateTime_DateTime * self,void * unused)4780 datetime_second(PyDateTime_DateTime *self, void *unused)
4781 {
4782 return PyLong_FromLong(DATE_GET_SECOND(self));
4783 }
4784
4785 static PyObject *
datetime_microsecond(PyDateTime_DateTime * self,void * unused)4786 datetime_microsecond(PyDateTime_DateTime *self, void *unused)
4787 {
4788 return PyLong_FromLong(DATE_GET_MICROSECOND(self));
4789 }
4790
4791 static PyObject *
datetime_tzinfo(PyDateTime_DateTime * self,void * unused)4792 datetime_tzinfo(PyDateTime_DateTime *self, void *unused)
4793 {
4794 PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
4795 Py_INCREF(result);
4796 return result;
4797 }
4798
4799 static PyObject *
datetime_fold(PyDateTime_DateTime * self,void * unused)4800 datetime_fold(PyDateTime_DateTime *self, void *unused)
4801 {
4802 return PyLong_FromLong(DATE_GET_FOLD(self));
4803 }
4804
4805 static PyGetSetDef datetime_getset[] = {
4806 {"hour", (getter)datetime_hour},
4807 {"minute", (getter)datetime_minute},
4808 {"second", (getter)datetime_second},
4809 {"microsecond", (getter)datetime_microsecond},
4810 {"tzinfo", (getter)datetime_tzinfo},
4811 {"fold", (getter)datetime_fold},
4812 {NULL}
4813 };
4814
4815 /*
4816 * Constructors.
4817 */
4818
4819 static char *datetime_kws[] = {
4820 "year", "month", "day", "hour", "minute", "second",
4821 "microsecond", "tzinfo", "fold", NULL
4822 };
4823
4824 static PyObject *
datetime_from_pickle(PyTypeObject * type,PyObject * state,PyObject * tzinfo)4825 datetime_from_pickle(PyTypeObject *type, PyObject *state, PyObject *tzinfo)
4826 {
4827 PyDateTime_DateTime *me;
4828 char aware = (char)(tzinfo != Py_None);
4829
4830 if (aware && check_tzinfo_subclass(tzinfo) < 0) {
4831 PyErr_SetString(PyExc_TypeError, "bad tzinfo state arg");
4832 return NULL;
4833 }
4834
4835 me = (PyDateTime_DateTime *) (type->tp_alloc(type , aware));
4836 if (me != NULL) {
4837 const char *pdata = PyBytes_AS_STRING(state);
4838
4839 memcpy(me->data, pdata, _PyDateTime_DATETIME_DATASIZE);
4840 me->hashcode = -1;
4841 me->hastzinfo = aware;
4842 if (aware) {
4843 Py_INCREF(tzinfo);
4844 me->tzinfo = tzinfo;
4845 }
4846 if (pdata[2] & (1 << 7)) {
4847 me->data[2] -= 128;
4848 me->fold = 1;
4849 }
4850 else {
4851 me->fold = 0;
4852 }
4853 }
4854 return (PyObject *)me;
4855 }
4856
4857 static PyObject *
datetime_new(PyTypeObject * type,PyObject * args,PyObject * kw)4858 datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4859 {
4860 PyObject *self = NULL;
4861 int year;
4862 int month;
4863 int day;
4864 int hour = 0;
4865 int minute = 0;
4866 int second = 0;
4867 int usecond = 0;
4868 int fold = 0;
4869 PyObject *tzinfo = Py_None;
4870
4871 /* Check for invocation from pickle with __getstate__ state */
4872 if (PyTuple_GET_SIZE(args) >= 1 && PyTuple_GET_SIZE(args) <= 2) {
4873 PyObject *state = PyTuple_GET_ITEM(args, 0);
4874 if (PyTuple_GET_SIZE(args) == 2) {
4875 tzinfo = PyTuple_GET_ITEM(args, 1);
4876 }
4877 if (PyBytes_Check(state)) {
4878 if (PyBytes_GET_SIZE(state) == _PyDateTime_DATETIME_DATASIZE &&
4879 MONTH_IS_SANE(PyBytes_AS_STRING(state)[2] & 0x7F))
4880 {
4881 return datetime_from_pickle(type, state, tzinfo);
4882 }
4883 }
4884 else if (PyUnicode_Check(state)) {
4885 if (PyUnicode_READY(state)) {
4886 return NULL;
4887 }
4888 if (PyUnicode_GET_LENGTH(state) == _PyDateTime_DATETIME_DATASIZE &&
4889 MONTH_IS_SANE(PyUnicode_READ_CHAR(state, 2) & 0x7F))
4890 {
4891 state = PyUnicode_AsLatin1String(state);
4892 if (state == NULL) {
4893 if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) {
4894 /* More informative error message. */
4895 PyErr_SetString(PyExc_ValueError,
4896 "Failed to encode latin1 string when unpickling "
4897 "a datetime object. "
4898 "pickle.load(data, encoding='latin1') is assumed.");
4899 }
4900 return NULL;
4901 }
4902 self = datetime_from_pickle(type, state, tzinfo);
4903 Py_DECREF(state);
4904 return self;
4905 }
4906 }
4907 tzinfo = Py_None;
4908 }
4909
4910 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO$i", datetime_kws,
4911 &year, &month, &day, &hour, &minute,
4912 &second, &usecond, &tzinfo, &fold)) {
4913 self = new_datetime_ex2(year, month, day,
4914 hour, minute, second, usecond,
4915 tzinfo, fold, type);
4916 }
4917 return self;
4918 }
4919
4920 /* TM_FUNC is the shared type of _PyTime_localtime() and
4921 * _PyTime_gmtime(). */
4922 typedef int (*TM_FUNC)(time_t timer, struct tm*);
4923
4924 /* As of version 2015f max fold in IANA database is
4925 * 23 hours at 1969-09-30 13:00:00 in Kwajalein. */
4926 static long long max_fold_seconds = 24 * 3600;
4927 /* NB: date(1970,1,1).toordinal() == 719163 */
4928 static long long epoch = 719163LL * 24 * 60 * 60;
4929
4930 static long long
utc_to_seconds(int year,int month,int day,int hour,int minute,int second)4931 utc_to_seconds(int year, int month, int day,
4932 int hour, int minute, int second)
4933 {
4934 long long ordinal;
4935
4936 /* ymd_to_ord() doesn't support year <= 0 */
4937 if (year < MINYEAR || year > MAXYEAR) {
4938 PyErr_Format(PyExc_ValueError, "year %i is out of range", year);
4939 return -1;
4940 }
4941
4942 ordinal = ymd_to_ord(year, month, day);
4943 return ((ordinal * 24 + hour) * 60 + minute) * 60 + second;
4944 }
4945
4946 static long long
local(long long u)4947 local(long long u)
4948 {
4949 struct tm local_time;
4950 time_t t;
4951 u -= epoch;
4952 t = u;
4953 if (t != u) {
4954 PyErr_SetString(PyExc_OverflowError,
4955 "timestamp out of range for platform time_t");
4956 return -1;
4957 }
4958 if (_PyTime_localtime(t, &local_time) != 0)
4959 return -1;
4960 return utc_to_seconds(local_time.tm_year + 1900,
4961 local_time.tm_mon + 1,
4962 local_time.tm_mday,
4963 local_time.tm_hour,
4964 local_time.tm_min,
4965 local_time.tm_sec);
4966 }
4967
4968 /* Internal helper.
4969 * Build datetime from a time_t and a distinct count of microseconds.
4970 * Pass localtime or gmtime for f, to control the interpretation of timet.
4971 */
4972 static PyObject *
datetime_from_timet_and_us(PyObject * cls,TM_FUNC f,time_t timet,int us,PyObject * tzinfo)4973 datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us,
4974 PyObject *tzinfo)
4975 {
4976 struct tm tm;
4977 int year, month, day, hour, minute, second, fold = 0;
4978
4979 if (f(timet, &tm) != 0)
4980 return NULL;
4981
4982 year = tm.tm_year + 1900;
4983 month = tm.tm_mon + 1;
4984 day = tm.tm_mday;
4985 hour = tm.tm_hour;
4986 minute = tm.tm_min;
4987 /* The platform localtime/gmtime may insert leap seconds,
4988 * indicated by tm.tm_sec > 59. We don't care about them,
4989 * except to the extent that passing them on to the datetime
4990 * constructor would raise ValueError for a reason that
4991 * made no sense to the user.
4992 */
4993 second = Py_MIN(59, tm.tm_sec);
4994
4995 /* local timezone requires to compute fold */
4996 if (tzinfo == Py_None && f == _PyTime_localtime
4997 /* On Windows, passing a negative value to local results
4998 * in an OSError because localtime_s on Windows does
4999 * not support negative timestamps. Unfortunately this
5000 * means that fold detection for time values between
5001 * 0 and max_fold_seconds will result in an identical
5002 * error since we subtract max_fold_seconds to detect a
5003 * fold. However, since we know there haven't been any
5004 * folds in the interval [0, max_fold_seconds) in any
5005 * timezone, we can hackily just forego fold detection
5006 * for this time range.
5007 */
5008 #ifdef MS_WINDOWS
5009 && (timet - max_fold_seconds > 0)
5010 #endif
5011 ) {
5012 long long probe_seconds, result_seconds, transition;
5013
5014 result_seconds = utc_to_seconds(year, month, day,
5015 hour, minute, second);
5016 /* Probe max_fold_seconds to detect a fold. */
5017 probe_seconds = local(epoch + timet - max_fold_seconds);
5018 if (probe_seconds == -1)
5019 return NULL;
5020 transition = result_seconds - probe_seconds - max_fold_seconds;
5021 if (transition < 0) {
5022 probe_seconds = local(epoch + timet + transition);
5023 if (probe_seconds == -1)
5024 return NULL;
5025 if (probe_seconds == result_seconds)
5026 fold = 1;
5027 }
5028 }
5029 return new_datetime_subclass_fold_ex(year, month, day, hour, minute,
5030 second, us, tzinfo, fold, cls);
5031 }
5032
5033 /* Internal helper.
5034 * Build datetime from a Python timestamp. Pass localtime or gmtime for f,
5035 * to control the interpretation of the timestamp. Since a double doesn't
5036 * have enough bits to cover a datetime's full range of precision, it's
5037 * better to call datetime_from_timet_and_us provided you have a way
5038 * to get that much precision (e.g., C time() isn't good enough).
5039 */
5040 static PyObject *
datetime_from_timestamp(PyObject * cls,TM_FUNC f,PyObject * timestamp,PyObject * tzinfo)5041 datetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp,
5042 PyObject *tzinfo)
5043 {
5044 time_t timet;
5045 long us;
5046
5047 if (_PyTime_ObjectToTimeval(timestamp,
5048 &timet, &us, _PyTime_ROUND_HALF_EVEN) == -1)
5049 return NULL;
5050
5051 return datetime_from_timet_and_us(cls, f, timet, (int)us, tzinfo);
5052 }
5053
5054 /* Internal helper.
5055 * Build most accurate possible datetime for current time. Pass localtime or
5056 * gmtime for f as appropriate.
5057 */
5058 static PyObject *
datetime_best_possible(PyObject * cls,TM_FUNC f,PyObject * tzinfo)5059 datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
5060 {
5061 _PyTime_t ts = _PyTime_GetSystemClock();
5062 time_t secs;
5063 int us;
5064
5065 if (_PyTime_AsTimevalTime_t(ts, &secs, &us, _PyTime_ROUND_FLOOR) < 0)
5066 return NULL;
5067 assert(0 <= us && us <= 999999);
5068
5069 return datetime_from_timet_and_us(cls, f, secs, us, tzinfo);
5070 }
5071
5072 /*[clinic input]
5073
5074 @classmethod
5075 datetime.datetime.now
5076
5077 tz: object = None
5078 Timezone object.
5079
5080 Returns new datetime object representing current time local to tz.
5081
5082 If no tz is specified, uses local timezone.
5083 [clinic start generated code]*/
5084
5085 static PyObject *
datetime_datetime_now_impl(PyTypeObject * type,PyObject * tz)5086 datetime_datetime_now_impl(PyTypeObject *type, PyObject *tz)
5087 /*[clinic end generated code: output=b3386e5345e2b47a input=80d09869c5267d00]*/
5088 {
5089 PyObject *self;
5090
5091 /* Return best possible local time -- this isn't constrained by the
5092 * precision of a timestamp.
5093 */
5094 if (check_tzinfo_subclass(tz) < 0)
5095 return NULL;
5096
5097 self = datetime_best_possible((PyObject *)type,
5098 tz == Py_None ? _PyTime_localtime :
5099 _PyTime_gmtime,
5100 tz);
5101 if (self != NULL && tz != Py_None) {
5102 /* Convert UTC to tzinfo's zone. */
5103 self = _PyObject_CallMethodId(tz, &PyId_fromutc, "N", self);
5104 }
5105 return self;
5106 }
5107
5108 /* Return best possible UTC time -- this isn't constrained by the
5109 * precision of a timestamp.
5110 */
5111 static PyObject *
datetime_utcnow(PyObject * cls,PyObject * dummy)5112 datetime_utcnow(PyObject *cls, PyObject *dummy)
5113 {
5114 return datetime_best_possible(cls, _PyTime_gmtime, Py_None);
5115 }
5116
5117 /* Return new local datetime from timestamp (Python timestamp -- a double). */
5118 static PyObject *
datetime_fromtimestamp(PyObject * cls,PyObject * args,PyObject * kw)5119 datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
5120 {
5121 PyObject *self;
5122 PyObject *timestamp;
5123 PyObject *tzinfo = Py_None;
5124 static char *keywords[] = {"timestamp", "tz", NULL};
5125
5126 if (! PyArg_ParseTupleAndKeywords(args, kw, "O|O:fromtimestamp",
5127 keywords, ×tamp, &tzinfo))
5128 return NULL;
5129 if (check_tzinfo_subclass(tzinfo) < 0)
5130 return NULL;
5131
5132 self = datetime_from_timestamp(cls,
5133 tzinfo == Py_None ? _PyTime_localtime :
5134 _PyTime_gmtime,
5135 timestamp,
5136 tzinfo);
5137 if (self != NULL && tzinfo != Py_None) {
5138 /* Convert UTC to tzinfo's zone. */
5139 self = _PyObject_CallMethodId(tzinfo, &PyId_fromutc, "N", self);
5140 }
5141 return self;
5142 }
5143
5144 /* Return new UTC datetime from timestamp (Python timestamp -- a double). */
5145 static PyObject *
datetime_utcfromtimestamp(PyObject * cls,PyObject * args)5146 datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
5147 {
5148 PyObject *timestamp;
5149 PyObject *result = NULL;
5150
5151 if (PyArg_ParseTuple(args, "O:utcfromtimestamp", ×tamp))
5152 result = datetime_from_timestamp(cls, _PyTime_gmtime, timestamp,
5153 Py_None);
5154 return result;
5155 }
5156
5157 /* Return new datetime from _strptime.strptime_datetime(). */
5158 static PyObject *
datetime_strptime(PyObject * cls,PyObject * args)5159 datetime_strptime(PyObject *cls, PyObject *args)
5160 {
5161 static PyObject *module = NULL;
5162 PyObject *string, *format;
5163 _Py_IDENTIFIER(_strptime_datetime);
5164
5165 if (!PyArg_ParseTuple(args, "UU:strptime", &string, &format))
5166 return NULL;
5167
5168 if (module == NULL) {
5169 module = PyImport_ImportModuleNoBlock("_strptime");
5170 if (module == NULL)
5171 return NULL;
5172 }
5173 return _PyObject_CallMethodIdObjArgs(module, &PyId__strptime_datetime,
5174 cls, string, format, NULL);
5175 }
5176
5177 /* Return new datetime from date/datetime and time arguments. */
5178 static PyObject *
datetime_combine(PyObject * cls,PyObject * args,PyObject * kw)5179 datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
5180 {
5181 static char *keywords[] = {"date", "time", "tzinfo", NULL};
5182 PyObject *date;
5183 PyObject *time;
5184 PyObject *tzinfo = NULL;
5185 PyObject *result = NULL;
5186
5187 if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!|O:combine", keywords,
5188 &PyDateTime_DateType, &date,
5189 &PyDateTime_TimeType, &time, &tzinfo)) {
5190 if (tzinfo == NULL) {
5191 if (HASTZINFO(time))
5192 tzinfo = ((PyDateTime_Time *)time)->tzinfo;
5193 else
5194 tzinfo = Py_None;
5195 }
5196 result = new_datetime_subclass_fold_ex(GET_YEAR(date),
5197 GET_MONTH(date),
5198 GET_DAY(date),
5199 TIME_GET_HOUR(time),
5200 TIME_GET_MINUTE(time),
5201 TIME_GET_SECOND(time),
5202 TIME_GET_MICROSECOND(time),
5203 tzinfo,
5204 TIME_GET_FOLD(time),
5205 cls);
5206 }
5207 return result;
5208 }
5209
5210 static PyObject *
_sanitize_isoformat_str(PyObject * dtstr)5211 _sanitize_isoformat_str(PyObject *dtstr)
5212 {
5213 // `fromisoformat` allows surrogate characters in exactly one position,
5214 // the separator; to allow datetime_fromisoformat to make the simplifying
5215 // assumption that all valid strings can be encoded in UTF-8, this function
5216 // replaces any surrogate character separators with `T`.
5217 //
5218 // The result of this, if not NULL, returns a new reference
5219 Py_ssize_t len = PyUnicode_GetLength(dtstr);
5220 if (len < 0) {
5221 return NULL;
5222 }
5223
5224 if (len <= 10 ||
5225 !Py_UNICODE_IS_SURROGATE(PyUnicode_READ_CHAR(dtstr, 10))) {
5226 Py_INCREF(dtstr);
5227 return dtstr;
5228 }
5229
5230 PyObject *str_out = _PyUnicode_Copy(dtstr);
5231 if (str_out == NULL) {
5232 return NULL;
5233 }
5234
5235 if (PyUnicode_WriteChar(str_out, 10, (Py_UCS4)'T')) {
5236 Py_DECREF(str_out);
5237 return NULL;
5238 }
5239
5240 return str_out;
5241 }
5242
5243 static PyObject *
datetime_fromisoformat(PyObject * cls,PyObject * dtstr)5244 datetime_fromisoformat(PyObject *cls, PyObject *dtstr)
5245 {
5246 assert(dtstr != NULL);
5247
5248 if (!PyUnicode_Check(dtstr)) {
5249 PyErr_SetString(PyExc_TypeError,
5250 "fromisoformat: argument must be str");
5251 return NULL;
5252 }
5253
5254 PyObject *dtstr_clean = _sanitize_isoformat_str(dtstr);
5255 if (dtstr_clean == NULL) {
5256 goto error;
5257 }
5258
5259 Py_ssize_t len;
5260 const char *dt_ptr = PyUnicode_AsUTF8AndSize(dtstr_clean, &len);
5261
5262 if (dt_ptr == NULL) {
5263 if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) {
5264 // Encoding errors are invalid string errors at this point
5265 goto invalid_string_error;
5266 }
5267 else {
5268 goto error;
5269 }
5270 }
5271
5272 const char *p = dt_ptr;
5273
5274 int year = 0, month = 0, day = 0;
5275 int hour = 0, minute = 0, second = 0, microsecond = 0;
5276 int tzoffset = 0, tzusec = 0;
5277
5278 // date has a fixed length of 10
5279 int rv = parse_isoformat_date(p, &year, &month, &day);
5280
5281 if (!rv && len > 10) {
5282 // In UTF-8, the length of multi-byte characters is encoded in the MSB
5283 if ((p[10] & 0x80) == 0) {
5284 p += 11;
5285 }
5286 else {
5287 switch (p[10] & 0xf0) {
5288 case 0xe0:
5289 p += 13;
5290 break;
5291 case 0xf0:
5292 p += 14;
5293 break;
5294 default:
5295 p += 12;
5296 break;
5297 }
5298 }
5299
5300 len -= (p - dt_ptr);
5301 rv = parse_isoformat_time(p, len, &hour, &minute, &second,
5302 µsecond, &tzoffset, &tzusec);
5303 }
5304 if (rv < 0) {
5305 goto invalid_string_error;
5306 }
5307
5308 PyObject *tzinfo = tzinfo_from_isoformat_results(rv, tzoffset, tzusec);
5309 if (tzinfo == NULL) {
5310 goto error;
5311 }
5312
5313 PyObject *dt = new_datetime_subclass_ex(year, month, day, hour, minute,
5314 second, microsecond, tzinfo, cls);
5315
5316 Py_DECREF(tzinfo);
5317 Py_DECREF(dtstr_clean);
5318 return dt;
5319
5320 invalid_string_error:
5321 PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %R", dtstr);
5322
5323 error:
5324 Py_XDECREF(dtstr_clean);
5325
5326 return NULL;
5327 }
5328
5329 /*
5330 * Destructor.
5331 */
5332
5333 static void
datetime_dealloc(PyDateTime_DateTime * self)5334 datetime_dealloc(PyDateTime_DateTime *self)
5335 {
5336 if (HASTZINFO(self)) {
5337 Py_XDECREF(self->tzinfo);
5338 }
5339 Py_TYPE(self)->tp_free((PyObject *)self);
5340 }
5341
5342 /*
5343 * Indirect access to tzinfo methods.
5344 */
5345
5346 /* These are all METH_NOARGS, so don't need to check the arglist. */
5347 static PyObject *
datetime_utcoffset(PyObject * self,PyObject * unused)5348 datetime_utcoffset(PyObject *self, PyObject *unused) {
5349 return call_utcoffset(GET_DT_TZINFO(self), self);
5350 }
5351
5352 static PyObject *
datetime_dst(PyObject * self,PyObject * unused)5353 datetime_dst(PyObject *self, PyObject *unused) {
5354 return call_dst(GET_DT_TZINFO(self), self);
5355 }
5356
5357 static PyObject *
datetime_tzname(PyObject * self,PyObject * unused)5358 datetime_tzname(PyObject *self, PyObject *unused) {
5359 return call_tzname(GET_DT_TZINFO(self), self);
5360 }
5361
5362 /*
5363 * datetime arithmetic.
5364 */
5365
5366 /* factor must be 1 (to add) or -1 (to subtract). The result inherits
5367 * the tzinfo state of date.
5368 */
5369 static PyObject *
add_datetime_timedelta(PyDateTime_DateTime * date,PyDateTime_Delta * delta,int factor)5370 add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta,
5371 int factor)
5372 {
5373 /* Note that the C-level additions can't overflow, because of
5374 * invariant bounds on the member values.
5375 */
5376 int year = GET_YEAR(date);
5377 int month = GET_MONTH(date);
5378 int day = GET_DAY(date) + GET_TD_DAYS(delta) * factor;
5379 int hour = DATE_GET_HOUR(date);
5380 int minute = DATE_GET_MINUTE(date);
5381 int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta) * factor;
5382 int microsecond = DATE_GET_MICROSECOND(date) +
5383 GET_TD_MICROSECONDS(delta) * factor;
5384
5385 assert(factor == 1 || factor == -1);
5386 if (normalize_datetime(&year, &month, &day,
5387 &hour, &minute, &second, µsecond) < 0) {
5388 return NULL;
5389 }
5390
5391 return new_datetime_subclass_ex(year, month, day,
5392 hour, minute, second, microsecond,
5393 HASTZINFO(date) ? date->tzinfo : Py_None,
5394 (PyObject *)Py_TYPE(date));
5395 }
5396
5397 static PyObject *
datetime_add(PyObject * left,PyObject * right)5398 datetime_add(PyObject *left, PyObject *right)
5399 {
5400 if (PyDateTime_Check(left)) {
5401 /* datetime + ??? */
5402 if (PyDelta_Check(right))
5403 /* datetime + delta */
5404 return add_datetime_timedelta(
5405 (PyDateTime_DateTime *)left,
5406 (PyDateTime_Delta *)right,
5407 1);
5408 }
5409 else if (PyDelta_Check(left)) {
5410 /* delta + datetime */
5411 return add_datetime_timedelta((PyDateTime_DateTime *) right,
5412 (PyDateTime_Delta *) left,
5413 1);
5414 }
5415 Py_RETURN_NOTIMPLEMENTED;
5416 }
5417
5418 static PyObject *
datetime_subtract(PyObject * left,PyObject * right)5419 datetime_subtract(PyObject *left, PyObject *right)
5420 {
5421 PyObject *result = Py_NotImplemented;
5422
5423 if (PyDateTime_Check(left)) {
5424 /* datetime - ??? */
5425 if (PyDateTime_Check(right)) {
5426 /* datetime - datetime */
5427 PyObject *offset1, *offset2, *offdiff = NULL;
5428 int delta_d, delta_s, delta_us;
5429
5430 if (GET_DT_TZINFO(left) == GET_DT_TZINFO(right)) {
5431 offset2 = offset1 = Py_None;
5432 Py_INCREF(offset1);
5433 Py_INCREF(offset2);
5434 }
5435 else {
5436 offset1 = datetime_utcoffset(left, NULL);
5437 if (offset1 == NULL)
5438 return NULL;
5439 offset2 = datetime_utcoffset(right, NULL);
5440 if (offset2 == NULL) {
5441 Py_DECREF(offset1);
5442 return NULL;
5443 }
5444 if ((offset1 != Py_None) != (offset2 != Py_None)) {
5445 PyErr_SetString(PyExc_TypeError,
5446 "can't subtract offset-naive and "
5447 "offset-aware datetimes");
5448 Py_DECREF(offset1);
5449 Py_DECREF(offset2);
5450 return NULL;
5451 }
5452 }
5453 if ((offset1 != offset2) &&
5454 delta_cmp(offset1, offset2) != 0) {
5455 offdiff = delta_subtract(offset1, offset2);
5456 if (offdiff == NULL) {
5457 Py_DECREF(offset1);
5458 Py_DECREF(offset2);
5459 return NULL;
5460 }
5461 }
5462 Py_DECREF(offset1);
5463 Py_DECREF(offset2);
5464 delta_d = ymd_to_ord(GET_YEAR(left),
5465 GET_MONTH(left),
5466 GET_DAY(left)) -
5467 ymd_to_ord(GET_YEAR(right),
5468 GET_MONTH(right),
5469 GET_DAY(right));
5470 /* These can't overflow, since the values are
5471 * normalized. At most this gives the number of
5472 * seconds in one day.
5473 */
5474 delta_s = (DATE_GET_HOUR(left) -
5475 DATE_GET_HOUR(right)) * 3600 +
5476 (DATE_GET_MINUTE(left) -
5477 DATE_GET_MINUTE(right)) * 60 +
5478 (DATE_GET_SECOND(left) -
5479 DATE_GET_SECOND(right));
5480 delta_us = DATE_GET_MICROSECOND(left) -
5481 DATE_GET_MICROSECOND(right);
5482 result = new_delta(delta_d, delta_s, delta_us, 1);
5483 if (result == NULL)
5484 return NULL;
5485
5486 if (offdiff != NULL) {
5487 Py_SETREF(result, delta_subtract(result, offdiff));
5488 Py_DECREF(offdiff);
5489 }
5490 }
5491 else if (PyDelta_Check(right)) {
5492 /* datetime - delta */
5493 result = add_datetime_timedelta(
5494 (PyDateTime_DateTime *)left,
5495 (PyDateTime_Delta *)right,
5496 -1);
5497 }
5498 }
5499
5500 if (result == Py_NotImplemented)
5501 Py_INCREF(result);
5502 return result;
5503 }
5504
5505 /* Various ways to turn a datetime into a string. */
5506
5507 static PyObject *
datetime_repr(PyDateTime_DateTime * self)5508 datetime_repr(PyDateTime_DateTime *self)
5509 {
5510 const char *type_name = Py_TYPE(self)->tp_name;
5511 PyObject *baserepr;
5512
5513 if (DATE_GET_MICROSECOND(self)) {
5514 baserepr = PyUnicode_FromFormat(
5515 "%s(%d, %d, %d, %d, %d, %d, %d)",
5516 type_name,
5517 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
5518 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
5519 DATE_GET_SECOND(self),
5520 DATE_GET_MICROSECOND(self));
5521 }
5522 else if (DATE_GET_SECOND(self)) {
5523 baserepr = PyUnicode_FromFormat(
5524 "%s(%d, %d, %d, %d, %d, %d)",
5525 type_name,
5526 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
5527 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
5528 DATE_GET_SECOND(self));
5529 }
5530 else {
5531 baserepr = PyUnicode_FromFormat(
5532 "%s(%d, %d, %d, %d, %d)",
5533 type_name,
5534 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
5535 DATE_GET_HOUR(self), DATE_GET_MINUTE(self));
5536 }
5537 if (baserepr != NULL && DATE_GET_FOLD(self) != 0)
5538 baserepr = append_keyword_fold(baserepr, DATE_GET_FOLD(self));
5539 if (baserepr == NULL || ! HASTZINFO(self))
5540 return baserepr;
5541 return append_keyword_tzinfo(baserepr, self->tzinfo);
5542 }
5543
5544 static PyObject *
datetime_str(PyDateTime_DateTime * self)5545 datetime_str(PyDateTime_DateTime *self)
5546 {
5547 return _PyObject_CallMethodId((PyObject *)self, &PyId_isoformat, "s", " ");
5548 }
5549
5550 static PyObject *
datetime_isoformat(PyDateTime_DateTime * self,PyObject * args,PyObject * kw)5551 datetime_isoformat(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
5552 {
5553 int sep = 'T';
5554 char *timespec = NULL;
5555 static char *keywords[] = {"sep", "timespec", NULL};
5556 char buffer[100];
5557 PyObject *result = NULL;
5558 int us = DATE_GET_MICROSECOND(self);
5559 static const char *specs[][2] = {
5560 {"hours", "%04d-%02d-%02d%c%02d"},
5561 {"minutes", "%04d-%02d-%02d%c%02d:%02d"},
5562 {"seconds", "%04d-%02d-%02d%c%02d:%02d:%02d"},
5563 {"milliseconds", "%04d-%02d-%02d%c%02d:%02d:%02d.%03d"},
5564 {"microseconds", "%04d-%02d-%02d%c%02d:%02d:%02d.%06d"},
5565 };
5566 size_t given_spec;
5567
5568 if (!PyArg_ParseTupleAndKeywords(args, kw, "|Cs:isoformat", keywords, &sep, ×pec))
5569 return NULL;
5570
5571 if (timespec == NULL || strcmp(timespec, "auto") == 0) {
5572 if (us == 0) {
5573 /* seconds */
5574 given_spec = 2;
5575 }
5576 else {
5577 /* microseconds */
5578 given_spec = 4;
5579 }
5580 }
5581 else {
5582 for (given_spec = 0; given_spec < Py_ARRAY_LENGTH(specs); given_spec++) {
5583 if (strcmp(timespec, specs[given_spec][0]) == 0) {
5584 if (given_spec == 3) {
5585 us = us / 1000;
5586 }
5587 break;
5588 }
5589 }
5590 }
5591
5592 if (given_spec == Py_ARRAY_LENGTH(specs)) {
5593 PyErr_Format(PyExc_ValueError, "Unknown timespec value");
5594 return NULL;
5595 }
5596 else {
5597 result = PyUnicode_FromFormat(specs[given_spec][1],
5598 GET_YEAR(self), GET_MONTH(self),
5599 GET_DAY(self), (int)sep,
5600 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
5601 DATE_GET_SECOND(self), us);
5602 }
5603
5604 if (!result || !HASTZINFO(self))
5605 return result;
5606
5607 /* We need to append the UTC offset. */
5608 if (format_utcoffset(buffer, sizeof(buffer), ":", self->tzinfo,
5609 (PyObject *)self) < 0) {
5610 Py_DECREF(result);
5611 return NULL;
5612 }
5613 PyUnicode_AppendAndDel(&result, PyUnicode_FromString(buffer));
5614 return result;
5615 }
5616
5617 static PyObject *
datetime_ctime(PyDateTime_DateTime * self,PyObject * Py_UNUSED (ignored))5618 datetime_ctime(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
5619 {
5620 return format_ctime((PyDateTime_Date *)self,
5621 DATE_GET_HOUR(self),
5622 DATE_GET_MINUTE(self),
5623 DATE_GET_SECOND(self));
5624 }
5625
5626 /* Miscellaneous methods. */
5627
5628 static PyObject *
flip_fold(PyObject * dt)5629 flip_fold(PyObject *dt)
5630 {
5631 return new_datetime_ex2(GET_YEAR(dt),
5632 GET_MONTH(dt),
5633 GET_DAY(dt),
5634 DATE_GET_HOUR(dt),
5635 DATE_GET_MINUTE(dt),
5636 DATE_GET_SECOND(dt),
5637 DATE_GET_MICROSECOND(dt),
5638 HASTZINFO(dt) ?
5639 ((PyDateTime_DateTime *)dt)->tzinfo : Py_None,
5640 !DATE_GET_FOLD(dt),
5641 Py_TYPE(dt));
5642 }
5643
5644 static PyObject *
get_flip_fold_offset(PyObject * dt)5645 get_flip_fold_offset(PyObject *dt)
5646 {
5647 PyObject *result, *flip_dt;
5648
5649 flip_dt = flip_fold(dt);
5650 if (flip_dt == NULL)
5651 return NULL;
5652 result = datetime_utcoffset(flip_dt, NULL);
5653 Py_DECREF(flip_dt);
5654 return result;
5655 }
5656
5657 /* PEP 495 exception: Whenever one or both of the operands in
5658 * inter-zone comparison is such that its utcoffset() depends
5659 * on the value of its fold attribute, the result is False.
5660 *
5661 * Return 1 if exception applies, 0 if not, and -1 on error.
5662 */
5663 static int
pep495_eq_exception(PyObject * self,PyObject * other,PyObject * offset_self,PyObject * offset_other)5664 pep495_eq_exception(PyObject *self, PyObject *other,
5665 PyObject *offset_self, PyObject *offset_other)
5666 {
5667 int result = 0;
5668 PyObject *flip_offset;
5669
5670 flip_offset = get_flip_fold_offset(self);
5671 if (flip_offset == NULL)
5672 return -1;
5673 if (flip_offset != offset_self &&
5674 delta_cmp(flip_offset, offset_self))
5675 {
5676 result = 1;
5677 goto done;
5678 }
5679 Py_DECREF(flip_offset);
5680
5681 flip_offset = get_flip_fold_offset(other);
5682 if (flip_offset == NULL)
5683 return -1;
5684 if (flip_offset != offset_other &&
5685 delta_cmp(flip_offset, offset_other))
5686 result = 1;
5687 done:
5688 Py_DECREF(flip_offset);
5689 return result;
5690 }
5691
5692 static PyObject *
datetime_richcompare(PyObject * self,PyObject * other,int op)5693 datetime_richcompare(PyObject *self, PyObject *other, int op)
5694 {
5695 PyObject *result = NULL;
5696 PyObject *offset1, *offset2;
5697 int diff;
5698
5699 if (! PyDateTime_Check(other)) {
5700 if (PyDate_Check(other)) {
5701 /* Prevent invocation of date_richcompare. We want to
5702 return NotImplemented here to give the other object
5703 a chance. But since DateTime is a subclass of
5704 Date, if the other object is a Date, it would
5705 compute an ordering based on the date part alone,
5706 and we don't want that. So force unequal or
5707 uncomparable here in that case. */
5708 if (op == Py_EQ)
5709 Py_RETURN_FALSE;
5710 if (op == Py_NE)
5711 Py_RETURN_TRUE;
5712 return cmperror(self, other);
5713 }
5714 Py_RETURN_NOTIMPLEMENTED;
5715 }
5716
5717 if (GET_DT_TZINFO(self) == GET_DT_TZINFO(other)) {
5718 diff = memcmp(((PyDateTime_DateTime *)self)->data,
5719 ((PyDateTime_DateTime *)other)->data,
5720 _PyDateTime_DATETIME_DATASIZE);
5721 return diff_to_bool(diff, op);
5722 }
5723 offset1 = datetime_utcoffset(self, NULL);
5724 if (offset1 == NULL)
5725 return NULL;
5726 offset2 = datetime_utcoffset(other, NULL);
5727 if (offset2 == NULL)
5728 goto done;
5729 /* If they're both naive, or both aware and have the same offsets,
5730 * we get off cheap. Note that if they're both naive, offset1 ==
5731 * offset2 == Py_None at this point.
5732 */
5733 if ((offset1 == offset2) ||
5734 (PyDelta_Check(offset1) && PyDelta_Check(offset2) &&
5735 delta_cmp(offset1, offset2) == 0)) {
5736 diff = memcmp(((PyDateTime_DateTime *)self)->data,
5737 ((PyDateTime_DateTime *)other)->data,
5738 _PyDateTime_DATETIME_DATASIZE);
5739 if ((op == Py_EQ || op == Py_NE) && diff == 0) {
5740 int ex = pep495_eq_exception(self, other, offset1, offset2);
5741 if (ex == -1)
5742 goto done;
5743 if (ex)
5744 diff = 1;
5745 }
5746 result = diff_to_bool(diff, op);
5747 }
5748 else if (offset1 != Py_None && offset2 != Py_None) {
5749 PyDateTime_Delta *delta;
5750
5751 assert(offset1 != offset2); /* else last "if" handled it */
5752 delta = (PyDateTime_Delta *)datetime_subtract((PyObject *)self,
5753 other);
5754 if (delta == NULL)
5755 goto done;
5756 diff = GET_TD_DAYS(delta);
5757 if (diff == 0)
5758 diff = GET_TD_SECONDS(delta) |
5759 GET_TD_MICROSECONDS(delta);
5760 Py_DECREF(delta);
5761 if ((op == Py_EQ || op == Py_NE) && diff == 0) {
5762 int ex = pep495_eq_exception(self, other, offset1, offset2);
5763 if (ex == -1)
5764 goto done;
5765 if (ex)
5766 diff = 1;
5767 }
5768 result = diff_to_bool(diff, op);
5769 }
5770 else if (op == Py_EQ) {
5771 result = Py_False;
5772 Py_INCREF(result);
5773 }
5774 else if (op == Py_NE) {
5775 result = Py_True;
5776 Py_INCREF(result);
5777 }
5778 else {
5779 PyErr_SetString(PyExc_TypeError,
5780 "can't compare offset-naive and "
5781 "offset-aware datetimes");
5782 }
5783 done:
5784 Py_DECREF(offset1);
5785 Py_XDECREF(offset2);
5786 return result;
5787 }
5788
5789 static Py_hash_t
datetime_hash(PyDateTime_DateTime * self)5790 datetime_hash(PyDateTime_DateTime *self)
5791 {
5792 if (self->hashcode == -1) {
5793 PyObject *offset, *self0;
5794 if (DATE_GET_FOLD(self)) {
5795 self0 = new_datetime_ex2(GET_YEAR(self),
5796 GET_MONTH(self),
5797 GET_DAY(self),
5798 DATE_GET_HOUR(self),
5799 DATE_GET_MINUTE(self),
5800 DATE_GET_SECOND(self),
5801 DATE_GET_MICROSECOND(self),
5802 HASTZINFO(self) ? self->tzinfo : Py_None,
5803 0, Py_TYPE(self));
5804 if (self0 == NULL)
5805 return -1;
5806 }
5807 else {
5808 self0 = (PyObject *)self;
5809 Py_INCREF(self0);
5810 }
5811 offset = datetime_utcoffset(self0, NULL);
5812 Py_DECREF(self0);
5813
5814 if (offset == NULL)
5815 return -1;
5816
5817 /* Reduce this to a hash of another object. */
5818 if (offset == Py_None)
5819 self->hashcode = generic_hash(
5820 (unsigned char *)self->data, _PyDateTime_DATETIME_DATASIZE);
5821 else {
5822 PyObject *temp1, *temp2;
5823 int days, seconds;
5824
5825 assert(HASTZINFO(self));
5826 days = ymd_to_ord(GET_YEAR(self),
5827 GET_MONTH(self),
5828 GET_DAY(self));
5829 seconds = DATE_GET_HOUR(self) * 3600 +
5830 DATE_GET_MINUTE(self) * 60 +
5831 DATE_GET_SECOND(self);
5832 temp1 = new_delta(days, seconds,
5833 DATE_GET_MICROSECOND(self),
5834 1);
5835 if (temp1 == NULL) {
5836 Py_DECREF(offset);
5837 return -1;
5838 }
5839 temp2 = delta_subtract(temp1, offset);
5840 Py_DECREF(temp1);
5841 if (temp2 == NULL) {
5842 Py_DECREF(offset);
5843 return -1;
5844 }
5845 self->hashcode = PyObject_Hash(temp2);
5846 Py_DECREF(temp2);
5847 }
5848 Py_DECREF(offset);
5849 }
5850 return self->hashcode;
5851 }
5852
5853 static PyObject *
datetime_replace(PyDateTime_DateTime * self,PyObject * args,PyObject * kw)5854 datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
5855 {
5856 PyObject *clone;
5857 PyObject *tuple;
5858 int y = GET_YEAR(self);
5859 int m = GET_MONTH(self);
5860 int d = GET_DAY(self);
5861 int hh = DATE_GET_HOUR(self);
5862 int mm = DATE_GET_MINUTE(self);
5863 int ss = DATE_GET_SECOND(self);
5864 int us = DATE_GET_MICROSECOND(self);
5865 PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
5866 int fold = DATE_GET_FOLD(self);
5867
5868 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO$i:replace",
5869 datetime_kws,
5870 &y, &m, &d, &hh, &mm, &ss, &us,
5871 &tzinfo, &fold))
5872 return NULL;
5873 if (fold != 0 && fold != 1) {
5874 PyErr_SetString(PyExc_ValueError,
5875 "fold must be either 0 or 1");
5876 return NULL;
5877 }
5878 tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
5879 if (tuple == NULL)
5880 return NULL;
5881 clone = datetime_new(Py_TYPE(self), tuple, NULL);
5882 if (clone != NULL) {
5883 DATE_SET_FOLD(clone, fold);
5884 }
5885 Py_DECREF(tuple);
5886 return clone;
5887 }
5888
5889 static PyObject *
local_timezone_from_timestamp(time_t timestamp)5890 local_timezone_from_timestamp(time_t timestamp)
5891 {
5892 PyObject *result = NULL;
5893 PyObject *delta;
5894 struct tm local_time_tm;
5895 PyObject *nameo = NULL;
5896 const char *zone = NULL;
5897
5898 if (_PyTime_localtime(timestamp, &local_time_tm) != 0)
5899 return NULL;
5900 #ifdef HAVE_STRUCT_TM_TM_ZONE
5901 zone = local_time_tm.tm_zone;
5902 delta = new_delta(0, local_time_tm.tm_gmtoff, 0, 1);
5903 #else /* HAVE_STRUCT_TM_TM_ZONE */
5904 {
5905 PyObject *local_time, *utc_time;
5906 struct tm utc_time_tm;
5907 char buf[100];
5908 strftime(buf, sizeof(buf), "%Z", &local_time_tm);
5909 zone = buf;
5910 local_time = new_datetime(local_time_tm.tm_year + 1900,
5911 local_time_tm.tm_mon + 1,
5912 local_time_tm.tm_mday,
5913 local_time_tm.tm_hour,
5914 local_time_tm.tm_min,
5915 local_time_tm.tm_sec, 0, Py_None, 0);
5916 if (local_time == NULL) {
5917 return NULL;
5918 }
5919 if (_PyTime_gmtime(timestamp, &utc_time_tm) != 0)
5920 return NULL;
5921 utc_time = new_datetime(utc_time_tm.tm_year + 1900,
5922 utc_time_tm.tm_mon + 1,
5923 utc_time_tm.tm_mday,
5924 utc_time_tm.tm_hour,
5925 utc_time_tm.tm_min,
5926 utc_time_tm.tm_sec, 0, Py_None, 0);
5927 if (utc_time == NULL) {
5928 Py_DECREF(local_time);
5929 return NULL;
5930 }
5931 delta = datetime_subtract(local_time, utc_time);
5932 Py_DECREF(local_time);
5933 Py_DECREF(utc_time);
5934 }
5935 #endif /* HAVE_STRUCT_TM_TM_ZONE */
5936 if (delta == NULL) {
5937 return NULL;
5938 }
5939 if (zone != NULL) {
5940 nameo = PyUnicode_DecodeLocale(zone, "surrogateescape");
5941 if (nameo == NULL)
5942 goto error;
5943 }
5944 result = new_timezone(delta, nameo);
5945 Py_XDECREF(nameo);
5946 error:
5947 Py_DECREF(delta);
5948 return result;
5949 }
5950
5951 static PyObject *
local_timezone(PyDateTime_DateTime * utc_time)5952 local_timezone(PyDateTime_DateTime *utc_time)
5953 {
5954 time_t timestamp;
5955 PyObject *delta;
5956 PyObject *one_second;
5957 PyObject *seconds;
5958
5959 delta = datetime_subtract((PyObject *)utc_time, PyDateTime_Epoch);
5960 if (delta == NULL)
5961 return NULL;
5962 one_second = new_delta(0, 1, 0, 0);
5963 if (one_second == NULL) {
5964 Py_DECREF(delta);
5965 return NULL;
5966 }
5967 seconds = divide_timedelta_timedelta((PyDateTime_Delta *)delta,
5968 (PyDateTime_Delta *)one_second);
5969 Py_DECREF(one_second);
5970 Py_DECREF(delta);
5971 if (seconds == NULL)
5972 return NULL;
5973 timestamp = _PyLong_AsTime_t(seconds);
5974 Py_DECREF(seconds);
5975 if (timestamp == -1 && PyErr_Occurred())
5976 return NULL;
5977 return local_timezone_from_timestamp(timestamp);
5978 }
5979
5980 static long long
5981 local_to_seconds(int year, int month, int day,
5982 int hour, int minute, int second, int fold);
5983
5984 static PyObject *
local_timezone_from_local(PyDateTime_DateTime * local_dt)5985 local_timezone_from_local(PyDateTime_DateTime *local_dt)
5986 {
5987 long long seconds;
5988 time_t timestamp;
5989 seconds = local_to_seconds(GET_YEAR(local_dt),
5990 GET_MONTH(local_dt),
5991 GET_DAY(local_dt),
5992 DATE_GET_HOUR(local_dt),
5993 DATE_GET_MINUTE(local_dt),
5994 DATE_GET_SECOND(local_dt),
5995 DATE_GET_FOLD(local_dt));
5996 if (seconds == -1)
5997 return NULL;
5998 /* XXX: add bounds check */
5999 timestamp = seconds - epoch;
6000 return local_timezone_from_timestamp(timestamp);
6001 }
6002
6003 static PyDateTime_DateTime *
datetime_astimezone(PyDateTime_DateTime * self,PyObject * args,PyObject * kw)6004 datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
6005 {
6006 PyDateTime_DateTime *result;
6007 PyObject *offset;
6008 PyObject *temp;
6009 PyObject *self_tzinfo;
6010 PyObject *tzinfo = Py_None;
6011 static char *keywords[] = {"tz", NULL};
6012
6013 if (! PyArg_ParseTupleAndKeywords(args, kw, "|O:astimezone", keywords,
6014 &tzinfo))
6015 return NULL;
6016
6017 if (check_tzinfo_subclass(tzinfo) == -1)
6018 return NULL;
6019
6020 if (!HASTZINFO(self) || self->tzinfo == Py_None) {
6021 naive:
6022 self_tzinfo = local_timezone_from_local(self);
6023 if (self_tzinfo == NULL)
6024 return NULL;
6025 } else {
6026 self_tzinfo = self->tzinfo;
6027 Py_INCREF(self_tzinfo);
6028 }
6029
6030 /* Conversion to self's own time zone is a NOP. */
6031 if (self_tzinfo == tzinfo) {
6032 Py_DECREF(self_tzinfo);
6033 Py_INCREF(self);
6034 return self;
6035 }
6036
6037 /* Convert self to UTC. */
6038 offset = call_utcoffset(self_tzinfo, (PyObject *)self);
6039 Py_DECREF(self_tzinfo);
6040 if (offset == NULL)
6041 return NULL;
6042 else if(offset == Py_None) {
6043 Py_DECREF(offset);
6044 goto naive;
6045 }
6046 else if (!PyDelta_Check(offset)) {
6047 Py_DECREF(offset);
6048 PyErr_Format(PyExc_TypeError, "utcoffset() returned %.200s,"
6049 " expected timedelta or None", Py_TYPE(offset)->tp_name);
6050 return NULL;
6051 }
6052 /* result = self - offset */
6053 result = (PyDateTime_DateTime *)add_datetime_timedelta(self,
6054 (PyDateTime_Delta *)offset, -1);
6055 Py_DECREF(offset);
6056 if (result == NULL)
6057 return NULL;
6058
6059 /* Make sure result is aware and UTC. */
6060 if (!HASTZINFO(result)) {
6061 temp = (PyObject *)result;
6062 result = (PyDateTime_DateTime *)
6063 new_datetime_ex2(GET_YEAR(result),
6064 GET_MONTH(result),
6065 GET_DAY(result),
6066 DATE_GET_HOUR(result),
6067 DATE_GET_MINUTE(result),
6068 DATE_GET_SECOND(result),
6069 DATE_GET_MICROSECOND(result),
6070 PyDateTime_TimeZone_UTC,
6071 DATE_GET_FOLD(result),
6072 Py_TYPE(result));
6073 Py_DECREF(temp);
6074 if (result == NULL)
6075 return NULL;
6076 }
6077 else {
6078 /* Result is already aware - just replace tzinfo. */
6079 temp = result->tzinfo;
6080 result->tzinfo = PyDateTime_TimeZone_UTC;
6081 Py_INCREF(result->tzinfo);
6082 Py_DECREF(temp);
6083 }
6084
6085 /* Attach new tzinfo and let fromutc() do the rest. */
6086 temp = result->tzinfo;
6087 if (tzinfo == Py_None) {
6088 tzinfo = local_timezone(result);
6089 if (tzinfo == NULL) {
6090 Py_DECREF(result);
6091 return NULL;
6092 }
6093 }
6094 else
6095 Py_INCREF(tzinfo);
6096 result->tzinfo = tzinfo;
6097 Py_DECREF(temp);
6098
6099 temp = (PyObject *)result;
6100 result = (PyDateTime_DateTime *)
6101 _PyObject_CallMethodIdOneArg(tzinfo, &PyId_fromutc, temp);
6102 Py_DECREF(temp);
6103
6104 return result;
6105 }
6106
6107 static PyObject *
datetime_timetuple(PyDateTime_DateTime * self,PyObject * Py_UNUSED (ignored))6108 datetime_timetuple(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
6109 {
6110 int dstflag = -1;
6111
6112 if (HASTZINFO(self) && self->tzinfo != Py_None) {
6113 PyObject * dst;
6114
6115 dst = call_dst(self->tzinfo, (PyObject *)self);
6116 if (dst == NULL)
6117 return NULL;
6118
6119 if (dst != Py_None)
6120 dstflag = delta_bool((PyDateTime_Delta *)dst);
6121 Py_DECREF(dst);
6122 }
6123 return build_struct_time(GET_YEAR(self),
6124 GET_MONTH(self),
6125 GET_DAY(self),
6126 DATE_GET_HOUR(self),
6127 DATE_GET_MINUTE(self),
6128 DATE_GET_SECOND(self),
6129 dstflag);
6130 }
6131
6132 static long long
local_to_seconds(int year,int month,int day,int hour,int minute,int second,int fold)6133 local_to_seconds(int year, int month, int day,
6134 int hour, int minute, int second, int fold)
6135 {
6136 long long t, a, b, u1, u2, t1, t2, lt;
6137 t = utc_to_seconds(year, month, day, hour, minute, second);
6138 /* Our goal is to solve t = local(u) for u. */
6139 lt = local(t);
6140 if (lt == -1)
6141 return -1;
6142 a = lt - t;
6143 u1 = t - a;
6144 t1 = local(u1);
6145 if (t1 == -1)
6146 return -1;
6147 if (t1 == t) {
6148 /* We found one solution, but it may not be the one we need.
6149 * Look for an earlier solution (if `fold` is 0), or a
6150 * later one (if `fold` is 1). */
6151 if (fold)
6152 u2 = u1 + max_fold_seconds;
6153 else
6154 u2 = u1 - max_fold_seconds;
6155 lt = local(u2);
6156 if (lt == -1)
6157 return -1;
6158 b = lt - u2;
6159 if (a == b)
6160 return u1;
6161 }
6162 else {
6163 b = t1 - u1;
6164 assert(a != b);
6165 }
6166 u2 = t - b;
6167 t2 = local(u2);
6168 if (t2 == -1)
6169 return -1;
6170 if (t2 == t)
6171 return u2;
6172 if (t1 == t)
6173 return u1;
6174 /* We have found both offsets a and b, but neither t - a nor t - b is
6175 * a solution. This means t is in the gap. */
6176 return fold?Py_MIN(u1, u2):Py_MAX(u1, u2);
6177 }
6178
6179 /* date(1970,1,1).toordinal() == 719163 */
6180 #define EPOCH_SECONDS (719163LL * 24 * 60 * 60)
6181
6182 static PyObject *
datetime_timestamp(PyDateTime_DateTime * self,PyObject * Py_UNUSED (ignored))6183 datetime_timestamp(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
6184 {
6185 PyObject *result;
6186
6187 if (HASTZINFO(self) && self->tzinfo != Py_None) {
6188 PyObject *delta;
6189 delta = datetime_subtract((PyObject *)self, PyDateTime_Epoch);
6190 if (delta == NULL)
6191 return NULL;
6192 result = delta_total_seconds(delta, NULL);
6193 Py_DECREF(delta);
6194 }
6195 else {
6196 long long seconds;
6197 seconds = local_to_seconds(GET_YEAR(self),
6198 GET_MONTH(self),
6199 GET_DAY(self),
6200 DATE_GET_HOUR(self),
6201 DATE_GET_MINUTE(self),
6202 DATE_GET_SECOND(self),
6203 DATE_GET_FOLD(self));
6204 if (seconds == -1)
6205 return NULL;
6206 result = PyFloat_FromDouble(seconds - EPOCH_SECONDS +
6207 DATE_GET_MICROSECOND(self) / 1e6);
6208 }
6209 return result;
6210 }
6211
6212 static PyObject *
datetime_getdate(PyDateTime_DateTime * self,PyObject * Py_UNUSED (ignored))6213 datetime_getdate(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
6214 {
6215 return new_date(GET_YEAR(self),
6216 GET_MONTH(self),
6217 GET_DAY(self));
6218 }
6219
6220 static PyObject *
datetime_gettime(PyDateTime_DateTime * self,PyObject * Py_UNUSED (ignored))6221 datetime_gettime(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
6222 {
6223 return new_time(DATE_GET_HOUR(self),
6224 DATE_GET_MINUTE(self),
6225 DATE_GET_SECOND(self),
6226 DATE_GET_MICROSECOND(self),
6227 Py_None,
6228 DATE_GET_FOLD(self));
6229 }
6230
6231 static PyObject *
datetime_gettimetz(PyDateTime_DateTime * self,PyObject * Py_UNUSED (ignored))6232 datetime_gettimetz(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
6233 {
6234 return new_time(DATE_GET_HOUR(self),
6235 DATE_GET_MINUTE(self),
6236 DATE_GET_SECOND(self),
6237 DATE_GET_MICROSECOND(self),
6238 GET_DT_TZINFO(self),
6239 DATE_GET_FOLD(self));
6240 }
6241
6242 static PyObject *
datetime_utctimetuple(PyDateTime_DateTime * self,PyObject * Py_UNUSED (ignored))6243 datetime_utctimetuple(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored))
6244 {
6245 int y, m, d, hh, mm, ss;
6246 PyObject *tzinfo;
6247 PyDateTime_DateTime *utcself;
6248
6249 tzinfo = GET_DT_TZINFO(self);
6250 if (tzinfo == Py_None) {
6251 utcself = self;
6252 Py_INCREF(utcself);
6253 }
6254 else {
6255 PyObject *offset;
6256 offset = call_utcoffset(tzinfo, (PyObject *)self);
6257 if (offset == NULL)
6258 return NULL;
6259 if (offset == Py_None) {
6260 Py_DECREF(offset);
6261 utcself = self;
6262 Py_INCREF(utcself);
6263 }
6264 else {
6265 utcself = (PyDateTime_DateTime *)add_datetime_timedelta(self,
6266 (PyDateTime_Delta *)offset, -1);
6267 Py_DECREF(offset);
6268 if (utcself == NULL)
6269 return NULL;
6270 }
6271 }
6272 y = GET_YEAR(utcself);
6273 m = GET_MONTH(utcself);
6274 d = GET_DAY(utcself);
6275 hh = DATE_GET_HOUR(utcself);
6276 mm = DATE_GET_MINUTE(utcself);
6277 ss = DATE_GET_SECOND(utcself);
6278
6279 Py_DECREF(utcself);
6280 return build_struct_time(y, m, d, hh, mm, ss, 0);
6281 }
6282
6283 /* Pickle support, a simple use of __reduce__. */
6284
6285 /* Let basestate be the non-tzinfo data string.
6286 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
6287 * So it's a tuple in any (non-error) case.
6288 * __getstate__ isn't exposed.
6289 */
6290 static PyObject *
datetime_getstate(PyDateTime_DateTime * self,int proto)6291 datetime_getstate(PyDateTime_DateTime *self, int proto)
6292 {
6293 PyObject *basestate;
6294 PyObject *result = NULL;
6295
6296 basestate = PyBytes_FromStringAndSize((char *)self->data,
6297 _PyDateTime_DATETIME_DATASIZE);
6298 if (basestate != NULL) {
6299 if (proto > 3 && DATE_GET_FOLD(self))
6300 /* Set the first bit of the third byte */
6301 PyBytes_AS_STRING(basestate)[2] |= (1 << 7);
6302 if (! HASTZINFO(self) || self->tzinfo == Py_None)
6303 result = PyTuple_Pack(1, basestate);
6304 else
6305 result = PyTuple_Pack(2, basestate, self->tzinfo);
6306 Py_DECREF(basestate);
6307 }
6308 return result;
6309 }
6310
6311 static PyObject *
datetime_reduce_ex(PyDateTime_DateTime * self,PyObject * args)6312 datetime_reduce_ex(PyDateTime_DateTime *self, PyObject *args)
6313 {
6314 int proto;
6315 if (!PyArg_ParseTuple(args, "i:__reduce_ex__", &proto))
6316 return NULL;
6317
6318 return Py_BuildValue("(ON)", Py_TYPE(self), datetime_getstate(self, proto));
6319 }
6320
6321 static PyObject *
datetime_reduce(PyDateTime_DateTime * self,PyObject * arg)6322 datetime_reduce(PyDateTime_DateTime *self, PyObject *arg)
6323 {
6324 return Py_BuildValue("(ON)", Py_TYPE(self), datetime_getstate(self, 2));
6325 }
6326
6327 static PyMethodDef datetime_methods[] = {
6328
6329 /* Class methods: */
6330
6331 DATETIME_DATETIME_NOW_METHODDEF
6332
6333 {"utcnow", (PyCFunction)datetime_utcnow,
6334 METH_NOARGS | METH_CLASS,
6335 PyDoc_STR("Return a new datetime representing UTC day and time.")},
6336
6337 {"fromtimestamp", (PyCFunction)(void(*)(void))datetime_fromtimestamp,
6338 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
6339 PyDoc_STR("timestamp[, tz] -> tz's local time from POSIX timestamp.")},
6340
6341 {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
6342 METH_VARARGS | METH_CLASS,
6343 PyDoc_STR("Construct a naive UTC datetime from a POSIX timestamp.")},
6344
6345 {"strptime", (PyCFunction)datetime_strptime,
6346 METH_VARARGS | METH_CLASS,
6347 PyDoc_STR("string, format -> new datetime parsed from a string "
6348 "(like time.strptime()).")},
6349
6350 {"combine", (PyCFunction)(void(*)(void))datetime_combine,
6351 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
6352 PyDoc_STR("date, time -> datetime with same date and time fields")},
6353
6354 {"fromisoformat", (PyCFunction)datetime_fromisoformat,
6355 METH_O | METH_CLASS,
6356 PyDoc_STR("string -> datetime from datetime.isoformat() output")},
6357
6358 /* Instance methods: */
6359
6360 {"date", (PyCFunction)datetime_getdate, METH_NOARGS,
6361 PyDoc_STR("Return date object with same year, month and day.")},
6362
6363 {"time", (PyCFunction)datetime_gettime, METH_NOARGS,
6364 PyDoc_STR("Return time object with same time but with tzinfo=None.")},
6365
6366 {"timetz", (PyCFunction)datetime_gettimetz, METH_NOARGS,
6367 PyDoc_STR("Return time object with same time and tzinfo.")},
6368
6369 {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
6370 PyDoc_STR("Return ctime() style string.")},
6371
6372 {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS,
6373 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
6374
6375 {"timestamp", (PyCFunction)datetime_timestamp, METH_NOARGS,
6376 PyDoc_STR("Return POSIX timestamp as float.")},
6377
6378 {"utctimetuple", (PyCFunction)datetime_utctimetuple, METH_NOARGS,
6379 PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")},
6380
6381 {"isoformat", (PyCFunction)(void(*)(void))datetime_isoformat, METH_VARARGS | METH_KEYWORDS,
6382 PyDoc_STR("[sep] -> string in ISO 8601 format, "
6383 "YYYY-MM-DDT[HH[:MM[:SS[.mmm[uuu]]]]][+HH:MM].\n"
6384 "sep is used to separate the year from the time, and "
6385 "defaults to 'T'.\n"
6386 "The optional argument timespec specifies the number "
6387 "of additional terms\nof the time to include. Valid "
6388 "options are 'auto', 'hours', 'minutes',\n'seconds', "
6389 "'milliseconds' and 'microseconds'.\n")},
6390
6391 {"utcoffset", (PyCFunction)datetime_utcoffset, METH_NOARGS,
6392 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
6393
6394 {"tzname", (PyCFunction)datetime_tzname, METH_NOARGS,
6395 PyDoc_STR("Return self.tzinfo.tzname(self).")},
6396
6397 {"dst", (PyCFunction)datetime_dst, METH_NOARGS,
6398 PyDoc_STR("Return self.tzinfo.dst(self).")},
6399
6400 {"replace", (PyCFunction)(void(*)(void))datetime_replace, METH_VARARGS | METH_KEYWORDS,
6401 PyDoc_STR("Return datetime with new specified fields.")},
6402
6403 {"astimezone", (PyCFunction)(void(*)(void))datetime_astimezone, METH_VARARGS | METH_KEYWORDS,
6404 PyDoc_STR("tz -> convert to local time in new timezone tz\n")},
6405
6406 {"__reduce_ex__", (PyCFunction)datetime_reduce_ex, METH_VARARGS,
6407 PyDoc_STR("__reduce_ex__(proto) -> (cls, state)")},
6408
6409 {"__reduce__", (PyCFunction)datetime_reduce, METH_NOARGS,
6410 PyDoc_STR("__reduce__() -> (cls, state)")},
6411
6412 {NULL, NULL}
6413 };
6414
6415 static const char datetime_doc[] =
6416 PyDoc_STR("datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])\n\
6417 \n\
6418 The year, month and day arguments are required. tzinfo may be None, or an\n\
6419 instance of a tzinfo subclass. The remaining arguments may be ints.\n");
6420
6421 static PyNumberMethods datetime_as_number = {
6422 datetime_add, /* nb_add */
6423 datetime_subtract, /* nb_subtract */
6424 0, /* nb_multiply */
6425 0, /* nb_remainder */
6426 0, /* nb_divmod */
6427 0, /* nb_power */
6428 0, /* nb_negative */
6429 0, /* nb_positive */
6430 0, /* nb_absolute */
6431 0, /* nb_bool */
6432 };
6433
6434 static PyTypeObject PyDateTime_DateTimeType = {
6435 PyVarObject_HEAD_INIT(NULL, 0)
6436 "datetime.datetime", /* tp_name */
6437 sizeof(PyDateTime_DateTime), /* tp_basicsize */
6438 0, /* tp_itemsize */
6439 (destructor)datetime_dealloc, /* tp_dealloc */
6440 0, /* tp_vectorcall_offset */
6441 0, /* tp_getattr */
6442 0, /* tp_setattr */
6443 0, /* tp_as_async */
6444 (reprfunc)datetime_repr, /* tp_repr */
6445 &datetime_as_number, /* tp_as_number */
6446 0, /* tp_as_sequence */
6447 0, /* tp_as_mapping */
6448 (hashfunc)datetime_hash, /* tp_hash */
6449 0, /* tp_call */
6450 (reprfunc)datetime_str, /* tp_str */
6451 PyObject_GenericGetAttr, /* tp_getattro */
6452 0, /* tp_setattro */
6453 0, /* tp_as_buffer */
6454 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
6455 datetime_doc, /* tp_doc */
6456 0, /* tp_traverse */
6457 0, /* tp_clear */
6458 datetime_richcompare, /* tp_richcompare */
6459 0, /* tp_weaklistoffset */
6460 0, /* tp_iter */
6461 0, /* tp_iternext */
6462 datetime_methods, /* tp_methods */
6463 0, /* tp_members */
6464 datetime_getset, /* tp_getset */
6465 0, /* tp_base; filled in
6466 PyInit__datetime */
6467 0, /* tp_dict */
6468 0, /* tp_descr_get */
6469 0, /* tp_descr_set */
6470 0, /* tp_dictoffset */
6471 0, /* tp_init */
6472 datetime_alloc, /* tp_alloc */
6473 datetime_new, /* tp_new */
6474 0, /* tp_free */
6475 };
6476
6477 /* ---------------------------------------------------------------------------
6478 * Module methods and initialization.
6479 */
6480
6481 static PyMethodDef module_methods[] = {
6482 {NULL, NULL}
6483 };
6484
6485 /* C API. Clients get at this via PyDateTime_IMPORT, defined in
6486 * datetime.h.
6487 */
6488 static PyDateTime_CAPI CAPI = {
6489 &PyDateTime_DateType,
6490 &PyDateTime_DateTimeType,
6491 &PyDateTime_TimeType,
6492 &PyDateTime_DeltaType,
6493 &PyDateTime_TZInfoType,
6494 NULL, // PyDatetime_TimeZone_UTC not initialized yet
6495 new_date_ex,
6496 new_datetime_ex,
6497 new_time_ex,
6498 new_delta_ex,
6499 new_timezone,
6500 datetime_fromtimestamp,
6501 datetime_date_fromtimestamp_capi,
6502 new_datetime_ex2,
6503 new_time_ex2
6504 };
6505
6506
6507
6508 static struct PyModuleDef datetimemodule = {
6509 PyModuleDef_HEAD_INIT,
6510 "_datetime",
6511 "Fast implementation of the datetime type.",
6512 -1,
6513 module_methods,
6514 NULL,
6515 NULL,
6516 NULL,
6517 NULL
6518 };
6519
6520 PyMODINIT_FUNC
PyInit__datetime(void)6521 PyInit__datetime(void)
6522 {
6523 PyObject *m; /* a module object */
6524 PyObject *d; /* its dict */
6525 PyObject *x;
6526 PyObject *delta;
6527
6528 m = PyModule_Create(&datetimemodule);
6529 if (m == NULL)
6530 return NULL;
6531
6532 // `&...` is not a constant expression according to a strict reading
6533 // of C standards. Fill tp_base at run-time rather than statically.
6534 // See https://bugs.python.org/issue40777
6535 PyDateTime_IsoCalendarDateType.tp_base = &PyTuple_Type;
6536 PyDateTime_TimeZoneType.tp_base = &PyDateTime_TZInfoType;
6537 PyDateTime_DateTimeType.tp_base = &PyDateTime_DateType;
6538
6539 PyTypeObject *types[] = {
6540 &PyDateTime_DateType,
6541 &PyDateTime_DateTimeType,
6542 &PyDateTime_TimeType,
6543 &PyDateTime_DeltaType,
6544 &PyDateTime_TZInfoType,
6545 &PyDateTime_TimeZoneType,
6546 };
6547
6548 for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) {
6549 if (PyModule_AddType(m, types[i]) < 0) {
6550 return NULL;
6551 }
6552 }
6553
6554 if (PyType_Ready(&PyDateTime_IsoCalendarDateType) < 0) {
6555 return NULL;
6556 }
6557 Py_INCREF(&PyDateTime_IsoCalendarDateType);
6558
6559 /* timedelta values */
6560 d = PyDateTime_DeltaType.tp_dict;
6561
6562 x = new_delta(0, 0, 1, 0);
6563 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
6564 return NULL;
6565 Py_DECREF(x);
6566
6567 x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0);
6568 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
6569 return NULL;
6570 Py_DECREF(x);
6571
6572 x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0);
6573 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
6574 return NULL;
6575 Py_DECREF(x);
6576
6577 /* date values */
6578 d = PyDateTime_DateType.tp_dict;
6579
6580 x = new_date(1, 1, 1);
6581 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
6582 return NULL;
6583 Py_DECREF(x);
6584
6585 x = new_date(MAXYEAR, 12, 31);
6586 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
6587 return NULL;
6588 Py_DECREF(x);
6589
6590 x = new_delta(1, 0, 0, 0);
6591 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
6592 return NULL;
6593 Py_DECREF(x);
6594
6595 /* time values */
6596 d = PyDateTime_TimeType.tp_dict;
6597
6598 x = new_time(0, 0, 0, 0, Py_None, 0);
6599 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
6600 return NULL;
6601 Py_DECREF(x);
6602
6603 x = new_time(23, 59, 59, 999999, Py_None, 0);
6604 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
6605 return NULL;
6606 Py_DECREF(x);
6607
6608 x = new_delta(0, 0, 1, 0);
6609 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
6610 return NULL;
6611 Py_DECREF(x);
6612
6613 /* datetime values */
6614 d = PyDateTime_DateTimeType.tp_dict;
6615
6616 x = new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None, 0);
6617 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
6618 return NULL;
6619 Py_DECREF(x);
6620
6621 x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None, 0);
6622 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
6623 return NULL;
6624 Py_DECREF(x);
6625
6626 x = new_delta(0, 0, 1, 0);
6627 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
6628 return NULL;
6629 Py_DECREF(x);
6630
6631 /* timezone values */
6632 d = PyDateTime_TimeZoneType.tp_dict;
6633
6634 delta = new_delta(0, 0, 0, 0);
6635 if (delta == NULL)
6636 return NULL;
6637 x = create_timezone(delta, NULL);
6638 Py_DECREF(delta);
6639 if (x == NULL || PyDict_SetItemString(d, "utc", x) < 0)
6640 return NULL;
6641 PyDateTime_TimeZone_UTC = x;
6642 CAPI.TimeZone_UTC = PyDateTime_TimeZone_UTC;
6643
6644 /* bpo-37642: These attributes are rounded to the nearest minute for backwards
6645 * compatibility, even though the constructor will accept a wider range of
6646 * values. This may change in the future.*/
6647 delta = new_delta(-1, 60, 0, 1); /* -23:59 */
6648 if (delta == NULL)
6649 return NULL;
6650 x = create_timezone(delta, NULL);
6651 Py_DECREF(delta);
6652 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
6653 return NULL;
6654 Py_DECREF(x);
6655
6656 delta = new_delta(0, (23 * 60 + 59) * 60, 0, 0); /* +23:59 */
6657 if (delta == NULL)
6658 return NULL;
6659 x = create_timezone(delta, NULL);
6660 Py_DECREF(delta);
6661 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
6662 return NULL;
6663 Py_DECREF(x);
6664
6665 /* Epoch */
6666 PyDateTime_Epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0,
6667 PyDateTime_TimeZone_UTC, 0);
6668 if (PyDateTime_Epoch == NULL)
6669 return NULL;
6670
6671 /* module initialization */
6672 PyModule_AddIntMacro(m, MINYEAR);
6673 PyModule_AddIntMacro(m, MAXYEAR);
6674
6675 x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL);
6676 if (x == NULL)
6677 return NULL;
6678 PyModule_AddObject(m, "datetime_CAPI", x);
6679
6680 /* A 4-year cycle has an extra leap day over what we'd get from
6681 * pasting together 4 single years.
6682 */
6683 Py_BUILD_ASSERT(DI4Y == 4 * 365 + 1);
6684 assert(DI4Y == days_before_year(4+1));
6685
6686 /* Similarly, a 400-year cycle has an extra leap day over what we'd
6687 * get from pasting together 4 100-year cycles.
6688 */
6689 Py_BUILD_ASSERT(DI400Y == 4 * DI100Y + 1);
6690 assert(DI400Y == days_before_year(400+1));
6691
6692 /* OTOH, a 100-year cycle has one fewer leap day than we'd get from
6693 * pasting together 25 4-year cycles.
6694 */
6695 Py_BUILD_ASSERT(DI100Y == 25 * DI4Y - 1);
6696 assert(DI100Y == days_before_year(100+1));
6697
6698 us_per_ms = PyLong_FromLong(1000);
6699 us_per_second = PyLong_FromLong(1000000);
6700 us_per_minute = PyLong_FromLong(60000000);
6701 seconds_per_day = PyLong_FromLong(24 * 3600);
6702 if (us_per_ms == NULL || us_per_second == NULL ||
6703 us_per_minute == NULL || seconds_per_day == NULL)
6704 return NULL;
6705
6706 /* The rest are too big for 32-bit ints, but even
6707 * us_per_week fits in 40 bits, so doubles should be exact.
6708 */
6709 us_per_hour = PyLong_FromDouble(3600000000.0);
6710 us_per_day = PyLong_FromDouble(86400000000.0);
6711 us_per_week = PyLong_FromDouble(604800000000.0);
6712 if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL)
6713 return NULL;
6714 return m;
6715 }
6716
6717 /* ---------------------------------------------------------------------------
6718 Some time zone algebra. For a datetime x, let
6719 x.n = x stripped of its timezone -- its naive time.
6720 x.o = x.utcoffset(), and assuming that doesn't raise an exception or
6721 return None
6722 x.d = x.dst(), and assuming that doesn't raise an exception or
6723 return None
6724 x.s = x's standard offset, x.o - x.d
6725
6726 Now some derived rules, where k is a duration (timedelta).
6727
6728 1. x.o = x.s + x.d
6729 This follows from the definition of x.s.
6730
6731 2. If x and y have the same tzinfo member, x.s = y.s.
6732 This is actually a requirement, an assumption we need to make about
6733 sane tzinfo classes.
6734
6735 3. The naive UTC time corresponding to x is x.n - x.o.
6736 This is again a requirement for a sane tzinfo class.
6737
6738 4. (x+k).s = x.s
6739 This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
6740
6741 5. (x+k).n = x.n + k
6742 Again follows from how arithmetic is defined.
6743
6744 Now we can explain tz.fromutc(x). Let's assume it's an interesting case
6745 (meaning that the various tzinfo methods exist, and don't blow up or return
6746 None when called).
6747
6748 The function wants to return a datetime y with timezone tz, equivalent to x.
6749 x is already in UTC.
6750
6751 By #3, we want
6752
6753 y.n - y.o = x.n [1]
6754
6755 The algorithm starts by attaching tz to x.n, and calling that y. So
6756 x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
6757 becomes true; in effect, we want to solve [2] for k:
6758
6759 (y+k).n - (y+k).o = x.n [2]
6760
6761 By #1, this is the same as
6762
6763 (y+k).n - ((y+k).s + (y+k).d) = x.n [3]
6764
6765 By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
6766 Substituting that into [3],
6767
6768 x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving
6769 k - (y+k).s - (y+k).d = 0; rearranging,
6770 k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so
6771 k = y.s - (y+k).d
6772
6773 On the RHS, (y+k).d can't be computed directly, but y.s can be, and we
6774 approximate k by ignoring the (y+k).d term at first. Note that k can't be
6775 very large, since all offset-returning methods return a duration of magnitude
6776 less than 24 hours. For that reason, if y is firmly in std time, (y+k).d must
6777 be 0, so ignoring it has no consequence then.
6778
6779 In any case, the new value is
6780
6781 z = y + y.s [4]
6782
6783 It's helpful to step back at look at [4] from a higher level: it's simply
6784 mapping from UTC to tz's standard time.
6785
6786 At this point, if
6787
6788 z.n - z.o = x.n [5]
6789
6790 we have an equivalent time, and are almost done. The insecurity here is
6791 at the start of daylight time. Picture US Eastern for concreteness. The wall
6792 time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
6793 sense then. The docs ask that an Eastern tzinfo class consider such a time to
6794 be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST
6795 on the day DST starts. We want to return the 1:MM EST spelling because that's
6796 the only spelling that makes sense on the local wall clock.
6797
6798 In fact, if [5] holds at this point, we do have the standard-time spelling,
6799 but that takes a bit of proof. We first prove a stronger result. What's the
6800 difference between the LHS and RHS of [5]? Let
6801
6802 diff = x.n - (z.n - z.o) [6]
6803
6804 Now
6805 z.n = by [4]
6806 (y + y.s).n = by #5
6807 y.n + y.s = since y.n = x.n
6808 x.n + y.s = since z and y are have the same tzinfo member,
6809 y.s = z.s by #2
6810 x.n + z.s
6811
6812 Plugging that back into [6] gives
6813
6814 diff =
6815 x.n - ((x.n + z.s) - z.o) = expanding
6816 x.n - x.n - z.s + z.o = cancelling
6817 - z.s + z.o = by #2
6818 z.d
6819
6820 So diff = z.d.
6821
6822 If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
6823 spelling we wanted in the endcase described above. We're done. Contrarily,
6824 if z.d = 0, then we have a UTC equivalent, and are also done.
6825
6826 If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
6827 add to z (in effect, z is in tz's standard time, and we need to shift the
6828 local clock into tz's daylight time).
6829
6830 Let
6831
6832 z' = z + z.d = z + diff [7]
6833
6834 and we can again ask whether
6835
6836 z'.n - z'.o = x.n [8]
6837
6838 If so, we're done. If not, the tzinfo class is insane, according to the
6839 assumptions we've made. This also requires a bit of proof. As before, let's
6840 compute the difference between the LHS and RHS of [8] (and skipping some of
6841 the justifications for the kinds of substitutions we've done several times
6842 already):
6843
6844 diff' = x.n - (z'.n - z'.o) = replacing z'.n via [7]
6845 x.n - (z.n + diff - z'.o) = replacing diff via [6]
6846 x.n - (z.n + x.n - (z.n - z.o) - z'.o) =
6847 x.n - z.n - x.n + z.n - z.o + z'.o = cancel x.n
6848 - z.n + z.n - z.o + z'.o = cancel z.n
6849 - z.o + z'.o = #1 twice
6850 -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
6851 z'.d - z.d
6852
6853 So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
6854 we've found the UTC-equivalent so are done. In fact, we stop with [7] and
6855 return z', not bothering to compute z'.d.
6856
6857 How could z.d and z'd differ? z' = z + z.d [7], so merely moving z' by
6858 a dst() offset, and starting *from* a time already in DST (we know z.d != 0),
6859 would have to change the result dst() returns: we start in DST, and moving
6860 a little further into it takes us out of DST.
6861
6862 There isn't a sane case where this can happen. The closest it gets is at
6863 the end of DST, where there's an hour in UTC with no spelling in a hybrid
6864 tzinfo class. In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT. During
6865 that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM
6866 UTC) because the docs insist on that, but 0:MM is taken as being in daylight
6867 time (4:MM UTC). There is no local time mapping to 5:MM UTC. The local
6868 clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in
6869 standard time. Since that's what the local clock *does*, we want to map both
6870 UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
6871 in local time, but so it goes -- it's the way the local clock works.
6872
6873 When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
6874 so z=0:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
6875 z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
6876 (correctly) concludes that z' is not UTC-equivalent to x.
6877
6878 Because we know z.d said z was in daylight time (else [5] would have held and
6879 we would have stopped then), and we know z.d != z'.d (else [8] would have held
6880 and we would have stopped then), and there are only 2 possible values dst() can
6881 return in Eastern, it follows that z'.d must be 0 (which it is in the example,
6882 but the reasoning doesn't depend on the example -- it depends on there being
6883 two possible dst() outcomes, one zero and the other non-zero). Therefore
6884 z' must be in standard time, and is the spelling we want in this case.
6885
6886 Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is
6887 concerned (because it takes z' as being in standard time rather than the
6888 daylight time we intend here), but returning it gives the real-life "local
6889 clock repeats an hour" behavior when mapping the "unspellable" UTC hour into
6890 tz.
6891
6892 When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with
6893 the 1:MM standard time spelling we want.
6894
6895 So how can this break? One of the assumptions must be violated. Two
6896 possibilities:
6897
6898 1) [2] effectively says that y.s is invariant across all y belong to a given
6899 time zone. This isn't true if, for political reasons or continental drift,
6900 a region decides to change its base offset from UTC.
6901
6902 2) There may be versions of "double daylight" time where the tail end of
6903 the analysis gives up a step too early. I haven't thought about that
6904 enough to say.
6905
6906 In any case, it's clear that the default fromutc() is strong enough to handle
6907 "almost all" time zones: so long as the standard offset is invariant, it
6908 doesn't matter if daylight time transition points change from year to year, or
6909 if daylight time is skipped in some years; it doesn't matter how large or
6910 small dst() may get within its bounds; and it doesn't even matter if some
6911 perverse time zone returns a negative dst()). So a breaking case must be
6912 pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
6913 --------------------------------------------------------------------------- */
6914