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, ¤t);
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, µseconds);
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, ×tamp)) {
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, ×pec))
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, µsecond,
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, ×tamp, &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", ×tamp))
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 µsecond, &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, µsecond) < 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, ×pec))
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