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