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