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