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 |
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 * |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 * |
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 * |
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 |
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 * |
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 |
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 |
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 |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 |
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 * |
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 |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
2760 | date_year(PyDateTime_Date *self, void *unused) |
2761 | { |
2762 | return PyLong_FromLong(GET_YEAR(self)); |
2763 | } |
2764 | |
2765 | static PyObject * |
2766 | date_month(PyDateTime_Date *self, void *unused) |
2767 | { |
2768 | return PyLong_FromLong(GET_MONTH(self)); |
2769 | } |
2770 | |
2771 | static PyObject * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
3157 | date_str(PyDateTime_Date *self) |
3158 | { |
3159 | return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat); |
3160 | } |
3161 | |
3162 | |
3163 | static PyObject * |
3164 | date_ctime(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) |
3165 | { |
3166 | return format_ctime(self, 0, 0, 0); |
3167 | } |
3168 | |
3169 | static PyObject * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 |
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 |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
3628 | tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt) |
3629 | { |
3630 | return tzinfo_nogo("tzname" ); |
3631 | } |
3632 | |
3633 | static PyObject * |
3634 | tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt) |
3635 | { |
3636 | return tzinfo_nogo("utcoffset" ); |
3637 | } |
3638 | |
3639 | static PyObject * |
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 * |
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 * |
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 * |
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 |
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 * |
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 |
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 |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
4091 | time_hour(PyDateTime_Time *self, void *unused) |
4092 | { |
4093 | return PyLong_FromLong(TIME_GET_HOUR(self)); |
4094 | } |
4095 | |
4096 | static PyObject * |
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 * |
4104 | py_time_second(PyDateTime_Time *self, void *unused) |
4105 | { |
4106 | return PyLong_FromLong(TIME_GET_SECOND(self)); |
4107 | } |
4108 | |
4109 | static PyObject * |
4110 | time_microsecond(PyDateTime_Time *self, void *unused) |
4111 | { |
4112 | return PyLong_FromLong(TIME_GET_MICROSECOND(self)); |
4113 | } |
4114 | |
4115 | static PyObject * |
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 * |
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 * |
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 * |
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 |
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 * |
4257 | time_utcoffset(PyObject *self, PyObject *unused) { |
4258 | return call_utcoffset(GET_TIME_TZINFO(self), Py_None); |
4259 | } |
4260 | |
4261 | static PyObject * |
4262 | time_dst(PyObject *self, PyObject *unused) { |
4263 | return call_dst(GET_TIME_TZINFO(self), Py_None); |
4264 | } |
4265 | |
4266 | static PyObject * |
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 * |
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 * |
4302 | time_str(PyDateTime_Time *self) |
4303 | { |
4304 | return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat); |
4305 | } |
4306 | |
4307 | static PyObject * |
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 * |
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 * |
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 |
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 * |
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 * |
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 * |
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 * |
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 * |
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 * |
4759 | datetime_hour(PyDateTime_DateTime *self, void *unused) |
4760 | { |
4761 | return PyLong_FromLong(DATE_GET_HOUR(self)); |
4762 | } |
4763 | |
4764 | static PyObject * |
4765 | datetime_minute(PyDateTime_DateTime *self, void *unused) |
4766 | { |
4767 | return PyLong_FromLong(DATE_GET_MINUTE(self)); |
4768 | } |
4769 | |
4770 | static PyObject * |
4771 | datetime_second(PyDateTime_DateTime *self, void *unused) |
4772 | { |
4773 | return PyLong_FromLong(DATE_GET_SECOND(self)); |
4774 | } |
4775 | |
4776 | static PyObject * |
4777 | datetime_microsecond(PyDateTime_DateTime *self, void *unused) |
4778 | { |
4779 | return PyLong_FromLong(DATE_GET_MICROSECOND(self)); |
4780 | } |
4781 | |
4782 | static PyObject * |
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 * |
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 * |
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 * |
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 |
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 |
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 * |
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 | if (result_seconds == -1 && PyErr_Occurred()) { |
5008 | return NULL; |
5009 | } |
5010 | |
5011 | /* Probe max_fold_seconds to detect a fold. */ |
5012 | probe_seconds = local(epoch + timet - max_fold_seconds); |
5013 | if (probe_seconds == -1) |
5014 | return NULL; |
5015 | transition = result_seconds - probe_seconds - max_fold_seconds; |
5016 | if (transition < 0) { |
5017 | probe_seconds = local(epoch + timet + transition); |
5018 | if (probe_seconds == -1) |
5019 | return NULL; |
5020 | if (probe_seconds == result_seconds) |
5021 | fold = 1; |
5022 | } |
5023 | } |
5024 | return new_datetime_subclass_fold_ex(year, month, day, hour, minute, |
5025 | second, us, tzinfo, fold, cls); |
5026 | } |
5027 | |
5028 | /* Internal helper. |
5029 | * Build datetime from a Python timestamp. Pass localtime or gmtime for f, |
5030 | * to control the interpretation of the timestamp. Since a double doesn't |
5031 | * have enough bits to cover a datetime's full range of precision, it's |
5032 | * better to call datetime_from_timet_and_us provided you have a way |
5033 | * to get that much precision (e.g., C time() isn't good enough). |
5034 | */ |
5035 | static PyObject * |
5036 | datetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp, |
5037 | PyObject *tzinfo) |
5038 | { |
5039 | time_t timet; |
5040 | long us; |
5041 | |
5042 | if (_PyTime_ObjectToTimeval(timestamp, |
5043 | &timet, &us, _PyTime_ROUND_HALF_EVEN) == -1) |
5044 | return NULL; |
5045 | |
5046 | return datetime_from_timet_and_us(cls, f, timet, (int)us, tzinfo); |
5047 | } |
5048 | |
5049 | /* Internal helper. |
5050 | * Build most accurate possible datetime for current time. Pass localtime or |
5051 | * gmtime for f as appropriate. |
5052 | */ |
5053 | static PyObject * |
5054 | datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo) |
5055 | { |
5056 | _PyTime_t ts = _PyTime_GetSystemClock(); |
5057 | time_t secs; |
5058 | int us; |
5059 | |
5060 | if (_PyTime_AsTimevalTime_t(ts, &secs, &us, _PyTime_ROUND_FLOOR) < 0) |
5061 | return NULL; |
5062 | assert(0 <= us && us <= 999999); |
5063 | |
5064 | return datetime_from_timet_and_us(cls, f, secs, us, tzinfo); |
5065 | } |
5066 | |
5067 | /*[clinic input] |
5068 | |
5069 | @classmethod |
5070 | datetime.datetime.now |
5071 | |
5072 | tz: object = None |
5073 | Timezone object. |
5074 | |
5075 | Returns new datetime object representing current time local to tz. |
5076 | |
5077 | If no tz is specified, uses local timezone. |
5078 | [clinic start generated code]*/ |
5079 | |
5080 | static PyObject * |
5081 | datetime_datetime_now_impl(PyTypeObject *type, PyObject *tz) |
5082 | /*[clinic end generated code: output=b3386e5345e2b47a input=80d09869c5267d00]*/ |
5083 | { |
5084 | PyObject *self; |
5085 | |
5086 | /* Return best possible local time -- this isn't constrained by the |
5087 | * precision of a timestamp. |
5088 | */ |
5089 | if (check_tzinfo_subclass(tz) < 0) |
5090 | return NULL; |
5091 | |
5092 | self = datetime_best_possible((PyObject *)type, |
5093 | tz == Py_None ? _PyTime_localtime : |
5094 | _PyTime_gmtime, |
5095 | tz); |
5096 | if (self != NULL && tz != Py_None) { |
5097 | /* Convert UTC to tzinfo's zone. */ |
5098 | self = _PyObject_CallMethodId(tz, &PyId_fromutc, "N" , self); |
5099 | } |
5100 | return self; |
5101 | } |
5102 | |
5103 | /* Return best possible UTC time -- this isn't constrained by the |
5104 | * precision of a timestamp. |
5105 | */ |
5106 | static PyObject * |
5107 | datetime_utcnow(PyObject *cls, PyObject *dummy) |
5108 | { |
5109 | return datetime_best_possible(cls, _PyTime_gmtime, Py_None); |
5110 | } |
5111 | |
5112 | /* Return new local datetime from timestamp (Python timestamp -- a double). */ |
5113 | static PyObject * |
5114 | datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw) |
5115 | { |
5116 | PyObject *self; |
5117 | PyObject *timestamp; |
5118 | PyObject *tzinfo = Py_None; |
5119 | static char *keywords[] = {"timestamp" , "tz" , NULL}; |
5120 | |
5121 | if (! PyArg_ParseTupleAndKeywords(args, kw, "O|O:fromtimestamp" , |
5122 | keywords, ×tamp, &tzinfo)) |
5123 | return NULL; |
5124 | if (check_tzinfo_subclass(tzinfo) < 0) |
5125 | return NULL; |
5126 | |
5127 | self = datetime_from_timestamp(cls, |
5128 | tzinfo == Py_None ? _PyTime_localtime : |
5129 | _PyTime_gmtime, |
5130 | timestamp, |
5131 | tzinfo); |
5132 | if (self != NULL && tzinfo != Py_None) { |
5133 | /* Convert UTC to tzinfo's zone. */ |
5134 | self = _PyObject_CallMethodId(tzinfo, &PyId_fromutc, "N" , self); |
5135 | } |
5136 | return self; |
5137 | } |
5138 | |
5139 | /* Return new UTC datetime from timestamp (Python timestamp -- a double). */ |
5140 | static PyObject * |
5141 | datetime_utcfromtimestamp(PyObject *cls, PyObject *args) |
5142 | { |
5143 | PyObject *timestamp; |
5144 | PyObject *result = NULL; |
5145 | |
5146 | if (PyArg_ParseTuple(args, "O:utcfromtimestamp" , ×tamp)) |
5147 | result = datetime_from_timestamp(cls, _PyTime_gmtime, timestamp, |
5148 | Py_None); |
5149 | return result; |
5150 | } |
5151 | |
5152 | /* Return new datetime from _strptime.strptime_datetime(). */ |
5153 | static PyObject * |
5154 | datetime_strptime(PyObject *cls, PyObject *args) |
5155 | { |
5156 | static PyObject *module = NULL; |
5157 | PyObject *string, *format; |
5158 | _Py_IDENTIFIER(_strptime_datetime); |
5159 | |
5160 | if (!PyArg_ParseTuple(args, "UU:strptime" , &string, &format)) |
5161 | return NULL; |
5162 | |
5163 | if (module == NULL) { |
5164 | module = PyImport_ImportModuleNoBlock("_strptime" ); |
5165 | if (module == NULL) |
5166 | return NULL; |
5167 | } |
5168 | return _PyObject_CallMethodIdObjArgs(module, &PyId__strptime_datetime, |
5169 | cls, string, format, NULL); |
5170 | } |
5171 | |
5172 | /* Return new datetime from date/datetime and time arguments. */ |
5173 | static PyObject * |
5174 | datetime_combine(PyObject *cls, PyObject *args, PyObject *kw) |
5175 | { |
5176 | static char *keywords[] = {"date" , "time" , "tzinfo" , NULL}; |
5177 | PyObject *date; |
5178 | PyObject *time; |
5179 | PyObject *tzinfo = NULL; |
5180 | PyObject *result = NULL; |
5181 | |
5182 | if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!|O:combine" , keywords, |
5183 | &PyDateTime_DateType, &date, |
5184 | &PyDateTime_TimeType, &time, &tzinfo)) { |
5185 | if (tzinfo == NULL) { |
5186 | if (HASTZINFO(time)) |
5187 | tzinfo = ((PyDateTime_Time *)time)->tzinfo; |
5188 | else |
5189 | tzinfo = Py_None; |
5190 | } |
5191 | result = new_datetime_subclass_fold_ex(GET_YEAR(date), |
5192 | GET_MONTH(date), |
5193 | GET_DAY(date), |
5194 | TIME_GET_HOUR(time), |
5195 | TIME_GET_MINUTE(time), |
5196 | TIME_GET_SECOND(time), |
5197 | TIME_GET_MICROSECOND(time), |
5198 | tzinfo, |
5199 | TIME_GET_FOLD(time), |
5200 | cls); |
5201 | } |
5202 | return result; |
5203 | } |
5204 | |
5205 | static PyObject * |
5206 | _sanitize_isoformat_str(PyObject *dtstr) |
5207 | { |
5208 | // `fromisoformat` allows surrogate characters in exactly one position, |
5209 | // the separator; to allow datetime_fromisoformat to make the simplifying |
5210 | // assumption that all valid strings can be encoded in UTF-8, this function |
5211 | // replaces any surrogate character separators with `T`. |
5212 | // |
5213 | // The result of this, if not NULL, returns a new reference |
5214 | Py_ssize_t len = PyUnicode_GetLength(dtstr); |
5215 | if (len < 0) { |
5216 | return NULL; |
5217 | } |
5218 | |
5219 | if (len <= 10 || |
5220 | !Py_UNICODE_IS_SURROGATE(PyUnicode_READ_CHAR(dtstr, 10))) { |
5221 | Py_INCREF(dtstr); |
5222 | return dtstr; |
5223 | } |
5224 | |
5225 | PyObject *str_out = _PyUnicode_Copy(dtstr); |
5226 | if (str_out == NULL) { |
5227 | return NULL; |
5228 | } |
5229 | |
5230 | if (PyUnicode_WriteChar(str_out, 10, (Py_UCS4)'T')) { |
5231 | Py_DECREF(str_out); |
5232 | return NULL; |
5233 | } |
5234 | |
5235 | return str_out; |
5236 | } |
5237 | |
5238 | static PyObject * |
5239 | datetime_fromisoformat(PyObject *cls, PyObject *dtstr) |
5240 | { |
5241 | assert(dtstr != NULL); |
5242 | |
5243 | if (!PyUnicode_Check(dtstr)) { |
5244 | PyErr_SetString(PyExc_TypeError, |
5245 | "fromisoformat: argument must be str" ); |
5246 | return NULL; |
5247 | } |
5248 | |
5249 | PyObject *dtstr_clean = _sanitize_isoformat_str(dtstr); |
5250 | if (dtstr_clean == NULL) { |
5251 | goto error; |
5252 | } |
5253 | |
5254 | Py_ssize_t len; |
5255 | const char *dt_ptr = PyUnicode_AsUTF8AndSize(dtstr_clean, &len); |
5256 | |
5257 | if (dt_ptr == NULL) { |
5258 | if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) { |
5259 | // Encoding errors are invalid string errors at this point |
5260 | goto invalid_string_error; |
5261 | } |
5262 | else { |
5263 | goto error; |
5264 | } |
5265 | } |
5266 | |
5267 | const char *p = dt_ptr; |
5268 | |
5269 | int year = 0, month = 0, day = 0; |
5270 | int hour = 0, minute = 0, second = 0, microsecond = 0; |
5271 | int tzoffset = 0, tzusec = 0; |
5272 | |
5273 | // date has a fixed length of 10 |
5274 | int rv = parse_isoformat_date(p, &year, &month, &day); |
5275 | |
5276 | if (!rv && len > 10) { |
5277 | // In UTF-8, the length of multi-byte characters is encoded in the MSB |
5278 | if ((p[10] & 0x80) == 0) { |
5279 | p += 11; |
5280 | } |
5281 | else { |
5282 | switch (p[10] & 0xf0) { |
5283 | case 0xe0: |
5284 | p += 13; |
5285 | break; |
5286 | case 0xf0: |
5287 | p += 14; |
5288 | break; |
5289 | default: |
5290 | p += 12; |
5291 | break; |
5292 | } |
5293 | } |
5294 | |
5295 | len -= (p - dt_ptr); |
5296 | rv = parse_isoformat_time(p, len, &hour, &minute, &second, |
5297 | µsecond, &tzoffset, &tzusec); |
5298 | } |
5299 | if (rv < 0) { |
5300 | goto invalid_string_error; |
5301 | } |
5302 | |
5303 | PyObject *tzinfo = tzinfo_from_isoformat_results(rv, tzoffset, tzusec); |
5304 | if (tzinfo == NULL) { |
5305 | goto error; |
5306 | } |
5307 | |
5308 | PyObject *dt = new_datetime_subclass_ex(year, month, day, hour, minute, |
5309 | second, microsecond, tzinfo, cls); |
5310 | |
5311 | Py_DECREF(tzinfo); |
5312 | Py_DECREF(dtstr_clean); |
5313 | return dt; |
5314 | |
5315 | invalid_string_error: |
5316 | PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %R" , dtstr); |
5317 | |
5318 | error: |
5319 | Py_XDECREF(dtstr_clean); |
5320 | |
5321 | return NULL; |
5322 | } |
5323 | |
5324 | /* |
5325 | * Destructor. |
5326 | */ |
5327 | |
5328 | static void |
5329 | datetime_dealloc(PyDateTime_DateTime *self) |
5330 | { |
5331 | if (HASTZINFO(self)) { |
5332 | Py_XDECREF(self->tzinfo); |
5333 | } |
5334 | Py_TYPE(self)->tp_free((PyObject *)self); |
5335 | } |
5336 | |
5337 | /* |
5338 | * Indirect access to tzinfo methods. |
5339 | */ |
5340 | |
5341 | /* These are all METH_NOARGS, so don't need to check the arglist. */ |
5342 | static PyObject * |
5343 | datetime_utcoffset(PyObject *self, PyObject *unused) { |
5344 | return call_utcoffset(GET_DT_TZINFO(self), self); |
5345 | } |
5346 | |
5347 | static PyObject * |
5348 | datetime_dst(PyObject *self, PyObject *unused) { |
5349 | return call_dst(GET_DT_TZINFO(self), self); |
5350 | } |
5351 | |
5352 | static PyObject * |
5353 | datetime_tzname(PyObject *self, PyObject *unused) { |
5354 | return call_tzname(GET_DT_TZINFO(self), self); |
5355 | } |
5356 | |
5357 | /* |
5358 | * datetime arithmetic. |
5359 | */ |
5360 | |
5361 | /* factor must be 1 (to add) or -1 (to subtract). The result inherits |
5362 | * the tzinfo state of date. |
5363 | */ |
5364 | static PyObject * |
5365 | add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta, |
5366 | int factor) |
5367 | { |
5368 | /* Note that the C-level additions can't overflow, because of |
5369 | * invariant bounds on the member values. |
5370 | */ |
5371 | int year = GET_YEAR(date); |
5372 | int month = GET_MONTH(date); |
5373 | int day = GET_DAY(date) + GET_TD_DAYS(delta) * factor; |
5374 | int hour = DATE_GET_HOUR(date); |
5375 | int minute = DATE_GET_MINUTE(date); |
5376 | int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta) * factor; |
5377 | int microsecond = DATE_GET_MICROSECOND(date) + |
5378 | GET_TD_MICROSECONDS(delta) * factor; |
5379 | |
5380 | assert(factor == 1 || factor == -1); |
5381 | if (normalize_datetime(&year, &month, &day, |
5382 | &hour, &minute, &second, µsecond) < 0) { |
5383 | return NULL; |
5384 | } |
5385 | |
5386 | return new_datetime_subclass_ex(year, month, day, |
5387 | hour, minute, second, microsecond, |
5388 | HASTZINFO(date) ? date->tzinfo : Py_None, |
5389 | (PyObject *)Py_TYPE(date)); |
5390 | } |
5391 | |
5392 | static PyObject * |
5393 | datetime_add(PyObject *left, PyObject *right) |
5394 | { |
5395 | if (PyDateTime_Check(left)) { |
5396 | /* datetime + ??? */ |
5397 | if (PyDelta_Check(right)) |
5398 | /* datetime + delta */ |
5399 | return add_datetime_timedelta( |
5400 | (PyDateTime_DateTime *)left, |
5401 | (PyDateTime_Delta *)right, |
5402 | 1); |
5403 | } |
5404 | else if (PyDelta_Check(left)) { |
5405 | /* delta + datetime */ |
5406 | return add_datetime_timedelta((PyDateTime_DateTime *) right, |
5407 | (PyDateTime_Delta *) left, |
5408 | 1); |
5409 | } |
5410 | Py_RETURN_NOTIMPLEMENTED; |
5411 | } |
5412 | |
5413 | static PyObject * |
5414 | datetime_subtract(PyObject *left, PyObject *right) |
5415 | { |
5416 | PyObject *result = Py_NotImplemented; |
5417 | |
5418 | if (PyDateTime_Check(left)) { |
5419 | /* datetime - ??? */ |
5420 | if (PyDateTime_Check(right)) { |
5421 | /* datetime - datetime */ |
5422 | PyObject *offset1, *offset2, *offdiff = NULL; |
5423 | int delta_d, delta_s, delta_us; |
5424 | |
5425 | if (GET_DT_TZINFO(left) == GET_DT_TZINFO(right)) { |
5426 | offset2 = offset1 = Py_None; |
5427 | Py_INCREF(offset1); |
5428 | Py_INCREF(offset2); |
5429 | } |
5430 | else { |
5431 | offset1 = datetime_utcoffset(left, NULL); |
5432 | if (offset1 == NULL) |
5433 | return NULL; |
5434 | offset2 = datetime_utcoffset(right, NULL); |
5435 | if (offset2 == NULL) { |
5436 | Py_DECREF(offset1); |
5437 | return NULL; |
5438 | } |
5439 | if ((offset1 != Py_None) != (offset2 != Py_None)) { |
5440 | PyErr_SetString(PyExc_TypeError, |
5441 | "can't subtract offset-naive and " |
5442 | "offset-aware datetimes" ); |
5443 | Py_DECREF(offset1); |
5444 | Py_DECREF(offset2); |
5445 | return NULL; |
5446 | } |
5447 | } |
5448 | if ((offset1 != offset2) && |
5449 | delta_cmp(offset1, offset2) != 0) { |
5450 | offdiff = delta_subtract(offset1, offset2); |
5451 | if (offdiff == NULL) { |
5452 | Py_DECREF(offset1); |
5453 | Py_DECREF(offset2); |
5454 | return NULL; |
5455 | } |
5456 | } |
5457 | Py_DECREF(offset1); |
5458 | Py_DECREF(offset2); |
5459 | delta_d = ymd_to_ord(GET_YEAR(left), |
5460 | GET_MONTH(left), |
5461 | GET_DAY(left)) - |
5462 | ymd_to_ord(GET_YEAR(right), |
5463 | GET_MONTH(right), |
5464 | GET_DAY(right)); |
5465 | /* These can't overflow, since the values are |
5466 | * normalized. At most this gives the number of |
5467 | * seconds in one day. |
5468 | */ |
5469 | delta_s = (DATE_GET_HOUR(left) - |
5470 | DATE_GET_HOUR(right)) * 3600 + |
5471 | (DATE_GET_MINUTE(left) - |
5472 | DATE_GET_MINUTE(right)) * 60 + |
5473 | (DATE_GET_SECOND(left) - |
5474 | DATE_GET_SECOND(right)); |
5475 | delta_us = DATE_GET_MICROSECOND(left) - |
5476 | DATE_GET_MICROSECOND(right); |
5477 | result = new_delta(delta_d, delta_s, delta_us, 1); |
5478 | if (result == NULL) |
5479 | return NULL; |
5480 | |
5481 | if (offdiff != NULL) { |
5482 | Py_SETREF(result, delta_subtract(result, offdiff)); |
5483 | Py_DECREF(offdiff); |
5484 | } |
5485 | } |
5486 | else if (PyDelta_Check(right)) { |
5487 | /* datetime - delta */ |
5488 | result = add_datetime_timedelta( |
5489 | (PyDateTime_DateTime *)left, |
5490 | (PyDateTime_Delta *)right, |
5491 | -1); |
5492 | } |
5493 | } |
5494 | |
5495 | if (result == Py_NotImplemented) |
5496 | Py_INCREF(result); |
5497 | return result; |
5498 | } |
5499 | |
5500 | /* Various ways to turn a datetime into a string. */ |
5501 | |
5502 | static PyObject * |
5503 | datetime_repr(PyDateTime_DateTime *self) |
5504 | { |
5505 | const char *type_name = Py_TYPE(self)->tp_name; |
5506 | PyObject *baserepr; |
5507 | |
5508 | if (DATE_GET_MICROSECOND(self)) { |
5509 | baserepr = PyUnicode_FromFormat( |
5510 | "%s(%d, %d, %d, %d, %d, %d, %d)" , |
5511 | type_name, |
5512 | GET_YEAR(self), GET_MONTH(self), GET_DAY(self), |
5513 | DATE_GET_HOUR(self), DATE_GET_MINUTE(self), |
5514 | DATE_GET_SECOND(self), |
5515 | DATE_GET_MICROSECOND(self)); |
5516 | } |
5517 | else if (DATE_GET_SECOND(self)) { |
5518 | baserepr = PyUnicode_FromFormat( |
5519 | "%s(%d, %d, %d, %d, %d, %d)" , |
5520 | type_name, |
5521 | GET_YEAR(self), GET_MONTH(self), GET_DAY(self), |
5522 | DATE_GET_HOUR(self), DATE_GET_MINUTE(self), |
5523 | DATE_GET_SECOND(self)); |
5524 | } |
5525 | else { |
5526 | baserepr = PyUnicode_FromFormat( |
5527 | "%s(%d, %d, %d, %d, %d)" , |
5528 | type_name, |
5529 | GET_YEAR(self), GET_MONTH(self), GET_DAY(self), |
5530 | DATE_GET_HOUR(self), DATE_GET_MINUTE(self)); |
5531 | } |
5532 | if (baserepr != NULL && DATE_GET_FOLD(self) != 0) |
5533 | baserepr = append_keyword_fold(baserepr, DATE_GET_FOLD(self)); |
5534 | if (baserepr == NULL || ! HASTZINFO(self)) |
5535 | return baserepr; |
5536 | return append_keyword_tzinfo(baserepr, self->tzinfo); |
5537 | } |
5538 | |
5539 | static PyObject * |
5540 | datetime_str(PyDateTime_DateTime *self) |
5541 | { |
5542 | return _PyObject_CallMethodId((PyObject *)self, &PyId_isoformat, "s" , " " ); |
5543 | } |
5544 | |
5545 | static PyObject * |
5546 | datetime_isoformat(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) |
5547 | { |
5548 | int sep = 'T'; |
5549 | char *timespec = NULL; |
5550 | static char *keywords[] = {"sep" , "timespec" , NULL}; |
5551 | char buffer[100]; |
5552 | PyObject *result = NULL; |
5553 | int us = DATE_GET_MICROSECOND(self); |
5554 | static const char *specs[][2] = { |
5555 | {"hours" , "%04d-%02d-%02d%c%02d" }, |
5556 | {"minutes" , "%04d-%02d-%02d%c%02d:%02d" }, |
5557 | {"seconds" , "%04d-%02d-%02d%c%02d:%02d:%02d" }, |
5558 | {"milliseconds" , "%04d-%02d-%02d%c%02d:%02d:%02d.%03d" }, |
5559 | {"microseconds" , "%04d-%02d-%02d%c%02d:%02d:%02d.%06d" }, |
5560 | }; |
5561 | size_t given_spec; |
5562 | |
5563 | if (!PyArg_ParseTupleAndKeywords(args, kw, "|Cs:isoformat" , keywords, &sep, ×pec)) |
5564 | return NULL; |
5565 | |
5566 | if (timespec == NULL || strcmp(timespec, "auto" ) == 0) { |
5567 | if (us == 0) { |
5568 | /* seconds */ |
5569 | given_spec = 2; |
5570 | } |
5571 | else { |
5572 | /* microseconds */ |
5573 | given_spec = 4; |
5574 | } |
5575 | } |
5576 | else { |
5577 | for (given_spec = 0; given_spec < Py_ARRAY_LENGTH(specs); given_spec++) { |
5578 | if (strcmp(timespec, specs[given_spec][0]) == 0) { |
5579 | if (given_spec == 3) { |
5580 | us = us / 1000; |
5581 | } |
5582 | break; |
5583 | } |
5584 | } |
5585 | } |
5586 | |
5587 | if (given_spec == Py_ARRAY_LENGTH(specs)) { |
5588 | PyErr_Format(PyExc_ValueError, "Unknown timespec value" ); |
5589 | return NULL; |
5590 | } |
5591 | else { |
5592 | result = PyUnicode_FromFormat(specs[given_spec][1], |
5593 | GET_YEAR(self), GET_MONTH(self), |
5594 | GET_DAY(self), (int)sep, |
5595 | DATE_GET_HOUR(self), DATE_GET_MINUTE(self), |
5596 | DATE_GET_SECOND(self), us); |
5597 | } |
5598 | |
5599 | if (!result || !HASTZINFO(self)) |
5600 | return result; |
5601 | |
5602 | /* We need to append the UTC offset. */ |
5603 | if (format_utcoffset(buffer, sizeof(buffer), ":" , self->tzinfo, |
5604 | (PyObject *)self) < 0) { |
5605 | Py_DECREF(result); |
5606 | return NULL; |
5607 | } |
5608 | PyUnicode_AppendAndDel(&result, PyUnicode_FromString(buffer)); |
5609 | return result; |
5610 | } |
5611 | |
5612 | static PyObject * |
5613 | datetime_ctime(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) |
5614 | { |
5615 | return format_ctime((PyDateTime_Date *)self, |
5616 | DATE_GET_HOUR(self), |
5617 | DATE_GET_MINUTE(self), |
5618 | DATE_GET_SECOND(self)); |
5619 | } |
5620 | |
5621 | /* Miscellaneous methods. */ |
5622 | |
5623 | static PyObject * |
5624 | flip_fold(PyObject *dt) |
5625 | { |
5626 | return new_datetime_ex2(GET_YEAR(dt), |
5627 | GET_MONTH(dt), |
5628 | GET_DAY(dt), |
5629 | DATE_GET_HOUR(dt), |
5630 | DATE_GET_MINUTE(dt), |
5631 | DATE_GET_SECOND(dt), |
5632 | DATE_GET_MICROSECOND(dt), |
5633 | HASTZINFO(dt) ? |
5634 | ((PyDateTime_DateTime *)dt)->tzinfo : Py_None, |
5635 | !DATE_GET_FOLD(dt), |
5636 | Py_TYPE(dt)); |
5637 | } |
5638 | |
5639 | static PyObject * |
5640 | get_flip_fold_offset(PyObject *dt) |
5641 | { |
5642 | PyObject *result, *flip_dt; |
5643 | |
5644 | flip_dt = flip_fold(dt); |
5645 | if (flip_dt == NULL) |
5646 | return NULL; |
5647 | result = datetime_utcoffset(flip_dt, NULL); |
5648 | Py_DECREF(flip_dt); |
5649 | return result; |
5650 | } |
5651 | |
5652 | /* PEP 495 exception: Whenever one or both of the operands in |
5653 | * inter-zone comparison is such that its utcoffset() depends |
5654 | * on the value of its fold attribute, the result is False. |
5655 | * |
5656 | * Return 1 if exception applies, 0 if not, and -1 on error. |
5657 | */ |
5658 | static int |
5659 | pep495_eq_exception(PyObject *self, PyObject *other, |
5660 | PyObject *offset_self, PyObject *offset_other) |
5661 | { |
5662 | int result = 0; |
5663 | PyObject *flip_offset; |
5664 | |
5665 | flip_offset = get_flip_fold_offset(self); |
5666 | if (flip_offset == NULL) |
5667 | return -1; |
5668 | if (flip_offset != offset_self && |
5669 | delta_cmp(flip_offset, offset_self)) |
5670 | { |
5671 | result = 1; |
5672 | goto done; |
5673 | } |
5674 | Py_DECREF(flip_offset); |
5675 | |
5676 | flip_offset = get_flip_fold_offset(other); |
5677 | if (flip_offset == NULL) |
5678 | return -1; |
5679 | if (flip_offset != offset_other && |
5680 | delta_cmp(flip_offset, offset_other)) |
5681 | result = 1; |
5682 | done: |
5683 | Py_DECREF(flip_offset); |
5684 | return result; |
5685 | } |
5686 | |
5687 | static PyObject * |
5688 | datetime_richcompare(PyObject *self, PyObject *other, int op) |
5689 | { |
5690 | PyObject *result = NULL; |
5691 | PyObject *offset1, *offset2; |
5692 | int diff; |
5693 | |
5694 | if (! PyDateTime_Check(other)) { |
5695 | if (PyDate_Check(other)) { |
5696 | /* Prevent invocation of date_richcompare. We want to |
5697 | return NotImplemented here to give the other object |
5698 | a chance. But since DateTime is a subclass of |
5699 | Date, if the other object is a Date, it would |
5700 | compute an ordering based on the date part alone, |
5701 | and we don't want that. So force unequal or |
5702 | uncomparable here in that case. */ |
5703 | if (op == Py_EQ) |
5704 | Py_RETURN_FALSE; |
5705 | if (op == Py_NE) |
5706 | Py_RETURN_TRUE; |
5707 | return cmperror(self, other); |
5708 | } |
5709 | Py_RETURN_NOTIMPLEMENTED; |
5710 | } |
5711 | |
5712 | if (GET_DT_TZINFO(self) == GET_DT_TZINFO(other)) { |
5713 | diff = memcmp(((PyDateTime_DateTime *)self)->data, |
5714 | ((PyDateTime_DateTime *)other)->data, |
5715 | _PyDateTime_DATETIME_DATASIZE); |
5716 | return diff_to_bool(diff, op); |
5717 | } |
5718 | offset1 = datetime_utcoffset(self, NULL); |
5719 | if (offset1 == NULL) |
5720 | return NULL; |
5721 | offset2 = datetime_utcoffset(other, NULL); |
5722 | if (offset2 == NULL) |
5723 | goto done; |
5724 | /* If they're both naive, or both aware and have the same offsets, |
5725 | * we get off cheap. Note that if they're both naive, offset1 == |
5726 | * offset2 == Py_None at this point. |
5727 | */ |
5728 | if ((offset1 == offset2) || |
5729 | (PyDelta_Check(offset1) && PyDelta_Check(offset2) && |
5730 | delta_cmp(offset1, offset2) == 0)) { |
5731 | diff = memcmp(((PyDateTime_DateTime *)self)->data, |
5732 | ((PyDateTime_DateTime *)other)->data, |
5733 | _PyDateTime_DATETIME_DATASIZE); |
5734 | if ((op == Py_EQ || op == Py_NE) && diff == 0) { |
5735 | int ex = pep495_eq_exception(self, other, offset1, offset2); |
5736 | if (ex == -1) |
5737 | goto done; |
5738 | if (ex) |
5739 | diff = 1; |
5740 | } |
5741 | result = diff_to_bool(diff, op); |
5742 | } |
5743 | else if (offset1 != Py_None && offset2 != Py_None) { |
5744 | PyDateTime_Delta *delta; |
5745 | |
5746 | assert(offset1 != offset2); /* else last "if" handled it */ |
5747 | delta = (PyDateTime_Delta *)datetime_subtract((PyObject *)self, |
5748 | other); |
5749 | if (delta == NULL) |
5750 | goto done; |
5751 | diff = GET_TD_DAYS(delta); |
5752 | if (diff == 0) |
5753 | diff = GET_TD_SECONDS(delta) | |
5754 | GET_TD_MICROSECONDS(delta); |
5755 | Py_DECREF(delta); |
5756 | if ((op == Py_EQ || op == Py_NE) && diff == 0) { |
5757 | int ex = pep495_eq_exception(self, other, offset1, offset2); |
5758 | if (ex == -1) |
5759 | goto done; |
5760 | if (ex) |
5761 | diff = 1; |
5762 | } |
5763 | result = diff_to_bool(diff, op); |
5764 | } |
5765 | else if (op == Py_EQ) { |
5766 | result = Py_False; |
5767 | Py_INCREF(result); |
5768 | } |
5769 | else if (op == Py_NE) { |
5770 | result = Py_True; |
5771 | Py_INCREF(result); |
5772 | } |
5773 | else { |
5774 | PyErr_SetString(PyExc_TypeError, |
5775 | "can't compare offset-naive and " |
5776 | "offset-aware datetimes" ); |
5777 | } |
5778 | done: |
5779 | Py_DECREF(offset1); |
5780 | Py_XDECREF(offset2); |
5781 | return result; |
5782 | } |
5783 | |
5784 | static Py_hash_t |
5785 | datetime_hash(PyDateTime_DateTime *self) |
5786 | { |
5787 | if (self->hashcode == -1) { |
5788 | PyObject *offset, *self0; |
5789 | if (DATE_GET_FOLD(self)) { |
5790 | self0 = new_datetime_ex2(GET_YEAR(self), |
5791 | GET_MONTH(self), |
5792 | GET_DAY(self), |
5793 | DATE_GET_HOUR(self), |
5794 | DATE_GET_MINUTE(self), |
5795 | DATE_GET_SECOND(self), |
5796 | DATE_GET_MICROSECOND(self), |
5797 | HASTZINFO(self) ? self->tzinfo : Py_None, |
5798 | 0, Py_TYPE(self)); |
5799 | if (self0 == NULL) |
5800 | return -1; |
5801 | } |
5802 | else { |
5803 | self0 = (PyObject *)self; |
5804 | Py_INCREF(self0); |
5805 | } |
5806 | offset = datetime_utcoffset(self0, NULL); |
5807 | Py_DECREF(self0); |
5808 | |
5809 | if (offset == NULL) |
5810 | return -1; |
5811 | |
5812 | /* Reduce this to a hash of another object. */ |
5813 | if (offset == Py_None) |
5814 | self->hashcode = generic_hash( |
5815 | (unsigned char *)self->data, _PyDateTime_DATETIME_DATASIZE); |
5816 | else { |
5817 | PyObject *temp1, *temp2; |
5818 | int days, seconds; |
5819 | |
5820 | assert(HASTZINFO(self)); |
5821 | days = ymd_to_ord(GET_YEAR(self), |
5822 | GET_MONTH(self), |
5823 | GET_DAY(self)); |
5824 | seconds = DATE_GET_HOUR(self) * 3600 + |
5825 | DATE_GET_MINUTE(self) * 60 + |
5826 | DATE_GET_SECOND(self); |
5827 | temp1 = new_delta(days, seconds, |
5828 | DATE_GET_MICROSECOND(self), |
5829 | 1); |
5830 | if (temp1 == NULL) { |
5831 | Py_DECREF(offset); |
5832 | return -1; |
5833 | } |
5834 | temp2 = delta_subtract(temp1, offset); |
5835 | Py_DECREF(temp1); |
5836 | if (temp2 == NULL) { |
5837 | Py_DECREF(offset); |
5838 | return -1; |
5839 | } |
5840 | self->hashcode = PyObject_Hash(temp2); |
5841 | Py_DECREF(temp2); |
5842 | } |
5843 | Py_DECREF(offset); |
5844 | } |
5845 | return self->hashcode; |
5846 | } |
5847 | |
5848 | static PyObject * |
5849 | datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) |
5850 | { |
5851 | PyObject *clone; |
5852 | PyObject *tuple; |
5853 | int y = GET_YEAR(self); |
5854 | int m = GET_MONTH(self); |
5855 | int d = GET_DAY(self); |
5856 | int hh = DATE_GET_HOUR(self); |
5857 | int mm = DATE_GET_MINUTE(self); |
5858 | int ss = DATE_GET_SECOND(self); |
5859 | int us = DATE_GET_MICROSECOND(self); |
5860 | PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None; |
5861 | int fold = DATE_GET_FOLD(self); |
5862 | |
5863 | if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO$i:replace" , |
5864 | datetime_kws, |
5865 | &y, &m, &d, &hh, &mm, &ss, &us, |
5866 | &tzinfo, &fold)) |
5867 | return NULL; |
5868 | if (fold != 0 && fold != 1) { |
5869 | PyErr_SetString(PyExc_ValueError, |
5870 | "fold must be either 0 or 1" ); |
5871 | return NULL; |
5872 | } |
5873 | tuple = Py_BuildValue("iiiiiiiO" , y, m, d, hh, mm, ss, us, tzinfo); |
5874 | if (tuple == NULL) |
5875 | return NULL; |
5876 | clone = datetime_new(Py_TYPE(self), tuple, NULL); |
5877 | if (clone != NULL) { |
5878 | DATE_SET_FOLD(clone, fold); |
5879 | } |
5880 | Py_DECREF(tuple); |
5881 | return clone; |
5882 | } |
5883 | |
5884 | static PyObject * |
5885 | local_timezone_from_timestamp(time_t timestamp) |
5886 | { |
5887 | PyObject *result = NULL; |
5888 | PyObject *delta; |
5889 | struct tm local_time_tm; |
5890 | PyObject *nameo = NULL; |
5891 | const char *zone = NULL; |
5892 | |
5893 | if (_PyTime_localtime(timestamp, &local_time_tm) != 0) |
5894 | return NULL; |
5895 | #ifdef HAVE_STRUCT_TM_TM_ZONE |
5896 | zone = local_time_tm.tm_zone; |
5897 | delta = new_delta(0, local_time_tm.tm_gmtoff, 0, 1); |
5898 | #else /* HAVE_STRUCT_TM_TM_ZONE */ |
5899 | { |
5900 | PyObject *local_time, *utc_time; |
5901 | struct tm utc_time_tm; |
5902 | char buf[100]; |
5903 | strftime(buf, sizeof(buf), "%Z" , &local_time_tm); |
5904 | zone = buf; |
5905 | local_time = new_datetime(local_time_tm.tm_year + 1900, |
5906 | local_time_tm.tm_mon + 1, |
5907 | local_time_tm.tm_mday, |
5908 | local_time_tm.tm_hour, |
5909 | local_time_tm.tm_min, |
5910 | local_time_tm.tm_sec, 0, Py_None, 0); |
5911 | if (local_time == NULL) { |
5912 | return NULL; |
5913 | } |
5914 | if (_PyTime_gmtime(timestamp, &utc_time_tm) != 0) |
5915 | return NULL; |
5916 | utc_time = new_datetime(utc_time_tm.tm_year + 1900, |
5917 | utc_time_tm.tm_mon + 1, |
5918 | utc_time_tm.tm_mday, |
5919 | utc_time_tm.tm_hour, |
5920 | utc_time_tm.tm_min, |
5921 | utc_time_tm.tm_sec, 0, Py_None, 0); |
5922 | if (utc_time == NULL) { |
5923 | Py_DECREF(local_time); |
5924 | return NULL; |
5925 | } |
5926 | delta = datetime_subtract(local_time, utc_time); |
5927 | Py_DECREF(local_time); |
5928 | Py_DECREF(utc_time); |
5929 | } |
5930 | #endif /* HAVE_STRUCT_TM_TM_ZONE */ |
5931 | if (delta == NULL) { |
5932 | return NULL; |
5933 | } |
5934 | if (zone != NULL) { |
5935 | nameo = PyUnicode_DecodeLocale(zone, "surrogateescape" ); |
5936 | if (nameo == NULL) |
5937 | goto error; |
5938 | } |
5939 | result = new_timezone(delta, nameo); |
5940 | Py_XDECREF(nameo); |
5941 | error: |
5942 | Py_DECREF(delta); |
5943 | return result; |
5944 | } |
5945 | |
5946 | static PyObject * |
5947 | local_timezone(PyDateTime_DateTime *utc_time) |
5948 | { |
5949 | time_t timestamp; |
5950 | PyObject *delta; |
5951 | PyObject *one_second; |
5952 | PyObject *seconds; |
5953 | |
5954 | delta = datetime_subtract((PyObject *)utc_time, PyDateTime_Epoch); |
5955 | if (delta == NULL) |
5956 | return NULL; |
5957 | one_second = new_delta(0, 1, 0, 0); |
5958 | if (one_second == NULL) { |
5959 | Py_DECREF(delta); |
5960 | return NULL; |
5961 | } |
5962 | seconds = divide_timedelta_timedelta((PyDateTime_Delta *)delta, |
5963 | (PyDateTime_Delta *)one_second); |
5964 | Py_DECREF(one_second); |
5965 | Py_DECREF(delta); |
5966 | if (seconds == NULL) |
5967 | return NULL; |
5968 | timestamp = _PyLong_AsTime_t(seconds); |
5969 | Py_DECREF(seconds); |
5970 | if (timestamp == -1 && PyErr_Occurred()) |
5971 | return NULL; |
5972 | return local_timezone_from_timestamp(timestamp); |
5973 | } |
5974 | |
5975 | static long long |
5976 | local_to_seconds(int year, int month, int day, |
5977 | int hour, int minute, int second, int fold); |
5978 | |
5979 | static PyObject * |
5980 | local_timezone_from_local(PyDateTime_DateTime *local_dt) |
5981 | { |
5982 | long long seconds; |
5983 | time_t timestamp; |
5984 | seconds = local_to_seconds(GET_YEAR(local_dt), |
5985 | GET_MONTH(local_dt), |
5986 | GET_DAY(local_dt), |
5987 | DATE_GET_HOUR(local_dt), |
5988 | DATE_GET_MINUTE(local_dt), |
5989 | DATE_GET_SECOND(local_dt), |
5990 | DATE_GET_FOLD(local_dt)); |
5991 | if (seconds == -1) |
5992 | return NULL; |
5993 | /* XXX: add bounds check */ |
5994 | timestamp = seconds - epoch; |
5995 | return local_timezone_from_timestamp(timestamp); |
5996 | } |
5997 | |
5998 | static PyDateTime_DateTime * |
5999 | datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) |
6000 | { |
6001 | PyDateTime_DateTime *result; |
6002 | PyObject *offset; |
6003 | PyObject *temp; |
6004 | PyObject *self_tzinfo; |
6005 | PyObject *tzinfo = Py_None; |
6006 | static char *keywords[] = {"tz" , NULL}; |
6007 | |
6008 | if (! PyArg_ParseTupleAndKeywords(args, kw, "|O:astimezone" , keywords, |
6009 | &tzinfo)) |
6010 | return NULL; |
6011 | |
6012 | if (check_tzinfo_subclass(tzinfo) == -1) |
6013 | return NULL; |
6014 | |
6015 | if (!HASTZINFO(self) || self->tzinfo == Py_None) { |
6016 | naive: |
6017 | self_tzinfo = local_timezone_from_local(self); |
6018 | if (self_tzinfo == NULL) |
6019 | return NULL; |
6020 | } else { |
6021 | self_tzinfo = self->tzinfo; |
6022 | Py_INCREF(self_tzinfo); |
6023 | } |
6024 | |
6025 | /* Conversion to self's own time zone is a NOP. */ |
6026 | if (self_tzinfo == tzinfo) { |
6027 | Py_DECREF(self_tzinfo); |
6028 | Py_INCREF(self); |
6029 | return self; |
6030 | } |
6031 | |
6032 | /* Convert self to UTC. */ |
6033 | offset = call_utcoffset(self_tzinfo, (PyObject *)self); |
6034 | Py_DECREF(self_tzinfo); |
6035 | if (offset == NULL) |
6036 | return NULL; |
6037 | else if(offset == Py_None) { |
6038 | Py_DECREF(offset); |
6039 | goto naive; |
6040 | } |
6041 | else if (!PyDelta_Check(offset)) { |
6042 | Py_DECREF(offset); |
6043 | PyErr_Format(PyExc_TypeError, "utcoffset() returned %.200s," |
6044 | " expected timedelta or None" , Py_TYPE(offset)->tp_name); |
6045 | return NULL; |
6046 | } |
6047 | /* result = self - offset */ |
6048 | result = (PyDateTime_DateTime *)add_datetime_timedelta(self, |
6049 | (PyDateTime_Delta *)offset, -1); |
6050 | Py_DECREF(offset); |
6051 | if (result == NULL) |
6052 | return NULL; |
6053 | |
6054 | /* Make sure result is aware and UTC. */ |
6055 | if (!HASTZINFO(result)) { |
6056 | temp = (PyObject *)result; |
6057 | result = (PyDateTime_DateTime *) |
6058 | new_datetime_ex2(GET_YEAR(result), |
6059 | GET_MONTH(result), |
6060 | GET_DAY(result), |
6061 | DATE_GET_HOUR(result), |
6062 | DATE_GET_MINUTE(result), |
6063 | DATE_GET_SECOND(result), |
6064 | DATE_GET_MICROSECOND(result), |
6065 | PyDateTime_TimeZone_UTC, |
6066 | DATE_GET_FOLD(result), |
6067 | Py_TYPE(result)); |
6068 | Py_DECREF(temp); |
6069 | if (result == NULL) |
6070 | return NULL; |
6071 | } |
6072 | else { |
6073 | /* Result is already aware - just replace tzinfo. */ |
6074 | temp = result->tzinfo; |
6075 | result->tzinfo = PyDateTime_TimeZone_UTC; |
6076 | Py_INCREF(result->tzinfo); |
6077 | Py_DECREF(temp); |
6078 | } |
6079 | |
6080 | /* Attach new tzinfo and let fromutc() do the rest. */ |
6081 | temp = result->tzinfo; |
6082 | if (tzinfo == Py_None) { |
6083 | tzinfo = local_timezone(result); |
6084 | if (tzinfo == NULL) { |
6085 | Py_DECREF(result); |
6086 | return NULL; |
6087 | } |
6088 | } |
6089 | else |
6090 | Py_INCREF(tzinfo); |
6091 | result->tzinfo = tzinfo; |
6092 | Py_DECREF(temp); |
6093 | |
6094 | temp = (PyObject *)result; |
6095 | result = (PyDateTime_DateTime *) |
6096 | _PyObject_CallMethodIdOneArg(tzinfo, &PyId_fromutc, temp); |
6097 | Py_DECREF(temp); |
6098 | |
6099 | return result; |
6100 | } |
6101 | |
6102 | static PyObject * |
6103 | datetime_timetuple(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) |
6104 | { |
6105 | int dstflag = -1; |
6106 | |
6107 | if (HASTZINFO(self) && self->tzinfo != Py_None) { |
6108 | PyObject * dst; |
6109 | |
6110 | dst = call_dst(self->tzinfo, (PyObject *)self); |
6111 | if (dst == NULL) |
6112 | return NULL; |
6113 | |
6114 | if (dst != Py_None) |
6115 | dstflag = delta_bool((PyDateTime_Delta *)dst); |
6116 | Py_DECREF(dst); |
6117 | } |
6118 | return build_struct_time(GET_YEAR(self), |
6119 | GET_MONTH(self), |
6120 | GET_DAY(self), |
6121 | DATE_GET_HOUR(self), |
6122 | DATE_GET_MINUTE(self), |
6123 | DATE_GET_SECOND(self), |
6124 | dstflag); |
6125 | } |
6126 | |
6127 | static long long |
6128 | local_to_seconds(int year, int month, int day, |
6129 | int hour, int minute, int second, int fold) |
6130 | { |
6131 | long long t, a, b, u1, u2, t1, t2, lt; |
6132 | t = utc_to_seconds(year, month, day, hour, minute, second); |
6133 | /* Our goal is to solve t = local(u) for u. */ |
6134 | lt = local(t); |
6135 | if (lt == -1) |
6136 | return -1; |
6137 | a = lt - t; |
6138 | u1 = t - a; |
6139 | t1 = local(u1); |
6140 | if (t1 == -1) |
6141 | return -1; |
6142 | if (t1 == t) { |
6143 | /* We found one solution, but it may not be the one we need. |
6144 | * Look for an earlier solution (if `fold` is 0), or a |
6145 | * later one (if `fold` is 1). */ |
6146 | if (fold) |
6147 | u2 = u1 + max_fold_seconds; |
6148 | else |
6149 | u2 = u1 - max_fold_seconds; |
6150 | lt = local(u2); |
6151 | if (lt == -1) |
6152 | return -1; |
6153 | b = lt - u2; |
6154 | if (a == b) |
6155 | return u1; |
6156 | } |
6157 | else { |
6158 | b = t1 - u1; |
6159 | assert(a != b); |
6160 | } |
6161 | u2 = t - b; |
6162 | t2 = local(u2); |
6163 | if (t2 == -1) |
6164 | return -1; |
6165 | if (t2 == t) |
6166 | return u2; |
6167 | if (t1 == t) |
6168 | return u1; |
6169 | /* We have found both offsets a and b, but neither t - a nor t - b is |
6170 | * a solution. This means t is in the gap. */ |
6171 | return fold?Py_MIN(u1, u2):Py_MAX(u1, u2); |
6172 | } |
6173 | |
6174 | /* date(1970,1,1).toordinal() == 719163 */ |
6175 | #define EPOCH_SECONDS (719163LL * 24 * 60 * 60) |
6176 | |
6177 | static PyObject * |
6178 | datetime_timestamp(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) |
6179 | { |
6180 | PyObject *result; |
6181 | |
6182 | if (HASTZINFO(self) && self->tzinfo != Py_None) { |
6183 | PyObject *delta; |
6184 | delta = datetime_subtract((PyObject *)self, PyDateTime_Epoch); |
6185 | if (delta == NULL) |
6186 | return NULL; |
6187 | result = delta_total_seconds(delta, NULL); |
6188 | Py_DECREF(delta); |
6189 | } |
6190 | else { |
6191 | long long seconds; |
6192 | seconds = local_to_seconds(GET_YEAR(self), |
6193 | GET_MONTH(self), |
6194 | GET_DAY(self), |
6195 | DATE_GET_HOUR(self), |
6196 | DATE_GET_MINUTE(self), |
6197 | DATE_GET_SECOND(self), |
6198 | DATE_GET_FOLD(self)); |
6199 | if (seconds == -1) |
6200 | return NULL; |
6201 | result = PyFloat_FromDouble(seconds - EPOCH_SECONDS + |
6202 | DATE_GET_MICROSECOND(self) / 1e6); |
6203 | } |
6204 | return result; |
6205 | } |
6206 | |
6207 | static PyObject * |
6208 | datetime_getdate(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) |
6209 | { |
6210 | return new_date(GET_YEAR(self), |
6211 | GET_MONTH(self), |
6212 | GET_DAY(self)); |
6213 | } |
6214 | |
6215 | static PyObject * |
6216 | datetime_gettime(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) |
6217 | { |
6218 | return new_time(DATE_GET_HOUR(self), |
6219 | DATE_GET_MINUTE(self), |
6220 | DATE_GET_SECOND(self), |
6221 | DATE_GET_MICROSECOND(self), |
6222 | Py_None, |
6223 | DATE_GET_FOLD(self)); |
6224 | } |
6225 | |
6226 | static PyObject * |
6227 | datetime_gettimetz(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) |
6228 | { |
6229 | return new_time(DATE_GET_HOUR(self), |
6230 | DATE_GET_MINUTE(self), |
6231 | DATE_GET_SECOND(self), |
6232 | DATE_GET_MICROSECOND(self), |
6233 | GET_DT_TZINFO(self), |
6234 | DATE_GET_FOLD(self)); |
6235 | } |
6236 | |
6237 | static PyObject * |
6238 | datetime_utctimetuple(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) |
6239 | { |
6240 | int y, m, d, hh, mm, ss; |
6241 | PyObject *tzinfo; |
6242 | PyDateTime_DateTime *utcself; |
6243 | |
6244 | tzinfo = GET_DT_TZINFO(self); |
6245 | if (tzinfo == Py_None) { |
6246 | utcself = self; |
6247 | Py_INCREF(utcself); |
6248 | } |
6249 | else { |
6250 | PyObject *offset; |
6251 | offset = call_utcoffset(tzinfo, (PyObject *)self); |
6252 | if (offset == NULL) |
6253 | return NULL; |
6254 | if (offset == Py_None) { |
6255 | Py_DECREF(offset); |
6256 | utcself = self; |
6257 | Py_INCREF(utcself); |
6258 | } |
6259 | else { |
6260 | utcself = (PyDateTime_DateTime *)add_datetime_timedelta(self, |
6261 | (PyDateTime_Delta *)offset, -1); |
6262 | Py_DECREF(offset); |
6263 | if (utcself == NULL) |
6264 | return NULL; |
6265 | } |
6266 | } |
6267 | y = GET_YEAR(utcself); |
6268 | m = GET_MONTH(utcself); |
6269 | d = GET_DAY(utcself); |
6270 | hh = DATE_GET_HOUR(utcself); |
6271 | mm = DATE_GET_MINUTE(utcself); |
6272 | ss = DATE_GET_SECOND(utcself); |
6273 | |
6274 | Py_DECREF(utcself); |
6275 | return build_struct_time(y, m, d, hh, mm, ss, 0); |
6276 | } |
6277 | |
6278 | /* Pickle support, a simple use of __reduce__. */ |
6279 | |
6280 | /* Let basestate be the non-tzinfo data string. |
6281 | * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo). |
6282 | * So it's a tuple in any (non-error) case. |
6283 | * __getstate__ isn't exposed. |
6284 | */ |
6285 | static PyObject * |
6286 | datetime_getstate(PyDateTime_DateTime *self, int proto) |
6287 | { |
6288 | PyObject *basestate; |
6289 | PyObject *result = NULL; |
6290 | |
6291 | basestate = PyBytes_FromStringAndSize((char *)self->data, |
6292 | _PyDateTime_DATETIME_DATASIZE); |
6293 | if (basestate != NULL) { |
6294 | if (proto > 3 && DATE_GET_FOLD(self)) |
6295 | /* Set the first bit of the third byte */ |
6296 | PyBytes_AS_STRING(basestate)[2] |= (1 << 7); |
6297 | if (! HASTZINFO(self) || self->tzinfo == Py_None) |
6298 | result = PyTuple_Pack(1, basestate); |
6299 | else |
6300 | result = PyTuple_Pack(2, basestate, self->tzinfo); |
6301 | Py_DECREF(basestate); |
6302 | } |
6303 | return result; |
6304 | } |
6305 | |
6306 | static PyObject * |
6307 | datetime_reduce_ex(PyDateTime_DateTime *self, PyObject *args) |
6308 | { |
6309 | int proto; |
6310 | if (!PyArg_ParseTuple(args, "i:__reduce_ex__" , &proto)) |
6311 | return NULL; |
6312 | |
6313 | return Py_BuildValue("(ON)" , Py_TYPE(self), datetime_getstate(self, proto)); |
6314 | } |
6315 | |
6316 | static PyObject * |
6317 | datetime_reduce(PyDateTime_DateTime *self, PyObject *arg) |
6318 | { |
6319 | return Py_BuildValue("(ON)" , Py_TYPE(self), datetime_getstate(self, 2)); |
6320 | } |
6321 | |
6322 | static PyMethodDef datetime_methods[] = { |
6323 | |
6324 | /* Class methods: */ |
6325 | |
6326 | DATETIME_DATETIME_NOW_METHODDEF |
6327 | |
6328 | {"utcnow" , (PyCFunction)datetime_utcnow, |
6329 | METH_NOARGS | METH_CLASS, |
6330 | PyDoc_STR("Return a new datetime representing UTC day and time." )}, |
6331 | |
6332 | {"fromtimestamp" , (PyCFunction)(void(*)(void))datetime_fromtimestamp, |
6333 | METH_VARARGS | METH_KEYWORDS | METH_CLASS, |
6334 | PyDoc_STR("timestamp[, tz] -> tz's local time from POSIX timestamp." )}, |
6335 | |
6336 | {"utcfromtimestamp" , (PyCFunction)datetime_utcfromtimestamp, |
6337 | METH_VARARGS | METH_CLASS, |
6338 | PyDoc_STR("Construct a naive UTC datetime from a POSIX timestamp." )}, |
6339 | |
6340 | {"strptime" , (PyCFunction)datetime_strptime, |
6341 | METH_VARARGS | METH_CLASS, |
6342 | PyDoc_STR("string, format -> new datetime parsed from a string " |
6343 | "(like time.strptime())." )}, |
6344 | |
6345 | {"combine" , (PyCFunction)(void(*)(void))datetime_combine, |
6346 | METH_VARARGS | METH_KEYWORDS | METH_CLASS, |
6347 | PyDoc_STR("date, time -> datetime with same date and time fields" )}, |
6348 | |
6349 | {"fromisoformat" , (PyCFunction)datetime_fromisoformat, |
6350 | METH_O | METH_CLASS, |
6351 | PyDoc_STR("string -> datetime from datetime.isoformat() output" )}, |
6352 | |
6353 | /* Instance methods: */ |
6354 | |
6355 | {"date" , (PyCFunction)datetime_getdate, METH_NOARGS, |
6356 | PyDoc_STR("Return date object with same year, month and day." )}, |
6357 | |
6358 | {"time" , (PyCFunction)datetime_gettime, METH_NOARGS, |
6359 | PyDoc_STR("Return time object with same time but with tzinfo=None." )}, |
6360 | |
6361 | {"timetz" , (PyCFunction)datetime_gettimetz, METH_NOARGS, |
6362 | PyDoc_STR("Return time object with same time and tzinfo." )}, |
6363 | |
6364 | {"ctime" , (PyCFunction)datetime_ctime, METH_NOARGS, |
6365 | PyDoc_STR("Return ctime() style string." )}, |
6366 | |
6367 | {"timetuple" , (PyCFunction)datetime_timetuple, METH_NOARGS, |
6368 | PyDoc_STR("Return time tuple, compatible with time.localtime()." )}, |
6369 | |
6370 | {"timestamp" , (PyCFunction)datetime_timestamp, METH_NOARGS, |
6371 | PyDoc_STR("Return POSIX timestamp as float." )}, |
6372 | |
6373 | {"utctimetuple" , (PyCFunction)datetime_utctimetuple, METH_NOARGS, |
6374 | PyDoc_STR("Return UTC time tuple, compatible with time.localtime()." )}, |
6375 | |
6376 | {"isoformat" , (PyCFunction)(void(*)(void))datetime_isoformat, METH_VARARGS | METH_KEYWORDS, |
6377 | PyDoc_STR("[sep] -> string in ISO 8601 format, " |
6378 | "YYYY-MM-DDT[HH[:MM[:SS[.mmm[uuu]]]]][+HH:MM].\n" |
6379 | "sep is used to separate the year from the time, and " |
6380 | "defaults to 'T'.\n" |
6381 | "The optional argument timespec specifies the number " |
6382 | "of additional terms\nof the time to include. Valid " |
6383 | "options are 'auto', 'hours', 'minutes',\n'seconds', " |
6384 | "'milliseconds' and 'microseconds'.\n" )}, |
6385 | |
6386 | {"utcoffset" , (PyCFunction)datetime_utcoffset, METH_NOARGS, |
6387 | PyDoc_STR("Return self.tzinfo.utcoffset(self)." )}, |
6388 | |
6389 | {"tzname" , (PyCFunction)datetime_tzname, METH_NOARGS, |
6390 | PyDoc_STR("Return self.tzinfo.tzname(self)." )}, |
6391 | |
6392 | {"dst" , (PyCFunction)datetime_dst, METH_NOARGS, |
6393 | PyDoc_STR("Return self.tzinfo.dst(self)." )}, |
6394 | |
6395 | {"replace" , (PyCFunction)(void(*)(void))datetime_replace, METH_VARARGS | METH_KEYWORDS, |
6396 | PyDoc_STR("Return datetime with new specified fields." )}, |
6397 | |
6398 | {"astimezone" , (PyCFunction)(void(*)(void))datetime_astimezone, METH_VARARGS | METH_KEYWORDS, |
6399 | PyDoc_STR("tz -> convert to local time in new timezone tz\n" )}, |
6400 | |
6401 | {"__reduce_ex__" , (PyCFunction)datetime_reduce_ex, METH_VARARGS, |
6402 | PyDoc_STR("__reduce_ex__(proto) -> (cls, state)" )}, |
6403 | |
6404 | {"__reduce__" , (PyCFunction)datetime_reduce, METH_NOARGS, |
6405 | PyDoc_STR("__reduce__() -> (cls, state)" )}, |
6406 | |
6407 | {NULL, NULL} |
6408 | }; |
6409 | |
6410 | static const char datetime_doc[] = |
6411 | PyDoc_STR("datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])\n\ |
6412 | \n\ |
6413 | The year, month and day arguments are required. tzinfo may be None, or an\n\ |
6414 | instance of a tzinfo subclass. The remaining arguments may be ints.\n" ); |
6415 | |
6416 | static PyNumberMethods datetime_as_number = { |
6417 | datetime_add, /* nb_add */ |
6418 | datetime_subtract, /* nb_subtract */ |
6419 | 0, /* nb_multiply */ |
6420 | 0, /* nb_remainder */ |
6421 | 0, /* nb_divmod */ |
6422 | 0, /* nb_power */ |
6423 | 0, /* nb_negative */ |
6424 | 0, /* nb_positive */ |
6425 | 0, /* nb_absolute */ |
6426 | 0, /* nb_bool */ |
6427 | }; |
6428 | |
6429 | static PyTypeObject PyDateTime_DateTimeType = { |
6430 | PyVarObject_HEAD_INIT(NULL, 0) |
6431 | "datetime.datetime" , /* tp_name */ |
6432 | sizeof(PyDateTime_DateTime), /* tp_basicsize */ |
6433 | 0, /* tp_itemsize */ |
6434 | (destructor)datetime_dealloc, /* tp_dealloc */ |
6435 | 0, /* tp_vectorcall_offset */ |
6436 | 0, /* tp_getattr */ |
6437 | 0, /* tp_setattr */ |
6438 | 0, /* tp_as_async */ |
6439 | (reprfunc)datetime_repr, /* tp_repr */ |
6440 | &datetime_as_number, /* tp_as_number */ |
6441 | 0, /* tp_as_sequence */ |
6442 | 0, /* tp_as_mapping */ |
6443 | (hashfunc)datetime_hash, /* tp_hash */ |
6444 | 0, /* tp_call */ |
6445 | (reprfunc)datetime_str, /* tp_str */ |
6446 | PyObject_GenericGetAttr, /* tp_getattro */ |
6447 | 0, /* tp_setattro */ |
6448 | 0, /* tp_as_buffer */ |
6449 | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ |
6450 | datetime_doc, /* tp_doc */ |
6451 | 0, /* tp_traverse */ |
6452 | 0, /* tp_clear */ |
6453 | datetime_richcompare, /* tp_richcompare */ |
6454 | 0, /* tp_weaklistoffset */ |
6455 | 0, /* tp_iter */ |
6456 | 0, /* tp_iternext */ |
6457 | datetime_methods, /* tp_methods */ |
6458 | 0, /* tp_members */ |
6459 | datetime_getset, /* tp_getset */ |
6460 | 0, /* tp_base; filled in |
6461 | PyInit__datetime */ |
6462 | 0, /* tp_dict */ |
6463 | 0, /* tp_descr_get */ |
6464 | 0, /* tp_descr_set */ |
6465 | 0, /* tp_dictoffset */ |
6466 | 0, /* tp_init */ |
6467 | datetime_alloc, /* tp_alloc */ |
6468 | datetime_new, /* tp_new */ |
6469 | 0, /* tp_free */ |
6470 | }; |
6471 | |
6472 | /* --------------------------------------------------------------------------- |
6473 | * Module methods and initialization. |
6474 | */ |
6475 | |
6476 | static PyMethodDef module_methods[] = { |
6477 | {NULL, NULL} |
6478 | }; |
6479 | |
6480 | /* Get a new C API by calling this function. |
6481 | * Clients get at C API via PyDateTime_IMPORT, defined in datetime.h. |
6482 | */ |
6483 | static inline PyDateTime_CAPI * |
6484 | get_datetime_capi(void) |
6485 | { |
6486 | PyDateTime_CAPI *capi = PyMem_Malloc(sizeof(PyDateTime_CAPI)); |
6487 | if (capi == NULL) { |
6488 | PyErr_NoMemory(); |
6489 | return NULL; |
6490 | } |
6491 | capi->DateType = &PyDateTime_DateType; |
6492 | capi->DateTimeType = &PyDateTime_DateTimeType; |
6493 | capi->TimeType = &PyDateTime_TimeType; |
6494 | capi->DeltaType = &PyDateTime_DeltaType; |
6495 | capi->TZInfoType = &PyDateTime_TZInfoType; |
6496 | capi->Date_FromDate = new_date_ex; |
6497 | capi->DateTime_FromDateAndTime = new_datetime_ex; |
6498 | capi->Time_FromTime = new_time_ex; |
6499 | capi->Delta_FromDelta = new_delta_ex; |
6500 | capi->TimeZone_FromTimeZone = new_timezone; |
6501 | capi->DateTime_FromTimestamp = datetime_fromtimestamp; |
6502 | capi->Date_FromTimestamp = datetime_date_fromtimestamp_capi; |
6503 | capi->DateTime_FromDateAndTimeAndFold = new_datetime_ex2; |
6504 | capi->Time_FromTimeAndFold = new_time_ex2; |
6505 | // Make sure this function is called after PyDateTime_TimeZone_UTC has |
6506 | // been initialized. |
6507 | assert(PyDateTime_TimeZone_UTC != NULL); |
6508 | capi->TimeZone_UTC = PyDateTime_TimeZone_UTC; // borrowed ref |
6509 | return capi; |
6510 | } |
6511 | |
6512 | static void |
6513 | datetime_destructor(PyObject *op) |
6514 | { |
6515 | void *ptr = PyCapsule_GetPointer(op, PyDateTime_CAPSULE_NAME); |
6516 | PyMem_Free(ptr); |
6517 | } |
6518 | |
6519 | static int |
6520 | _datetime_exec(PyObject *module) |
6521 | { |
6522 | // `&...` is not a constant expression according to a strict reading |
6523 | // of C standards. Fill tp_base at run-time rather than statically. |
6524 | // See https://bugs.python.org/issue40777 |
6525 | PyDateTime_IsoCalendarDateType.tp_base = &PyTuple_Type; |
6526 | PyDateTime_TimeZoneType.tp_base = &PyDateTime_TZInfoType; |
6527 | PyDateTime_DateTimeType.tp_base = &PyDateTime_DateType; |
6528 | |
6529 | PyTypeObject *types[] = { |
6530 | &PyDateTime_DateType, |
6531 | &PyDateTime_DateTimeType, |
6532 | &PyDateTime_TimeType, |
6533 | &PyDateTime_DeltaType, |
6534 | &PyDateTime_TZInfoType, |
6535 | &PyDateTime_TimeZoneType, |
6536 | }; |
6537 | |
6538 | for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) { |
6539 | if (PyModule_AddType(module, types[i]) < 0) { |
6540 | return -1; |
6541 | } |
6542 | } |
6543 | |
6544 | if (PyType_Ready(&PyDateTime_IsoCalendarDateType) < 0) { |
6545 | return -1; |
6546 | } |
6547 | |
6548 | #define DATETIME_ADD_MACRO(dict, c, value_expr) \ |
6549 | do { \ |
6550 | PyObject *value = (value_expr); \ |
6551 | if (value == NULL) { \ |
6552 | return -1; \ |
6553 | } \ |
6554 | if (PyDict_SetItemString(dict, c, value) < 0) { \ |
6555 | Py_DECREF(value); \ |
6556 | return -1; \ |
6557 | } \ |
6558 | Py_DECREF(value); \ |
6559 | } while(0) |
6560 | |
6561 | /* timedelta values */ |
6562 | PyObject *d = PyDateTime_DeltaType.tp_dict; |
6563 | DATETIME_ADD_MACRO(d, "resolution" , new_delta(0, 0, 1, 0)); |
6564 | DATETIME_ADD_MACRO(d, "min" , new_delta(-MAX_DELTA_DAYS, 0, 0, 0)); |
6565 | DATETIME_ADD_MACRO(d, "max" , |
6566 | new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0)); |
6567 | |
6568 | /* date values */ |
6569 | d = PyDateTime_DateType.tp_dict; |
6570 | DATETIME_ADD_MACRO(d, "min" , new_date(1, 1, 1)); |
6571 | DATETIME_ADD_MACRO(d, "max" , new_date(MAXYEAR, 12, 31)); |
6572 | DATETIME_ADD_MACRO(d, "resolution" , new_delta(1, 0, 0, 0)); |
6573 | |
6574 | /* time values */ |
6575 | d = PyDateTime_TimeType.tp_dict; |
6576 | DATETIME_ADD_MACRO(d, "min" , new_time(0, 0, 0, 0, Py_None, 0)); |
6577 | DATETIME_ADD_MACRO(d, "max" , new_time(23, 59, 59, 999999, Py_None, 0)); |
6578 | DATETIME_ADD_MACRO(d, "resolution" , new_delta(0, 0, 1, 0)); |
6579 | |
6580 | /* datetime values */ |
6581 | d = PyDateTime_DateTimeType.tp_dict; |
6582 | DATETIME_ADD_MACRO(d, "min" , |
6583 | new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None, 0)); |
6584 | DATETIME_ADD_MACRO(d, "max" , new_datetime(MAXYEAR, 12, 31, 23, 59, 59, |
6585 | 999999, Py_None, 0)); |
6586 | DATETIME_ADD_MACRO(d, "resolution" , new_delta(0, 0, 1, 0)); |
6587 | |
6588 | /* timezone values */ |
6589 | d = PyDateTime_TimeZoneType.tp_dict; |
6590 | PyObject *delta = new_delta(0, 0, 0, 0); |
6591 | if (delta == NULL) { |
6592 | return -1; |
6593 | } |
6594 | |
6595 | PyObject *x = create_timezone(delta, NULL); |
6596 | Py_DECREF(delta); |
6597 | if (x == NULL) { |
6598 | return -1; |
6599 | } |
6600 | if (PyDict_SetItemString(d, "utc" , x) < 0) { |
6601 | Py_DECREF(x); |
6602 | return -1; |
6603 | } |
6604 | |
6605 | PyDateTime_TimeZone_UTC = x; |
6606 | |
6607 | /* bpo-37642: These attributes are rounded to the nearest minute for backwards |
6608 | * compatibility, even though the constructor will accept a wider range of |
6609 | * values. This may change in the future.*/ |
6610 | delta = new_delta(-1, 60, 0, 1); /* -23:59 */ |
6611 | if (delta == NULL) { |
6612 | return -1; |
6613 | } |
6614 | |
6615 | x = create_timezone(delta, NULL); |
6616 | Py_DECREF(delta); |
6617 | DATETIME_ADD_MACRO(d, "min" , x); |
6618 | |
6619 | delta = new_delta(0, (23 * 60 + 59) * 60, 0, 0); /* +23:59 */ |
6620 | if (delta == NULL) { |
6621 | return -1; |
6622 | } |
6623 | |
6624 | x = create_timezone(delta, NULL); |
6625 | Py_DECREF(delta); |
6626 | DATETIME_ADD_MACRO(d, "max" , x); |
6627 | |
6628 | /* Epoch */ |
6629 | PyDateTime_Epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0, |
6630 | PyDateTime_TimeZone_UTC, 0); |
6631 | if (PyDateTime_Epoch == NULL) { |
6632 | return -1; |
6633 | } |
6634 | |
6635 | /* module initialization */ |
6636 | if (PyModule_AddIntMacro(module, MINYEAR) < 0) { |
6637 | return -1; |
6638 | } |
6639 | if (PyModule_AddIntMacro(module, MAXYEAR) < 0) { |
6640 | return -1; |
6641 | } |
6642 | |
6643 | PyDateTime_CAPI *capi = get_datetime_capi(); |
6644 | if (capi == NULL) { |
6645 | return -1; |
6646 | } |
6647 | x = PyCapsule_New(capi, PyDateTime_CAPSULE_NAME, datetime_destructor); |
6648 | if (x == NULL) { |
6649 | PyMem_Free(capi); |
6650 | return -1; |
6651 | } |
6652 | |
6653 | if (PyModule_AddObject(module, "datetime_CAPI" , x) < 0) { |
6654 | Py_DECREF(x); |
6655 | return -1; |
6656 | } |
6657 | |
6658 | /* A 4-year cycle has an extra leap day over what we'd get from |
6659 | * pasting together 4 single years. |
6660 | */ |
6661 | Py_BUILD_ASSERT(DI4Y == 4 * 365 + 1); |
6662 | assert(DI4Y == days_before_year(4+1)); |
6663 | |
6664 | /* Similarly, a 400-year cycle has an extra leap day over what we'd |
6665 | * get from pasting together 4 100-year cycles. |
6666 | */ |
6667 | Py_BUILD_ASSERT(DI400Y == 4 * DI100Y + 1); |
6668 | assert(DI400Y == days_before_year(400+1)); |
6669 | |
6670 | /* OTOH, a 100-year cycle has one fewer leap day than we'd get from |
6671 | * pasting together 25 4-year cycles. |
6672 | */ |
6673 | Py_BUILD_ASSERT(DI100Y == 25 * DI4Y - 1); |
6674 | assert(DI100Y == days_before_year(100+1)); |
6675 | |
6676 | us_per_ms = PyLong_FromLong(1000); |
6677 | us_per_second = PyLong_FromLong(1000000); |
6678 | us_per_minute = PyLong_FromLong(60000000); |
6679 | seconds_per_day = PyLong_FromLong(24 * 3600); |
6680 | if (us_per_ms == NULL || us_per_second == NULL || |
6681 | us_per_minute == NULL || seconds_per_day == NULL) { |
6682 | return -1; |
6683 | } |
6684 | |
6685 | /* The rest are too big for 32-bit ints, but even |
6686 | * us_per_week fits in 40 bits, so doubles should be exact. |
6687 | */ |
6688 | us_per_hour = PyLong_FromDouble(3600000000.0); |
6689 | us_per_day = PyLong_FromDouble(86400000000.0); |
6690 | us_per_week = PyLong_FromDouble(604800000000.0); |
6691 | if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL) { |
6692 | return -1; |
6693 | } |
6694 | return 0; |
6695 | } |
6696 | |
6697 | static struct PyModuleDef datetimemodule = { |
6698 | PyModuleDef_HEAD_INIT, |
6699 | .m_name = "_datetime" , |
6700 | .m_doc = "Fast implementation of the datetime type." , |
6701 | .m_size = -1, |
6702 | .m_methods = module_methods, |
6703 | }; |
6704 | |
6705 | PyMODINIT_FUNC |
6706 | PyInit__datetime(void) |
6707 | { |
6708 | PyObject *mod = PyModule_Create(&datetimemodule); |
6709 | if (mod == NULL) |
6710 | return NULL; |
6711 | |
6712 | if (_datetime_exec(mod) < 0) { |
6713 | Py_DECREF(mod); |
6714 | return NULL; |
6715 | } |
6716 | |
6717 | return mod; |
6718 | } |
6719 | |
6720 | /* --------------------------------------------------------------------------- |
6721 | Some time zone algebra. For a datetime x, let |
6722 | x.n = x stripped of its timezone -- its naive time. |
6723 | x.o = x.utcoffset(), and assuming that doesn't raise an exception or |
6724 | return None |
6725 | x.d = x.dst(), and assuming that doesn't raise an exception or |
6726 | return None |
6727 | x.s = x's standard offset, x.o - x.d |
6728 | |
6729 | Now some derived rules, where k is a duration (timedelta). |
6730 | |
6731 | 1. x.o = x.s + x.d |
6732 | This follows from the definition of x.s. |
6733 | |
6734 | 2. If x and y have the same tzinfo member, x.s = y.s. |
6735 | This is actually a requirement, an assumption we need to make about |
6736 | sane tzinfo classes. |
6737 | |
6738 | 3. The naive UTC time corresponding to x is x.n - x.o. |
6739 | This is again a requirement for a sane tzinfo class. |
6740 | |
6741 | 4. (x+k).s = x.s |
6742 | This follows from #2, and that datimetimetz+timedelta preserves tzinfo. |
6743 | |
6744 | 5. (x+k).n = x.n + k |
6745 | Again follows from how arithmetic is defined. |
6746 | |
6747 | Now we can explain tz.fromutc(x). Let's assume it's an interesting case |
6748 | (meaning that the various tzinfo methods exist, and don't blow up or return |
6749 | None when called). |
6750 | |
6751 | The function wants to return a datetime y with timezone tz, equivalent to x. |
6752 | x is already in UTC. |
6753 | |
6754 | By #3, we want |
6755 | |
6756 | y.n - y.o = x.n [1] |
6757 | |
6758 | The algorithm starts by attaching tz to x.n, and calling that y. So |
6759 | x.n = y.n at the start. Then it wants to add a duration k to y, so that [1] |
6760 | becomes true; in effect, we want to solve [2] for k: |
6761 | |
6762 | (y+k).n - (y+k).o = x.n [2] |
6763 | |
6764 | By #1, this is the same as |
6765 | |
6766 | (y+k).n - ((y+k).s + (y+k).d) = x.n [3] |
6767 | |
6768 | By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start. |
6769 | Substituting that into [3], |
6770 | |
6771 | x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving |
6772 | k - (y+k).s - (y+k).d = 0; rearranging, |
6773 | k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so |
6774 | k = y.s - (y+k).d |
6775 | |
6776 | On the RHS, (y+k).d can't be computed directly, but y.s can be, and we |
6777 | approximate k by ignoring the (y+k).d term at first. Note that k can't be |
6778 | very large, since all offset-returning methods return a duration of magnitude |
6779 | less than 24 hours. For that reason, if y is firmly in std time, (y+k).d must |
6780 | be 0, so ignoring it has no consequence then. |
6781 | |
6782 | In any case, the new value is |
6783 | |
6784 | z = y + y.s [4] |
6785 | |
6786 | It's helpful to step back at look at [4] from a higher level: it's simply |
6787 | mapping from UTC to tz's standard time. |
6788 | |
6789 | At this point, if |
6790 | |
6791 | z.n - z.o = x.n [5] |
6792 | |
6793 | we have an equivalent time, and are almost done. The insecurity here is |
6794 | at the start of daylight time. Picture US Eastern for concreteness. The wall |
6795 | time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good |
6796 | sense then. The docs ask that an Eastern tzinfo class consider such a time to |
6797 | be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST |
6798 | on the day DST starts. We want to return the 1:MM EST spelling because that's |
6799 | the only spelling that makes sense on the local wall clock. |
6800 | |
6801 | In fact, if [5] holds at this point, we do have the standard-time spelling, |
6802 | but that takes a bit of proof. We first prove a stronger result. What's the |
6803 | difference between the LHS and RHS of [5]? Let |
6804 | |
6805 | diff = x.n - (z.n - z.o) [6] |
6806 | |
6807 | Now |
6808 | z.n = by [4] |
6809 | (y + y.s).n = by #5 |
6810 | y.n + y.s = since y.n = x.n |
6811 | x.n + y.s = since z and y are have the same tzinfo member, |
6812 | y.s = z.s by #2 |
6813 | x.n + z.s |
6814 | |
6815 | Plugging that back into [6] gives |
6816 | |
6817 | diff = |
6818 | x.n - ((x.n + z.s) - z.o) = expanding |
6819 | x.n - x.n - z.s + z.o = cancelling |
6820 | - z.s + z.o = by #2 |
6821 | z.d |
6822 | |
6823 | So diff = z.d. |
6824 | |
6825 | If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time |
6826 | spelling we wanted in the endcase described above. We're done. Contrarily, |
6827 | if z.d = 0, then we have a UTC equivalent, and are also done. |
6828 | |
6829 | If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to |
6830 | add to z (in effect, z is in tz's standard time, and we need to shift the |
6831 | local clock into tz's daylight time). |
6832 | |
6833 | Let |
6834 | |
6835 | z' = z + z.d = z + diff [7] |
6836 | |
6837 | and we can again ask whether |
6838 | |
6839 | z'.n - z'.o = x.n [8] |
6840 | |
6841 | If so, we're done. If not, the tzinfo class is insane, according to the |
6842 | assumptions we've made. This also requires a bit of proof. As before, let's |
6843 | compute the difference between the LHS and RHS of [8] (and skipping some of |
6844 | the justifications for the kinds of substitutions we've done several times |
6845 | already): |
6846 | |
6847 | diff' = x.n - (z'.n - z'.o) = replacing z'.n via [7] |
6848 | x.n - (z.n + diff - z'.o) = replacing diff via [6] |
6849 | x.n - (z.n + x.n - (z.n - z.o) - z'.o) = |
6850 | x.n - z.n - x.n + z.n - z.o + z'.o = cancel x.n |
6851 | - z.n + z.n - z.o + z'.o = cancel z.n |
6852 | - z.o + z'.o = #1 twice |
6853 | -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo |
6854 | z'.d - z.d |
6855 | |
6856 | So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal, |
6857 | we've found the UTC-equivalent so are done. In fact, we stop with [7] and |
6858 | return z', not bothering to compute z'.d. |
6859 | |
6860 | How could z.d and z'd differ? z' = z + z.d [7], so merely moving z' by |
6861 | a dst() offset, and starting *from* a time already in DST (we know z.d != 0), |
6862 | would have to change the result dst() returns: we start in DST, and moving |
6863 | a little further into it takes us out of DST. |
6864 | |
6865 | There isn't a sane case where this can happen. The closest it gets is at |
6866 | the end of DST, where there's an hour in UTC with no spelling in a hybrid |
6867 | tzinfo class. In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT. During |
6868 | that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM |
6869 | UTC) because the docs insist on that, but 0:MM is taken as being in daylight |
6870 | time (4:MM UTC). There is no local time mapping to 5:MM UTC. The local |
6871 | clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in |
6872 | standard time. Since that's what the local clock *does*, we want to map both |
6873 | UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous |
6874 | in local time, but so it goes -- it's the way the local clock works. |
6875 | |
6876 | When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0, |
6877 | so z=0:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going. |
6878 | z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8] |
6879 | (correctly) concludes that z' is not UTC-equivalent to x. |
6880 | |
6881 | Because we know z.d said z was in daylight time (else [5] would have held and |
6882 | we would have stopped then), and we know z.d != z'.d (else [8] would have held |
6883 | and we would have stopped then), and there are only 2 possible values dst() can |
6884 | return in Eastern, it follows that z'.d must be 0 (which it is in the example, |
6885 | but the reasoning doesn't depend on the example -- it depends on there being |
6886 | two possible dst() outcomes, one zero and the other non-zero). Therefore |
6887 | z' must be in standard time, and is the spelling we want in this case. |
6888 | |
6889 | Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is |
6890 | concerned (because it takes z' as being in standard time rather than the |
6891 | daylight time we intend here), but returning it gives the real-life "local |
6892 | clock repeats an hour" behavior when mapping the "unspellable" UTC hour into |
6893 | tz. |
6894 | |
6895 | When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with |
6896 | the 1:MM standard time spelling we want. |
6897 | |
6898 | So how can this break? One of the assumptions must be violated. Two |
6899 | possibilities: |
6900 | |
6901 | 1) [2] effectively says that y.s is invariant across all y belong to a given |
6902 | time zone. This isn't true if, for political reasons or continental drift, |
6903 | a region decides to change its base offset from UTC. |
6904 | |
6905 | 2) There may be versions of "double daylight" time where the tail end of |
6906 | the analysis gives up a step too early. I haven't thought about that |
6907 | enough to say. |
6908 | |
6909 | In any case, it's clear that the default fromutc() is strong enough to handle |
6910 | "almost all" time zones: so long as the standard offset is invariant, it |
6911 | doesn't matter if daylight time transition points change from year to year, or |
6912 | if daylight time is skipped in some years; it doesn't matter how large or |
6913 | small dst() may get within its bounds; and it doesn't even matter if some |
6914 | perverse time zone returns a negative dst()). So a breaking case must be |
6915 | pretty bizarre, and a tzinfo subclass can override fromutc() if it is. |
6916 | --------------------------------------------------------------------------- */ |
6917 | |