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