blob: e85c955dc566888714e81c5200cf4c9359e794b6 [file] [log] [blame]
Tim Peters2a799bf2002-12-16 20:18:38 +00001/* C implementation for the date/time type documented at
2 * http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage
3 */
4
5#include "Python.h"
6#include "modsupport.h"
7#include "structmember.h"
8
9#include <time.h>
10
11#include "datetime.h"
12
13/* We require that C int be at least 32 bits, and use int virtually
14 * everywhere. In just a few cases we use a temp long, where a Python
15 * API returns a C long. In such cases, we have to ensure that the
16 * final result fits in a C int (this can be an issue on 64-bit boxes).
17 */
18#if SIZEOF_INT < 4
19# error "datetime.c requires that C int have at least 32 bits"
20#endif
21
22#define MINYEAR 1
23#define MAXYEAR 9999
24
25/* Nine decimal digits is easy to communicate, and leaves enough room
26 * so that two delta days can be added w/o fear of overflowing a signed
27 * 32-bit int, and with plenty of room left over to absorb any possible
28 * carries from adding seconds.
29 */
30#define MAX_DELTA_DAYS 999999999
31
32/* Rename the long macros in datetime.h to more reasonable short names. */
33#define GET_YEAR PyDateTime_GET_YEAR
34#define GET_MONTH PyDateTime_GET_MONTH
35#define GET_DAY PyDateTime_GET_DAY
36#define DATE_GET_HOUR PyDateTime_DATE_GET_HOUR
37#define DATE_GET_MINUTE PyDateTime_DATE_GET_MINUTE
38#define DATE_GET_SECOND PyDateTime_DATE_GET_SECOND
39#define DATE_GET_MICROSECOND PyDateTime_DATE_GET_MICROSECOND
40
41/* Date accessors for date and datetime. */
42#define SET_YEAR(o, v) (((o)->data[0] = ((v) & 0xff00) >> 8), \
43 ((o)->data[1] = ((v) & 0x00ff)))
44#define SET_MONTH(o, v) (PyDateTime_GET_MONTH(o) = (v))
45#define SET_DAY(o, v) (PyDateTime_GET_DAY(o) = (v))
46
47/* Date/Time accessors for datetime. */
48#define DATE_SET_HOUR(o, v) (PyDateTime_DATE_GET_HOUR(o) = (v))
49#define DATE_SET_MINUTE(o, v) (PyDateTime_DATE_GET_MINUTE(o) = (v))
50#define DATE_SET_SECOND(o, v) (PyDateTime_DATE_GET_SECOND(o) = (v))
51#define DATE_SET_MICROSECOND(o, v) \
52 (((o)->data[7] = ((v) & 0xff0000) >> 16), \
53 ((o)->data[8] = ((v) & 0x00ff00) >> 8), \
54 ((o)->data[9] = ((v) & 0x0000ff)))
55
56/* Time accessors for time. */
57#define TIME_GET_HOUR PyDateTime_TIME_GET_HOUR
58#define TIME_GET_MINUTE PyDateTime_TIME_GET_MINUTE
59#define TIME_GET_SECOND PyDateTime_TIME_GET_SECOND
60#define TIME_GET_MICROSECOND PyDateTime_TIME_GET_MICROSECOND
61#define TIME_SET_HOUR(o, v) (PyDateTime_TIME_GET_HOUR(o) = (v))
62#define TIME_SET_MINUTE(o, v) (PyDateTime_TIME_GET_MINUTE(o) = (v))
63#define TIME_SET_SECOND(o, v) (PyDateTime_TIME_GET_SECOND(o) = (v))
64#define TIME_SET_MICROSECOND(o, v) \
65 (((o)->data[3] = ((v) & 0xff0000) >> 16), \
66 ((o)->data[4] = ((v) & 0x00ff00) >> 8), \
67 ((o)->data[5] = ((v) & 0x0000ff)))
68
69/* Delta accessors for timedelta. */
70#define GET_TD_DAYS(o) (((PyDateTime_Delta *)(o))->days)
71#define GET_TD_SECONDS(o) (((PyDateTime_Delta *)(o))->seconds)
72#define GET_TD_MICROSECONDS(o) (((PyDateTime_Delta *)(o))->microseconds)
73
74#define SET_TD_DAYS(o, v) ((o)->days = (v))
75#define SET_TD_SECONDS(o, v) ((o)->seconds = (v))
76#define SET_TD_MICROSECONDS(o, v) ((o)->microseconds = (v))
77
Tim Petersa032d2e2003-01-11 00:15:54 +000078/* p is a pointer to a time or a datetime object; HASTZINFO(p) returns
79 * p->hastzinfo.
80 */
81#define HASTZINFO(p) (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo)
82
Tim Peters2a799bf2002-12-16 20:18:38 +000083/* Forward declarations. */
84static PyTypeObject PyDateTime_DateType;
85static PyTypeObject PyDateTime_DateTimeType;
Tim Peters2a799bf2002-12-16 20:18:38 +000086static PyTypeObject PyDateTime_DeltaType;
87static PyTypeObject PyDateTime_TimeType;
88static PyTypeObject PyDateTime_TZInfoType;
Tim Peters2a799bf2002-12-16 20:18:38 +000089
90/* ---------------------------------------------------------------------------
91 * Math utilities.
92 */
93
94/* k = i+j overflows iff k differs in sign from both inputs,
95 * iff k^i has sign bit set and k^j has sign bit set,
96 * iff (k^i)&(k^j) has sign bit set.
97 */
98#define SIGNED_ADD_OVERFLOWED(RESULT, I, J) \
99 ((((RESULT) ^ (I)) & ((RESULT) ^ (J))) < 0)
100
101/* Compute Python divmod(x, y), returning the quotient and storing the
102 * remainder into *r. The quotient is the floor of x/y, and that's
103 * the real point of this. C will probably truncate instead (C99
104 * requires truncation; C89 left it implementation-defined).
105 * Simplification: we *require* that y > 0 here. That's appropriate
106 * for all the uses made of it. This simplifies the code and makes
107 * the overflow case impossible (divmod(LONG_MIN, -1) is the only
108 * overflow case).
109 */
110static int
111divmod(int x, int y, int *r)
112{
113 int quo;
114
115 assert(y > 0);
116 quo = x / y;
117 *r = x - quo * y;
118 if (*r < 0) {
119 --quo;
120 *r += y;
121 }
122 assert(0 <= *r && *r < y);
123 return quo;
124}
125
Tim Peters5d644dd2003-01-02 16:32:54 +0000126/* Round a double to the nearest long. |x| must be small enough to fit
127 * in a C long; this is not checked.
128 */
129static long
130round_to_long(double x)
131{
132 if (x >= 0.0)
133 x = floor(x + 0.5);
134 else
135 x = ceil(x - 0.5);
136 return (long)x;
137}
138
Tim Peters2a799bf2002-12-16 20:18:38 +0000139/* ---------------------------------------------------------------------------
140 * General calendrical helper functions
141 */
142
143/* For each month ordinal in 1..12, the number of days in that month,
144 * and the number of days before that month in the same year. These
145 * are correct for non-leap years only.
146 */
147static int _days_in_month[] = {
148 0, /* unused; this vector uses 1-based indexing */
149 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
150};
151
152static int _days_before_month[] = {
153 0, /* unused; this vector uses 1-based indexing */
154 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
155};
156
157/* year -> 1 if leap year, else 0. */
158static int
159is_leap(int year)
160{
161 /* Cast year to unsigned. The result is the same either way, but
162 * C can generate faster code for unsigned mod than for signed
163 * mod (especially for % 4 -- a good compiler should just grab
164 * the last 2 bits when the LHS is unsigned).
165 */
166 const unsigned int ayear = (unsigned int)year;
167 return ayear % 4 == 0 && (ayear % 100 != 0 || ayear % 400 == 0);
168}
169
170/* year, month -> number of days in that month in that year */
171static int
172days_in_month(int year, int month)
173{
174 assert(month >= 1);
175 assert(month <= 12);
176 if (month == 2 && is_leap(year))
177 return 29;
178 else
179 return _days_in_month[month];
180}
181
182/* year, month -> number of days in year preceeding first day of month */
183static int
184days_before_month(int year, int month)
185{
186 int days;
187
188 assert(month >= 1);
189 assert(month <= 12);
190 days = _days_before_month[month];
191 if (month > 2 && is_leap(year))
192 ++days;
193 return days;
194}
195
196/* year -> number of days before January 1st of year. Remember that we
197 * start with year 1, so days_before_year(1) == 0.
198 */
199static int
200days_before_year(int year)
201{
202 int y = year - 1;
203 /* This is incorrect if year <= 0; we really want the floor
204 * here. But so long as MINYEAR is 1, the smallest year this
205 * can see is 0 (this can happen in some normalization endcases),
206 * so we'll just special-case that.
207 */
208 assert (year >= 0);
209 if (y >= 0)
210 return y*365 + y/4 - y/100 + y/400;
211 else {
212 assert(y == -1);
213 return -366;
214 }
215}
216
217/* Number of days in 4, 100, and 400 year cycles. That these have
218 * the correct values is asserted in the module init function.
219 */
220#define DI4Y 1461 /* days_before_year(5); days in 4 years */
221#define DI100Y 36524 /* days_before_year(101); days in 100 years */
222#define DI400Y 146097 /* days_before_year(401); days in 400 years */
223
224/* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */
225static void
226ord_to_ymd(int ordinal, int *year, int *month, int *day)
227{
228 int n, n1, n4, n100, n400, leapyear, preceding;
229
230 /* ordinal is a 1-based index, starting at 1-Jan-1. The pattern of
231 * leap years repeats exactly every 400 years. The basic strategy is
232 * to find the closest 400-year boundary at or before ordinal, then
233 * work with the offset from that boundary to ordinal. Life is much
234 * clearer if we subtract 1 from ordinal first -- then the values
235 * of ordinal at 400-year boundaries are exactly those divisible
236 * by DI400Y:
237 *
238 * D M Y n n-1
239 * -- --- ---- ---------- ----------------
240 * 31 Dec -400 -DI400Y -DI400Y -1
241 * 1 Jan -399 -DI400Y +1 -DI400Y 400-year boundary
242 * ...
243 * 30 Dec 000 -1 -2
244 * 31 Dec 000 0 -1
245 * 1 Jan 001 1 0 400-year boundary
246 * 2 Jan 001 2 1
247 * 3 Jan 001 3 2
248 * ...
249 * 31 Dec 400 DI400Y DI400Y -1
250 * 1 Jan 401 DI400Y +1 DI400Y 400-year boundary
251 */
252 assert(ordinal >= 1);
253 --ordinal;
254 n400 = ordinal / DI400Y;
255 n = ordinal % DI400Y;
256 *year = n400 * 400 + 1;
257
258 /* Now n is the (non-negative) offset, in days, from January 1 of
259 * year, to the desired date. Now compute how many 100-year cycles
260 * precede n.
261 * Note that it's possible for n100 to equal 4! In that case 4 full
262 * 100-year cycles precede the desired day, which implies the
263 * desired day is December 31 at the end of a 400-year cycle.
264 */
265 n100 = n / DI100Y;
266 n = n % DI100Y;
267
268 /* Now compute how many 4-year cycles precede it. */
269 n4 = n / DI4Y;
270 n = n % DI4Y;
271
272 /* And now how many single years. Again n1 can be 4, and again
273 * meaning that the desired day is December 31 at the end of the
274 * 4-year cycle.
275 */
276 n1 = n / 365;
277 n = n % 365;
278
279 *year += n100 * 100 + n4 * 4 + n1;
280 if (n1 == 4 || n100 == 4) {
281 assert(n == 0);
282 *year -= 1;
283 *month = 12;
284 *day = 31;
285 return;
286 }
287
288 /* Now the year is correct, and n is the offset from January 1. We
289 * find the month via an estimate that's either exact or one too
290 * large.
291 */
292 leapyear = n1 == 3 && (n4 != 24 || n100 == 3);
293 assert(leapyear == is_leap(*year));
294 *month = (n + 50) >> 5;
295 preceding = (_days_before_month[*month] + (*month > 2 && leapyear));
296 if (preceding > n) {
297 /* estimate is too large */
298 *month -= 1;
299 preceding -= days_in_month(*year, *month);
300 }
301 n -= preceding;
302 assert(0 <= n);
303 assert(n < days_in_month(*year, *month));
304
305 *day = n + 1;
306}
307
308/* year, month, day -> ordinal, considering 01-Jan-0001 as day 1. */
309static int
310ymd_to_ord(int year, int month, int day)
311{
312 return days_before_year(year) + days_before_month(year, month) + day;
313}
314
315/* Day of week, where Monday==0, ..., Sunday==6. 1/1/1 was a Monday. */
316static int
317weekday(int year, int month, int day)
318{
319 return (ymd_to_ord(year, month, day) + 6) % 7;
320}
321
322/* Ordinal of the Monday starting week 1 of the ISO year. Week 1 is the
323 * first calendar week containing a Thursday.
324 */
325static int
326iso_week1_monday(int year)
327{
328 int first_day = ymd_to_ord(year, 1, 1); /* ord of 1/1 */
329 /* 0 if 1/1 is a Monday, 1 if a Tue, etc. */
330 int first_weekday = (first_day + 6) % 7;
331 /* ordinal of closest Monday at or before 1/1 */
332 int week1_monday = first_day - first_weekday;
333
334 if (first_weekday > 3) /* if 1/1 was Fri, Sat, Sun */
335 week1_monday += 7;
336 return week1_monday;
337}
338
339/* ---------------------------------------------------------------------------
340 * Range checkers.
341 */
342
343/* Check that -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS. If so, return 0.
344 * If not, raise OverflowError and return -1.
345 */
346static int
347check_delta_day_range(int days)
348{
349 if (-MAX_DELTA_DAYS <= days && days <= MAX_DELTA_DAYS)
350 return 0;
351 PyErr_Format(PyExc_OverflowError,
352 "days=%d; must have magnitude <= %d",
Guido van Rossumbd43e912002-12-16 20:34:55 +0000353 days, MAX_DELTA_DAYS);
Tim Peters2a799bf2002-12-16 20:18:38 +0000354 return -1;
355}
356
357/* Check that date arguments are in range. Return 0 if they are. If they
358 * aren't, raise ValueError and return -1.
359 */
360static int
361check_date_args(int year, int month, int day)
362{
363
364 if (year < MINYEAR || year > MAXYEAR) {
365 PyErr_SetString(PyExc_ValueError,
366 "year is out of range");
367 return -1;
368 }
369 if (month < 1 || month > 12) {
370 PyErr_SetString(PyExc_ValueError,
371 "month must be in 1..12");
372 return -1;
373 }
374 if (day < 1 || day > days_in_month(year, month)) {
375 PyErr_SetString(PyExc_ValueError,
376 "day is out of range for month");
377 return -1;
378 }
379 return 0;
380}
381
382/* Check that time arguments are in range. Return 0 if they are. If they
383 * aren't, raise ValueError and return -1.
384 */
385static int
386check_time_args(int h, int m, int s, int us)
387{
388 if (h < 0 || h > 23) {
389 PyErr_SetString(PyExc_ValueError,
390 "hour must be in 0..23");
391 return -1;
392 }
393 if (m < 0 || m > 59) {
394 PyErr_SetString(PyExc_ValueError,
395 "minute must be in 0..59");
396 return -1;
397 }
398 if (s < 0 || s > 59) {
399 PyErr_SetString(PyExc_ValueError,
400 "second must be in 0..59");
401 return -1;
402 }
403 if (us < 0 || us > 999999) {
404 PyErr_SetString(PyExc_ValueError,
405 "microsecond must be in 0..999999");
406 return -1;
407 }
408 return 0;
409}
410
411/* ---------------------------------------------------------------------------
412 * Normalization utilities.
413 */
414
415/* One step of a mixed-radix conversion. A "hi" unit is equivalent to
416 * factor "lo" units. factor must be > 0. If *lo is less than 0, or
417 * at least factor, enough of *lo is converted into "hi" units so that
418 * 0 <= *lo < factor. The input values must be such that int overflow
419 * is impossible.
420 */
421static void
422normalize_pair(int *hi, int *lo, int factor)
423{
424 assert(factor > 0);
425 assert(lo != hi);
426 if (*lo < 0 || *lo >= factor) {
427 const int num_hi = divmod(*lo, factor, lo);
428 const int new_hi = *hi + num_hi;
429 assert(! SIGNED_ADD_OVERFLOWED(new_hi, *hi, num_hi));
430 *hi = new_hi;
431 }
432 assert(0 <= *lo && *lo < factor);
433}
434
435/* Fiddle days (d), seconds (s), and microseconds (us) so that
436 * 0 <= *s < 24*3600
437 * 0 <= *us < 1000000
438 * The input values must be such that the internals don't overflow.
439 * The way this routine is used, we don't get close.
440 */
441static void
442normalize_d_s_us(int *d, int *s, int *us)
443{
444 if (*us < 0 || *us >= 1000000) {
445 normalize_pair(s, us, 1000000);
446 /* |s| can't be bigger than about
447 * |original s| + |original us|/1000000 now.
448 */
449
450 }
451 if (*s < 0 || *s >= 24*3600) {
452 normalize_pair(d, s, 24*3600);
453 /* |d| can't be bigger than about
454 * |original d| +
455 * (|original s| + |original us|/1000000) / (24*3600) now.
456 */
457 }
458 assert(0 <= *s && *s < 24*3600);
459 assert(0 <= *us && *us < 1000000);
460}
461
462/* Fiddle years (y), months (m), and days (d) so that
463 * 1 <= *m <= 12
464 * 1 <= *d <= days_in_month(*y, *m)
465 * The input values must be such that the internals don't overflow.
466 * The way this routine is used, we don't get close.
467 */
468static void
469normalize_y_m_d(int *y, int *m, int *d)
470{
471 int dim; /* # of days in month */
472
473 /* This gets muddy: the proper range for day can't be determined
474 * without knowing the correct month and year, but if day is, e.g.,
475 * plus or minus a million, the current month and year values make
476 * no sense (and may also be out of bounds themselves).
477 * Saying 12 months == 1 year should be non-controversial.
478 */
479 if (*m < 1 || *m > 12) {
480 --*m;
481 normalize_pair(y, m, 12);
482 ++*m;
483 /* |y| can't be bigger than about
484 * |original y| + |original m|/12 now.
485 */
486 }
487 assert(1 <= *m && *m <= 12);
488
489 /* Now only day can be out of bounds (year may also be out of bounds
490 * for a datetime object, but we don't care about that here).
491 * If day is out of bounds, what to do is arguable, but at least the
492 * method here is principled and explainable.
493 */
494 dim = days_in_month(*y, *m);
495 if (*d < 1 || *d > dim) {
496 /* Move day-1 days from the first of the month. First try to
497 * get off cheap if we're only one day out of range
498 * (adjustments for timezone alone can't be worse than that).
499 */
500 if (*d == 0) {
501 --*m;
502 if (*m > 0)
503 *d = days_in_month(*y, *m);
504 else {
505 --*y;
506 *m = 12;
507 *d = 31;
508 }
509 }
510 else if (*d == dim + 1) {
511 /* move forward a day */
512 ++*m;
513 *d = 1;
514 if (*m > 12) {
515 *m = 1;
516 ++*y;
517 }
518 }
519 else {
520 int ordinal = ymd_to_ord(*y, *m, 1) +
521 *d - 1;
522 ord_to_ymd(ordinal, y, m, d);
523 }
524 }
525 assert(*m > 0);
526 assert(*d > 0);
527}
528
529/* Fiddle out-of-bounds months and days so that the result makes some kind
530 * of sense. The parameters are both inputs and outputs. Returns < 0 on
531 * failure, where failure means the adjusted year is out of bounds.
532 */
533static int
534normalize_date(int *year, int *month, int *day)
535{
536 int result;
537
538 normalize_y_m_d(year, month, day);
539 if (MINYEAR <= *year && *year <= MAXYEAR)
540 result = 0;
541 else {
542 PyErr_SetString(PyExc_OverflowError,
543 "date value out of range");
544 result = -1;
545 }
546 return result;
547}
548
549/* Force all the datetime fields into range. The parameters are both
550 * inputs and outputs. Returns < 0 on error.
551 */
552static int
553normalize_datetime(int *year, int *month, int *day,
554 int *hour, int *minute, int *second,
555 int *microsecond)
556{
557 normalize_pair(second, microsecond, 1000000);
558 normalize_pair(minute, second, 60);
559 normalize_pair(hour, minute, 60);
560 normalize_pair(day, hour, 24);
561 return normalize_date(year, month, day);
562}
563
564/* ---------------------------------------------------------------------------
Tim Petersb0c854d2003-05-17 15:57:00 +0000565 * Basic object allocation: tp_alloc implementations. These allocate
566 * Python objects of the right size and type, and do the Python object-
567 * initialization bit. If there's not enough memory, they return NULL after
568 * setting MemoryError. All data members remain uninitialized trash.
569 *
570 * We abuse the tp_alloc "nitems" argument to communicate whether a tzinfo
571 * member is needed. This is ugly.
572 */
573
574static PyObject *
575time_alloc(PyTypeObject *type, int aware)
576{
577 PyObject *self;
578
579 self = (PyObject *)
580 PyObject_MALLOC(aware ?
581 sizeof(PyDateTime_Time) :
582 sizeof(_PyDateTime_BaseTime));
583 if (self == NULL)
584 return (PyObject *)PyErr_NoMemory();
585 PyObject_INIT(self, type);
586 return self;
587}
588
589static PyObject *
590datetime_alloc(PyTypeObject *type, int aware)
591{
592 PyObject *self;
593
594 self = (PyObject *)
595 PyObject_MALLOC(aware ?
596 sizeof(PyDateTime_DateTime) :
597 sizeof(_PyDateTime_BaseDateTime));
598 if (self == NULL)
599 return (PyObject *)PyErr_NoMemory();
600 PyObject_INIT(self, type);
601 return self;
602}
603
604/* ---------------------------------------------------------------------------
605 * Helpers for setting object fields. These work on pointers to the
606 * appropriate base class.
607 */
608
609/* For date and datetime. */
610static void
611set_date_fields(PyDateTime_Date *self, int y, int m, int d)
612{
613 self->hashcode = -1;
614 SET_YEAR(self, y);
615 SET_MONTH(self, m);
616 SET_DAY(self, d);
617}
618
619/* ---------------------------------------------------------------------------
620 * Create various objects, mostly without range checking.
621 */
622
623/* Create a date instance with no range checking. */
624static PyObject *
625new_date_ex(int year, int month, int day, PyTypeObject *type)
626{
627 PyDateTime_Date *self;
628
629 self = (PyDateTime_Date *) (type->tp_alloc(type, 0));
630 if (self != NULL)
631 set_date_fields(self, year, month, day);
632 return (PyObject *) self;
633}
634
635#define new_date(year, month, day) \
636 new_date_ex(year, month, day, &PyDateTime_DateType)
637
638/* Create a datetime instance with no range checking. */
639static PyObject *
640new_datetime_ex(int year, int month, int day, int hour, int minute,
641 int second, int usecond, PyObject *tzinfo, PyTypeObject *type)
642{
643 PyDateTime_DateTime *self;
644 char aware = tzinfo != Py_None;
645
646 self = (PyDateTime_DateTime *) (type->tp_alloc(type, aware));
647 if (self != NULL) {
648 self->hastzinfo = aware;
649 set_date_fields((PyDateTime_Date *)self, year, month, day);
650 DATE_SET_HOUR(self, hour);
651 DATE_SET_MINUTE(self, minute);
652 DATE_SET_SECOND(self, second);
653 DATE_SET_MICROSECOND(self, usecond);
654 if (aware) {
655 Py_INCREF(tzinfo);
656 self->tzinfo = tzinfo;
657 }
658 }
659 return (PyObject *)self;
660}
661
662#define new_datetime(y, m, d, hh, mm, ss, us, tzinfo) \
663 new_datetime_ex(y, m, d, hh, mm, ss, us, tzinfo, \
664 &PyDateTime_DateTimeType)
665
666/* Create a time instance with no range checking. */
667static PyObject *
668new_time_ex(int hour, int minute, int second, int usecond,
669 PyObject *tzinfo, PyTypeObject *type)
670{
671 PyDateTime_Time *self;
672 char aware = tzinfo != Py_None;
673
674 self = (PyDateTime_Time *) (type->tp_alloc(type, aware));
675 if (self != NULL) {
676 self->hastzinfo = aware;
677 self->hashcode = -1;
678 TIME_SET_HOUR(self, hour);
679 TIME_SET_MINUTE(self, minute);
680 TIME_SET_SECOND(self, second);
681 TIME_SET_MICROSECOND(self, usecond);
682 if (aware) {
683 Py_INCREF(tzinfo);
684 self->tzinfo = tzinfo;
685 }
686 }
687 return (PyObject *)self;
688}
689
690#define new_time(hh, mm, ss, us, tzinfo) \
691 new_time_ex(hh, mm, ss, us, tzinfo, &PyDateTime_TimeType)
692
693/* Create a timedelta instance. Normalize the members iff normalize is
694 * true. Passing false is a speed optimization, if you know for sure
695 * that seconds and microseconds are already in their proper ranges. In any
696 * case, raises OverflowError and returns NULL if the normalized days is out
697 * of range).
698 */
699static PyObject *
700new_delta_ex(int days, int seconds, int microseconds, int normalize,
701 PyTypeObject *type)
702{
703 PyDateTime_Delta *self;
704
705 if (normalize)
706 normalize_d_s_us(&days, &seconds, &microseconds);
707 assert(0 <= seconds && seconds < 24*3600);
708 assert(0 <= microseconds && microseconds < 1000000);
709
710 if (check_delta_day_range(days) < 0)
711 return NULL;
712
713 self = (PyDateTime_Delta *) (type->tp_alloc(type, 0));
714 if (self != NULL) {
715 self->hashcode = -1;
716 SET_TD_DAYS(self, days);
717 SET_TD_SECONDS(self, seconds);
718 SET_TD_MICROSECONDS(self, microseconds);
719 }
720 return (PyObject *) self;
721}
722
723#define new_delta(d, s, us, normalize) \
724 new_delta_ex(d, s, us, normalize, &PyDateTime_DeltaType)
725
726/* ---------------------------------------------------------------------------
Tim Peters2a799bf2002-12-16 20:18:38 +0000727 * tzinfo helpers.
728 */
729
Tim Peters855fe882002-12-22 03:43:39 +0000730/* Ensure that p is None or of a tzinfo subclass. Return 0 if OK; if not
731 * raise TypeError and return -1.
732 */
733static int
734check_tzinfo_subclass(PyObject *p)
735{
736 if (p == Py_None || PyTZInfo_Check(p))
737 return 0;
738 PyErr_Format(PyExc_TypeError,
739 "tzinfo argument must be None or of a tzinfo subclass, "
740 "not type '%s'",
741 p->ob_type->tp_name);
742 return -1;
743}
744
Tim Petersbad8ff02002-12-30 20:52:32 +0000745/* Return tzinfo.methname(tzinfoarg), without any checking of results.
Tim Peters855fe882002-12-22 03:43:39 +0000746 * If tzinfo is None, returns None.
747 */
748static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000749call_tzinfo_method(PyObject *tzinfo, char *methname, PyObject *tzinfoarg)
Tim Peters855fe882002-12-22 03:43:39 +0000750{
751 PyObject *result;
752
Tim Petersbad8ff02002-12-30 20:52:32 +0000753 assert(tzinfo && methname && tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000754 assert(check_tzinfo_subclass(tzinfo) >= 0);
755 if (tzinfo == Py_None) {
756 result = Py_None;
757 Py_INCREF(result);
758 }
759 else
Tim Petersbad8ff02002-12-30 20:52:32 +0000760 result = PyObject_CallMethod(tzinfo, methname, "O", tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000761 return result;
762}
763
Tim Peters2a799bf2002-12-16 20:18:38 +0000764/* If self has a tzinfo member, return a BORROWED reference to it. Else
765 * return NULL, which is NOT AN ERROR. There are no error returns here,
766 * and the caller must not decref the result.
767 */
768static PyObject *
769get_tzinfo_member(PyObject *self)
770{
771 PyObject *tzinfo = NULL;
772
Tim Petersa9bc1682003-01-11 03:39:11 +0000773 if (PyDateTime_Check(self) && HASTZINFO(self))
774 tzinfo = ((PyDateTime_DateTime *)self)->tzinfo;
Tim Petersa032d2e2003-01-11 00:15:54 +0000775 else if (PyTime_Check(self) && HASTZINFO(self))
Tim Peters37f39822003-01-10 03:49:02 +0000776 tzinfo = ((PyDateTime_Time *)self)->tzinfo;
Tim Peters2a799bf2002-12-16 20:18:38 +0000777
778 return tzinfo;
779}
780
Tim Petersbad8ff02002-12-30 20:52:32 +0000781/* Call getattr(tzinfo, name)(tzinfoarg), and extract an int from the
Tim Peters2a799bf2002-12-16 20:18:38 +0000782 * result. tzinfo must be an instance of the tzinfo class. If the method
783 * returns None, this returns 0 and sets *none to 1. If the method doesn't
Tim Peters397301e2003-01-02 21:28:08 +0000784 * return None or timedelta, TypeError is raised and this returns -1. If it
785 * returnsa timedelta and the value is out of range or isn't a whole number
786 * of minutes, ValueError is raised and this returns -1.
Tim Peters2a799bf2002-12-16 20:18:38 +0000787 * Else *none is set to 0 and the integer method result is returned.
788 */
789static int
790call_utc_tzinfo_method(PyObject *tzinfo, char *name, PyObject *tzinfoarg,
791 int *none)
792{
793 PyObject *u;
Tim Peters397301e2003-01-02 21:28:08 +0000794 int result = -1;
Tim Peters2a799bf2002-12-16 20:18:38 +0000795
796 assert(tzinfo != NULL);
797 assert(PyTZInfo_Check(tzinfo));
798 assert(tzinfoarg != NULL);
799
800 *none = 0;
Tim Petersbad8ff02002-12-30 20:52:32 +0000801 u = call_tzinfo_method(tzinfo, name, tzinfoarg);
Tim Peters2a799bf2002-12-16 20:18:38 +0000802 if (u == NULL)
803 return -1;
804
Tim Peters27362852002-12-23 16:17:39 +0000805 else if (u == Py_None) {
Tim Peters2a799bf2002-12-16 20:18:38 +0000806 result = 0;
807 *none = 1;
Tim Peters2a799bf2002-12-16 20:18:38 +0000808 }
Tim Peters855fe882002-12-22 03:43:39 +0000809 else if (PyDelta_Check(u)) {
810 const int days = GET_TD_DAYS(u);
811 if (days < -1 || days > 0)
812 result = 24*60; /* trigger ValueError below */
813 else {
814 /* next line can't overflow because we know days
815 * is -1 or 0 now
816 */
817 int ss = days * 24 * 3600 + GET_TD_SECONDS(u);
818 result = divmod(ss, 60, &ss);
819 if (ss || GET_TD_MICROSECONDS(u)) {
820 PyErr_Format(PyExc_ValueError,
821 "tzinfo.%s() must return a "
822 "whole number of minutes",
823 name);
824 result = -1;
Tim Peters855fe882002-12-22 03:43:39 +0000825 }
826 }
827 }
Tim Peters2a799bf2002-12-16 20:18:38 +0000828 else {
829 PyErr_Format(PyExc_TypeError,
Tim Peters397301e2003-01-02 21:28:08 +0000830 "tzinfo.%s() must return None or "
Tim Peters855fe882002-12-22 03:43:39 +0000831 "timedelta, not '%s'",
832 name, u->ob_type->tp_name);
Tim Peters2a799bf2002-12-16 20:18:38 +0000833 }
834
Tim Peters2a799bf2002-12-16 20:18:38 +0000835 Py_DECREF(u);
836 if (result < -1439 || result > 1439) {
837 PyErr_Format(PyExc_ValueError,
Neal Norwitz506a2242003-01-04 01:02:25 +0000838 "tzinfo.%s() returned %d; must be in "
Tim Peters2a799bf2002-12-16 20:18:38 +0000839 "-1439 .. 1439",
840 name, result);
841 result = -1;
842 }
Tim Peters397301e2003-01-02 21:28:08 +0000843 return result;
Tim Peters2a799bf2002-12-16 20:18:38 +0000844}
845
846/* Call tzinfo.utcoffset(tzinfoarg), and extract an integer from the
847 * result. tzinfo must be an instance of the tzinfo class. If utcoffset()
848 * returns None, call_utcoffset returns 0 and sets *none to 1. If uctoffset()
Tim Peters397301e2003-01-02 21:28:08 +0000849 * doesn't return None or timedelta, TypeError is raised and this returns -1.
850 * If utcoffset() returns an invalid timedelta (out of range, or not a whole
851 * # of minutes), ValueError is raised and this returns -1. Else *none is
852 * set to 0 and the offset is returned (as int # of minutes east of UTC).
Tim Peters2a799bf2002-12-16 20:18:38 +0000853 */
854static int
855call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
856{
857 return call_utc_tzinfo_method(tzinfo, "utcoffset", tzinfoarg, none);
858}
859
Tim Petersbad8ff02002-12-30 20:52:32 +0000860/* Call tzinfo.name(tzinfoarg), and return the offset as a timedelta or None.
861 */
Tim Peters855fe882002-12-22 03:43:39 +0000862static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000863offset_as_timedelta(PyObject *tzinfo, char *name, PyObject *tzinfoarg) {
Tim Peters855fe882002-12-22 03:43:39 +0000864 PyObject *result;
865
Tim Petersbad8ff02002-12-30 20:52:32 +0000866 assert(tzinfo && name && tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000867 if (tzinfo == Py_None) {
868 result = Py_None;
869 Py_INCREF(result);
870 }
871 else {
872 int none;
Tim Petersbad8ff02002-12-30 20:52:32 +0000873 int offset = call_utc_tzinfo_method(tzinfo, name, tzinfoarg,
874 &none);
Tim Peters855fe882002-12-22 03:43:39 +0000875 if (offset < 0 && PyErr_Occurred())
876 return NULL;
877 if (none) {
878 result = Py_None;
879 Py_INCREF(result);
880 }
881 else
882 result = new_delta(0, offset * 60, 0, 1);
883 }
884 return result;
885}
886
Tim Peters2a799bf2002-12-16 20:18:38 +0000887/* Call tzinfo.dst(tzinfoarg), and extract an integer from the
888 * result. tzinfo must be an instance of the tzinfo class. If dst()
889 * returns None, call_dst returns 0 and sets *none to 1. If dst()
Tim Peters397301e2003-01-02 21:28:08 +0000890 & doesn't return None or timedelta, TypeError is raised and this
891 * returns -1. If dst() returns an invalid timedelta for for a UTC offset,
892 * ValueError is raised and this returns -1. Else *none is set to 0 and
893 * the offset is returned (as an int # of minutes east of UTC).
Tim Peters2a799bf2002-12-16 20:18:38 +0000894 */
895static int
896call_dst(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
897{
898 return call_utc_tzinfo_method(tzinfo, "dst", tzinfoarg, none);
899}
900
Tim Petersbad8ff02002-12-30 20:52:32 +0000901/* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be
Tim Peters855fe882002-12-22 03:43:39 +0000902 * an instance of the tzinfo class or None. If tzinfo isn't None, and
Tim Petersbad8ff02002-12-30 20:52:32 +0000903 * tzname() doesn't return None or a string, TypeError is raised and this
Tim Peters855fe882002-12-22 03:43:39 +0000904 * returns NULL.
Tim Peters2a799bf2002-12-16 20:18:38 +0000905 */
906static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000907call_tzname(PyObject *tzinfo, PyObject *tzinfoarg)
Tim Peters2a799bf2002-12-16 20:18:38 +0000908{
909 PyObject *result;
910
911 assert(tzinfo != NULL);
Tim Peters855fe882002-12-22 03:43:39 +0000912 assert(check_tzinfo_subclass(tzinfo) >= 0);
Tim Petersbad8ff02002-12-30 20:52:32 +0000913 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +0000914
Tim Peters855fe882002-12-22 03:43:39 +0000915 if (tzinfo == Py_None) {
916 result = Py_None;
917 Py_INCREF(result);
918 }
919 else
Tim Petersbad8ff02002-12-30 20:52:32 +0000920 result = PyObject_CallMethod(tzinfo, "tzname", "O", tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000921
922 if (result != NULL && result != Py_None && ! PyString_Check(result)) {
923 PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must "
Tim Peters2a799bf2002-12-16 20:18:38 +0000924 "return None or a string, not '%s'",
925 result->ob_type->tp_name);
926 Py_DECREF(result);
927 result = NULL;
928 }
929 return result;
930}
931
932typedef enum {
933 /* an exception has been set; the caller should pass it on */
934 OFFSET_ERROR,
935
Tim Petersa9bc1682003-01-11 03:39:11 +0000936 /* type isn't date, datetime, or time subclass */
Tim Peters2a799bf2002-12-16 20:18:38 +0000937 OFFSET_UNKNOWN,
938
939 /* date,
Tim Petersa9bc1682003-01-11 03:39:11 +0000940 * datetime with !hastzinfo
941 * datetime with None tzinfo,
942 * datetime where utcoffset() returns None
Tim Peters37f39822003-01-10 03:49:02 +0000943 * time with !hastzinfo
944 * time with None tzinfo,
945 * time where utcoffset() returns None
Tim Peters2a799bf2002-12-16 20:18:38 +0000946 */
947 OFFSET_NAIVE,
948
Tim Petersa9bc1682003-01-11 03:39:11 +0000949 /* time or datetime where utcoffset() doesn't return None */
Tim Peters2a799bf2002-12-16 20:18:38 +0000950 OFFSET_AWARE,
951} naivety;
952
Tim Peters14b69412002-12-22 18:10:22 +0000953/* Classify an object as to whether it's naive or offset-aware. See
Tim Peters2a799bf2002-12-16 20:18:38 +0000954 * the "naivety" typedef for details. If the type is aware, *offset is set
955 * to minutes east of UTC (as returned by the tzinfo.utcoffset() method).
Tim Peters14b69412002-12-22 18:10:22 +0000956 * If the type is offset-naive (or unknown, or error), *offset is set to 0.
Tim Peterse39a80c2002-12-30 21:28:52 +0000957 * tzinfoarg is the argument to pass to the tzinfo.utcoffset() method.
Tim Peters2a799bf2002-12-16 20:18:38 +0000958 */
959static naivety
Tim Peterse39a80c2002-12-30 21:28:52 +0000960classify_utcoffset(PyObject *op, PyObject *tzinfoarg, int *offset)
Tim Peters2a799bf2002-12-16 20:18:38 +0000961{
962 int none;
963 PyObject *tzinfo;
964
Tim Peterse39a80c2002-12-30 21:28:52 +0000965 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +0000966 *offset = 0;
Tim Peters14b69412002-12-22 18:10:22 +0000967 tzinfo = get_tzinfo_member(op); /* NULL means no tzinfo, not error */
Tim Peters2a799bf2002-12-16 20:18:38 +0000968 if (tzinfo == Py_None)
969 return OFFSET_NAIVE;
Tim Peters14b69412002-12-22 18:10:22 +0000970 if (tzinfo == NULL) {
971 /* note that a datetime passes the PyDate_Check test */
972 return (PyTime_Check(op) || PyDate_Check(op)) ?
973 OFFSET_NAIVE : OFFSET_UNKNOWN;
974 }
Tim Peterse39a80c2002-12-30 21:28:52 +0000975 *offset = call_utcoffset(tzinfo, tzinfoarg, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +0000976 if (*offset == -1 && PyErr_Occurred())
977 return OFFSET_ERROR;
978 return none ? OFFSET_NAIVE : OFFSET_AWARE;
979}
980
Tim Peters00237032002-12-27 02:21:51 +0000981/* Classify two objects as to whether they're naive or offset-aware.
982 * This isn't quite the same as calling classify_utcoffset() twice: for
983 * binary operations (comparison and subtraction), we generally want to
984 * ignore the tzinfo members if they're identical. This is by design,
985 * so that results match "naive" expectations when mixing objects from a
986 * single timezone. So in that case, this sets both offsets to 0 and
987 * both naiveties to OFFSET_NAIVE.
988 * The function returns 0 if everything's OK, and -1 on error.
989 */
990static int
991classify_two_utcoffsets(PyObject *o1, int *offset1, naivety *n1,
Tim Peterse39a80c2002-12-30 21:28:52 +0000992 PyObject *tzinfoarg1,
993 PyObject *o2, int *offset2, naivety *n2,
994 PyObject *tzinfoarg2)
Tim Peters00237032002-12-27 02:21:51 +0000995{
996 if (get_tzinfo_member(o1) == get_tzinfo_member(o2)) {
997 *offset1 = *offset2 = 0;
998 *n1 = *n2 = OFFSET_NAIVE;
999 }
1000 else {
Tim Peterse39a80c2002-12-30 21:28:52 +00001001 *n1 = classify_utcoffset(o1, tzinfoarg1, offset1);
Tim Peters00237032002-12-27 02:21:51 +00001002 if (*n1 == OFFSET_ERROR)
1003 return -1;
Tim Peterse39a80c2002-12-30 21:28:52 +00001004 *n2 = classify_utcoffset(o2, tzinfoarg2, offset2);
Tim Peters00237032002-12-27 02:21:51 +00001005 if (*n2 == OFFSET_ERROR)
1006 return -1;
1007 }
1008 return 0;
1009}
1010
Tim Peters2a799bf2002-12-16 20:18:38 +00001011/* repr is like "someclass(arg1, arg2)". If tzinfo isn't None,
1012 * stuff
1013 * ", tzinfo=" + repr(tzinfo)
1014 * before the closing ")".
1015 */
1016static PyObject *
1017append_keyword_tzinfo(PyObject *repr, PyObject *tzinfo)
1018{
1019 PyObject *temp;
1020
1021 assert(PyString_Check(repr));
1022 assert(tzinfo);
1023 if (tzinfo == Py_None)
1024 return repr;
1025 /* Get rid of the trailing ')'. */
1026 assert(PyString_AsString(repr)[PyString_Size(repr)-1] == ')');
1027 temp = PyString_FromStringAndSize(PyString_AsString(repr),
1028 PyString_Size(repr) - 1);
1029 Py_DECREF(repr);
1030 if (temp == NULL)
1031 return NULL;
1032 repr = temp;
1033
1034 /* Append ", tzinfo=". */
1035 PyString_ConcatAndDel(&repr, PyString_FromString(", tzinfo="));
1036
1037 /* Append repr(tzinfo). */
1038 PyString_ConcatAndDel(&repr, PyObject_Repr(tzinfo));
1039
1040 /* Add a closing paren. */
1041 PyString_ConcatAndDel(&repr, PyString_FromString(")"));
1042 return repr;
1043}
1044
1045/* ---------------------------------------------------------------------------
1046 * String format helpers.
1047 */
1048
1049static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00001050format_ctime(PyDateTime_Date *date, int hours, int minutes, int seconds)
Tim Peters2a799bf2002-12-16 20:18:38 +00001051{
1052 static char *DayNames[] = {
1053 "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
1054 };
1055 static char *MonthNames[] = {
1056 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1057 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1058 };
1059
1060 char buffer[128];
1061 int wday = weekday(GET_YEAR(date), GET_MONTH(date), GET_DAY(date));
1062
1063 PyOS_snprintf(buffer, sizeof(buffer), "%s %s %2d %02d:%02d:%02d %04d",
1064 DayNames[wday], MonthNames[GET_MONTH(date) - 1],
1065 GET_DAY(date), hours, minutes, seconds,
1066 GET_YEAR(date));
1067 return PyString_FromString(buffer);
1068}
1069
1070/* Add an hours & minutes UTC offset string to buf. buf has no more than
1071 * buflen bytes remaining. The UTC offset is gotten by calling
1072 * tzinfo.uctoffset(tzinfoarg). If that returns None, \0 is stored into
1073 * *buf, and that's all. Else the returned value is checked for sanity (an
1074 * integer in range), and if that's OK it's converted to an hours & minutes
1075 * string of the form
1076 * sign HH sep MM
1077 * Returns 0 if everything is OK. If the return value from utcoffset() is
1078 * bogus, an appropriate exception is set and -1 is returned.
1079 */
1080static int
Tim Peters328fff72002-12-20 01:31:27 +00001081format_utcoffset(char *buf, size_t buflen, const char *sep,
Tim Peters2a799bf2002-12-16 20:18:38 +00001082 PyObject *tzinfo, PyObject *tzinfoarg)
1083{
1084 int offset;
1085 int hours;
1086 int minutes;
1087 char sign;
1088 int none;
1089
1090 offset = call_utcoffset(tzinfo, tzinfoarg, &none);
1091 if (offset == -1 && PyErr_Occurred())
1092 return -1;
1093 if (none) {
1094 *buf = '\0';
1095 return 0;
1096 }
1097 sign = '+';
1098 if (offset < 0) {
1099 sign = '-';
1100 offset = - offset;
1101 }
1102 hours = divmod(offset, 60, &minutes);
1103 PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes);
1104 return 0;
1105}
1106
1107/* I sure don't want to reproduce the strftime code from the time module,
1108 * so this imports the module and calls it. All the hair is due to
1109 * giving special meanings to the %z and %Z format codes via a preprocessing
1110 * step on the format string.
Tim Petersbad8ff02002-12-30 20:52:32 +00001111 * tzinfoarg is the argument to pass to the object's tzinfo method, if
1112 * needed.
Tim Peters2a799bf2002-12-16 20:18:38 +00001113 */
1114static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +00001115wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
1116 PyObject *tzinfoarg)
Tim Peters2a799bf2002-12-16 20:18:38 +00001117{
1118 PyObject *result = NULL; /* guilty until proved innocent */
1119
1120 PyObject *zreplacement = NULL; /* py string, replacement for %z */
1121 PyObject *Zreplacement = NULL; /* py string, replacement for %Z */
1122
1123 char *pin; /* pointer to next char in input format */
1124 char ch; /* next char in input format */
1125
1126 PyObject *newfmt = NULL; /* py string, the output format */
1127 char *pnew; /* pointer to available byte in output format */
1128 char totalnew; /* number bytes total in output format buffer,
1129 exclusive of trailing \0 */
1130 char usednew; /* number bytes used so far in output format buffer */
1131
1132 char *ptoappend; /* pointer to string to append to output buffer */
1133 int ntoappend; /* # of bytes to append to output buffer */
1134
Tim Peters2a799bf2002-12-16 20:18:38 +00001135 assert(object && format && timetuple);
1136 assert(PyString_Check(format));
1137
Tim Petersd6844152002-12-22 20:58:42 +00001138 /* Give up if the year is before 1900.
1139 * Python strftime() plays games with the year, and different
1140 * games depending on whether envar PYTHON2K is set. This makes
1141 * years before 1900 a nightmare, even if the platform strftime
1142 * supports them (and not all do).
1143 * We could get a lot farther here by avoiding Python's strftime
1144 * wrapper and calling the C strftime() directly, but that isn't
1145 * an option in the Python implementation of this module.
1146 */
1147 {
1148 long year;
1149 PyObject *pyyear = PySequence_GetItem(timetuple, 0);
1150 if (pyyear == NULL) return NULL;
1151 assert(PyInt_Check(pyyear));
1152 year = PyInt_AsLong(pyyear);
1153 Py_DECREF(pyyear);
1154 if (year < 1900) {
1155 PyErr_Format(PyExc_ValueError, "year=%ld is before "
1156 "1900; the datetime strftime() "
1157 "methods require year >= 1900",
1158 year);
1159 return NULL;
1160 }
1161 }
1162
Tim Peters2a799bf2002-12-16 20:18:38 +00001163 /* Scan the input format, looking for %z and %Z escapes, building
Tim Peters328fff72002-12-20 01:31:27 +00001164 * a new format. Since computing the replacements for those codes
1165 * is expensive, don't unless they're actually used.
Tim Peters2a799bf2002-12-16 20:18:38 +00001166 */
1167 totalnew = PyString_Size(format); /* realistic if no %z/%Z */
1168 newfmt = PyString_FromStringAndSize(NULL, totalnew);
1169 if (newfmt == NULL) goto Done;
1170 pnew = PyString_AsString(newfmt);
1171 usednew = 0;
1172
1173 pin = PyString_AsString(format);
1174 while ((ch = *pin++) != '\0') {
1175 if (ch != '%') {
Tim Peters328fff72002-12-20 01:31:27 +00001176 ptoappend = pin - 1;
Tim Peters2a799bf2002-12-16 20:18:38 +00001177 ntoappend = 1;
1178 }
1179 else if ((ch = *pin++) == '\0') {
1180 /* There's a lone trailing %; doesn't make sense. */
1181 PyErr_SetString(PyExc_ValueError, "strftime format "
1182 "ends with raw %");
1183 goto Done;
1184 }
1185 /* A % has been seen and ch is the character after it. */
1186 else if (ch == 'z') {
1187 if (zreplacement == NULL) {
1188 /* format utcoffset */
Tim Peters328fff72002-12-20 01:31:27 +00001189 char buf[100];
Tim Peters2a799bf2002-12-16 20:18:38 +00001190 PyObject *tzinfo = get_tzinfo_member(object);
1191 zreplacement = PyString_FromString("");
1192 if (zreplacement == NULL) goto Done;
1193 if (tzinfo != Py_None && tzinfo != NULL) {
Tim Petersbad8ff02002-12-30 20:52:32 +00001194 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +00001195 if (format_utcoffset(buf,
Tim Peters328fff72002-12-20 01:31:27 +00001196 sizeof(buf),
Tim Peters2a799bf2002-12-16 20:18:38 +00001197 "",
1198 tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00001199 tzinfoarg) < 0)
Tim Peters2a799bf2002-12-16 20:18:38 +00001200 goto Done;
1201 Py_DECREF(zreplacement);
1202 zreplacement = PyString_FromString(buf);
1203 if (zreplacement == NULL) goto Done;
1204 }
1205 }
1206 assert(zreplacement != NULL);
1207 ptoappend = PyString_AsString(zreplacement);
1208 ntoappend = PyString_Size(zreplacement);
1209 }
1210 else if (ch == 'Z') {
1211 /* format tzname */
1212 if (Zreplacement == NULL) {
1213 PyObject *tzinfo = get_tzinfo_member(object);
1214 Zreplacement = PyString_FromString("");
1215 if (Zreplacement == NULL) goto Done;
1216 if (tzinfo != Py_None && tzinfo != NULL) {
Tim Petersbad8ff02002-12-30 20:52:32 +00001217 PyObject *temp;
1218 assert(tzinfoarg != NULL);
1219 temp = call_tzname(tzinfo, tzinfoarg);
Tim Peters2a799bf2002-12-16 20:18:38 +00001220 if (temp == NULL) goto Done;
1221 if (temp != Py_None) {
1222 assert(PyString_Check(temp));
1223 /* Since the tzname is getting
1224 * stuffed into the format, we
1225 * have to double any % signs
1226 * so that strftime doesn't
1227 * treat them as format codes.
1228 */
1229 Py_DECREF(Zreplacement);
1230 Zreplacement = PyObject_CallMethod(
1231 temp, "replace",
1232 "ss", "%", "%%");
1233 Py_DECREF(temp);
1234 if (Zreplacement == NULL)
1235 goto Done;
1236 }
1237 else
1238 Py_DECREF(temp);
1239 }
1240 }
1241 assert(Zreplacement != NULL);
1242 ptoappend = PyString_AsString(Zreplacement);
1243 ntoappend = PyString_Size(Zreplacement);
1244 }
1245 else {
Tim Peters328fff72002-12-20 01:31:27 +00001246 /* percent followed by neither z nor Z */
1247 ptoappend = pin - 2;
Tim Peters2a799bf2002-12-16 20:18:38 +00001248 ntoappend = 2;
1249 }
1250
1251 /* Append the ntoappend chars starting at ptoappend to
1252 * the new format.
1253 */
1254 assert(ntoappend >= 0);
1255 if (ntoappend == 0)
1256 continue;
1257 while (usednew + ntoappend > totalnew) {
1258 int bigger = totalnew << 1;
1259 if ((bigger >> 1) != totalnew) { /* overflow */
1260 PyErr_NoMemory();
1261 goto Done;
1262 }
1263 if (_PyString_Resize(&newfmt, bigger) < 0)
1264 goto Done;
1265 totalnew = bigger;
1266 pnew = PyString_AsString(newfmt) + usednew;
1267 }
1268 memcpy(pnew, ptoappend, ntoappend);
1269 pnew += ntoappend;
1270 usednew += ntoappend;
1271 assert(usednew <= totalnew);
1272 } /* end while() */
1273
1274 if (_PyString_Resize(&newfmt, usednew) < 0)
1275 goto Done;
1276 {
1277 PyObject *time = PyImport_ImportModule("time");
1278 if (time == NULL)
1279 goto Done;
1280 result = PyObject_CallMethod(time, "strftime", "OO",
1281 newfmt, timetuple);
1282 Py_DECREF(time);
1283 }
1284 Done:
1285 Py_XDECREF(zreplacement);
1286 Py_XDECREF(Zreplacement);
1287 Py_XDECREF(newfmt);
1288 return result;
1289}
1290
1291static char *
1292isoformat_date(PyDateTime_Date *dt, char buffer[], int bufflen)
1293{
1294 int x;
1295 x = PyOS_snprintf(buffer, bufflen,
1296 "%04d-%02d-%02d",
1297 GET_YEAR(dt), GET_MONTH(dt), GET_DAY(dt));
1298 return buffer + x;
1299}
1300
1301static void
1302isoformat_time(PyDateTime_DateTime *dt, char buffer[], int bufflen)
1303{
1304 int us = DATE_GET_MICROSECOND(dt);
1305
1306 PyOS_snprintf(buffer, bufflen,
1307 "%02d:%02d:%02d", /* 8 characters */
1308 DATE_GET_HOUR(dt),
1309 DATE_GET_MINUTE(dt),
1310 DATE_GET_SECOND(dt));
1311 if (us)
1312 PyOS_snprintf(buffer + 8, bufflen - 8, ".%06d", us);
1313}
1314
1315/* ---------------------------------------------------------------------------
1316 * Wrap functions from the time module. These aren't directly available
1317 * from C. Perhaps they should be.
1318 */
1319
1320/* Call time.time() and return its result (a Python float). */
1321static PyObject *
Guido van Rossumbd43e912002-12-16 20:34:55 +00001322time_time(void)
Tim Peters2a799bf2002-12-16 20:18:38 +00001323{
1324 PyObject *result = NULL;
1325 PyObject *time = PyImport_ImportModule("time");
1326
1327 if (time != NULL) {
1328 result = PyObject_CallMethod(time, "time", "()");
1329 Py_DECREF(time);
1330 }
1331 return result;
1332}
1333
1334/* Build a time.struct_time. The weekday and day number are automatically
1335 * computed from the y,m,d args.
1336 */
1337static PyObject *
1338build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
1339{
1340 PyObject *time;
1341 PyObject *result = NULL;
1342
1343 time = PyImport_ImportModule("time");
1344 if (time != NULL) {
1345 result = PyObject_CallMethod(time, "struct_time",
1346 "((iiiiiiiii))",
1347 y, m, d,
1348 hh, mm, ss,
1349 weekday(y, m, d),
1350 days_before_month(y, m) + d,
1351 dstflag);
1352 Py_DECREF(time);
1353 }
1354 return result;
1355}
1356
1357/* ---------------------------------------------------------------------------
1358 * Miscellaneous helpers.
1359 */
1360
1361/* For obscure reasons, we need to use tp_richcompare instead of tp_compare.
1362 * The comparisons here all most naturally compute a cmp()-like result.
1363 * This little helper turns that into a bool result for rich comparisons.
1364 */
1365static PyObject *
1366diff_to_bool(int diff, int op)
1367{
1368 PyObject *result;
1369 int istrue;
1370
1371 switch (op) {
1372 case Py_EQ: istrue = diff == 0; break;
1373 case Py_NE: istrue = diff != 0; break;
1374 case Py_LE: istrue = diff <= 0; break;
1375 case Py_GE: istrue = diff >= 0; break;
1376 case Py_LT: istrue = diff < 0; break;
1377 case Py_GT: istrue = diff > 0; break;
1378 default:
1379 assert(! "op unknown");
1380 istrue = 0; /* To shut up compiler */
1381 }
1382 result = istrue ? Py_True : Py_False;
1383 Py_INCREF(result);
1384 return result;
1385}
1386
Tim Peters07534a62003-02-07 22:50:28 +00001387/* Raises a "can't compare" TypeError and returns NULL. */
1388static PyObject *
1389cmperror(PyObject *a, PyObject *b)
1390{
1391 PyErr_Format(PyExc_TypeError,
1392 "can't compare %s to %s",
1393 a->ob_type->tp_name, b->ob_type->tp_name);
1394 return NULL;
1395}
1396
Tim Peters2a799bf2002-12-16 20:18:38 +00001397/* ---------------------------------------------------------------------------
Tim Peters2a799bf2002-12-16 20:18:38 +00001398 * Cached Python objects; these are set by the module init function.
1399 */
1400
1401/* Conversion factors. */
1402static PyObject *us_per_us = NULL; /* 1 */
1403static PyObject *us_per_ms = NULL; /* 1000 */
1404static PyObject *us_per_second = NULL; /* 1000000 */
1405static PyObject *us_per_minute = NULL; /* 1e6 * 60 as Python int */
1406static PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python long */
1407static PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python long */
1408static PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python long */
1409static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */
1410
Tim Peters2a799bf2002-12-16 20:18:38 +00001411/* ---------------------------------------------------------------------------
1412 * Class implementations.
1413 */
1414
1415/*
1416 * PyDateTime_Delta implementation.
1417 */
1418
1419/* Convert a timedelta to a number of us,
1420 * (24*3600*self.days + self.seconds)*1000000 + self.microseconds
1421 * as a Python int or long.
1422 * Doing mixed-radix arithmetic by hand instead is excruciating in C,
1423 * due to ubiquitous overflow possibilities.
1424 */
1425static PyObject *
1426delta_to_microseconds(PyDateTime_Delta *self)
1427{
1428 PyObject *x1 = NULL;
1429 PyObject *x2 = NULL;
1430 PyObject *x3 = NULL;
1431 PyObject *result = NULL;
1432
1433 x1 = PyInt_FromLong(GET_TD_DAYS(self));
1434 if (x1 == NULL)
1435 goto Done;
1436 x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */
1437 if (x2 == NULL)
1438 goto Done;
1439 Py_DECREF(x1);
1440 x1 = NULL;
1441
1442 /* x2 has days in seconds */
1443 x1 = PyInt_FromLong(GET_TD_SECONDS(self)); /* seconds */
1444 if (x1 == NULL)
1445 goto Done;
1446 x3 = PyNumber_Add(x1, x2); /* days and seconds in seconds */
1447 if (x3 == NULL)
1448 goto Done;
1449 Py_DECREF(x1);
1450 Py_DECREF(x2);
1451 x1 = x2 = NULL;
1452
1453 /* x3 has days+seconds in seconds */
1454 x1 = PyNumber_Multiply(x3, us_per_second); /* us */
1455 if (x1 == NULL)
1456 goto Done;
1457 Py_DECREF(x3);
1458 x3 = NULL;
1459
1460 /* x1 has days+seconds in us */
1461 x2 = PyInt_FromLong(GET_TD_MICROSECONDS(self));
1462 if (x2 == NULL)
1463 goto Done;
1464 result = PyNumber_Add(x1, x2);
1465
1466Done:
1467 Py_XDECREF(x1);
1468 Py_XDECREF(x2);
1469 Py_XDECREF(x3);
1470 return result;
1471}
1472
1473/* Convert a number of us (as a Python int or long) to a timedelta.
1474 */
1475static PyObject *
Tim Petersb0c854d2003-05-17 15:57:00 +00001476microseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type)
Tim Peters2a799bf2002-12-16 20:18:38 +00001477{
1478 int us;
1479 int s;
1480 int d;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001481 long temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001482
1483 PyObject *tuple = NULL;
1484 PyObject *num = NULL;
1485 PyObject *result = NULL;
1486
1487 tuple = PyNumber_Divmod(pyus, us_per_second);
1488 if (tuple == NULL)
1489 goto Done;
1490
1491 num = PyTuple_GetItem(tuple, 1); /* us */
1492 if (num == NULL)
1493 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001494 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001495 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001496 if (temp == -1 && PyErr_Occurred())
1497 goto Done;
1498 assert(0 <= temp && temp < 1000000);
1499 us = (int)temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001500 if (us < 0) {
1501 /* The divisor was positive, so this must be an error. */
1502 assert(PyErr_Occurred());
1503 goto Done;
1504 }
1505
1506 num = PyTuple_GetItem(tuple, 0); /* leftover seconds */
1507 if (num == NULL)
1508 goto Done;
1509 Py_INCREF(num);
1510 Py_DECREF(tuple);
1511
1512 tuple = PyNumber_Divmod(num, seconds_per_day);
1513 if (tuple == NULL)
1514 goto Done;
1515 Py_DECREF(num);
1516
1517 num = PyTuple_GetItem(tuple, 1); /* seconds */
1518 if (num == NULL)
1519 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001520 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001521 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001522 if (temp == -1 && PyErr_Occurred())
1523 goto Done;
1524 assert(0 <= temp && temp < 24*3600);
1525 s = (int)temp;
1526
Tim Peters2a799bf2002-12-16 20:18:38 +00001527 if (s < 0) {
1528 /* The divisor was positive, so this must be an error. */
1529 assert(PyErr_Occurred());
1530 goto Done;
1531 }
1532
1533 num = PyTuple_GetItem(tuple, 0); /* leftover days */
1534 if (num == NULL)
1535 goto Done;
1536 Py_INCREF(num);
Tim Peters0b0f41c2002-12-19 01:44:38 +00001537 temp = PyLong_AsLong(num);
1538 if (temp == -1 && PyErr_Occurred())
Tim Peters2a799bf2002-12-16 20:18:38 +00001539 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001540 d = (int)temp;
1541 if ((long)d != temp) {
1542 PyErr_SetString(PyExc_OverflowError, "normalized days too "
1543 "large to fit in a C int");
1544 goto Done;
1545 }
Tim Petersb0c854d2003-05-17 15:57:00 +00001546 result = new_delta_ex(d, s, us, 0, type);
Tim Peters2a799bf2002-12-16 20:18:38 +00001547
1548Done:
1549 Py_XDECREF(tuple);
1550 Py_XDECREF(num);
1551 return result;
1552}
1553
Tim Petersb0c854d2003-05-17 15:57:00 +00001554#define microseconds_to_delta(pymicros) \
1555 microseconds_to_delta_ex(pymicros, &PyDateTime_DeltaType)
1556
Tim Peters2a799bf2002-12-16 20:18:38 +00001557static PyObject *
1558multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
1559{
1560 PyObject *pyus_in;
1561 PyObject *pyus_out;
1562 PyObject *result;
1563
1564 pyus_in = delta_to_microseconds(delta);
1565 if (pyus_in == NULL)
1566 return NULL;
1567
1568 pyus_out = PyNumber_Multiply(pyus_in, intobj);
1569 Py_DECREF(pyus_in);
1570 if (pyus_out == NULL)
1571 return NULL;
1572
1573 result = microseconds_to_delta(pyus_out);
1574 Py_DECREF(pyus_out);
1575 return result;
1576}
1577
1578static PyObject *
1579divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj)
1580{
1581 PyObject *pyus_in;
1582 PyObject *pyus_out;
1583 PyObject *result;
1584
1585 pyus_in = delta_to_microseconds(delta);
1586 if (pyus_in == NULL)
1587 return NULL;
1588
1589 pyus_out = PyNumber_FloorDivide(pyus_in, intobj);
1590 Py_DECREF(pyus_in);
1591 if (pyus_out == NULL)
1592 return NULL;
1593
1594 result = microseconds_to_delta(pyus_out);
1595 Py_DECREF(pyus_out);
1596 return result;
1597}
1598
1599static PyObject *
1600delta_add(PyObject *left, PyObject *right)
1601{
1602 PyObject *result = Py_NotImplemented;
1603
1604 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1605 /* delta + delta */
1606 /* The C-level additions can't overflow because of the
1607 * invariant bounds.
1608 */
1609 int days = GET_TD_DAYS(left) + GET_TD_DAYS(right);
1610 int seconds = GET_TD_SECONDS(left) + GET_TD_SECONDS(right);
1611 int microseconds = GET_TD_MICROSECONDS(left) +
1612 GET_TD_MICROSECONDS(right);
1613 result = new_delta(days, seconds, microseconds, 1);
1614 }
1615
1616 if (result == Py_NotImplemented)
1617 Py_INCREF(result);
1618 return result;
1619}
1620
1621static PyObject *
1622delta_negative(PyDateTime_Delta *self)
1623{
1624 return new_delta(-GET_TD_DAYS(self),
1625 -GET_TD_SECONDS(self),
1626 -GET_TD_MICROSECONDS(self),
1627 1);
1628}
1629
1630static PyObject *
1631delta_positive(PyDateTime_Delta *self)
1632{
1633 /* Could optimize this (by returning self) if this isn't a
1634 * subclass -- but who uses unary + ? Approximately nobody.
1635 */
1636 return new_delta(GET_TD_DAYS(self),
1637 GET_TD_SECONDS(self),
1638 GET_TD_MICROSECONDS(self),
1639 0);
1640}
1641
1642static PyObject *
1643delta_abs(PyDateTime_Delta *self)
1644{
1645 PyObject *result;
1646
1647 assert(GET_TD_MICROSECONDS(self) >= 0);
1648 assert(GET_TD_SECONDS(self) >= 0);
1649
1650 if (GET_TD_DAYS(self) < 0)
1651 result = delta_negative(self);
1652 else
1653 result = delta_positive(self);
1654
1655 return result;
1656}
1657
1658static PyObject *
1659delta_subtract(PyObject *left, PyObject *right)
1660{
1661 PyObject *result = Py_NotImplemented;
1662
1663 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1664 /* delta - delta */
1665 PyObject *minus_right = PyNumber_Negative(right);
1666 if (minus_right) {
1667 result = delta_add(left, minus_right);
1668 Py_DECREF(minus_right);
1669 }
1670 else
1671 result = NULL;
1672 }
1673
1674 if (result == Py_NotImplemented)
1675 Py_INCREF(result);
1676 return result;
1677}
1678
1679/* This is more natural as a tp_compare, but doesn't work then: for whatever
1680 * reason, Python's try_3way_compare ignores tp_compare unless
1681 * PyInstance_Check returns true, but these aren't old-style classes.
1682 */
1683static PyObject *
1684delta_richcompare(PyDateTime_Delta *self, PyObject *other, int op)
1685{
Tim Peters07534a62003-02-07 22:50:28 +00001686 int diff = 42; /* nonsense */
Tim Peters2a799bf2002-12-16 20:18:38 +00001687
Tim Petersaa7d8492003-02-08 03:28:59 +00001688 if (PyDelta_Check(other)) {
Tim Peters07534a62003-02-07 22:50:28 +00001689 diff = GET_TD_DAYS(self) - GET_TD_DAYS(other);
1690 if (diff == 0) {
1691 diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other);
1692 if (diff == 0)
1693 diff = GET_TD_MICROSECONDS(self) -
1694 GET_TD_MICROSECONDS(other);
1695 }
Tim Peters2a799bf2002-12-16 20:18:38 +00001696 }
Tim Peters07534a62003-02-07 22:50:28 +00001697 else if (op == Py_EQ || op == Py_NE)
1698 diff = 1; /* any non-zero value will do */
1699
1700 else /* stop this from falling back to address comparison */
1701 return cmperror((PyObject *)self, other);
1702
Tim Peters2a799bf2002-12-16 20:18:38 +00001703 return diff_to_bool(diff, op);
1704}
1705
1706static PyObject *delta_getstate(PyDateTime_Delta *self);
1707
1708static long
1709delta_hash(PyDateTime_Delta *self)
1710{
1711 if (self->hashcode == -1) {
1712 PyObject *temp = delta_getstate(self);
1713 if (temp != NULL) {
1714 self->hashcode = PyObject_Hash(temp);
1715 Py_DECREF(temp);
1716 }
1717 }
1718 return self->hashcode;
1719}
1720
1721static PyObject *
1722delta_multiply(PyObject *left, PyObject *right)
1723{
1724 PyObject *result = Py_NotImplemented;
1725
1726 if (PyDelta_Check(left)) {
1727 /* delta * ??? */
1728 if (PyInt_Check(right) || PyLong_Check(right))
1729 result = multiply_int_timedelta(right,
1730 (PyDateTime_Delta *) left);
1731 }
1732 else if (PyInt_Check(left) || PyLong_Check(left))
1733 result = multiply_int_timedelta(left,
1734 (PyDateTime_Delta *) right);
1735
1736 if (result == Py_NotImplemented)
1737 Py_INCREF(result);
1738 return result;
1739}
1740
1741static PyObject *
1742delta_divide(PyObject *left, PyObject *right)
1743{
1744 PyObject *result = Py_NotImplemented;
1745
1746 if (PyDelta_Check(left)) {
1747 /* delta * ??? */
1748 if (PyInt_Check(right) || PyLong_Check(right))
1749 result = divide_timedelta_int(
1750 (PyDateTime_Delta *)left,
1751 right);
1752 }
1753
1754 if (result == Py_NotImplemented)
1755 Py_INCREF(result);
1756 return result;
1757}
1758
1759/* Fold in the value of the tag ("seconds", "weeks", etc) component of a
1760 * timedelta constructor. sofar is the # of microseconds accounted for
1761 * so far, and there are factor microseconds per current unit, the number
1762 * of which is given by num. num * factor is added to sofar in a
1763 * numerically careful way, and that's the result. Any fractional
1764 * microseconds left over (this can happen if num is a float type) are
1765 * added into *leftover.
1766 * Note that there are many ways this can give an error (NULL) return.
1767 */
1768static PyObject *
1769accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
1770 double *leftover)
1771{
1772 PyObject *prod;
1773 PyObject *sum;
1774
1775 assert(num != NULL);
1776
1777 if (PyInt_Check(num) || PyLong_Check(num)) {
1778 prod = PyNumber_Multiply(num, factor);
1779 if (prod == NULL)
1780 return NULL;
1781 sum = PyNumber_Add(sofar, prod);
1782 Py_DECREF(prod);
1783 return sum;
1784 }
1785
1786 if (PyFloat_Check(num)) {
1787 double dnum;
1788 double fracpart;
1789 double intpart;
1790 PyObject *x;
1791 PyObject *y;
1792
1793 /* The Plan: decompose num into an integer part and a
1794 * fractional part, num = intpart + fracpart.
1795 * Then num * factor ==
1796 * intpart * factor + fracpart * factor
1797 * and the LHS can be computed exactly in long arithmetic.
1798 * The RHS is again broken into an int part and frac part.
1799 * and the frac part is added into *leftover.
1800 */
1801 dnum = PyFloat_AsDouble(num);
1802 if (dnum == -1.0 && PyErr_Occurred())
1803 return NULL;
1804 fracpart = modf(dnum, &intpart);
1805 x = PyLong_FromDouble(intpart);
1806 if (x == NULL)
1807 return NULL;
1808
1809 prod = PyNumber_Multiply(x, factor);
1810 Py_DECREF(x);
1811 if (prod == NULL)
1812 return NULL;
1813
1814 sum = PyNumber_Add(sofar, prod);
1815 Py_DECREF(prod);
1816 if (sum == NULL)
1817 return NULL;
1818
1819 if (fracpart == 0.0)
1820 return sum;
1821 /* So far we've lost no information. Dealing with the
1822 * fractional part requires float arithmetic, and may
1823 * lose a little info.
1824 */
1825 assert(PyInt_Check(factor) || PyLong_Check(factor));
1826 if (PyInt_Check(factor))
1827 dnum = (double)PyInt_AsLong(factor);
1828 else
1829 dnum = PyLong_AsDouble(factor);
1830
1831 dnum *= fracpart;
1832 fracpart = modf(dnum, &intpart);
1833 x = PyLong_FromDouble(intpart);
1834 if (x == NULL) {
1835 Py_DECREF(sum);
1836 return NULL;
1837 }
1838
1839 y = PyNumber_Add(sum, x);
1840 Py_DECREF(sum);
1841 Py_DECREF(x);
1842 *leftover += fracpart;
1843 return y;
1844 }
1845
1846 PyErr_Format(PyExc_TypeError,
1847 "unsupported type for timedelta %s component: %s",
1848 tag, num->ob_type->tp_name);
1849 return NULL;
1850}
1851
1852static PyObject *
1853delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1854{
1855 PyObject *self = NULL;
1856
1857 /* Argument objects. */
1858 PyObject *day = NULL;
1859 PyObject *second = NULL;
1860 PyObject *us = NULL;
1861 PyObject *ms = NULL;
1862 PyObject *minute = NULL;
1863 PyObject *hour = NULL;
1864 PyObject *week = NULL;
1865
1866 PyObject *x = NULL; /* running sum of microseconds */
1867 PyObject *y = NULL; /* temp sum of microseconds */
1868 double leftover_us = 0.0;
1869
1870 static char *keywords[] = {
1871 "days", "seconds", "microseconds", "milliseconds",
1872 "minutes", "hours", "weeks", NULL
1873 };
1874
1875 if (PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOO:__new__",
1876 keywords,
1877 &day, &second, &us,
1878 &ms, &minute, &hour, &week) == 0)
1879 goto Done;
1880
1881 x = PyInt_FromLong(0);
1882 if (x == NULL)
1883 goto Done;
1884
1885#define CLEANUP \
1886 Py_DECREF(x); \
1887 x = y; \
1888 if (x == NULL) \
1889 goto Done
1890
1891 if (us) {
1892 y = accum("microseconds", x, us, us_per_us, &leftover_us);
1893 CLEANUP;
1894 }
1895 if (ms) {
1896 y = accum("milliseconds", x, ms, us_per_ms, &leftover_us);
1897 CLEANUP;
1898 }
1899 if (second) {
1900 y = accum("seconds", x, second, us_per_second, &leftover_us);
1901 CLEANUP;
1902 }
1903 if (minute) {
1904 y = accum("minutes", x, minute, us_per_minute, &leftover_us);
1905 CLEANUP;
1906 }
1907 if (hour) {
1908 y = accum("hours", x, hour, us_per_hour, &leftover_us);
1909 CLEANUP;
1910 }
1911 if (day) {
1912 y = accum("days", x, day, us_per_day, &leftover_us);
1913 CLEANUP;
1914 }
1915 if (week) {
1916 y = accum("weeks", x, week, us_per_week, &leftover_us);
1917 CLEANUP;
1918 }
1919 if (leftover_us) {
1920 /* Round to nearest whole # of us, and add into x. */
Tim Peters5d644dd2003-01-02 16:32:54 +00001921 PyObject *temp = PyLong_FromLong(round_to_long(leftover_us));
Tim Peters2a799bf2002-12-16 20:18:38 +00001922 if (temp == NULL) {
1923 Py_DECREF(x);
1924 goto Done;
1925 }
1926 y = PyNumber_Add(x, temp);
1927 Py_DECREF(temp);
1928 CLEANUP;
1929 }
1930
Tim Petersb0c854d2003-05-17 15:57:00 +00001931 self = microseconds_to_delta_ex(x, type);
Tim Peters2a799bf2002-12-16 20:18:38 +00001932 Py_DECREF(x);
1933Done:
1934 return self;
1935
1936#undef CLEANUP
1937}
1938
1939static int
1940delta_nonzero(PyDateTime_Delta *self)
1941{
1942 return (GET_TD_DAYS(self) != 0
1943 || GET_TD_SECONDS(self) != 0
1944 || GET_TD_MICROSECONDS(self) != 0);
1945}
1946
1947static PyObject *
1948delta_repr(PyDateTime_Delta *self)
1949{
1950 if (GET_TD_MICROSECONDS(self) != 0)
1951 return PyString_FromFormat("%s(%d, %d, %d)",
1952 self->ob_type->tp_name,
1953 GET_TD_DAYS(self),
1954 GET_TD_SECONDS(self),
1955 GET_TD_MICROSECONDS(self));
1956 if (GET_TD_SECONDS(self) != 0)
1957 return PyString_FromFormat("%s(%d, %d)",
1958 self->ob_type->tp_name,
1959 GET_TD_DAYS(self),
1960 GET_TD_SECONDS(self));
1961
1962 return PyString_FromFormat("%s(%d)",
1963 self->ob_type->tp_name,
1964 GET_TD_DAYS(self));
1965}
1966
1967static PyObject *
1968delta_str(PyDateTime_Delta *self)
1969{
1970 int days = GET_TD_DAYS(self);
1971 int seconds = GET_TD_SECONDS(self);
1972 int us = GET_TD_MICROSECONDS(self);
1973 int hours;
1974 int minutes;
Tim Petersba873472002-12-18 20:19:21 +00001975 char buf[100];
1976 char *pbuf = buf;
1977 size_t buflen = sizeof(buf);
1978 int n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001979
1980 minutes = divmod(seconds, 60, &seconds);
1981 hours = divmod(minutes, 60, &minutes);
1982
1983 if (days) {
Tim Petersba873472002-12-18 20:19:21 +00001984 n = PyOS_snprintf(pbuf, buflen, "%d day%s, ", days,
1985 (days == 1 || days == -1) ? "" : "s");
1986 if (n < 0 || (size_t)n >= buflen)
1987 goto Fail;
1988 pbuf += n;
1989 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001990 }
1991
Tim Petersba873472002-12-18 20:19:21 +00001992 n = PyOS_snprintf(pbuf, buflen, "%d:%02d:%02d",
1993 hours, minutes, seconds);
1994 if (n < 0 || (size_t)n >= buflen)
1995 goto Fail;
1996 pbuf += n;
1997 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001998
1999 if (us) {
Tim Petersba873472002-12-18 20:19:21 +00002000 n = PyOS_snprintf(pbuf, buflen, ".%06d", us);
2001 if (n < 0 || (size_t)n >= buflen)
2002 goto Fail;
2003 pbuf += n;
Tim Peters2a799bf2002-12-16 20:18:38 +00002004 }
2005
Tim Petersba873472002-12-18 20:19:21 +00002006 return PyString_FromStringAndSize(buf, pbuf - buf);
2007
2008 Fail:
2009 PyErr_SetString(PyExc_SystemError, "goofy result from PyOS_snprintf");
2010 return NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00002011}
2012
Tim Peters371935f2003-02-01 01:52:50 +00002013/* Pickle support, a simple use of __reduce__. */
2014
Tim Petersb57f8f02003-02-01 02:54:15 +00002015/* __getstate__ isn't exposed */
Tim Peters2a799bf2002-12-16 20:18:38 +00002016static PyObject *
2017delta_getstate(PyDateTime_Delta *self)
2018{
2019 return Py_BuildValue("iii", GET_TD_DAYS(self),
2020 GET_TD_SECONDS(self),
2021 GET_TD_MICROSECONDS(self));
2022}
2023
Tim Peters2a799bf2002-12-16 20:18:38 +00002024static PyObject *
2025delta_reduce(PyDateTime_Delta* self)
2026{
Tim Peters8a60c222003-02-01 01:47:29 +00002027 return Py_BuildValue("ON", self->ob_type, delta_getstate(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00002028}
2029
2030#define OFFSET(field) offsetof(PyDateTime_Delta, field)
2031
2032static PyMemberDef delta_members[] = {
Guido van Rossum177e41a2003-01-30 22:06:23 +00002033
Neal Norwitzdfb80862002-12-19 02:30:56 +00002034 {"days", T_INT, OFFSET(days), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002035 PyDoc_STR("Number of days.")},
2036
Neal Norwitzdfb80862002-12-19 02:30:56 +00002037 {"seconds", T_INT, OFFSET(seconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002038 PyDoc_STR("Number of seconds (>= 0 and less than 1 day).")},
2039
Neal Norwitzdfb80862002-12-19 02:30:56 +00002040 {"microseconds", T_INT, OFFSET(microseconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002041 PyDoc_STR("Number of microseconds (>= 0 and less than 1 second).")},
2042 {NULL}
2043};
2044
2045static PyMethodDef delta_methods[] = {
Guido van Rossum177e41a2003-01-30 22:06:23 +00002046 {"__reduce__", (PyCFunction)delta_reduce, METH_NOARGS,
2047 PyDoc_STR("__reduce__() -> (cls, state)")},
2048
Tim Peters2a799bf2002-12-16 20:18:38 +00002049 {NULL, NULL},
2050};
2051
2052static char delta_doc[] =
2053PyDoc_STR("Difference between two datetime values.");
2054
2055static PyNumberMethods delta_as_number = {
2056 delta_add, /* nb_add */
2057 delta_subtract, /* nb_subtract */
2058 delta_multiply, /* nb_multiply */
2059 delta_divide, /* nb_divide */
2060 0, /* nb_remainder */
2061 0, /* nb_divmod */
2062 0, /* nb_power */
2063 (unaryfunc)delta_negative, /* nb_negative */
2064 (unaryfunc)delta_positive, /* nb_positive */
2065 (unaryfunc)delta_abs, /* nb_absolute */
2066 (inquiry)delta_nonzero, /* nb_nonzero */
2067 0, /*nb_invert*/
2068 0, /*nb_lshift*/
2069 0, /*nb_rshift*/
2070 0, /*nb_and*/
2071 0, /*nb_xor*/
2072 0, /*nb_or*/
2073 0, /*nb_coerce*/
2074 0, /*nb_int*/
2075 0, /*nb_long*/
2076 0, /*nb_float*/
2077 0, /*nb_oct*/
2078 0, /*nb_hex*/
2079 0, /*nb_inplace_add*/
2080 0, /*nb_inplace_subtract*/
2081 0, /*nb_inplace_multiply*/
2082 0, /*nb_inplace_divide*/
2083 0, /*nb_inplace_remainder*/
2084 0, /*nb_inplace_power*/
2085 0, /*nb_inplace_lshift*/
2086 0, /*nb_inplace_rshift*/
2087 0, /*nb_inplace_and*/
2088 0, /*nb_inplace_xor*/
2089 0, /*nb_inplace_or*/
2090 delta_divide, /* nb_floor_divide */
2091 0, /* nb_true_divide */
2092 0, /* nb_inplace_floor_divide */
2093 0, /* nb_inplace_true_divide */
2094};
2095
2096static PyTypeObject PyDateTime_DeltaType = {
2097 PyObject_HEAD_INIT(NULL)
2098 0, /* ob_size */
2099 "datetime.timedelta", /* tp_name */
2100 sizeof(PyDateTime_Delta), /* tp_basicsize */
2101 0, /* tp_itemsize */
2102 0, /* tp_dealloc */
2103 0, /* tp_print */
2104 0, /* tp_getattr */
2105 0, /* tp_setattr */
2106 0, /* tp_compare */
2107 (reprfunc)delta_repr, /* tp_repr */
2108 &delta_as_number, /* tp_as_number */
2109 0, /* tp_as_sequence */
2110 0, /* tp_as_mapping */
2111 (hashfunc)delta_hash, /* tp_hash */
2112 0, /* tp_call */
2113 (reprfunc)delta_str, /* tp_str */
2114 PyObject_GenericGetAttr, /* tp_getattro */
2115 0, /* tp_setattro */
2116 0, /* tp_as_buffer */
Tim Petersb0c854d2003-05-17 15:57:00 +00002117 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
2118 Py_TPFLAGS_BASETYPE, /* tp_flags */
Tim Peters2a799bf2002-12-16 20:18:38 +00002119 delta_doc, /* tp_doc */
2120 0, /* tp_traverse */
2121 0, /* tp_clear */
2122 (richcmpfunc)delta_richcompare, /* tp_richcompare */
2123 0, /* tp_weaklistoffset */
2124 0, /* tp_iter */
2125 0, /* tp_iternext */
2126 delta_methods, /* tp_methods */
2127 delta_members, /* tp_members */
2128 0, /* tp_getset */
2129 0, /* tp_base */
2130 0, /* tp_dict */
2131 0, /* tp_descr_get */
2132 0, /* tp_descr_set */
2133 0, /* tp_dictoffset */
2134 0, /* tp_init */
2135 0, /* tp_alloc */
2136 delta_new, /* tp_new */
Tim Peters4c530132003-05-16 22:44:06 +00002137 0, /* tp_free */
Tim Peters2a799bf2002-12-16 20:18:38 +00002138};
2139
2140/*
2141 * PyDateTime_Date implementation.
2142 */
2143
2144/* Accessor properties. */
2145
2146static PyObject *
2147date_year(PyDateTime_Date *self, void *unused)
2148{
2149 return PyInt_FromLong(GET_YEAR(self));
2150}
2151
2152static PyObject *
2153date_month(PyDateTime_Date *self, void *unused)
2154{
2155 return PyInt_FromLong(GET_MONTH(self));
2156}
2157
2158static PyObject *
2159date_day(PyDateTime_Date *self, void *unused)
2160{
2161 return PyInt_FromLong(GET_DAY(self));
2162}
2163
2164static PyGetSetDef date_getset[] = {
2165 {"year", (getter)date_year},
2166 {"month", (getter)date_month},
2167 {"day", (getter)date_day},
2168 {NULL}
2169};
2170
2171/* Constructors. */
2172
Tim Peters12bf3392002-12-24 05:41:27 +00002173static char *date_kws[] = {"year", "month", "day", NULL};
2174
Tim Peters2a799bf2002-12-16 20:18:38 +00002175static PyObject *
2176date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2177{
2178 PyObject *self = NULL;
Tim Peters70533e22003-02-01 04:40:04 +00002179 PyObject *state;
Tim Peters2a799bf2002-12-16 20:18:38 +00002180 int year;
2181 int month;
2182 int day;
2183
Guido van Rossum177e41a2003-01-30 22:06:23 +00002184 /* Check for invocation from pickle with __getstate__ state */
2185 if (PyTuple_GET_SIZE(args) == 1 &&
Tim Peters70533e22003-02-01 04:40:04 +00002186 PyString_Check(state = PyTuple_GET_ITEM(args, 0)) &&
2187 PyString_GET_SIZE(state) == _PyDateTime_DATE_DATASIZE)
Guido van Rossum177e41a2003-01-30 22:06:23 +00002188 {
Tim Peters70533e22003-02-01 04:40:04 +00002189 PyDateTime_Date *me;
2190
Guido van Rossum8b7a9a32003-04-14 22:01:58 +00002191 me = PyObject_New(PyDateTime_Date, type);
Tim Peters70533e22003-02-01 04:40:04 +00002192 if (me != NULL) {
2193 char *pdata = PyString_AS_STRING(state);
2194 memcpy(me->data, pdata, _PyDateTime_DATE_DATASIZE);
2195 me->hashcode = -1;
Guido van Rossum177e41a2003-01-30 22:06:23 +00002196 }
Tim Peters70533e22003-02-01 04:40:04 +00002197 return (PyObject *)me;
Guido van Rossum177e41a2003-01-30 22:06:23 +00002198 }
2199
Tim Peters12bf3392002-12-24 05:41:27 +00002200 if (PyArg_ParseTupleAndKeywords(args, kw, "iii", date_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002201 &year, &month, &day)) {
2202 if (check_date_args(year, month, day) < 0)
2203 return NULL;
Guido van Rossum8b7a9a32003-04-14 22:01:58 +00002204 self = new_date_ex(year, month, day, type);
Tim Peters2a799bf2002-12-16 20:18:38 +00002205 }
2206 return self;
2207}
2208
2209/* Return new date from localtime(t). */
2210static PyObject *
2211date_local_from_time_t(PyObject *cls, time_t t)
2212{
2213 struct tm *tm;
2214 PyObject *result = NULL;
2215
2216 tm = localtime(&t);
2217 if (tm)
2218 result = PyObject_CallFunction(cls, "iii",
2219 tm->tm_year + 1900,
2220 tm->tm_mon + 1,
2221 tm->tm_mday);
2222 else
2223 PyErr_SetString(PyExc_ValueError,
2224 "timestamp out of range for "
2225 "platform localtime() function");
2226 return result;
2227}
2228
2229/* Return new date from current time.
2230 * We say this is equivalent to fromtimestamp(time.time()), and the
2231 * only way to be sure of that is to *call* time.time(). That's not
2232 * generally the same as calling C's time.
2233 */
2234static PyObject *
2235date_today(PyObject *cls, PyObject *dummy)
2236{
2237 PyObject *time;
2238 PyObject *result;
2239
2240 time = time_time();
2241 if (time == NULL)
2242 return NULL;
2243
2244 /* Note well: today() is a class method, so this may not call
2245 * date.fromtimestamp. For example, it may call
2246 * datetime.fromtimestamp. That's why we need all the accuracy
2247 * time.time() delivers; if someone were gonzo about optimization,
2248 * date.today() could get away with plain C time().
2249 */
2250 result = PyObject_CallMethod(cls, "fromtimestamp", "O", time);
2251 Py_DECREF(time);
2252 return result;
2253}
2254
2255/* Return new date from given timestamp (Python timestamp -- a double). */
2256static PyObject *
2257date_fromtimestamp(PyObject *cls, PyObject *args)
2258{
2259 double timestamp;
2260 PyObject *result = NULL;
2261
2262 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2263 result = date_local_from_time_t(cls, (time_t)timestamp);
2264 return result;
2265}
2266
2267/* Return new date from proleptic Gregorian ordinal. Raises ValueError if
2268 * the ordinal is out of range.
2269 */
2270static PyObject *
2271date_fromordinal(PyObject *cls, PyObject *args)
2272{
2273 PyObject *result = NULL;
2274 int ordinal;
2275
2276 if (PyArg_ParseTuple(args, "i:fromordinal", &ordinal)) {
2277 int year;
2278 int month;
2279 int day;
2280
2281 if (ordinal < 1)
2282 PyErr_SetString(PyExc_ValueError, "ordinal must be "
2283 ">= 1");
2284 else {
2285 ord_to_ymd(ordinal, &year, &month, &day);
2286 result = PyObject_CallFunction(cls, "iii",
2287 year, month, day);
2288 }
2289 }
2290 return result;
2291}
2292
2293/*
2294 * Date arithmetic.
2295 */
2296
2297/* date + timedelta -> date. If arg negate is true, subtract the timedelta
2298 * instead.
2299 */
2300static PyObject *
2301add_date_timedelta(PyDateTime_Date *date, PyDateTime_Delta *delta, int negate)
2302{
2303 PyObject *result = NULL;
2304 int year = GET_YEAR(date);
2305 int month = GET_MONTH(date);
2306 int deltadays = GET_TD_DAYS(delta);
2307 /* C-level overflow is impossible because |deltadays| < 1e9. */
2308 int day = GET_DAY(date) + (negate ? -deltadays : deltadays);
2309
2310 if (normalize_date(&year, &month, &day) >= 0)
2311 result = new_date(year, month, day);
2312 return result;
2313}
2314
2315static PyObject *
2316date_add(PyObject *left, PyObject *right)
2317{
2318 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2319 Py_INCREF(Py_NotImplemented);
2320 return Py_NotImplemented;
2321 }
Tim Petersaa7d8492003-02-08 03:28:59 +00002322 if (PyDate_Check(left)) {
Tim Peters2a799bf2002-12-16 20:18:38 +00002323 /* date + ??? */
2324 if (PyDelta_Check(right))
2325 /* date + delta */
2326 return add_date_timedelta((PyDateTime_Date *) left,
2327 (PyDateTime_Delta *) right,
2328 0);
2329 }
2330 else {
2331 /* ??? + date
2332 * 'right' must be one of us, or we wouldn't have been called
2333 */
2334 if (PyDelta_Check(left))
2335 /* delta + date */
2336 return add_date_timedelta((PyDateTime_Date *) right,
2337 (PyDateTime_Delta *) left,
2338 0);
2339 }
2340 Py_INCREF(Py_NotImplemented);
2341 return Py_NotImplemented;
2342}
2343
2344static PyObject *
2345date_subtract(PyObject *left, PyObject *right)
2346{
2347 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2348 Py_INCREF(Py_NotImplemented);
2349 return Py_NotImplemented;
2350 }
Tim Petersaa7d8492003-02-08 03:28:59 +00002351 if (PyDate_Check(left)) {
2352 if (PyDate_Check(right)) {
Tim Peters2a799bf2002-12-16 20:18:38 +00002353 /* date - date */
2354 int left_ord = ymd_to_ord(GET_YEAR(left),
2355 GET_MONTH(left),
2356 GET_DAY(left));
2357 int right_ord = ymd_to_ord(GET_YEAR(right),
2358 GET_MONTH(right),
2359 GET_DAY(right));
2360 return new_delta(left_ord - right_ord, 0, 0, 0);
2361 }
2362 if (PyDelta_Check(right)) {
2363 /* date - delta */
2364 return add_date_timedelta((PyDateTime_Date *) left,
2365 (PyDateTime_Delta *) right,
2366 1);
2367 }
2368 }
2369 Py_INCREF(Py_NotImplemented);
2370 return Py_NotImplemented;
2371}
2372
2373
2374/* Various ways to turn a date into a string. */
2375
2376static PyObject *
2377date_repr(PyDateTime_Date *self)
2378{
2379 char buffer[1028];
2380 char *typename;
2381
2382 typename = self->ob_type->tp_name;
2383 PyOS_snprintf(buffer, sizeof(buffer), "%s(%d, %d, %d)",
2384 typename,
2385 GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2386
2387 return PyString_FromString(buffer);
2388}
2389
2390static PyObject *
2391date_isoformat(PyDateTime_Date *self)
2392{
2393 char buffer[128];
2394
2395 isoformat_date(self, buffer, sizeof(buffer));
2396 return PyString_FromString(buffer);
2397}
2398
Tim Peterse2df5ff2003-05-02 18:39:55 +00002399/* str() calls the appropriate isoformat() method. */
Tim Peters2a799bf2002-12-16 20:18:38 +00002400static PyObject *
2401date_str(PyDateTime_Date *self)
2402{
2403 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
2404}
2405
2406
2407static PyObject *
2408date_ctime(PyDateTime_Date *self)
2409{
2410 return format_ctime(self, 0, 0, 0);
2411}
2412
2413static PyObject *
2414date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2415{
2416 /* This method can be inherited, and needs to call the
2417 * timetuple() method appropriate to self's class.
2418 */
2419 PyObject *result;
2420 PyObject *format;
2421 PyObject *tuple;
2422 static char *keywords[] = {"format", NULL};
2423
2424 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
2425 &PyString_Type, &format))
2426 return NULL;
2427
2428 tuple = PyObject_CallMethod((PyObject *)self, "timetuple", "()");
2429 if (tuple == NULL)
2430 return NULL;
Tim Petersbad8ff02002-12-30 20:52:32 +00002431 result = wrap_strftime((PyObject *)self, format, tuple,
2432 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00002433 Py_DECREF(tuple);
2434 return result;
2435}
2436
2437/* ISO methods. */
2438
2439static PyObject *
2440date_isoweekday(PyDateTime_Date *self)
2441{
2442 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2443
2444 return PyInt_FromLong(dow + 1);
2445}
2446
2447static PyObject *
2448date_isocalendar(PyDateTime_Date *self)
2449{
2450 int year = GET_YEAR(self);
2451 int week1_monday = iso_week1_monday(year);
2452 int today = ymd_to_ord(year, GET_MONTH(self), GET_DAY(self));
2453 int week;
2454 int day;
2455
2456 week = divmod(today - week1_monday, 7, &day);
2457 if (week < 0) {
2458 --year;
2459 week1_monday = iso_week1_monday(year);
2460 week = divmod(today - week1_monday, 7, &day);
2461 }
2462 else if (week >= 52 && today >= iso_week1_monday(year + 1)) {
2463 ++year;
2464 week = 0;
2465 }
2466 return Py_BuildValue("iii", year, week + 1, day + 1);
2467}
2468
2469/* Miscellaneous methods. */
2470
2471/* This is more natural as a tp_compare, but doesn't work then: for whatever
2472 * reason, Python's try_3way_compare ignores tp_compare unless
2473 * PyInstance_Check returns true, but these aren't old-style classes.
2474 */
2475static PyObject *
2476date_richcompare(PyDateTime_Date *self, PyObject *other, int op)
2477{
Tim Peters07534a62003-02-07 22:50:28 +00002478 int diff = 42; /* nonsense */
Tim Peters2a799bf2002-12-16 20:18:38 +00002479
Tim Peters07534a62003-02-07 22:50:28 +00002480 if (PyDate_Check(other))
2481 diff = memcmp(self->data, ((PyDateTime_Date *)other)->data,
2482 _PyDateTime_DATE_DATASIZE);
2483
2484 else if (PyObject_HasAttrString(other, "timetuple")) {
2485 /* A hook for other kinds of date objects. */
2486 Py_INCREF(Py_NotImplemented);
2487 return Py_NotImplemented;
Tim Peters2a799bf2002-12-16 20:18:38 +00002488 }
Tim Peters07534a62003-02-07 22:50:28 +00002489 else if (op == Py_EQ || op == Py_NE)
2490 diff = 1; /* any non-zero value will do */
2491
2492 else /* stop this from falling back to address comparison */
2493 return cmperror((PyObject *)self, other);
2494
Tim Peters2a799bf2002-12-16 20:18:38 +00002495 return diff_to_bool(diff, op);
2496}
2497
2498static PyObject *
2499date_timetuple(PyDateTime_Date *self)
2500{
2501 return build_struct_time(GET_YEAR(self),
2502 GET_MONTH(self),
2503 GET_DAY(self),
2504 0, 0, 0, -1);
2505}
2506
Tim Peters12bf3392002-12-24 05:41:27 +00002507static PyObject *
2508date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2509{
2510 PyObject *clone;
2511 PyObject *tuple;
2512 int year = GET_YEAR(self);
2513 int month = GET_MONTH(self);
2514 int day = GET_DAY(self);
2515
2516 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iii:replace", date_kws,
2517 &year, &month, &day))
2518 return NULL;
2519 tuple = Py_BuildValue("iii", year, month, day);
2520 if (tuple == NULL)
2521 return NULL;
2522 clone = date_new(self->ob_type, tuple, NULL);
2523 Py_DECREF(tuple);
2524 return clone;
2525}
2526
Tim Peters2a799bf2002-12-16 20:18:38 +00002527static PyObject *date_getstate(PyDateTime_Date *self);
2528
2529static long
2530date_hash(PyDateTime_Date *self)
2531{
2532 if (self->hashcode == -1) {
2533 PyObject *temp = date_getstate(self);
2534 if (temp != NULL) {
2535 self->hashcode = PyObject_Hash(temp);
2536 Py_DECREF(temp);
2537 }
2538 }
2539 return self->hashcode;
2540}
2541
2542static PyObject *
2543date_toordinal(PyDateTime_Date *self)
2544{
2545 return PyInt_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self),
2546 GET_DAY(self)));
2547}
2548
2549static PyObject *
2550date_weekday(PyDateTime_Date *self)
2551{
2552 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2553
2554 return PyInt_FromLong(dow);
2555}
2556
Tim Peters371935f2003-02-01 01:52:50 +00002557/* Pickle support, a simple use of __reduce__. */
Tim Peters2a799bf2002-12-16 20:18:38 +00002558
Tim Petersb57f8f02003-02-01 02:54:15 +00002559/* __getstate__ isn't exposed */
Tim Peters2a799bf2002-12-16 20:18:38 +00002560static PyObject *
2561date_getstate(PyDateTime_Date *self)
2562{
Guido van Rossum177e41a2003-01-30 22:06:23 +00002563 return Py_BuildValue(
2564 "(N)",
2565 PyString_FromStringAndSize((char *)self->data,
2566 _PyDateTime_DATE_DATASIZE));
Tim Peters2a799bf2002-12-16 20:18:38 +00002567}
2568
2569static PyObject *
Guido van Rossum177e41a2003-01-30 22:06:23 +00002570date_reduce(PyDateTime_Date *self, PyObject *arg)
Tim Peters2a799bf2002-12-16 20:18:38 +00002571{
Guido van Rossum177e41a2003-01-30 22:06:23 +00002572 return Py_BuildValue("(ON)", self->ob_type, date_getstate(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00002573}
2574
2575static PyMethodDef date_methods[] = {
Guido van Rossum177e41a2003-01-30 22:06:23 +00002576
Tim Peters2a799bf2002-12-16 20:18:38 +00002577 /* Class methods: */
Guido van Rossum177e41a2003-01-30 22:06:23 +00002578
Tim Peters2a799bf2002-12-16 20:18:38 +00002579 {"fromtimestamp", (PyCFunction)date_fromtimestamp, METH_VARARGS |
2580 METH_CLASS,
2581 PyDoc_STR("timestamp -> local date from a POSIX timestamp (like "
2582 "time.time()).")},
2583
2584 {"fromordinal", (PyCFunction)date_fromordinal, METH_VARARGS |
2585 METH_CLASS,
2586 PyDoc_STR("int -> date corresponding to a proleptic Gregorian "
2587 "ordinal.")},
2588
2589 {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS,
2590 PyDoc_STR("Current date or datetime: same as "
2591 "self.__class__.fromtimestamp(time.time()).")},
2592
2593 /* Instance methods: */
2594
2595 {"ctime", (PyCFunction)date_ctime, METH_NOARGS,
2596 PyDoc_STR("Return ctime() style string.")},
2597
2598 {"strftime", (PyCFunction)date_strftime, METH_KEYWORDS,
2599 PyDoc_STR("format -> strftime() style string.")},
2600
2601 {"timetuple", (PyCFunction)date_timetuple, METH_NOARGS,
2602 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
2603
2604 {"isocalendar", (PyCFunction)date_isocalendar, METH_NOARGS,
2605 PyDoc_STR("Return a 3-tuple containing ISO year, week number, and "
2606 "weekday.")},
2607
2608 {"isoformat", (PyCFunction)date_isoformat, METH_NOARGS,
2609 PyDoc_STR("Return string in ISO 8601 format, YYYY-MM-DD.")},
2610
2611 {"isoweekday", (PyCFunction)date_isoweekday, METH_NOARGS,
2612 PyDoc_STR("Return the day of the week represented by the date.\n"
2613 "Monday == 1 ... Sunday == 7")},
2614
2615 {"toordinal", (PyCFunction)date_toordinal, METH_NOARGS,
2616 PyDoc_STR("Return proleptic Gregorian ordinal. January 1 of year "
2617 "1 is day 1.")},
2618
2619 {"weekday", (PyCFunction)date_weekday, METH_NOARGS,
2620 PyDoc_STR("Return the day of the week represented by the date.\n"
2621 "Monday == 0 ... Sunday == 6")},
2622
Tim Peters12bf3392002-12-24 05:41:27 +00002623 {"replace", (PyCFunction)date_replace, METH_KEYWORDS,
2624 PyDoc_STR("Return date with new specified fields.")},
2625
Guido van Rossum177e41a2003-01-30 22:06:23 +00002626 {"__reduce__", (PyCFunction)date_reduce, METH_NOARGS,
2627 PyDoc_STR("__reduce__() -> (cls, state)")},
2628
Tim Peters2a799bf2002-12-16 20:18:38 +00002629 {NULL, NULL}
2630};
2631
2632static char date_doc[] =
2633PyDoc_STR("Basic date type.");
2634
2635static PyNumberMethods date_as_number = {
2636 date_add, /* nb_add */
2637 date_subtract, /* nb_subtract */
2638 0, /* nb_multiply */
2639 0, /* nb_divide */
2640 0, /* nb_remainder */
2641 0, /* nb_divmod */
2642 0, /* nb_power */
2643 0, /* nb_negative */
2644 0, /* nb_positive */
2645 0, /* nb_absolute */
2646 0, /* nb_nonzero */
2647};
2648
2649static PyTypeObject PyDateTime_DateType = {
2650 PyObject_HEAD_INIT(NULL)
2651 0, /* ob_size */
2652 "datetime.date", /* tp_name */
2653 sizeof(PyDateTime_Date), /* tp_basicsize */
2654 0, /* tp_itemsize */
Guido van Rossum8b7a9a32003-04-14 22:01:58 +00002655 0, /* tp_dealloc */
Tim Peters2a799bf2002-12-16 20:18:38 +00002656 0, /* tp_print */
2657 0, /* tp_getattr */
2658 0, /* tp_setattr */
2659 0, /* tp_compare */
2660 (reprfunc)date_repr, /* tp_repr */
2661 &date_as_number, /* tp_as_number */
2662 0, /* tp_as_sequence */
2663 0, /* tp_as_mapping */
2664 (hashfunc)date_hash, /* tp_hash */
2665 0, /* tp_call */
2666 (reprfunc)date_str, /* tp_str */
2667 PyObject_GenericGetAttr, /* tp_getattro */
2668 0, /* tp_setattro */
2669 0, /* tp_as_buffer */
2670 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
2671 Py_TPFLAGS_BASETYPE, /* tp_flags */
2672 date_doc, /* tp_doc */
2673 0, /* tp_traverse */
2674 0, /* tp_clear */
2675 (richcmpfunc)date_richcompare, /* tp_richcompare */
2676 0, /* tp_weaklistoffset */
2677 0, /* tp_iter */
2678 0, /* tp_iternext */
2679 date_methods, /* tp_methods */
2680 0, /* tp_members */
2681 date_getset, /* tp_getset */
2682 0, /* tp_base */
2683 0, /* tp_dict */
2684 0, /* tp_descr_get */
2685 0, /* tp_descr_set */
2686 0, /* tp_dictoffset */
2687 0, /* tp_init */
2688 0, /* tp_alloc */
2689 date_new, /* tp_new */
Tim Peters4c530132003-05-16 22:44:06 +00002690 0, /* tp_free */
Tim Peters2a799bf2002-12-16 20:18:38 +00002691};
2692
2693/*
Tim Peters2a799bf2002-12-16 20:18:38 +00002694 * PyDateTime_TZInfo implementation.
2695 */
2696
2697/* This is a pure abstract base class, so doesn't do anything beyond
2698 * raising NotImplemented exceptions. Real tzinfo classes need
2699 * to derive from this. This is mostly for clarity, and for efficiency in
Tim Petersa9bc1682003-01-11 03:39:11 +00002700 * datetime and time constructors (their tzinfo arguments need to
Tim Peters2a799bf2002-12-16 20:18:38 +00002701 * be subclasses of this tzinfo class, which is easy and quick to check).
2702 *
2703 * Note: For reasons having to do with pickling of subclasses, we have
2704 * to allow tzinfo objects to be instantiated. This wasn't an issue
2705 * in the Python implementation (__init__() could raise NotImplementedError
2706 * there without ill effect), but doing so in the C implementation hit a
2707 * brick wall.
2708 */
2709
2710static PyObject *
2711tzinfo_nogo(const char* methodname)
2712{
2713 PyErr_Format(PyExc_NotImplementedError,
2714 "a tzinfo subclass must implement %s()",
2715 methodname);
2716 return NULL;
2717}
2718
2719/* Methods. A subclass must implement these. */
2720
Tim Peters52dcce22003-01-23 16:36:11 +00002721static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00002722tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt)
2723{
2724 return tzinfo_nogo("tzname");
2725}
2726
Tim Peters52dcce22003-01-23 16:36:11 +00002727static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00002728tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt)
2729{
2730 return tzinfo_nogo("utcoffset");
2731}
2732
Tim Peters52dcce22003-01-23 16:36:11 +00002733static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00002734tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
2735{
2736 return tzinfo_nogo("dst");
2737}
2738
Tim Peters52dcce22003-01-23 16:36:11 +00002739static PyObject *
2740tzinfo_fromutc(PyDateTime_TZInfo *self, PyDateTime_DateTime *dt)
2741{
2742 int y, m, d, hh, mm, ss, us;
2743
2744 PyObject *result;
2745 int off, dst;
2746 int none;
2747 int delta;
2748
2749 if (! PyDateTime_Check(dt)) {
2750 PyErr_SetString(PyExc_TypeError,
2751 "fromutc: argument must be a datetime");
2752 return NULL;
2753 }
2754 if (! HASTZINFO(dt) || dt->tzinfo != (PyObject *)self) {
2755 PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo "
2756 "is not self");
2757 return NULL;
2758 }
2759
2760 off = call_utcoffset(dt->tzinfo, (PyObject *)dt, &none);
2761 if (off == -1 && PyErr_Occurred())
2762 return NULL;
2763 if (none) {
2764 PyErr_SetString(PyExc_ValueError, "fromutc: non-None "
2765 "utcoffset() result required");
2766 return NULL;
2767 }
2768
2769 dst = call_dst(dt->tzinfo, (PyObject *)dt, &none);
2770 if (dst == -1 && PyErr_Occurred())
2771 return NULL;
2772 if (none) {
2773 PyErr_SetString(PyExc_ValueError, "fromutc: non-None "
2774 "dst() result required");
2775 return NULL;
2776 }
2777
2778 y = GET_YEAR(dt);
2779 m = GET_MONTH(dt);
2780 d = GET_DAY(dt);
2781 hh = DATE_GET_HOUR(dt);
2782 mm = DATE_GET_MINUTE(dt);
2783 ss = DATE_GET_SECOND(dt);
2784 us = DATE_GET_MICROSECOND(dt);
2785
2786 delta = off - dst;
2787 mm += delta;
2788 if ((mm < 0 || mm >= 60) &&
2789 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Petersb1049e82003-01-23 17:20:36 +00002790 return NULL;
Tim Peters52dcce22003-01-23 16:36:11 +00002791 result = new_datetime(y, m, d, hh, mm, ss, us, dt->tzinfo);
2792 if (result == NULL)
2793 return result;
2794
2795 dst = call_dst(dt->tzinfo, result, &none);
2796 if (dst == -1 && PyErr_Occurred())
2797 goto Fail;
2798 if (none)
2799 goto Inconsistent;
2800 if (dst == 0)
2801 return result;
2802
2803 mm += dst;
2804 if ((mm < 0 || mm >= 60) &&
2805 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
2806 goto Fail;
2807 Py_DECREF(result);
2808 result = new_datetime(y, m, d, hh, mm, ss, us, dt->tzinfo);
2809 return result;
2810
2811Inconsistent:
2812 PyErr_SetString(PyExc_ValueError, "fromutc: tz.dst() gave"
2813 "inconsistent results; cannot convert");
2814
2815 /* fall thru to failure */
2816Fail:
2817 Py_DECREF(result);
2818 return NULL;
2819}
2820
Tim Peters2a799bf2002-12-16 20:18:38 +00002821/*
2822 * Pickle support. This is solely so that tzinfo subclasses can use
Guido van Rossum177e41a2003-01-30 22:06:23 +00002823 * pickling -- tzinfo itself is supposed to be uninstantiable.
Tim Peters2a799bf2002-12-16 20:18:38 +00002824 */
2825
Guido van Rossum177e41a2003-01-30 22:06:23 +00002826static PyObject *
2827tzinfo_reduce(PyObject *self)
2828{
2829 PyObject *args, *state, *tmp;
2830 PyObject *getinitargs, *getstate;
Tim Peters2a799bf2002-12-16 20:18:38 +00002831
Guido van Rossum177e41a2003-01-30 22:06:23 +00002832 tmp = PyTuple_New(0);
2833 if (tmp == NULL)
2834 return NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00002835
Guido van Rossum177e41a2003-01-30 22:06:23 +00002836 getinitargs = PyObject_GetAttrString(self, "__getinitargs__");
2837 if (getinitargs != NULL) {
2838 args = PyObject_CallObject(getinitargs, tmp);
2839 Py_DECREF(getinitargs);
2840 if (args == NULL) {
2841 Py_DECREF(tmp);
2842 return NULL;
2843 }
2844 }
2845 else {
2846 PyErr_Clear();
2847 args = tmp;
2848 Py_INCREF(args);
2849 }
2850
2851 getstate = PyObject_GetAttrString(self, "__getstate__");
2852 if (getstate != NULL) {
2853 state = PyObject_CallObject(getstate, tmp);
2854 Py_DECREF(getstate);
2855 if (state == NULL) {
2856 Py_DECREF(args);
2857 Py_DECREF(tmp);
2858 return NULL;
2859 }
2860 }
2861 else {
2862 PyObject **dictptr;
2863 PyErr_Clear();
2864 state = Py_None;
2865 dictptr = _PyObject_GetDictPtr(self);
2866 if (dictptr && *dictptr && PyDict_Size(*dictptr))
2867 state = *dictptr;
2868 Py_INCREF(state);
2869 }
2870
2871 Py_DECREF(tmp);
2872
2873 if (state == Py_None) {
2874 Py_DECREF(state);
2875 return Py_BuildValue("(ON)", self->ob_type, args);
2876 }
2877 else
2878 return Py_BuildValue("(ONN)", self->ob_type, args, state);
2879}
Tim Peters2a799bf2002-12-16 20:18:38 +00002880
2881static PyMethodDef tzinfo_methods[] = {
Guido van Rossum177e41a2003-01-30 22:06:23 +00002882
Tim Peters2a799bf2002-12-16 20:18:38 +00002883 {"tzname", (PyCFunction)tzinfo_tzname, METH_O,
2884 PyDoc_STR("datetime -> string name of time zone.")},
2885
2886 {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
2887 PyDoc_STR("datetime -> minutes east of UTC (negative for "
2888 "west of UTC).")},
2889
2890 {"dst", (PyCFunction)tzinfo_dst, METH_O,
2891 PyDoc_STR("datetime -> DST offset in minutes east of UTC.")},
2892
Tim Peters52dcce22003-01-23 16:36:11 +00002893 {"fromutc", (PyCFunction)tzinfo_fromutc, METH_O,
2894 PyDoc_STR("datetime in UTC -> datetime in local time.")},
2895
Guido van Rossum177e41a2003-01-30 22:06:23 +00002896 {"__reduce__", (PyCFunction)tzinfo_reduce, METH_NOARGS,
2897 PyDoc_STR("-> (cls, state)")},
2898
Tim Peters2a799bf2002-12-16 20:18:38 +00002899 {NULL, NULL}
2900};
2901
2902static char tzinfo_doc[] =
2903PyDoc_STR("Abstract base class for time zone info objects.");
2904
Neal Norwitzce3d34d2003-02-04 20:45:17 +00002905statichere PyTypeObject PyDateTime_TZInfoType = {
Tim Peters2a799bf2002-12-16 20:18:38 +00002906 PyObject_HEAD_INIT(NULL)
2907 0, /* ob_size */
2908 "datetime.tzinfo", /* tp_name */
2909 sizeof(PyDateTime_TZInfo), /* tp_basicsize */
2910 0, /* tp_itemsize */
2911 0, /* tp_dealloc */
2912 0, /* tp_print */
2913 0, /* tp_getattr */
2914 0, /* tp_setattr */
2915 0, /* tp_compare */
2916 0, /* tp_repr */
2917 0, /* tp_as_number */
2918 0, /* tp_as_sequence */
2919 0, /* tp_as_mapping */
2920 0, /* tp_hash */
2921 0, /* tp_call */
2922 0, /* tp_str */
2923 PyObject_GenericGetAttr, /* tp_getattro */
2924 0, /* tp_setattro */
2925 0, /* tp_as_buffer */
2926 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
2927 Py_TPFLAGS_BASETYPE, /* tp_flags */
2928 tzinfo_doc, /* tp_doc */
2929 0, /* tp_traverse */
2930 0, /* tp_clear */
2931 0, /* tp_richcompare */
2932 0, /* tp_weaklistoffset */
2933 0, /* tp_iter */
2934 0, /* tp_iternext */
2935 tzinfo_methods, /* tp_methods */
2936 0, /* tp_members */
2937 0, /* tp_getset */
2938 0, /* tp_base */
2939 0, /* tp_dict */
2940 0, /* tp_descr_get */
2941 0, /* tp_descr_set */
2942 0, /* tp_dictoffset */
2943 0, /* tp_init */
2944 0, /* tp_alloc */
2945 PyType_GenericNew, /* tp_new */
2946 0, /* tp_free */
2947};
2948
2949/*
Tim Peters37f39822003-01-10 03:49:02 +00002950 * PyDateTime_Time implementation.
Tim Peters2a799bf2002-12-16 20:18:38 +00002951 */
2952
Tim Peters37f39822003-01-10 03:49:02 +00002953/* Accessor properties.
Tim Peters2a799bf2002-12-16 20:18:38 +00002954 */
2955
2956static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00002957time_hour(PyDateTime_Time *self, void *unused)
Tim Peters2a799bf2002-12-16 20:18:38 +00002958{
Tim Peters37f39822003-01-10 03:49:02 +00002959 return PyInt_FromLong(TIME_GET_HOUR(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00002960}
2961
Tim Peters37f39822003-01-10 03:49:02 +00002962static PyObject *
2963time_minute(PyDateTime_Time *self, void *unused)
2964{
2965 return PyInt_FromLong(TIME_GET_MINUTE(self));
2966}
2967
2968/* The name time_second conflicted with some platform header file. */
2969static PyObject *
2970py_time_second(PyDateTime_Time *self, void *unused)
2971{
2972 return PyInt_FromLong(TIME_GET_SECOND(self));
2973}
2974
2975static PyObject *
2976time_microsecond(PyDateTime_Time *self, void *unused)
2977{
2978 return PyInt_FromLong(TIME_GET_MICROSECOND(self));
2979}
2980
2981static PyObject *
2982time_tzinfo(PyDateTime_Time *self, void *unused)
2983{
Tim Petersa032d2e2003-01-11 00:15:54 +00002984 PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
Tim Peters37f39822003-01-10 03:49:02 +00002985 Py_INCREF(result);
2986 return result;
2987}
2988
2989static PyGetSetDef time_getset[] = {
2990 {"hour", (getter)time_hour},
2991 {"minute", (getter)time_minute},
2992 {"second", (getter)py_time_second},
2993 {"microsecond", (getter)time_microsecond},
2994 {"tzinfo", (getter)time_tzinfo},
Tim Peters2a799bf2002-12-16 20:18:38 +00002995 {NULL}
2996};
2997
2998/*
2999 * Constructors.
3000 */
3001
Tim Peters37f39822003-01-10 03:49:02 +00003002static char *time_kws[] = {"hour", "minute", "second", "microsecond",
3003 "tzinfo", NULL};
Tim Peters12bf3392002-12-24 05:41:27 +00003004
Tim Peters2a799bf2002-12-16 20:18:38 +00003005static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003006time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003007{
3008 PyObject *self = NULL;
Tim Peters70533e22003-02-01 04:40:04 +00003009 PyObject *state;
Tim Peters2a799bf2002-12-16 20:18:38 +00003010 int hour = 0;
3011 int minute = 0;
3012 int second = 0;
3013 int usecond = 0;
3014 PyObject *tzinfo = Py_None;
3015
Guido van Rossum177e41a2003-01-30 22:06:23 +00003016 /* Check for invocation from pickle with __getstate__ state */
3017 if (PyTuple_GET_SIZE(args) >= 1 &&
3018 PyTuple_GET_SIZE(args) <= 2 &&
Tim Peters70533e22003-02-01 04:40:04 +00003019 PyString_Check(state = PyTuple_GET_ITEM(args, 0)) &&
3020 PyString_GET_SIZE(state) == _PyDateTime_TIME_DATASIZE)
Guido van Rossum177e41a2003-01-30 22:06:23 +00003021 {
Tim Peters70533e22003-02-01 04:40:04 +00003022 PyDateTime_Time *me;
3023 char aware;
3024
3025 if (PyTuple_GET_SIZE(args) == 2) {
Guido van Rossum177e41a2003-01-30 22:06:23 +00003026 tzinfo = PyTuple_GET_ITEM(args, 1);
Tim Peters70533e22003-02-01 04:40:04 +00003027 if (check_tzinfo_subclass(tzinfo) < 0) {
3028 PyErr_SetString(PyExc_TypeError, "bad "
3029 "tzinfo state arg");
3030 return NULL;
Guido van Rossum177e41a2003-01-30 22:06:23 +00003031 }
3032 }
Tim Peters70533e22003-02-01 04:40:04 +00003033 aware = (char)(tzinfo != Py_None);
Tim Petersa98924a2003-05-17 05:55:19 +00003034 me = (PyDateTime_Time *) time_alloc(&PyDateTime_TimeType,
3035 aware);
Tim Peters70533e22003-02-01 04:40:04 +00003036 if (me != NULL) {
3037 char *pdata = PyString_AS_STRING(state);
3038
3039 memcpy(me->data, pdata, _PyDateTime_TIME_DATASIZE);
3040 me->hashcode = -1;
3041 me->hastzinfo = aware;
3042 if (aware) {
3043 Py_INCREF(tzinfo);
3044 me->tzinfo = tzinfo;
3045 }
3046 }
3047 return (PyObject *)me;
Guido van Rossum177e41a2003-01-30 22:06:23 +00003048 }
3049
Tim Peters37f39822003-01-10 03:49:02 +00003050 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", time_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00003051 &hour, &minute, &second, &usecond,
3052 &tzinfo)) {
3053 if (check_time_args(hour, minute, second, usecond) < 0)
3054 return NULL;
3055 if (check_tzinfo_subclass(tzinfo) < 0)
3056 return NULL;
Tim Petersa98924a2003-05-17 05:55:19 +00003057 self = new_time_ex(hour, minute, second, usecond, tzinfo,
3058 type);
Tim Peters2a799bf2002-12-16 20:18:38 +00003059 }
3060 return self;
3061}
3062
3063/*
3064 * Destructor.
3065 */
3066
3067static void
Tim Peters37f39822003-01-10 03:49:02 +00003068time_dealloc(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003069{
Tim Petersa032d2e2003-01-11 00:15:54 +00003070 if (HASTZINFO(self)) {
Tim Peters37f39822003-01-10 03:49:02 +00003071 Py_XDECREF(self->tzinfo);
Neal Norwitz8e914d92003-01-10 15:29:16 +00003072 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003073 self->ob_type->tp_free((PyObject *)self);
3074}
3075
3076/*
Tim Peters855fe882002-12-22 03:43:39 +00003077 * Indirect access to tzinfo methods.
Tim Peters2a799bf2002-12-16 20:18:38 +00003078 */
3079
Tim Peters2a799bf2002-12-16 20:18:38 +00003080/* These are all METH_NOARGS, so don't need to check the arglist. */
3081static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003082time_utcoffset(PyDateTime_Time *self, PyObject *unused) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003083 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
Tim Peters37f39822003-01-10 03:49:02 +00003084 "utcoffset", Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003085}
3086
3087static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003088time_dst(PyDateTime_Time *self, PyObject *unused) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003089 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
Tim Peters37f39822003-01-10 03:49:02 +00003090 "dst", Py_None);
Tim Peters855fe882002-12-22 03:43:39 +00003091}
3092
3093static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003094time_tzname(PyDateTime_Time *self, PyObject *unused) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003095 return call_tzname(HASTZINFO(self) ? self->tzinfo : Py_None,
Tim Peters37f39822003-01-10 03:49:02 +00003096 Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003097}
3098
3099/*
Tim Peters37f39822003-01-10 03:49:02 +00003100 * Various ways to turn a time into a string.
Tim Peters2a799bf2002-12-16 20:18:38 +00003101 */
3102
3103static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003104time_repr(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003105{
Tim Peters37f39822003-01-10 03:49:02 +00003106 char buffer[100];
3107 char *typename = self->ob_type->tp_name;
3108 int h = TIME_GET_HOUR(self);
3109 int m = TIME_GET_MINUTE(self);
3110 int s = TIME_GET_SECOND(self);
3111 int us = TIME_GET_MICROSECOND(self);
3112 PyObject *result = NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00003113
Tim Peters37f39822003-01-10 03:49:02 +00003114 if (us)
3115 PyOS_snprintf(buffer, sizeof(buffer),
3116 "%s(%d, %d, %d, %d)", typename, h, m, s, us);
3117 else if (s)
3118 PyOS_snprintf(buffer, sizeof(buffer),
3119 "%s(%d, %d, %d)", typename, h, m, s);
3120 else
3121 PyOS_snprintf(buffer, sizeof(buffer),
3122 "%s(%d, %d)", typename, h, m);
3123 result = PyString_FromString(buffer);
Tim Petersa032d2e2003-01-11 00:15:54 +00003124 if (result != NULL && HASTZINFO(self))
Tim Peters37f39822003-01-10 03:49:02 +00003125 result = append_keyword_tzinfo(result, self->tzinfo);
3126 return result;
Tim Peters2a799bf2002-12-16 20:18:38 +00003127}
3128
Tim Peters37f39822003-01-10 03:49:02 +00003129static PyObject *
3130time_str(PyDateTime_Time *self)
3131{
3132 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
3133}
Tim Peters2a799bf2002-12-16 20:18:38 +00003134
3135static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003136time_isoformat(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003137{
3138 char buf[100];
Tim Peters37f39822003-01-10 03:49:02 +00003139 PyObject *result;
3140 /* Reuse the time format code from the datetime type. */
3141 PyDateTime_DateTime datetime;
3142 PyDateTime_DateTime *pdatetime = &datetime;
Tim Peters2a799bf2002-12-16 20:18:38 +00003143
Tim Peters37f39822003-01-10 03:49:02 +00003144 /* Copy over just the time bytes. */
3145 memcpy(pdatetime->data + _PyDateTime_DATE_DATASIZE,
3146 self->data,
3147 _PyDateTime_TIME_DATASIZE);
3148
3149 isoformat_time(pdatetime, buf, sizeof(buf));
3150 result = PyString_FromString(buf);
Tim Petersa032d2e2003-01-11 00:15:54 +00003151 if (result == NULL || ! HASTZINFO(self) || self->tzinfo == Py_None)
Tim Peters2a799bf2002-12-16 20:18:38 +00003152 return result;
3153
3154 /* We need to append the UTC offset. */
3155 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00003156 Py_None) < 0) {
Tim Peters2a799bf2002-12-16 20:18:38 +00003157 Py_DECREF(result);
3158 return NULL;
3159 }
3160 PyString_ConcatAndDel(&result, PyString_FromString(buf));
3161 return result;
3162}
3163
Tim Peters37f39822003-01-10 03:49:02 +00003164static PyObject *
3165time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3166{
3167 PyObject *result;
3168 PyObject *format;
3169 PyObject *tuple;
3170 static char *keywords[] = {"format", NULL};
3171
3172 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
3173 &PyString_Type, &format))
3174 return NULL;
3175
3176 /* Python's strftime does insane things with the year part of the
3177 * timetuple. The year is forced to (the otherwise nonsensical)
3178 * 1900 to worm around that.
3179 */
3180 tuple = Py_BuildValue("iiiiiiiii",
3181 1900, 0, 0, /* year, month, day */
3182 TIME_GET_HOUR(self),
3183 TIME_GET_MINUTE(self),
3184 TIME_GET_SECOND(self),
3185 0, 0, -1); /* weekday, daynum, dst */
3186 if (tuple == NULL)
3187 return NULL;
3188 assert(PyTuple_Size(tuple) == 9);
3189 result = wrap_strftime((PyObject *)self, format, tuple, Py_None);
3190 Py_DECREF(tuple);
3191 return result;
3192}
Tim Peters2a799bf2002-12-16 20:18:38 +00003193
3194/*
3195 * Miscellaneous methods.
3196 */
3197
Tim Peters37f39822003-01-10 03:49:02 +00003198/* This is more natural as a tp_compare, but doesn't work then: for whatever
3199 * reason, Python's try_3way_compare ignores tp_compare unless
3200 * PyInstance_Check returns true, but these aren't old-style classes.
3201 */
3202static PyObject *
3203time_richcompare(PyDateTime_Time *self, PyObject *other, int op)
3204{
3205 int diff;
3206 naivety n1, n2;
3207 int offset1, offset2;
3208
3209 if (! PyTime_Check(other)) {
Tim Peters07534a62003-02-07 22:50:28 +00003210 if (op == Py_EQ || op == Py_NE) {
3211 PyObject *result = op == Py_EQ ? Py_False : Py_True;
3212 Py_INCREF(result);
3213 return result;
3214 }
Tim Peters37f39822003-01-10 03:49:02 +00003215 /* Stop this from falling back to address comparison. */
Tim Peters07534a62003-02-07 22:50:28 +00003216 return cmperror((PyObject *)self, other);
Tim Peters37f39822003-01-10 03:49:02 +00003217 }
3218 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1, Py_None,
3219 other, &offset2, &n2, Py_None) < 0)
3220 return NULL;
3221 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
3222 /* If they're both naive, or both aware and have the same offsets,
3223 * we get off cheap. Note that if they're both naive, offset1 ==
3224 * offset2 == 0 at this point.
3225 */
3226 if (n1 == n2 && offset1 == offset2) {
3227 diff = memcmp(self->data, ((PyDateTime_Time *)other)->data,
3228 _PyDateTime_TIME_DATASIZE);
3229 return diff_to_bool(diff, op);
3230 }
3231
3232 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3233 assert(offset1 != offset2); /* else last "if" handled it */
3234 /* Convert everything except microseconds to seconds. These
3235 * can't overflow (no more than the # of seconds in 2 days).
3236 */
3237 offset1 = TIME_GET_HOUR(self) * 3600 +
3238 (TIME_GET_MINUTE(self) - offset1) * 60 +
3239 TIME_GET_SECOND(self);
3240 offset2 = TIME_GET_HOUR(other) * 3600 +
3241 (TIME_GET_MINUTE(other) - offset2) * 60 +
3242 TIME_GET_SECOND(other);
3243 diff = offset1 - offset2;
3244 if (diff == 0)
3245 diff = TIME_GET_MICROSECOND(self) -
3246 TIME_GET_MICROSECOND(other);
3247 return diff_to_bool(diff, op);
3248 }
3249
3250 assert(n1 != n2);
3251 PyErr_SetString(PyExc_TypeError,
3252 "can't compare offset-naive and "
3253 "offset-aware times");
3254 return NULL;
3255}
3256
3257static long
3258time_hash(PyDateTime_Time *self)
3259{
3260 if (self->hashcode == -1) {
3261 naivety n;
3262 int offset;
3263 PyObject *temp;
3264
3265 n = classify_utcoffset((PyObject *)self, Py_None, &offset);
3266 assert(n != OFFSET_UNKNOWN);
3267 if (n == OFFSET_ERROR)
3268 return -1;
3269
3270 /* Reduce this to a hash of another object. */
3271 if (offset == 0)
3272 temp = PyString_FromStringAndSize((char *)self->data,
3273 _PyDateTime_TIME_DATASIZE);
3274 else {
3275 int hour;
3276 int minute;
3277
3278 assert(n == OFFSET_AWARE);
Tim Petersa032d2e2003-01-11 00:15:54 +00003279 assert(HASTZINFO(self));
Tim Peters37f39822003-01-10 03:49:02 +00003280 hour = divmod(TIME_GET_HOUR(self) * 60 +
3281 TIME_GET_MINUTE(self) - offset,
3282 60,
3283 &minute);
3284 if (0 <= hour && hour < 24)
3285 temp = new_time(hour, minute,
3286 TIME_GET_SECOND(self),
3287 TIME_GET_MICROSECOND(self),
3288 Py_None);
3289 else
3290 temp = Py_BuildValue("iiii",
3291 hour, minute,
3292 TIME_GET_SECOND(self),
3293 TIME_GET_MICROSECOND(self));
3294 }
3295 if (temp != NULL) {
3296 self->hashcode = PyObject_Hash(temp);
3297 Py_DECREF(temp);
3298 }
3299 }
3300 return self->hashcode;
3301}
Tim Peters2a799bf2002-12-16 20:18:38 +00003302
Tim Peters12bf3392002-12-24 05:41:27 +00003303static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003304time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
Tim Peters12bf3392002-12-24 05:41:27 +00003305{
3306 PyObject *clone;
3307 PyObject *tuple;
3308 int hh = TIME_GET_HOUR(self);
3309 int mm = TIME_GET_MINUTE(self);
3310 int ss = TIME_GET_SECOND(self);
3311 int us = TIME_GET_MICROSECOND(self);
Tim Petersa032d2e2003-01-11 00:15:54 +00003312 PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
Tim Peters12bf3392002-12-24 05:41:27 +00003313
3314 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
Tim Peters37f39822003-01-10 03:49:02 +00003315 time_kws,
Tim Peters12bf3392002-12-24 05:41:27 +00003316 &hh, &mm, &ss, &us, &tzinfo))
3317 return NULL;
3318 tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
3319 if (tuple == NULL)
3320 return NULL;
Tim Peters37f39822003-01-10 03:49:02 +00003321 clone = time_new(self->ob_type, tuple, NULL);
Tim Peters12bf3392002-12-24 05:41:27 +00003322 Py_DECREF(tuple);
3323 return clone;
3324}
3325
Tim Peters2a799bf2002-12-16 20:18:38 +00003326static int
Tim Peters37f39822003-01-10 03:49:02 +00003327time_nonzero(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003328{
3329 int offset;
3330 int none;
3331
3332 if (TIME_GET_SECOND(self) || TIME_GET_MICROSECOND(self)) {
3333 /* Since utcoffset is in whole minutes, nothing can
3334 * alter the conclusion that this is nonzero.
3335 */
3336 return 1;
3337 }
3338 offset = 0;
Tim Petersa032d2e2003-01-11 00:15:54 +00003339 if (HASTZINFO(self) && self->tzinfo != Py_None) {
Tim Petersbad8ff02002-12-30 20:52:32 +00003340 offset = call_utcoffset(self->tzinfo, Py_None, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +00003341 if (offset == -1 && PyErr_Occurred())
3342 return -1;
3343 }
3344 return (TIME_GET_MINUTE(self) - offset + TIME_GET_HOUR(self)*60) != 0;
3345}
3346
Tim Peters371935f2003-02-01 01:52:50 +00003347/* Pickle support, a simple use of __reduce__. */
Tim Peters2a799bf2002-12-16 20:18:38 +00003348
Tim Peters33e0f382003-01-10 02:05:14 +00003349/* Let basestate be the non-tzinfo data string.
Tim Peters2a799bf2002-12-16 20:18:38 +00003350 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
3351 * So it's a tuple in any (non-error) case.
Tim Petersb57f8f02003-02-01 02:54:15 +00003352 * __getstate__ isn't exposed.
Tim Peters2a799bf2002-12-16 20:18:38 +00003353 */
3354static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003355time_getstate(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003356{
3357 PyObject *basestate;
3358 PyObject *result = NULL;
3359
Tim Peters33e0f382003-01-10 02:05:14 +00003360 basestate = PyString_FromStringAndSize((char *)self->data,
3361 _PyDateTime_TIME_DATASIZE);
Tim Peters2a799bf2002-12-16 20:18:38 +00003362 if (basestate != NULL) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003363 if (! HASTZINFO(self) || self->tzinfo == Py_None)
Tim Peters2a799bf2002-12-16 20:18:38 +00003364 result = Py_BuildValue("(O)", basestate);
3365 else
3366 result = Py_BuildValue("OO", basestate, self->tzinfo);
3367 Py_DECREF(basestate);
3368 }
3369 return result;
3370}
3371
3372static PyObject *
Guido van Rossum177e41a2003-01-30 22:06:23 +00003373time_reduce(PyDateTime_Time *self, PyObject *arg)
Tim Peters2a799bf2002-12-16 20:18:38 +00003374{
Guido van Rossum177e41a2003-01-30 22:06:23 +00003375 return Py_BuildValue("(ON)", self->ob_type, time_getstate(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00003376}
3377
Tim Peters37f39822003-01-10 03:49:02 +00003378static PyMethodDef time_methods[] = {
Guido van Rossum177e41a2003-01-30 22:06:23 +00003379
Tim Peters37f39822003-01-10 03:49:02 +00003380 {"isoformat", (PyCFunction)time_isoformat, METH_KEYWORDS,
Tim Peters2a799bf2002-12-16 20:18:38 +00003381 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]"
3382 "[+HH:MM].")},
3383
Tim Peters37f39822003-01-10 03:49:02 +00003384 {"strftime", (PyCFunction)time_strftime, METH_KEYWORDS,
3385 PyDoc_STR("format -> strftime() style string.")},
3386
3387 {"utcoffset", (PyCFunction)time_utcoffset, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00003388 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
3389
Tim Peters37f39822003-01-10 03:49:02 +00003390 {"tzname", (PyCFunction)time_tzname, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00003391 PyDoc_STR("Return self.tzinfo.tzname(self).")},
3392
Tim Peters37f39822003-01-10 03:49:02 +00003393 {"dst", (PyCFunction)time_dst, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00003394 PyDoc_STR("Return self.tzinfo.dst(self).")},
3395
Tim Peters37f39822003-01-10 03:49:02 +00003396 {"replace", (PyCFunction)time_replace, METH_KEYWORDS,
3397 PyDoc_STR("Return time with new specified fields.")},
Tim Peters12bf3392002-12-24 05:41:27 +00003398
Guido van Rossum177e41a2003-01-30 22:06:23 +00003399 {"__reduce__", (PyCFunction)time_reduce, METH_NOARGS,
3400 PyDoc_STR("__reduce__() -> (cls, state)")},
3401
Tim Peters2a799bf2002-12-16 20:18:38 +00003402 {NULL, NULL}
Tim Peters2a799bf2002-12-16 20:18:38 +00003403};
3404
Tim Peters37f39822003-01-10 03:49:02 +00003405static char time_doc[] =
Tim Peters2a799bf2002-12-16 20:18:38 +00003406PyDoc_STR("Time type.");
3407
Tim Peters37f39822003-01-10 03:49:02 +00003408static PyNumberMethods time_as_number = {
Tim Peters2a799bf2002-12-16 20:18:38 +00003409 0, /* nb_add */
3410 0, /* nb_subtract */
3411 0, /* nb_multiply */
3412 0, /* nb_divide */
3413 0, /* nb_remainder */
3414 0, /* nb_divmod */
3415 0, /* nb_power */
3416 0, /* nb_negative */
3417 0, /* nb_positive */
3418 0, /* nb_absolute */
Tim Peters37f39822003-01-10 03:49:02 +00003419 (inquiry)time_nonzero, /* nb_nonzero */
Tim Peters2a799bf2002-12-16 20:18:38 +00003420};
3421
Tim Peters37f39822003-01-10 03:49:02 +00003422statichere PyTypeObject PyDateTime_TimeType = {
Tim Peters2a799bf2002-12-16 20:18:38 +00003423 PyObject_HEAD_INIT(NULL)
3424 0, /* ob_size */
Tim Peters0bf60bd2003-01-08 20:40:01 +00003425 "datetime.time", /* tp_name */
Tim Peters37f39822003-01-10 03:49:02 +00003426 sizeof(PyDateTime_Time), /* tp_basicsize */
Tim Peters2a799bf2002-12-16 20:18:38 +00003427 0, /* tp_itemsize */
Tim Peters37f39822003-01-10 03:49:02 +00003428 (destructor)time_dealloc, /* tp_dealloc */
Tim Peters2a799bf2002-12-16 20:18:38 +00003429 0, /* tp_print */
3430 0, /* tp_getattr */
3431 0, /* tp_setattr */
3432 0, /* tp_compare */
Tim Peters37f39822003-01-10 03:49:02 +00003433 (reprfunc)time_repr, /* tp_repr */
3434 &time_as_number, /* tp_as_number */
Tim Peters2a799bf2002-12-16 20:18:38 +00003435 0, /* tp_as_sequence */
3436 0, /* tp_as_mapping */
Tim Peters37f39822003-01-10 03:49:02 +00003437 (hashfunc)time_hash, /* tp_hash */
Tim Peters2a799bf2002-12-16 20:18:38 +00003438 0, /* tp_call */
Tim Peters37f39822003-01-10 03:49:02 +00003439 (reprfunc)time_str, /* tp_str */
Tim Peters2a799bf2002-12-16 20:18:38 +00003440 PyObject_GenericGetAttr, /* tp_getattro */
3441 0, /* tp_setattro */
3442 0, /* tp_as_buffer */
3443 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3444 Py_TPFLAGS_BASETYPE, /* tp_flags */
Tim Peters37f39822003-01-10 03:49:02 +00003445 time_doc, /* tp_doc */
Tim Peters2a799bf2002-12-16 20:18:38 +00003446 0, /* tp_traverse */
3447 0, /* tp_clear */
Tim Peters37f39822003-01-10 03:49:02 +00003448 (richcmpfunc)time_richcompare, /* tp_richcompare */
Tim Peters2a799bf2002-12-16 20:18:38 +00003449 0, /* tp_weaklistoffset */
3450 0, /* tp_iter */
3451 0, /* tp_iternext */
Tim Peters37f39822003-01-10 03:49:02 +00003452 time_methods, /* tp_methods */
Tim Peters2a799bf2002-12-16 20:18:38 +00003453 0, /* tp_members */
Tim Peters37f39822003-01-10 03:49:02 +00003454 time_getset, /* tp_getset */
3455 0, /* tp_base */
Tim Peters2a799bf2002-12-16 20:18:38 +00003456 0, /* tp_dict */
3457 0, /* tp_descr_get */
3458 0, /* tp_descr_set */
3459 0, /* tp_dictoffset */
3460 0, /* tp_init */
Tim Petersa98924a2003-05-17 05:55:19 +00003461 time_alloc, /* tp_alloc */
Tim Peters37f39822003-01-10 03:49:02 +00003462 time_new, /* tp_new */
Tim Peters4c530132003-05-16 22:44:06 +00003463 0, /* tp_free */
Tim Peters2a799bf2002-12-16 20:18:38 +00003464};
3465
3466/*
Tim Petersa9bc1682003-01-11 03:39:11 +00003467 * PyDateTime_DateTime implementation.
Tim Peters2a799bf2002-12-16 20:18:38 +00003468 */
3469
Tim Petersa9bc1682003-01-11 03:39:11 +00003470/* Accessor properties. Properties for day, month, and year are inherited
3471 * from date.
Tim Peters2a799bf2002-12-16 20:18:38 +00003472 */
3473
3474static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003475datetime_hour(PyDateTime_DateTime *self, void *unused)
Tim Peters2a799bf2002-12-16 20:18:38 +00003476{
Tim Petersa9bc1682003-01-11 03:39:11 +00003477 return PyInt_FromLong(DATE_GET_HOUR(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00003478}
3479
Tim Petersa9bc1682003-01-11 03:39:11 +00003480static PyObject *
3481datetime_minute(PyDateTime_DateTime *self, void *unused)
3482{
3483 return PyInt_FromLong(DATE_GET_MINUTE(self));
3484}
3485
3486static PyObject *
3487datetime_second(PyDateTime_DateTime *self, void *unused)
3488{
3489 return PyInt_FromLong(DATE_GET_SECOND(self));
3490}
3491
3492static PyObject *
3493datetime_microsecond(PyDateTime_DateTime *self, void *unused)
3494{
3495 return PyInt_FromLong(DATE_GET_MICROSECOND(self));
3496}
3497
3498static PyObject *
3499datetime_tzinfo(PyDateTime_DateTime *self, void *unused)
3500{
3501 PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
3502 Py_INCREF(result);
3503 return result;
3504}
3505
3506static PyGetSetDef datetime_getset[] = {
3507 {"hour", (getter)datetime_hour},
3508 {"minute", (getter)datetime_minute},
3509 {"second", (getter)datetime_second},
3510 {"microsecond", (getter)datetime_microsecond},
3511 {"tzinfo", (getter)datetime_tzinfo},
Tim Peters2a799bf2002-12-16 20:18:38 +00003512 {NULL}
3513};
3514
3515/*
3516 * Constructors.
Tim Peters2a799bf2002-12-16 20:18:38 +00003517 */
3518
Tim Petersa9bc1682003-01-11 03:39:11 +00003519static char *datetime_kws[] = {
Tim Peters12bf3392002-12-24 05:41:27 +00003520 "year", "month", "day", "hour", "minute", "second",
3521 "microsecond", "tzinfo", NULL
3522};
3523
Tim Peters2a799bf2002-12-16 20:18:38 +00003524static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003525datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003526{
3527 PyObject *self = NULL;
Tim Peters70533e22003-02-01 04:40:04 +00003528 PyObject *state;
Tim Peters2a799bf2002-12-16 20:18:38 +00003529 int year;
3530 int month;
3531 int day;
3532 int hour = 0;
3533 int minute = 0;
3534 int second = 0;
3535 int usecond = 0;
3536 PyObject *tzinfo = Py_None;
3537
Guido van Rossum177e41a2003-01-30 22:06:23 +00003538 /* Check for invocation from pickle with __getstate__ state */
3539 if (PyTuple_GET_SIZE(args) >= 1 &&
3540 PyTuple_GET_SIZE(args) <= 2 &&
Tim Peters70533e22003-02-01 04:40:04 +00003541 PyString_Check(state = PyTuple_GET_ITEM(args, 0)) &&
3542 PyString_GET_SIZE(state) == _PyDateTime_DATETIME_DATASIZE)
Guido van Rossum177e41a2003-01-30 22:06:23 +00003543 {
Tim Peters70533e22003-02-01 04:40:04 +00003544 PyDateTime_DateTime *me;
3545 char aware;
3546
3547 if (PyTuple_GET_SIZE(args) == 2) {
Guido van Rossum177e41a2003-01-30 22:06:23 +00003548 tzinfo = PyTuple_GET_ITEM(args, 1);
Tim Peters70533e22003-02-01 04:40:04 +00003549 if (check_tzinfo_subclass(tzinfo) < 0) {
3550 PyErr_SetString(PyExc_TypeError, "bad "
3551 "tzinfo state arg");
3552 return NULL;
Guido van Rossum177e41a2003-01-30 22:06:23 +00003553 }
3554 }
Tim Peters70533e22003-02-01 04:40:04 +00003555 aware = (char)(tzinfo != Py_None);
Tim Petersa98924a2003-05-17 05:55:19 +00003556 me = (PyDateTime_DateTime *) datetime_alloc(
3557 &PyDateTime_DateTimeType,
3558 aware);
Tim Peters70533e22003-02-01 04:40:04 +00003559 if (me != NULL) {
3560 char *pdata = PyString_AS_STRING(state);
3561
3562 memcpy(me->data, pdata, _PyDateTime_DATETIME_DATASIZE);
3563 me->hashcode = -1;
3564 me->hastzinfo = aware;
3565 if (aware) {
3566 Py_INCREF(tzinfo);
3567 me->tzinfo = tzinfo;
3568 }
3569 }
3570 return (PyObject *)me;
Guido van Rossum177e41a2003-01-30 22:06:23 +00003571 }
3572
Tim Petersa9bc1682003-01-11 03:39:11 +00003573 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO", datetime_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00003574 &year, &month, &day, &hour, &minute,
3575 &second, &usecond, &tzinfo)) {
3576 if (check_date_args(year, month, day) < 0)
3577 return NULL;
3578 if (check_time_args(hour, minute, second, usecond) < 0)
3579 return NULL;
3580 if (check_tzinfo_subclass(tzinfo) < 0)
3581 return NULL;
Tim Petersa98924a2003-05-17 05:55:19 +00003582 self = new_datetime_ex(year, month, day,
3583 hour, minute, second, usecond,
3584 tzinfo, type);
Tim Peters2a799bf2002-12-16 20:18:38 +00003585 }
3586 return self;
3587}
3588
Tim Petersa9bc1682003-01-11 03:39:11 +00003589/* TM_FUNC is the shared type of localtime() and gmtime(). */
3590typedef struct tm *(*TM_FUNC)(const time_t *timer);
3591
3592/* Internal helper.
3593 * Build datetime from a time_t and a distinct count of microseconds.
3594 * Pass localtime or gmtime for f, to control the interpretation of timet.
3595 */
3596static PyObject *
3597datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us,
3598 PyObject *tzinfo)
3599{
3600 struct tm *tm;
3601 PyObject *result = NULL;
3602
3603 tm = f(&timet);
3604 if (tm) {
3605 /* The platform localtime/gmtime may insert leap seconds,
3606 * indicated by tm->tm_sec > 59. We don't care about them,
3607 * except to the extent that passing them on to the datetime
3608 * constructor would raise ValueError for a reason that
3609 * made no sense to the user.
3610 */
3611 if (tm->tm_sec > 59)
3612 tm->tm_sec = 59;
3613 result = PyObject_CallFunction(cls, "iiiiiiiO",
3614 tm->tm_year + 1900,
3615 tm->tm_mon + 1,
3616 tm->tm_mday,
3617 tm->tm_hour,
3618 tm->tm_min,
3619 tm->tm_sec,
3620 us,
3621 tzinfo);
3622 }
3623 else
3624 PyErr_SetString(PyExc_ValueError,
3625 "timestamp out of range for "
3626 "platform localtime()/gmtime() function");
3627 return result;
3628}
3629
3630/* Internal helper.
3631 * Build datetime from a Python timestamp. Pass localtime or gmtime for f,
3632 * to control the interpretation of the timestamp. Since a double doesn't
3633 * have enough bits to cover a datetime's full range of precision, it's
3634 * better to call datetime_from_timet_and_us provided you have a way
3635 * to get that much precision (e.g., C time() isn't good enough).
3636 */
3637static PyObject *
3638datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp,
3639 PyObject *tzinfo)
3640{
3641 time_t timet = (time_t)timestamp;
3642 double fraction = timestamp - (double)timet;
3643 int us = (int)round_to_long(fraction * 1e6);
3644
3645 return datetime_from_timet_and_us(cls, f, timet, us, tzinfo);
3646}
3647
3648/* Internal helper.
3649 * Build most accurate possible datetime for current time. Pass localtime or
3650 * gmtime for f as appropriate.
3651 */
3652static PyObject *
3653datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
3654{
3655#ifdef HAVE_GETTIMEOFDAY
3656 struct timeval t;
3657
3658#ifdef GETTIMEOFDAY_NO_TZ
3659 gettimeofday(&t);
3660#else
3661 gettimeofday(&t, (struct timezone *)NULL);
3662#endif
3663 return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec,
3664 tzinfo);
3665
3666#else /* ! HAVE_GETTIMEOFDAY */
3667 /* No flavor of gettimeofday exists on this platform. Python's
3668 * time.time() does a lot of other platform tricks to get the
3669 * best time it can on the platform, and we're not going to do
3670 * better than that (if we could, the better code would belong
3671 * in time.time()!) We're limited by the precision of a double,
3672 * though.
3673 */
3674 PyObject *time;
3675 double dtime;
3676
3677 time = time_time();
3678 if (time == NULL)
3679 return NULL;
3680 dtime = PyFloat_AsDouble(time);
3681 Py_DECREF(time);
3682 if (dtime == -1.0 && PyErr_Occurred())
3683 return NULL;
3684 return datetime_from_timestamp(cls, f, dtime, tzinfo);
3685#endif /* ! HAVE_GETTIMEOFDAY */
3686}
3687
Tim Peters2a799bf2002-12-16 20:18:38 +00003688/* Return best possible local time -- this isn't constrained by the
3689 * precision of a timestamp.
3690 */
3691static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003692datetime_now(PyObject *cls, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003693{
Tim Peters10cadce2003-01-23 19:58:02 +00003694 PyObject *self;
Tim Peters2a799bf2002-12-16 20:18:38 +00003695 PyObject *tzinfo = Py_None;
Tim Peters10cadce2003-01-23 19:58:02 +00003696 static char *keywords[] = {"tz", NULL};
Tim Peters2a799bf2002-12-16 20:18:38 +00003697
Tim Peters10cadce2003-01-23 19:58:02 +00003698 if (! PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords,
3699 &tzinfo))
3700 return NULL;
3701 if (check_tzinfo_subclass(tzinfo) < 0)
3702 return NULL;
3703
3704 self = datetime_best_possible(cls,
3705 tzinfo == Py_None ? localtime : gmtime,
3706 tzinfo);
3707 if (self != NULL && tzinfo != Py_None) {
3708 /* Convert UTC to tzinfo's zone. */
3709 PyObject *temp = self;
Tim Peters2a44a8d2003-01-23 20:53:10 +00003710 self = PyObject_CallMethod(tzinfo, "fromutc", "O", self);
Tim Peters10cadce2003-01-23 19:58:02 +00003711 Py_DECREF(temp);
Tim Peters2a799bf2002-12-16 20:18:38 +00003712 }
3713 return self;
3714}
3715
Tim Petersa9bc1682003-01-11 03:39:11 +00003716/* Return best possible UTC time -- this isn't constrained by the
3717 * precision of a timestamp.
3718 */
3719static PyObject *
3720datetime_utcnow(PyObject *cls, PyObject *dummy)
3721{
3722 return datetime_best_possible(cls, gmtime, Py_None);
3723}
3724
Tim Peters2a799bf2002-12-16 20:18:38 +00003725/* Return new local datetime from timestamp (Python timestamp -- a double). */
3726static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003727datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003728{
Tim Peters2a44a8d2003-01-23 20:53:10 +00003729 PyObject *self;
Tim Peters2a799bf2002-12-16 20:18:38 +00003730 double timestamp;
3731 PyObject *tzinfo = Py_None;
Tim Peters2a44a8d2003-01-23 20:53:10 +00003732 static char *keywords[] = {"timestamp", "tz", NULL};
Tim Peters2a799bf2002-12-16 20:18:38 +00003733
Tim Peters2a44a8d2003-01-23 20:53:10 +00003734 if (! PyArg_ParseTupleAndKeywords(args, kw, "d|O:fromtimestamp",
3735 keywords, &timestamp, &tzinfo))
3736 return NULL;
3737 if (check_tzinfo_subclass(tzinfo) < 0)
3738 return NULL;
3739
3740 self = datetime_from_timestamp(cls,
3741 tzinfo == Py_None ? localtime : gmtime,
3742 timestamp,
3743 tzinfo);
3744 if (self != NULL && tzinfo != Py_None) {
3745 /* Convert UTC to tzinfo's zone. */
3746 PyObject *temp = self;
3747 self = PyObject_CallMethod(tzinfo, "fromutc", "O", self);
3748 Py_DECREF(temp);
Tim Peters2a799bf2002-12-16 20:18:38 +00003749 }
3750 return self;
3751}
3752
Tim Petersa9bc1682003-01-11 03:39:11 +00003753/* Return new UTC datetime from timestamp (Python timestamp -- a double). */
3754static PyObject *
3755datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
3756{
3757 double timestamp;
3758 PyObject *result = NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00003759
Tim Petersa9bc1682003-01-11 03:39:11 +00003760 if (PyArg_ParseTuple(args, "d:utcfromtimestamp", &timestamp))
3761 result = datetime_from_timestamp(cls, gmtime, timestamp,
3762 Py_None);
3763 return result;
3764}
3765
3766/* Return new datetime from date/datetime and time arguments. */
3767static PyObject *
3768datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
3769{
3770 static char *keywords[] = {"date", "time", NULL};
3771 PyObject *date;
3772 PyObject *time;
3773 PyObject *result = NULL;
3774
3775 if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!:combine", keywords,
3776 &PyDateTime_DateType, &date,
3777 &PyDateTime_TimeType, &time)) {
3778 PyObject *tzinfo = Py_None;
3779
3780 if (HASTZINFO(time))
3781 tzinfo = ((PyDateTime_Time *)time)->tzinfo;
3782 result = PyObject_CallFunction(cls, "iiiiiiiO",
3783 GET_YEAR(date),
3784 GET_MONTH(date),
3785 GET_DAY(date),
3786 TIME_GET_HOUR(time),
3787 TIME_GET_MINUTE(time),
3788 TIME_GET_SECOND(time),
3789 TIME_GET_MICROSECOND(time),
3790 tzinfo);
3791 }
3792 return result;
3793}
Tim Peters2a799bf2002-12-16 20:18:38 +00003794
3795/*
3796 * Destructor.
3797 */
3798
3799static void
Tim Petersa9bc1682003-01-11 03:39:11 +00003800datetime_dealloc(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003801{
Tim Petersa9bc1682003-01-11 03:39:11 +00003802 if (HASTZINFO(self)) {
3803 Py_XDECREF(self->tzinfo);
3804 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003805 self->ob_type->tp_free((PyObject *)self);
3806}
3807
3808/*
3809 * Indirect access to tzinfo methods.
3810 */
3811
Tim Peters2a799bf2002-12-16 20:18:38 +00003812/* These are all METH_NOARGS, so don't need to check the arglist. */
3813static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003814datetime_utcoffset(PyDateTime_DateTime *self, PyObject *unused) {
3815 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
3816 "utcoffset", (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00003817}
3818
3819static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003820datetime_dst(PyDateTime_DateTime *self, PyObject *unused) {
3821 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
3822 "dst", (PyObject *)self);
Tim Peters855fe882002-12-22 03:43:39 +00003823}
3824
3825static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003826datetime_tzname(PyDateTime_DateTime *self, PyObject *unused) {
3827 return call_tzname(HASTZINFO(self) ? self->tzinfo : Py_None,
3828 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00003829}
3830
3831/*
Tim Petersa9bc1682003-01-11 03:39:11 +00003832 * datetime arithmetic.
Tim Peters2a799bf2002-12-16 20:18:38 +00003833 */
3834
Tim Petersa9bc1682003-01-11 03:39:11 +00003835/* factor must be 1 (to add) or -1 (to subtract). The result inherits
3836 * the tzinfo state of date.
Tim Peters2a799bf2002-12-16 20:18:38 +00003837 */
3838static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003839add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta,
3840 int factor)
Tim Peters2a799bf2002-12-16 20:18:38 +00003841{
Tim Petersa9bc1682003-01-11 03:39:11 +00003842 /* Note that the C-level additions can't overflow, because of
3843 * invariant bounds on the member values.
3844 */
3845 int year = GET_YEAR(date);
3846 int month = GET_MONTH(date);
3847 int day = GET_DAY(date) + GET_TD_DAYS(delta) * factor;
3848 int hour = DATE_GET_HOUR(date);
3849 int minute = DATE_GET_MINUTE(date);
3850 int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta) * factor;
3851 int microsecond = DATE_GET_MICROSECOND(date) +
3852 GET_TD_MICROSECONDS(delta) * factor;
Tim Peters2a799bf2002-12-16 20:18:38 +00003853
Tim Petersa9bc1682003-01-11 03:39:11 +00003854 assert(factor == 1 || factor == -1);
3855 if (normalize_datetime(&year, &month, &day,
3856 &hour, &minute, &second, &microsecond) < 0)
3857 return NULL;
3858 else
3859 return new_datetime(year, month, day,
3860 hour, minute, second, microsecond,
3861 HASTZINFO(date) ? date->tzinfo : Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003862}
3863
3864static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003865datetime_add(PyObject *left, PyObject *right)
Tim Peters2a799bf2002-12-16 20:18:38 +00003866{
Tim Petersa9bc1682003-01-11 03:39:11 +00003867 if (PyDateTime_Check(left)) {
3868 /* datetime + ??? */
3869 if (PyDelta_Check(right))
3870 /* datetime + delta */
3871 return add_datetime_timedelta(
3872 (PyDateTime_DateTime *)left,
3873 (PyDateTime_Delta *)right,
3874 1);
3875 }
3876 else if (PyDelta_Check(left)) {
3877 /* delta + datetime */
3878 return add_datetime_timedelta((PyDateTime_DateTime *) right,
3879 (PyDateTime_Delta *) left,
3880 1);
3881 }
3882 Py_INCREF(Py_NotImplemented);
3883 return Py_NotImplemented;
Tim Peters2a799bf2002-12-16 20:18:38 +00003884}
3885
3886static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003887datetime_subtract(PyObject *left, PyObject *right)
Tim Peters2a799bf2002-12-16 20:18:38 +00003888{
3889 PyObject *result = Py_NotImplemented;
3890
3891 if (PyDateTime_Check(left)) {
3892 /* datetime - ??? */
3893 if (PyDateTime_Check(right)) {
3894 /* datetime - datetime */
3895 naivety n1, n2;
3896 int offset1, offset2;
Tim Petersa9bc1682003-01-11 03:39:11 +00003897 int delta_d, delta_s, delta_us;
Tim Peters2a799bf2002-12-16 20:18:38 +00003898
Tim Peterse39a80c2002-12-30 21:28:52 +00003899 if (classify_two_utcoffsets(left, &offset1, &n1, left,
3900 right, &offset2, &n2,
3901 right) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003902 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003903 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00003904 if (n1 != n2) {
3905 PyErr_SetString(PyExc_TypeError,
3906 "can't subtract offset-naive and "
3907 "offset-aware datetimes");
3908 return NULL;
3909 }
Tim Petersa9bc1682003-01-11 03:39:11 +00003910 delta_d = ymd_to_ord(GET_YEAR(left),
3911 GET_MONTH(left),
3912 GET_DAY(left)) -
3913 ymd_to_ord(GET_YEAR(right),
3914 GET_MONTH(right),
3915 GET_DAY(right));
3916 /* These can't overflow, since the values are
3917 * normalized. At most this gives the number of
3918 * seconds in one day.
3919 */
3920 delta_s = (DATE_GET_HOUR(left) -
3921 DATE_GET_HOUR(right)) * 3600 +
3922 (DATE_GET_MINUTE(left) -
3923 DATE_GET_MINUTE(right)) * 60 +
3924 (DATE_GET_SECOND(left) -
3925 DATE_GET_SECOND(right));
3926 delta_us = DATE_GET_MICROSECOND(left) -
3927 DATE_GET_MICROSECOND(right);
Tim Peters2a799bf2002-12-16 20:18:38 +00003928 /* (left - offset1) - (right - offset2) =
3929 * (left - right) + (offset2 - offset1)
3930 */
Tim Petersa9bc1682003-01-11 03:39:11 +00003931 delta_s += (offset2 - offset1) * 60;
3932 result = new_delta(delta_d, delta_s, delta_us, 1);
Tim Peters2a799bf2002-12-16 20:18:38 +00003933 }
3934 else if (PyDelta_Check(right)) {
Tim Petersa9bc1682003-01-11 03:39:11 +00003935 /* datetime - delta */
3936 result = add_datetime_timedelta(
Tim Peters2a799bf2002-12-16 20:18:38 +00003937 (PyDateTime_DateTime *)left,
Tim Petersa9bc1682003-01-11 03:39:11 +00003938 (PyDateTime_Delta *)right,
3939 -1);
Tim Peters2a799bf2002-12-16 20:18:38 +00003940 }
3941 }
3942
3943 if (result == Py_NotImplemented)
3944 Py_INCREF(result);
3945 return result;
3946}
3947
3948/* Various ways to turn a datetime into a string. */
3949
3950static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003951datetime_repr(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003952{
Tim Petersa9bc1682003-01-11 03:39:11 +00003953 char buffer[1000];
3954 char *typename = self->ob_type->tp_name;
3955 PyObject *baserepr;
Tim Peters2a799bf2002-12-16 20:18:38 +00003956
Tim Petersa9bc1682003-01-11 03:39:11 +00003957 if (DATE_GET_MICROSECOND(self)) {
3958 PyOS_snprintf(buffer, sizeof(buffer),
3959 "%s(%d, %d, %d, %d, %d, %d, %d)",
3960 typename,
3961 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3962 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3963 DATE_GET_SECOND(self),
3964 DATE_GET_MICROSECOND(self));
3965 }
3966 else if (DATE_GET_SECOND(self)) {
3967 PyOS_snprintf(buffer, sizeof(buffer),
3968 "%s(%d, %d, %d, %d, %d, %d)",
3969 typename,
3970 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3971 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3972 DATE_GET_SECOND(self));
3973 }
3974 else {
3975 PyOS_snprintf(buffer, sizeof(buffer),
3976 "%s(%d, %d, %d, %d, %d)",
3977 typename,
3978 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3979 DATE_GET_HOUR(self), DATE_GET_MINUTE(self));
3980 }
3981 baserepr = PyString_FromString(buffer);
3982 if (baserepr == NULL || ! HASTZINFO(self))
3983 return baserepr;
Tim Peters2a799bf2002-12-16 20:18:38 +00003984 return append_keyword_tzinfo(baserepr, self->tzinfo);
3985}
3986
Tim Petersa9bc1682003-01-11 03:39:11 +00003987static PyObject *
3988datetime_str(PyDateTime_DateTime *self)
3989{
3990 return PyObject_CallMethod((PyObject *)self, "isoformat", "(s)", " ");
3991}
Tim Peters2a799bf2002-12-16 20:18:38 +00003992
3993static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003994datetime_isoformat(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003995{
Tim Petersa9bc1682003-01-11 03:39:11 +00003996 char sep = 'T';
3997 static char *keywords[] = {"sep", NULL};
3998 char buffer[100];
3999 char *cp;
4000 PyObject *result;
Tim Peters2a799bf2002-12-16 20:18:38 +00004001
Tim Petersa9bc1682003-01-11 03:39:11 +00004002 if (!PyArg_ParseTupleAndKeywords(args, kw, "|c:isoformat", keywords,
4003 &sep))
4004 return NULL;
4005 cp = isoformat_date((PyDateTime_Date *)self, buffer, sizeof(buffer));
4006 assert(cp != NULL);
4007 *cp++ = sep;
4008 isoformat_time(self, cp, sizeof(buffer) - (cp - buffer));
4009 result = PyString_FromString(buffer);
4010 if (result == NULL || ! HASTZINFO(self))
Tim Peters2a799bf2002-12-16 20:18:38 +00004011 return result;
4012
4013 /* We need to append the UTC offset. */
Tim Petersa9bc1682003-01-11 03:39:11 +00004014 if (format_utcoffset(buffer, sizeof(buffer), ":", self->tzinfo,
Tim Peters2a799bf2002-12-16 20:18:38 +00004015 (PyObject *)self) < 0) {
4016 Py_DECREF(result);
4017 return NULL;
4018 }
Tim Petersa9bc1682003-01-11 03:39:11 +00004019 PyString_ConcatAndDel(&result, PyString_FromString(buffer));
Tim Peters2a799bf2002-12-16 20:18:38 +00004020 return result;
4021}
4022
Tim Petersa9bc1682003-01-11 03:39:11 +00004023static PyObject *
4024datetime_ctime(PyDateTime_DateTime *self)
4025{
4026 return format_ctime((PyDateTime_Date *)self,
4027 DATE_GET_HOUR(self),
4028 DATE_GET_MINUTE(self),
4029 DATE_GET_SECOND(self));
4030}
4031
Tim Peters2a799bf2002-12-16 20:18:38 +00004032/* Miscellaneous methods. */
4033
Tim Petersa9bc1682003-01-11 03:39:11 +00004034/* This is more natural as a tp_compare, but doesn't work then: for whatever
4035 * reason, Python's try_3way_compare ignores tp_compare unless
4036 * PyInstance_Check returns true, but these aren't old-style classes.
4037 */
4038static PyObject *
4039datetime_richcompare(PyDateTime_DateTime *self, PyObject *other, int op)
4040{
4041 int diff;
4042 naivety n1, n2;
4043 int offset1, offset2;
4044
4045 if (! PyDateTime_Check(other)) {
Tim Peters8d81a012003-01-24 22:36:34 +00004046 if (PyObject_HasAttrString(other, "timetuple")) {
4047 /* A hook for other kinds of datetime objects. */
4048 Py_INCREF(Py_NotImplemented);
4049 return Py_NotImplemented;
4050 }
Tim Peters07534a62003-02-07 22:50:28 +00004051 if (op == Py_EQ || op == Py_NE) {
4052 PyObject *result = op == Py_EQ ? Py_False : Py_True;
4053 Py_INCREF(result);
4054 return result;
4055 }
Tim Petersa9bc1682003-01-11 03:39:11 +00004056 /* Stop this from falling back to address comparison. */
Tim Peters07534a62003-02-07 22:50:28 +00004057 return cmperror((PyObject *)self, other);
Tim Petersa9bc1682003-01-11 03:39:11 +00004058 }
4059
4060 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1,
4061 (PyObject *)self,
4062 other, &offset2, &n2,
4063 other) < 0)
4064 return NULL;
4065 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
4066 /* If they're both naive, or both aware and have the same offsets,
4067 * we get off cheap. Note that if they're both naive, offset1 ==
4068 * offset2 == 0 at this point.
4069 */
4070 if (n1 == n2 && offset1 == offset2) {
4071 diff = memcmp(self->data, ((PyDateTime_DateTime *)other)->data,
4072 _PyDateTime_DATETIME_DATASIZE);
4073 return diff_to_bool(diff, op);
4074 }
4075
4076 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
4077 PyDateTime_Delta *delta;
4078
4079 assert(offset1 != offset2); /* else last "if" handled it */
4080 delta = (PyDateTime_Delta *)datetime_subtract((PyObject *)self,
4081 other);
4082 if (delta == NULL)
4083 return NULL;
4084 diff = GET_TD_DAYS(delta);
4085 if (diff == 0)
4086 diff = GET_TD_SECONDS(delta) |
4087 GET_TD_MICROSECONDS(delta);
4088 Py_DECREF(delta);
4089 return diff_to_bool(diff, op);
4090 }
4091
4092 assert(n1 != n2);
4093 PyErr_SetString(PyExc_TypeError,
4094 "can't compare offset-naive and "
4095 "offset-aware datetimes");
4096 return NULL;
4097}
4098
4099static long
4100datetime_hash(PyDateTime_DateTime *self)
4101{
4102 if (self->hashcode == -1) {
4103 naivety n;
4104 int offset;
4105 PyObject *temp;
4106
4107 n = classify_utcoffset((PyObject *)self, (PyObject *)self,
4108 &offset);
4109 assert(n != OFFSET_UNKNOWN);
4110 if (n == OFFSET_ERROR)
4111 return -1;
4112
4113 /* Reduce this to a hash of another object. */
4114 if (n == OFFSET_NAIVE)
4115 temp = PyString_FromStringAndSize(
4116 (char *)self->data,
4117 _PyDateTime_DATETIME_DATASIZE);
4118 else {
4119 int days;
4120 int seconds;
4121
4122 assert(n == OFFSET_AWARE);
4123 assert(HASTZINFO(self));
4124 days = ymd_to_ord(GET_YEAR(self),
4125 GET_MONTH(self),
4126 GET_DAY(self));
4127 seconds = DATE_GET_HOUR(self) * 3600 +
4128 (DATE_GET_MINUTE(self) - offset) * 60 +
4129 DATE_GET_SECOND(self);
4130 temp = new_delta(days,
4131 seconds,
4132 DATE_GET_MICROSECOND(self),
4133 1);
4134 }
4135 if (temp != NULL) {
4136 self->hashcode = PyObject_Hash(temp);
4137 Py_DECREF(temp);
4138 }
4139 }
4140 return self->hashcode;
4141}
Tim Peters2a799bf2002-12-16 20:18:38 +00004142
4143static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004144datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
Tim Peters12bf3392002-12-24 05:41:27 +00004145{
4146 PyObject *clone;
4147 PyObject *tuple;
4148 int y = GET_YEAR(self);
4149 int m = GET_MONTH(self);
4150 int d = GET_DAY(self);
4151 int hh = DATE_GET_HOUR(self);
4152 int mm = DATE_GET_MINUTE(self);
4153 int ss = DATE_GET_SECOND(self);
4154 int us = DATE_GET_MICROSECOND(self);
Tim Petersa9bc1682003-01-11 03:39:11 +00004155 PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
Tim Peters12bf3392002-12-24 05:41:27 +00004156
4157 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO:replace",
Tim Petersa9bc1682003-01-11 03:39:11 +00004158 datetime_kws,
Tim Peters12bf3392002-12-24 05:41:27 +00004159 &y, &m, &d, &hh, &mm, &ss, &us,
4160 &tzinfo))
4161 return NULL;
4162 tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
4163 if (tuple == NULL)
4164 return NULL;
Tim Petersa9bc1682003-01-11 03:39:11 +00004165 clone = datetime_new(self->ob_type, tuple, NULL);
Tim Peters12bf3392002-12-24 05:41:27 +00004166 Py_DECREF(tuple);
4167 return clone;
4168}
4169
4170static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004171datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
Tim Peters80475bb2002-12-25 07:40:55 +00004172{
Tim Peters52dcce22003-01-23 16:36:11 +00004173 int y, m, d, hh, mm, ss, us;
Tim Peters521fc152002-12-31 17:36:56 +00004174 PyObject *result;
Tim Peters52dcce22003-01-23 16:36:11 +00004175 int offset, none;
Tim Peters521fc152002-12-31 17:36:56 +00004176
Tim Peters80475bb2002-12-25 07:40:55 +00004177 PyObject *tzinfo;
4178 static char *keywords[] = {"tz", NULL};
4179
Tim Peters52dcce22003-01-23 16:36:11 +00004180 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:astimezone", keywords,
4181 &PyDateTime_TZInfoType, &tzinfo))
Tim Peters80475bb2002-12-25 07:40:55 +00004182 return NULL;
4183
Tim Peters52dcce22003-01-23 16:36:11 +00004184 if (!HASTZINFO(self) || self->tzinfo == Py_None)
4185 goto NeedAware;
Tim Peters521fc152002-12-31 17:36:56 +00004186
Tim Peters52dcce22003-01-23 16:36:11 +00004187 /* Conversion to self's own time zone is a NOP. */
4188 if (self->tzinfo == tzinfo) {
4189 Py_INCREF(self);
4190 return (PyObject *)self;
Tim Peters710fb152003-01-02 19:35:54 +00004191 }
Tim Peters521fc152002-12-31 17:36:56 +00004192
Tim Peters52dcce22003-01-23 16:36:11 +00004193 /* Convert self to UTC. */
4194 offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4195 if (offset == -1 && PyErr_Occurred())
4196 return NULL;
4197 if (none)
4198 goto NeedAware;
Tim Petersf3615152003-01-01 21:51:37 +00004199
Tim Peters52dcce22003-01-23 16:36:11 +00004200 y = GET_YEAR(self);
4201 m = GET_MONTH(self);
4202 d = GET_DAY(self);
4203 hh = DATE_GET_HOUR(self);
4204 mm = DATE_GET_MINUTE(self);
4205 ss = DATE_GET_SECOND(self);
4206 us = DATE_GET_MICROSECOND(self);
4207
4208 mm -= offset;
Tim Petersf3615152003-01-01 21:51:37 +00004209 if ((mm < 0 || mm >= 60) &&
4210 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters52dcce22003-01-23 16:36:11 +00004211 return NULL;
4212
4213 /* Attach new tzinfo and let fromutc() do the rest. */
4214 result = new_datetime(y, m, d, hh, mm, ss, us, tzinfo);
4215 if (result != NULL) {
4216 PyObject *temp = result;
4217
4218 result = PyObject_CallMethod(tzinfo, "fromutc", "O", temp);
4219 Py_DECREF(temp);
4220 }
Tim Petersadf64202003-01-04 06:03:15 +00004221 return result;
Tim Peters521fc152002-12-31 17:36:56 +00004222
Tim Peters52dcce22003-01-23 16:36:11 +00004223NeedAware:
4224 PyErr_SetString(PyExc_ValueError, "astimezone() cannot be applied to "
4225 "a naive datetime");
Tim Peters521fc152002-12-31 17:36:56 +00004226 return NULL;
Tim Peters80475bb2002-12-25 07:40:55 +00004227}
4228
4229static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004230datetime_timetuple(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00004231{
4232 int dstflag = -1;
4233
Tim Petersa9bc1682003-01-11 03:39:11 +00004234 if (HASTZINFO(self) && self->tzinfo != Py_None) {
Tim Peters2a799bf2002-12-16 20:18:38 +00004235 int none;
4236
4237 dstflag = call_dst(self->tzinfo, (PyObject *)self, &none);
4238 if (dstflag == -1 && PyErr_Occurred())
4239 return NULL;
4240
4241 if (none)
4242 dstflag = -1;
4243 else if (dstflag != 0)
4244 dstflag = 1;
4245
4246 }
4247 return build_struct_time(GET_YEAR(self),
4248 GET_MONTH(self),
4249 GET_DAY(self),
4250 DATE_GET_HOUR(self),
4251 DATE_GET_MINUTE(self),
4252 DATE_GET_SECOND(self),
4253 dstflag);
4254}
4255
4256static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004257datetime_getdate(PyDateTime_DateTime *self)
4258{
4259 return new_date(GET_YEAR(self),
4260 GET_MONTH(self),
4261 GET_DAY(self));
4262}
4263
4264static PyObject *
4265datetime_gettime(PyDateTime_DateTime *self)
4266{
4267 return new_time(DATE_GET_HOUR(self),
4268 DATE_GET_MINUTE(self),
4269 DATE_GET_SECOND(self),
4270 DATE_GET_MICROSECOND(self),
4271 Py_None);
4272}
4273
4274static PyObject *
4275datetime_gettimetz(PyDateTime_DateTime *self)
4276{
4277 return new_time(DATE_GET_HOUR(self),
4278 DATE_GET_MINUTE(self),
4279 DATE_GET_SECOND(self),
4280 DATE_GET_MICROSECOND(self),
4281 HASTZINFO(self) ? self->tzinfo : Py_None);
4282}
4283
4284static PyObject *
4285datetime_utctimetuple(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00004286{
4287 int y = GET_YEAR(self);
4288 int m = GET_MONTH(self);
4289 int d = GET_DAY(self);
4290 int hh = DATE_GET_HOUR(self);
4291 int mm = DATE_GET_MINUTE(self);
4292 int ss = DATE_GET_SECOND(self);
4293 int us = 0; /* microseconds are ignored in a timetuple */
4294 int offset = 0;
4295
Tim Petersa9bc1682003-01-11 03:39:11 +00004296 if (HASTZINFO(self) && self->tzinfo != Py_None) {
Tim Peters2a799bf2002-12-16 20:18:38 +00004297 int none;
4298
4299 offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4300 if (offset == -1 && PyErr_Occurred())
4301 return NULL;
4302 }
4303 /* Even if offset is 0, don't call timetuple() -- tm_isdst should be
4304 * 0 in a UTC timetuple regardless of what dst() says.
4305 */
4306 if (offset) {
4307 /* Subtract offset minutes & normalize. */
4308 int stat;
4309
4310 mm -= offset;
4311 stat = normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us);
4312 if (stat < 0) {
4313 /* At the edges, it's possible we overflowed
4314 * beyond MINYEAR or MAXYEAR.
4315 */
4316 if (PyErr_ExceptionMatches(PyExc_OverflowError))
4317 PyErr_Clear();
4318 else
4319 return NULL;
4320 }
4321 }
4322 return build_struct_time(y, m, d, hh, mm, ss, 0);
4323}
4324
Tim Peters371935f2003-02-01 01:52:50 +00004325/* Pickle support, a simple use of __reduce__. */
Tim Peters33e0f382003-01-10 02:05:14 +00004326
Tim Petersa9bc1682003-01-11 03:39:11 +00004327/* Let basestate be the non-tzinfo data string.
Tim Peters2a799bf2002-12-16 20:18:38 +00004328 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4329 * So it's a tuple in any (non-error) case.
Tim Petersb57f8f02003-02-01 02:54:15 +00004330 * __getstate__ isn't exposed.
Tim Peters2a799bf2002-12-16 20:18:38 +00004331 */
4332static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004333datetime_getstate(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00004334{
4335 PyObject *basestate;
4336 PyObject *result = NULL;
4337
Tim Peters33e0f382003-01-10 02:05:14 +00004338 basestate = PyString_FromStringAndSize((char *)self->data,
4339 _PyDateTime_DATETIME_DATASIZE);
Tim Peters2a799bf2002-12-16 20:18:38 +00004340 if (basestate != NULL) {
Tim Petersa9bc1682003-01-11 03:39:11 +00004341 if (! HASTZINFO(self) || self->tzinfo == Py_None)
Tim Peters2a799bf2002-12-16 20:18:38 +00004342 result = Py_BuildValue("(O)", basestate);
4343 else
4344 result = Py_BuildValue("OO", basestate, self->tzinfo);
4345 Py_DECREF(basestate);
4346 }
4347 return result;
4348}
4349
4350static PyObject *
Guido van Rossum177e41a2003-01-30 22:06:23 +00004351datetime_reduce(PyDateTime_DateTime *self, PyObject *arg)
Tim Peters2a799bf2002-12-16 20:18:38 +00004352{
Guido van Rossum177e41a2003-01-30 22:06:23 +00004353 return Py_BuildValue("(ON)", self->ob_type, datetime_getstate(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00004354}
4355
Tim Petersa9bc1682003-01-11 03:39:11 +00004356static PyMethodDef datetime_methods[] = {
Guido van Rossum177e41a2003-01-30 22:06:23 +00004357
Tim Peters2a799bf2002-12-16 20:18:38 +00004358 /* Class methods: */
Tim Peters2a799bf2002-12-16 20:18:38 +00004359
Tim Petersa9bc1682003-01-11 03:39:11 +00004360 {"now", (PyCFunction)datetime_now,
Tim Peters2a799bf2002-12-16 20:18:38 +00004361 METH_KEYWORDS | METH_CLASS,
Neal Norwitz2fbe5372003-01-23 21:09:05 +00004362 PyDoc_STR("[tz] -> new datetime with tz's local day and time.")},
Tim Peters2a799bf2002-12-16 20:18:38 +00004363
Tim Petersa9bc1682003-01-11 03:39:11 +00004364 {"utcnow", (PyCFunction)datetime_utcnow,
4365 METH_NOARGS | METH_CLASS,
4366 PyDoc_STR("Return a new datetime representing UTC day and time.")},
4367
4368 {"fromtimestamp", (PyCFunction)datetime_fromtimestamp,
Tim Peters2a799bf2002-12-16 20:18:38 +00004369 METH_KEYWORDS | METH_CLASS,
Tim Peters2a44a8d2003-01-23 20:53:10 +00004370 PyDoc_STR("timestamp[, tz] -> tz's local time from POSIX timestamp.")},
Tim Peters2a799bf2002-12-16 20:18:38 +00004371
Tim Petersa9bc1682003-01-11 03:39:11 +00004372 {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
4373 METH_VARARGS | METH_CLASS,
4374 PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp "
4375 "(like time.time()).")},
4376
4377 {"combine", (PyCFunction)datetime_combine,
4378 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
4379 PyDoc_STR("date, time -> datetime with same date and time fields")},
4380
Tim Peters2a799bf2002-12-16 20:18:38 +00004381 /* Instance methods: */
Guido van Rossum177e41a2003-01-30 22:06:23 +00004382
Tim Petersa9bc1682003-01-11 03:39:11 +00004383 {"date", (PyCFunction)datetime_getdate, METH_NOARGS,
4384 PyDoc_STR("Return date object with same year, month and day.")},
4385
4386 {"time", (PyCFunction)datetime_gettime, METH_NOARGS,
4387 PyDoc_STR("Return time object with same time but with tzinfo=None.")},
4388
4389 {"timetz", (PyCFunction)datetime_gettimetz, METH_NOARGS,
4390 PyDoc_STR("Return time object with same time and tzinfo.")},
4391
4392 {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
4393 PyDoc_STR("Return ctime() style string.")},
4394
4395 {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004396 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
4397
Tim Petersa9bc1682003-01-11 03:39:11 +00004398 {"utctimetuple", (PyCFunction)datetime_utctimetuple, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004399 PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")},
4400
Tim Petersa9bc1682003-01-11 03:39:11 +00004401 {"isoformat", (PyCFunction)datetime_isoformat, METH_KEYWORDS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004402 PyDoc_STR("[sep] -> string in ISO 8601 format, "
4403 "YYYY-MM-DDTHH:MM:SS[.mmmmmm][+HH:MM].\n\n"
4404 "sep is used to separate the year from the time, and "
4405 "defaults to 'T'.")},
4406
Tim Petersa9bc1682003-01-11 03:39:11 +00004407 {"utcoffset", (PyCFunction)datetime_utcoffset, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004408 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
4409
Tim Petersa9bc1682003-01-11 03:39:11 +00004410 {"tzname", (PyCFunction)datetime_tzname, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004411 PyDoc_STR("Return self.tzinfo.tzname(self).")},
4412
Tim Petersa9bc1682003-01-11 03:39:11 +00004413 {"dst", (PyCFunction)datetime_dst, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004414 PyDoc_STR("Return self.tzinfo.dst(self).")},
4415
Tim Petersa9bc1682003-01-11 03:39:11 +00004416 {"replace", (PyCFunction)datetime_replace, METH_KEYWORDS,
4417 PyDoc_STR("Return datetime with new specified fields.")},
Tim Peters12bf3392002-12-24 05:41:27 +00004418
Tim Petersa9bc1682003-01-11 03:39:11 +00004419 {"astimezone", (PyCFunction)datetime_astimezone, METH_KEYWORDS,
Tim Peters80475bb2002-12-25 07:40:55 +00004420 PyDoc_STR("tz -> convert to local time in new timezone tz\n")},
4421
Guido van Rossum177e41a2003-01-30 22:06:23 +00004422 {"__reduce__", (PyCFunction)datetime_reduce, METH_NOARGS,
4423 PyDoc_STR("__reduce__() -> (cls, state)")},
4424
Tim Peters2a799bf2002-12-16 20:18:38 +00004425 {NULL, NULL}
4426};
4427
Tim Petersa9bc1682003-01-11 03:39:11 +00004428static char datetime_doc[] =
Tim Peters2a799bf2002-12-16 20:18:38 +00004429PyDoc_STR("date/time type.");
4430
Tim Petersa9bc1682003-01-11 03:39:11 +00004431static PyNumberMethods datetime_as_number = {
4432 datetime_add, /* nb_add */
4433 datetime_subtract, /* nb_subtract */
Tim Peters2a799bf2002-12-16 20:18:38 +00004434 0, /* nb_multiply */
4435 0, /* nb_divide */
4436 0, /* nb_remainder */
4437 0, /* nb_divmod */
4438 0, /* nb_power */
4439 0, /* nb_negative */
4440 0, /* nb_positive */
4441 0, /* nb_absolute */
4442 0, /* nb_nonzero */
4443};
4444
Tim Petersa9bc1682003-01-11 03:39:11 +00004445statichere PyTypeObject PyDateTime_DateTimeType = {
Tim Peters2a799bf2002-12-16 20:18:38 +00004446 PyObject_HEAD_INIT(NULL)
4447 0, /* ob_size */
Tim Peters0bf60bd2003-01-08 20:40:01 +00004448 "datetime.datetime", /* tp_name */
Tim Petersa9bc1682003-01-11 03:39:11 +00004449 sizeof(PyDateTime_DateTime), /* tp_basicsize */
Tim Peters2a799bf2002-12-16 20:18:38 +00004450 0, /* tp_itemsize */
Tim Petersa9bc1682003-01-11 03:39:11 +00004451 (destructor)datetime_dealloc, /* tp_dealloc */
Tim Peters2a799bf2002-12-16 20:18:38 +00004452 0, /* tp_print */
4453 0, /* tp_getattr */
4454 0, /* tp_setattr */
4455 0, /* tp_compare */
Tim Petersa9bc1682003-01-11 03:39:11 +00004456 (reprfunc)datetime_repr, /* tp_repr */
4457 &datetime_as_number, /* tp_as_number */
Tim Peters2a799bf2002-12-16 20:18:38 +00004458 0, /* tp_as_sequence */
4459 0, /* tp_as_mapping */
Tim Petersa9bc1682003-01-11 03:39:11 +00004460 (hashfunc)datetime_hash, /* tp_hash */
Tim Peters2a799bf2002-12-16 20:18:38 +00004461 0, /* tp_call */
Tim Petersa9bc1682003-01-11 03:39:11 +00004462 (reprfunc)datetime_str, /* tp_str */
Tim Peters2a799bf2002-12-16 20:18:38 +00004463 PyObject_GenericGetAttr, /* tp_getattro */
4464 0, /* tp_setattro */
4465 0, /* tp_as_buffer */
4466 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4467 Py_TPFLAGS_BASETYPE, /* tp_flags */
Tim Petersa9bc1682003-01-11 03:39:11 +00004468 datetime_doc, /* tp_doc */
Tim Peters2a799bf2002-12-16 20:18:38 +00004469 0, /* tp_traverse */
4470 0, /* tp_clear */
Tim Petersa9bc1682003-01-11 03:39:11 +00004471 (richcmpfunc)datetime_richcompare, /* tp_richcompare */
Tim Peters2a799bf2002-12-16 20:18:38 +00004472 0, /* tp_weaklistoffset */
4473 0, /* tp_iter */
4474 0, /* tp_iternext */
Tim Petersa9bc1682003-01-11 03:39:11 +00004475 datetime_methods, /* tp_methods */
Tim Peters2a799bf2002-12-16 20:18:38 +00004476 0, /* tp_members */
Tim Petersa9bc1682003-01-11 03:39:11 +00004477 datetime_getset, /* tp_getset */
4478 &PyDateTime_DateType, /* tp_base */
Tim Peters2a799bf2002-12-16 20:18:38 +00004479 0, /* tp_dict */
4480 0, /* tp_descr_get */
4481 0, /* tp_descr_set */
4482 0, /* tp_dictoffset */
4483 0, /* tp_init */
Tim Petersa98924a2003-05-17 05:55:19 +00004484 datetime_alloc, /* tp_alloc */
Tim Petersa9bc1682003-01-11 03:39:11 +00004485 datetime_new, /* tp_new */
Tim Peters4c530132003-05-16 22:44:06 +00004486 0, /* tp_free */
Tim Peters2a799bf2002-12-16 20:18:38 +00004487};
4488
4489/* ---------------------------------------------------------------------------
4490 * Module methods and initialization.
4491 */
4492
4493static PyMethodDef module_methods[] = {
Tim Peters2a799bf2002-12-16 20:18:38 +00004494 {NULL, NULL}
4495};
4496
4497PyMODINIT_FUNC
4498initdatetime(void)
4499{
4500 PyObject *m; /* a module object */
4501 PyObject *d; /* its dict */
4502 PyObject *x;
4503
Tim Peters2a799bf2002-12-16 20:18:38 +00004504 m = Py_InitModule3("datetime", module_methods,
4505 "Fast implementation of the datetime type.");
4506
4507 if (PyType_Ready(&PyDateTime_DateType) < 0)
4508 return;
4509 if (PyType_Ready(&PyDateTime_DateTimeType) < 0)
4510 return;
4511 if (PyType_Ready(&PyDateTime_DeltaType) < 0)
4512 return;
4513 if (PyType_Ready(&PyDateTime_TimeType) < 0)
4514 return;
4515 if (PyType_Ready(&PyDateTime_TZInfoType) < 0)
4516 return;
Tim Peters2a799bf2002-12-16 20:18:38 +00004517
Tim Peters2a799bf2002-12-16 20:18:38 +00004518 /* timedelta values */
4519 d = PyDateTime_DeltaType.tp_dict;
4520
Tim Peters2a799bf2002-12-16 20:18:38 +00004521 x = new_delta(0, 0, 1, 0);
4522 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
4523 return;
4524 Py_DECREF(x);
4525
4526 x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0);
4527 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
4528 return;
4529 Py_DECREF(x);
4530
4531 x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0);
4532 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
4533 return;
4534 Py_DECREF(x);
4535
4536 /* date values */
4537 d = PyDateTime_DateType.tp_dict;
4538
4539 x = new_date(1, 1, 1);
4540 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
4541 return;
4542 Py_DECREF(x);
4543
4544 x = new_date(MAXYEAR, 12, 31);
4545 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
4546 return;
4547 Py_DECREF(x);
4548
4549 x = new_delta(1, 0, 0, 0);
4550 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
4551 return;
4552 Py_DECREF(x);
4553
Tim Peters37f39822003-01-10 03:49:02 +00004554 /* time values */
4555 d = PyDateTime_TimeType.tp_dict;
Tim Peters2a799bf2002-12-16 20:18:38 +00004556
Tim Peters37f39822003-01-10 03:49:02 +00004557 x = new_time(0, 0, 0, 0, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004558 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
4559 return;
4560 Py_DECREF(x);
4561
Tim Peters37f39822003-01-10 03:49:02 +00004562 x = new_time(23, 59, 59, 999999, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004563 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
4564 return;
4565 Py_DECREF(x);
4566
4567 x = new_delta(0, 0, 1, 0);
4568 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
4569 return;
4570 Py_DECREF(x);
4571
Tim Petersa9bc1682003-01-11 03:39:11 +00004572 /* datetime values */
4573 d = PyDateTime_DateTimeType.tp_dict;
Tim Peters2a799bf2002-12-16 20:18:38 +00004574
Tim Petersa9bc1682003-01-11 03:39:11 +00004575 x = new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004576 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
4577 return;
4578 Py_DECREF(x);
4579
Tim Petersa9bc1682003-01-11 03:39:11 +00004580 x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004581 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
4582 return;
4583 Py_DECREF(x);
4584
4585 x = new_delta(0, 0, 1, 0);
4586 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
4587 return;
4588 Py_DECREF(x);
4589
Tim Peters2a799bf2002-12-16 20:18:38 +00004590 /* module initialization */
4591 PyModule_AddIntConstant(m, "MINYEAR", MINYEAR);
4592 PyModule_AddIntConstant(m, "MAXYEAR", MAXYEAR);
4593
4594 Py_INCREF(&PyDateTime_DateType);
4595 PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType);
4596
Tim Petersa9bc1682003-01-11 03:39:11 +00004597 Py_INCREF(&PyDateTime_DateTimeType);
4598 PyModule_AddObject(m, "datetime",
4599 (PyObject *)&PyDateTime_DateTimeType);
4600
4601 Py_INCREF(&PyDateTime_TimeType);
4602 PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType);
4603
Tim Peters2a799bf2002-12-16 20:18:38 +00004604 Py_INCREF(&PyDateTime_DeltaType);
4605 PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType);
4606
Tim Peters2a799bf2002-12-16 20:18:38 +00004607 Py_INCREF(&PyDateTime_TZInfoType);
4608 PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
4609
Tim Peters2a799bf2002-12-16 20:18:38 +00004610 /* A 4-year cycle has an extra leap day over what we'd get from
4611 * pasting together 4 single years.
4612 */
4613 assert(DI4Y == 4 * 365 + 1);
4614 assert(DI4Y == days_before_year(4+1));
4615
4616 /* Similarly, a 400-year cycle has an extra leap day over what we'd
4617 * get from pasting together 4 100-year cycles.
4618 */
4619 assert(DI400Y == 4 * DI100Y + 1);
4620 assert(DI400Y == days_before_year(400+1));
4621
4622 /* OTOH, a 100-year cycle has one fewer leap day than we'd get from
4623 * pasting together 25 4-year cycles.
4624 */
4625 assert(DI100Y == 25 * DI4Y - 1);
4626 assert(DI100Y == days_before_year(100+1));
4627
4628 us_per_us = PyInt_FromLong(1);
4629 us_per_ms = PyInt_FromLong(1000);
4630 us_per_second = PyInt_FromLong(1000000);
4631 us_per_minute = PyInt_FromLong(60000000);
4632 seconds_per_day = PyInt_FromLong(24 * 3600);
4633 if (us_per_us == NULL || us_per_ms == NULL || us_per_second == NULL ||
4634 us_per_minute == NULL || seconds_per_day == NULL)
4635 return;
4636
4637 /* The rest are too big for 32-bit ints, but even
4638 * us_per_week fits in 40 bits, so doubles should be exact.
4639 */
4640 us_per_hour = PyLong_FromDouble(3600000000.0);
4641 us_per_day = PyLong_FromDouble(86400000000.0);
4642 us_per_week = PyLong_FromDouble(604800000000.0);
4643 if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL)
4644 return;
4645}
Tim Petersf3615152003-01-01 21:51:37 +00004646
4647/* ---------------------------------------------------------------------------
Tim Petersa9bc1682003-01-11 03:39:11 +00004648Some time zone algebra. For a datetime x, let
Tim Petersf3615152003-01-01 21:51:37 +00004649 x.n = x stripped of its timezone -- its naive time.
4650 x.o = x.utcoffset(), and assuming that doesn't raise an exception or
4651 return None
4652 x.d = x.dst(), and assuming that doesn't raise an exception or
4653 return None
4654 x.s = x's standard offset, x.o - x.d
4655
4656Now some derived rules, where k is a duration (timedelta).
4657
46581. x.o = x.s + x.d
4659 This follows from the definition of x.s.
4660
Tim Petersc5dc4da2003-01-02 17:55:03 +000046612. If x and y have the same tzinfo member, x.s = y.s.
Tim Petersf3615152003-01-01 21:51:37 +00004662 This is actually a requirement, an assumption we need to make about
4663 sane tzinfo classes.
4664
46653. The naive UTC time corresponding to x is x.n - x.o.
4666 This is again a requirement for a sane tzinfo class.
4667
46684. (x+k).s = x.s
Tim Peters8bb5ad22003-01-24 02:44:45 +00004669 This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
Tim Petersf3615152003-01-01 21:51:37 +00004670
Tim Petersc5dc4da2003-01-02 17:55:03 +000046715. (x+k).n = x.n + k
Tim Petersf3615152003-01-01 21:51:37 +00004672 Again follows from how arithmetic is defined.
4673
Tim Peters8bb5ad22003-01-24 02:44:45 +00004674Now we can explain tz.fromutc(x). Let's assume it's an interesting case
Tim Petersf3615152003-01-01 21:51:37 +00004675(meaning that the various tzinfo methods exist, and don't blow up or return
4676None when called).
4677
Tim Petersa9bc1682003-01-11 03:39:11 +00004678The function wants to return a datetime y with timezone tz, equivalent to x.
Tim Peters8bb5ad22003-01-24 02:44:45 +00004679x is already in UTC.
Tim Petersf3615152003-01-01 21:51:37 +00004680
4681By #3, we want
4682
Tim Peters8bb5ad22003-01-24 02:44:45 +00004683 y.n - y.o = x.n [1]
Tim Petersf3615152003-01-01 21:51:37 +00004684
4685The algorithm starts by attaching tz to x.n, and calling that y. So
4686x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
4687becomes true; in effect, we want to solve [2] for k:
4688
Tim Peters8bb5ad22003-01-24 02:44:45 +00004689 (y+k).n - (y+k).o = x.n [2]
Tim Petersf3615152003-01-01 21:51:37 +00004690
4691By #1, this is the same as
4692
Tim Peters8bb5ad22003-01-24 02:44:45 +00004693 (y+k).n - ((y+k).s + (y+k).d) = x.n [3]
Tim Petersf3615152003-01-01 21:51:37 +00004694
4695By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
4696Substituting that into [3],
4697
Tim Peters8bb5ad22003-01-24 02:44:45 +00004698 x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving
4699 k - (y+k).s - (y+k).d = 0; rearranging,
4700 k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so
4701 k = y.s - (y+k).d
Tim Petersf3615152003-01-01 21:51:37 +00004702
Tim Peters8bb5ad22003-01-24 02:44:45 +00004703On the RHS, (y+k).d can't be computed directly, but y.s can be, and we
4704approximate k by ignoring the (y+k).d term at first. Note that k can't be
4705very large, since all offset-returning methods return a duration of magnitude
4706less than 24 hours. For that reason, if y is firmly in std time, (y+k).d must
4707be 0, so ignoring it has no consequence then.
Tim Petersf3615152003-01-01 21:51:37 +00004708
4709In any case, the new value is
4710
Tim Peters8bb5ad22003-01-24 02:44:45 +00004711 z = y + y.s [4]
Tim Petersf3615152003-01-01 21:51:37 +00004712
Tim Peters8bb5ad22003-01-24 02:44:45 +00004713It's helpful to step back at look at [4] from a higher level: it's simply
4714mapping from UTC to tz's standard time.
Tim Petersc5dc4da2003-01-02 17:55:03 +00004715
4716At this point, if
4717
Tim Peters8bb5ad22003-01-24 02:44:45 +00004718 z.n - z.o = x.n [5]
Tim Petersc5dc4da2003-01-02 17:55:03 +00004719
4720we have an equivalent time, and are almost done. The insecurity here is
Tim Petersf3615152003-01-01 21:51:37 +00004721at the start of daylight time. Picture US Eastern for concreteness. The wall
4722time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
Tim Peters8bb5ad22003-01-24 02:44:45 +00004723sense then. The docs ask that an Eastern tzinfo class consider such a time to
4724be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST
4725on the day DST starts. We want to return the 1:MM EST spelling because that's
Tim Petersf3615152003-01-01 21:51:37 +00004726the only spelling that makes sense on the local wall clock.
4727
Tim Petersc5dc4da2003-01-02 17:55:03 +00004728In fact, if [5] holds at this point, we do have the standard-time spelling,
4729but that takes a bit of proof. We first prove a stronger result. What's the
4730difference between the LHS and RHS of [5]? Let
Tim Petersf3615152003-01-01 21:51:37 +00004731
Tim Peters8bb5ad22003-01-24 02:44:45 +00004732 diff = x.n - (z.n - z.o) [6]
Tim Petersf3615152003-01-01 21:51:37 +00004733
Tim Petersc5dc4da2003-01-02 17:55:03 +00004734Now
4735 z.n = by [4]
Tim Peters8bb5ad22003-01-24 02:44:45 +00004736 (y + y.s).n = by #5
4737 y.n + y.s = since y.n = x.n
4738 x.n + y.s = since z and y are have the same tzinfo member,
4739 y.s = z.s by #2
4740 x.n + z.s
Tim Petersf3615152003-01-01 21:51:37 +00004741
Tim Petersc5dc4da2003-01-02 17:55:03 +00004742Plugging that back into [6] gives
Tim Petersf3615152003-01-01 21:51:37 +00004743
Tim Petersc5dc4da2003-01-02 17:55:03 +00004744 diff =
Tim Peters8bb5ad22003-01-24 02:44:45 +00004745 x.n - ((x.n + z.s) - z.o) = expanding
4746 x.n - x.n - z.s + z.o = cancelling
4747 - z.s + z.o = by #2
Tim Petersc5dc4da2003-01-02 17:55:03 +00004748 z.d
Tim Petersf3615152003-01-01 21:51:37 +00004749
Tim Petersc5dc4da2003-01-02 17:55:03 +00004750So diff = z.d.
Tim Petersf3615152003-01-01 21:51:37 +00004751
Tim Petersc5dc4da2003-01-02 17:55:03 +00004752If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
Tim Peters8bb5ad22003-01-24 02:44:45 +00004753spelling we wanted in the endcase described above. We're done. Contrarily,
4754if z.d = 0, then we have a UTC equivalent, and are also done.
Tim Petersf3615152003-01-01 21:51:37 +00004755
Tim Petersc5dc4da2003-01-02 17:55:03 +00004756If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
4757add to z (in effect, z is in tz's standard time, and we need to shift the
Tim Peters8bb5ad22003-01-24 02:44:45 +00004758local clock into tz's daylight time).
Tim Petersf3615152003-01-01 21:51:37 +00004759
Tim Petersc5dc4da2003-01-02 17:55:03 +00004760Let
Tim Petersf3615152003-01-01 21:51:37 +00004761
Tim Peters4fede1a2003-01-04 00:26:59 +00004762 z' = z + z.d = z + diff [7]
Tim Petersc3bb26a2003-01-02 03:14:59 +00004763
Tim Peters4fede1a2003-01-04 00:26:59 +00004764and we can again ask whether
Tim Petersc3bb26a2003-01-02 03:14:59 +00004765
Tim Peters8bb5ad22003-01-24 02:44:45 +00004766 z'.n - z'.o = x.n [8]
Tim Petersc3bb26a2003-01-02 03:14:59 +00004767
Tim Peters8bb5ad22003-01-24 02:44:45 +00004768If so, we're done. If not, the tzinfo class is insane, according to the
4769assumptions we've made. This also requires a bit of proof. As before, let's
4770compute the difference between the LHS and RHS of [8] (and skipping some of
4771the justifications for the kinds of substitutions we've done several times
4772already):
Tim Peters4fede1a2003-01-04 00:26:59 +00004773
Tim Peters8bb5ad22003-01-24 02:44:45 +00004774 diff' = x.n - (z'.n - z'.o) = replacing z'.n via [7]
4775 x.n - (z.n + diff - z'.o) = replacing diff via [6]
4776 x.n - (z.n + x.n - (z.n - z.o) - z'.o) =
4777 x.n - z.n - x.n + z.n - z.o + z'.o = cancel x.n
4778 - z.n + z.n - z.o + z'.o = cancel z.n
Tim Peters4fede1a2003-01-04 00:26:59 +00004779 - z.o + z'.o = #1 twice
4780 -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
4781 z'.d - z.d
4782
4783So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
Tim Peters8bb5ad22003-01-24 02:44:45 +00004784we've found the UTC-equivalent so are done. In fact, we stop with [7] and
4785return z', not bothering to compute z'.d.
Tim Peters4fede1a2003-01-04 00:26:59 +00004786
Tim Peters8bb5ad22003-01-24 02:44:45 +00004787How could z.d and z'd differ? z' = z + z.d [7], so merely moving z' by
4788a dst() offset, and starting *from* a time already in DST (we know z.d != 0),
4789would have to change the result dst() returns: we start in DST, and moving
4790a little further into it takes us out of DST.
Tim Peters4fede1a2003-01-04 00:26:59 +00004791
Tim Peters8bb5ad22003-01-24 02:44:45 +00004792There isn't a sane case where this can happen. The closest it gets is at
4793the end of DST, where there's an hour in UTC with no spelling in a hybrid
4794tzinfo class. In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT. During
4795that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM
4796UTC) because the docs insist on that, but 0:MM is taken as being in daylight
4797time (4:MM UTC). There is no local time mapping to 5:MM UTC. The local
4798clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in
4799standard time. Since that's what the local clock *does*, we want to map both
4800UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
Tim Peters4fede1a2003-01-04 00:26:59 +00004801in local time, but so it goes -- it's the way the local clock works.
4802
Tim Peters8bb5ad22003-01-24 02:44:45 +00004803When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
4804so z=0:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
4805z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
Tim Peters4fede1a2003-01-04 00:26:59 +00004806(correctly) concludes that z' is not UTC-equivalent to x.
4807
4808Because we know z.d said z was in daylight time (else [5] would have held and
4809we would have stopped then), and we know z.d != z'.d (else [8] would have held
4810and we we have stopped then), and there are only 2 possible values dst() can
4811return in Eastern, it follows that z'.d must be 0 (which it is in the example,
4812but the reasoning doesn't depend on the example -- it depends on there being
4813two possible dst() outcomes, one zero and the other non-zero). Therefore
Tim Peters8bb5ad22003-01-24 02:44:45 +00004814z' must be in standard time, and is the spelling we want in this case.
4815
4816Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is
4817concerned (because it takes z' as being in standard time rather than the
4818daylight time we intend here), but returning it gives the real-life "local
4819clock repeats an hour" behavior when mapping the "unspellable" UTC hour into
4820tz.
4821
4822When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with
4823the 1:MM standard time spelling we want.
4824
4825So how can this break? One of the assumptions must be violated. Two
4826possibilities:
4827
48281) [2] effectively says that y.s is invariant across all y belong to a given
4829 time zone. This isn't true if, for political reasons or continental drift,
4830 a region decides to change its base offset from UTC.
4831
48322) There may be versions of "double daylight" time where the tail end of
4833 the analysis gives up a step too early. I haven't thought about that
4834 enough to say.
4835
4836In any case, it's clear that the default fromutc() is strong enough to handle
4837"almost all" time zones: so long as the standard offset is invariant, it
4838doesn't matter if daylight time transition points change from year to year, or
4839if daylight time is skipped in some years; it doesn't matter how large or
4840small dst() may get within its bounds; and it doesn't even matter if some
4841perverse time zone returns a negative dst()). So a breaking case must be
4842pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
Tim Petersf3615152003-01-01 21:51:37 +00004843--------------------------------------------------------------------------- */