blob: 973034bfe19871c5738c51bef031a73ef47cb57f [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;
86static PyTypeObject PyDateTime_DateTimeTZType;
87static PyTypeObject PyDateTime_DeltaType;
88static PyTypeObject PyDateTime_TimeType;
89static PyTypeObject PyDateTime_TZInfoType;
Tim Peters2a799bf2002-12-16 20:18:38 +000090
91/* ---------------------------------------------------------------------------
92 * Math utilities.
93 */
94
95/* k = i+j overflows iff k differs in sign from both inputs,
96 * iff k^i has sign bit set and k^j has sign bit set,
97 * iff (k^i)&(k^j) has sign bit set.
98 */
99#define SIGNED_ADD_OVERFLOWED(RESULT, I, J) \
100 ((((RESULT) ^ (I)) & ((RESULT) ^ (J))) < 0)
101
102/* Compute Python divmod(x, y), returning the quotient and storing the
103 * remainder into *r. The quotient is the floor of x/y, and that's
104 * the real point of this. C will probably truncate instead (C99
105 * requires truncation; C89 left it implementation-defined).
106 * Simplification: we *require* that y > 0 here. That's appropriate
107 * for all the uses made of it. This simplifies the code and makes
108 * the overflow case impossible (divmod(LONG_MIN, -1) is the only
109 * overflow case).
110 */
111static int
112divmod(int x, int y, int *r)
113{
114 int quo;
115
116 assert(y > 0);
117 quo = x / y;
118 *r = x - quo * y;
119 if (*r < 0) {
120 --quo;
121 *r += y;
122 }
123 assert(0 <= *r && *r < y);
124 return quo;
125}
126
Tim Peters5d644dd2003-01-02 16:32:54 +0000127/* Round a double to the nearest long. |x| must be small enough to fit
128 * in a C long; this is not checked.
129 */
130static long
131round_to_long(double x)
132{
133 if (x >= 0.0)
134 x = floor(x + 0.5);
135 else
136 x = ceil(x - 0.5);
137 return (long)x;
138}
139
Tim Peters2a799bf2002-12-16 20:18:38 +0000140/* ---------------------------------------------------------------------------
141 * General calendrical helper functions
142 */
143
144/* For each month ordinal in 1..12, the number of days in that month,
145 * and the number of days before that month in the same year. These
146 * are correct for non-leap years only.
147 */
148static int _days_in_month[] = {
149 0, /* unused; this vector uses 1-based indexing */
150 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
151};
152
153static int _days_before_month[] = {
154 0, /* unused; this vector uses 1-based indexing */
155 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
156};
157
158/* year -> 1 if leap year, else 0. */
159static int
160is_leap(int year)
161{
162 /* Cast year to unsigned. The result is the same either way, but
163 * C can generate faster code for unsigned mod than for signed
164 * mod (especially for % 4 -- a good compiler should just grab
165 * the last 2 bits when the LHS is unsigned).
166 */
167 const unsigned int ayear = (unsigned int)year;
168 return ayear % 4 == 0 && (ayear % 100 != 0 || ayear % 400 == 0);
169}
170
171/* year, month -> number of days in that month in that year */
172static int
173days_in_month(int year, int month)
174{
175 assert(month >= 1);
176 assert(month <= 12);
177 if (month == 2 && is_leap(year))
178 return 29;
179 else
180 return _days_in_month[month];
181}
182
183/* year, month -> number of days in year preceeding first day of month */
184static int
185days_before_month(int year, int month)
186{
187 int days;
188
189 assert(month >= 1);
190 assert(month <= 12);
191 days = _days_before_month[month];
192 if (month > 2 && is_leap(year))
193 ++days;
194 return days;
195}
196
197/* year -> number of days before January 1st of year. Remember that we
198 * start with year 1, so days_before_year(1) == 0.
199 */
200static int
201days_before_year(int year)
202{
203 int y = year - 1;
204 /* This is incorrect if year <= 0; we really want the floor
205 * here. But so long as MINYEAR is 1, the smallest year this
206 * can see is 0 (this can happen in some normalization endcases),
207 * so we'll just special-case that.
208 */
209 assert (year >= 0);
210 if (y >= 0)
211 return y*365 + y/4 - y/100 + y/400;
212 else {
213 assert(y == -1);
214 return -366;
215 }
216}
217
218/* Number of days in 4, 100, and 400 year cycles. That these have
219 * the correct values is asserted in the module init function.
220 */
221#define DI4Y 1461 /* days_before_year(5); days in 4 years */
222#define DI100Y 36524 /* days_before_year(101); days in 100 years */
223#define DI400Y 146097 /* days_before_year(401); days in 400 years */
224
225/* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */
226static void
227ord_to_ymd(int ordinal, int *year, int *month, int *day)
228{
229 int n, n1, n4, n100, n400, leapyear, preceding;
230
231 /* ordinal is a 1-based index, starting at 1-Jan-1. The pattern of
232 * leap years repeats exactly every 400 years. The basic strategy is
233 * to find the closest 400-year boundary at or before ordinal, then
234 * work with the offset from that boundary to ordinal. Life is much
235 * clearer if we subtract 1 from ordinal first -- then the values
236 * of ordinal at 400-year boundaries are exactly those divisible
237 * by DI400Y:
238 *
239 * D M Y n n-1
240 * -- --- ---- ---------- ----------------
241 * 31 Dec -400 -DI400Y -DI400Y -1
242 * 1 Jan -399 -DI400Y +1 -DI400Y 400-year boundary
243 * ...
244 * 30 Dec 000 -1 -2
245 * 31 Dec 000 0 -1
246 * 1 Jan 001 1 0 400-year boundary
247 * 2 Jan 001 2 1
248 * 3 Jan 001 3 2
249 * ...
250 * 31 Dec 400 DI400Y DI400Y -1
251 * 1 Jan 401 DI400Y +1 DI400Y 400-year boundary
252 */
253 assert(ordinal >= 1);
254 --ordinal;
255 n400 = ordinal / DI400Y;
256 n = ordinal % DI400Y;
257 *year = n400 * 400 + 1;
258
259 /* Now n is the (non-negative) offset, in days, from January 1 of
260 * year, to the desired date. Now compute how many 100-year cycles
261 * precede n.
262 * Note that it's possible for n100 to equal 4! In that case 4 full
263 * 100-year cycles precede the desired day, which implies the
264 * desired day is December 31 at the end of a 400-year cycle.
265 */
266 n100 = n / DI100Y;
267 n = n % DI100Y;
268
269 /* Now compute how many 4-year cycles precede it. */
270 n4 = n / DI4Y;
271 n = n % DI4Y;
272
273 /* And now how many single years. Again n1 can be 4, and again
274 * meaning that the desired day is December 31 at the end of the
275 * 4-year cycle.
276 */
277 n1 = n / 365;
278 n = n % 365;
279
280 *year += n100 * 100 + n4 * 4 + n1;
281 if (n1 == 4 || n100 == 4) {
282 assert(n == 0);
283 *year -= 1;
284 *month = 12;
285 *day = 31;
286 return;
287 }
288
289 /* Now the year is correct, and n is the offset from January 1. We
290 * find the month via an estimate that's either exact or one too
291 * large.
292 */
293 leapyear = n1 == 3 && (n4 != 24 || n100 == 3);
294 assert(leapyear == is_leap(*year));
295 *month = (n + 50) >> 5;
296 preceding = (_days_before_month[*month] + (*month > 2 && leapyear));
297 if (preceding > n) {
298 /* estimate is too large */
299 *month -= 1;
300 preceding -= days_in_month(*year, *month);
301 }
302 n -= preceding;
303 assert(0 <= n);
304 assert(n < days_in_month(*year, *month));
305
306 *day = n + 1;
307}
308
309/* year, month, day -> ordinal, considering 01-Jan-0001 as day 1. */
310static int
311ymd_to_ord(int year, int month, int day)
312{
313 return days_before_year(year) + days_before_month(year, month) + day;
314}
315
316/* Day of week, where Monday==0, ..., Sunday==6. 1/1/1 was a Monday. */
317static int
318weekday(int year, int month, int day)
319{
320 return (ymd_to_ord(year, month, day) + 6) % 7;
321}
322
323/* Ordinal of the Monday starting week 1 of the ISO year. Week 1 is the
324 * first calendar week containing a Thursday.
325 */
326static int
327iso_week1_monday(int year)
328{
329 int first_day = ymd_to_ord(year, 1, 1); /* ord of 1/1 */
330 /* 0 if 1/1 is a Monday, 1 if a Tue, etc. */
331 int first_weekday = (first_day + 6) % 7;
332 /* ordinal of closest Monday at or before 1/1 */
333 int week1_monday = first_day - first_weekday;
334
335 if (first_weekday > 3) /* if 1/1 was Fri, Sat, Sun */
336 week1_monday += 7;
337 return week1_monday;
338}
339
340/* ---------------------------------------------------------------------------
341 * Range checkers.
342 */
343
344/* Check that -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS. If so, return 0.
345 * If not, raise OverflowError and return -1.
346 */
347static int
348check_delta_day_range(int days)
349{
350 if (-MAX_DELTA_DAYS <= days && days <= MAX_DELTA_DAYS)
351 return 0;
352 PyErr_Format(PyExc_OverflowError,
353 "days=%d; must have magnitude <= %d",
Guido van Rossumbd43e912002-12-16 20:34:55 +0000354 days, MAX_DELTA_DAYS);
Tim Peters2a799bf2002-12-16 20:18:38 +0000355 return -1;
356}
357
358/* Check that date arguments are in range. Return 0 if they are. If they
359 * aren't, raise ValueError and return -1.
360 */
361static int
362check_date_args(int year, int month, int day)
363{
364
365 if (year < MINYEAR || year > MAXYEAR) {
366 PyErr_SetString(PyExc_ValueError,
367 "year is out of range");
368 return -1;
369 }
370 if (month < 1 || month > 12) {
371 PyErr_SetString(PyExc_ValueError,
372 "month must be in 1..12");
373 return -1;
374 }
375 if (day < 1 || day > days_in_month(year, month)) {
376 PyErr_SetString(PyExc_ValueError,
377 "day is out of range for month");
378 return -1;
379 }
380 return 0;
381}
382
383/* Check that time arguments are in range. Return 0 if they are. If they
384 * aren't, raise ValueError and return -1.
385 */
386static int
387check_time_args(int h, int m, int s, int us)
388{
389 if (h < 0 || h > 23) {
390 PyErr_SetString(PyExc_ValueError,
391 "hour must be in 0..23");
392 return -1;
393 }
394 if (m < 0 || m > 59) {
395 PyErr_SetString(PyExc_ValueError,
396 "minute must be in 0..59");
397 return -1;
398 }
399 if (s < 0 || s > 59) {
400 PyErr_SetString(PyExc_ValueError,
401 "second must be in 0..59");
402 return -1;
403 }
404 if (us < 0 || us > 999999) {
405 PyErr_SetString(PyExc_ValueError,
406 "microsecond must be in 0..999999");
407 return -1;
408 }
409 return 0;
410}
411
412/* ---------------------------------------------------------------------------
413 * Normalization utilities.
414 */
415
416/* One step of a mixed-radix conversion. A "hi" unit is equivalent to
417 * factor "lo" units. factor must be > 0. If *lo is less than 0, or
418 * at least factor, enough of *lo is converted into "hi" units so that
419 * 0 <= *lo < factor. The input values must be such that int overflow
420 * is impossible.
421 */
422static void
423normalize_pair(int *hi, int *lo, int factor)
424{
425 assert(factor > 0);
426 assert(lo != hi);
427 if (*lo < 0 || *lo >= factor) {
428 const int num_hi = divmod(*lo, factor, lo);
429 const int new_hi = *hi + num_hi;
430 assert(! SIGNED_ADD_OVERFLOWED(new_hi, *hi, num_hi));
431 *hi = new_hi;
432 }
433 assert(0 <= *lo && *lo < factor);
434}
435
436/* Fiddle days (d), seconds (s), and microseconds (us) so that
437 * 0 <= *s < 24*3600
438 * 0 <= *us < 1000000
439 * The input values must be such that the internals don't overflow.
440 * The way this routine is used, we don't get close.
441 */
442static void
443normalize_d_s_us(int *d, int *s, int *us)
444{
445 if (*us < 0 || *us >= 1000000) {
446 normalize_pair(s, us, 1000000);
447 /* |s| can't be bigger than about
448 * |original s| + |original us|/1000000 now.
449 */
450
451 }
452 if (*s < 0 || *s >= 24*3600) {
453 normalize_pair(d, s, 24*3600);
454 /* |d| can't be bigger than about
455 * |original d| +
456 * (|original s| + |original us|/1000000) / (24*3600) now.
457 */
458 }
459 assert(0 <= *s && *s < 24*3600);
460 assert(0 <= *us && *us < 1000000);
461}
462
463/* Fiddle years (y), months (m), and days (d) so that
464 * 1 <= *m <= 12
465 * 1 <= *d <= days_in_month(*y, *m)
466 * The input values must be such that the internals don't overflow.
467 * The way this routine is used, we don't get close.
468 */
469static void
470normalize_y_m_d(int *y, int *m, int *d)
471{
472 int dim; /* # of days in month */
473
474 /* This gets muddy: the proper range for day can't be determined
475 * without knowing the correct month and year, but if day is, e.g.,
476 * plus or minus a million, the current month and year values make
477 * no sense (and may also be out of bounds themselves).
478 * Saying 12 months == 1 year should be non-controversial.
479 */
480 if (*m < 1 || *m > 12) {
481 --*m;
482 normalize_pair(y, m, 12);
483 ++*m;
484 /* |y| can't be bigger than about
485 * |original y| + |original m|/12 now.
486 */
487 }
488 assert(1 <= *m && *m <= 12);
489
490 /* Now only day can be out of bounds (year may also be out of bounds
491 * for a datetime object, but we don't care about that here).
492 * If day is out of bounds, what to do is arguable, but at least the
493 * method here is principled and explainable.
494 */
495 dim = days_in_month(*y, *m);
496 if (*d < 1 || *d > dim) {
497 /* Move day-1 days from the first of the month. First try to
498 * get off cheap if we're only one day out of range
499 * (adjustments for timezone alone can't be worse than that).
500 */
501 if (*d == 0) {
502 --*m;
503 if (*m > 0)
504 *d = days_in_month(*y, *m);
505 else {
506 --*y;
507 *m = 12;
508 *d = 31;
509 }
510 }
511 else if (*d == dim + 1) {
512 /* move forward a day */
513 ++*m;
514 *d = 1;
515 if (*m > 12) {
516 *m = 1;
517 ++*y;
518 }
519 }
520 else {
521 int ordinal = ymd_to_ord(*y, *m, 1) +
522 *d - 1;
523 ord_to_ymd(ordinal, y, m, d);
524 }
525 }
526 assert(*m > 0);
527 assert(*d > 0);
528}
529
530/* Fiddle out-of-bounds months and days so that the result makes some kind
531 * of sense. The parameters are both inputs and outputs. Returns < 0 on
532 * failure, where failure means the adjusted year is out of bounds.
533 */
534static int
535normalize_date(int *year, int *month, int *day)
536{
537 int result;
538
539 normalize_y_m_d(year, month, day);
540 if (MINYEAR <= *year && *year <= MAXYEAR)
541 result = 0;
542 else {
543 PyErr_SetString(PyExc_OverflowError,
544 "date value out of range");
545 result = -1;
546 }
547 return result;
548}
549
550/* Force all the datetime fields into range. The parameters are both
551 * inputs and outputs. Returns < 0 on error.
552 */
553static int
554normalize_datetime(int *year, int *month, int *day,
555 int *hour, int *minute, int *second,
556 int *microsecond)
557{
558 normalize_pair(second, microsecond, 1000000);
559 normalize_pair(minute, second, 60);
560 normalize_pair(hour, minute, 60);
561 normalize_pair(day, hour, 24);
562 return normalize_date(year, month, day);
563}
564
565/* ---------------------------------------------------------------------------
566 * tzinfo helpers.
567 */
568
Tim Peters855fe882002-12-22 03:43:39 +0000569/* Ensure that p is None or of a tzinfo subclass. Return 0 if OK; if not
570 * raise TypeError and return -1.
571 */
572static int
573check_tzinfo_subclass(PyObject *p)
574{
575 if (p == Py_None || PyTZInfo_Check(p))
576 return 0;
577 PyErr_Format(PyExc_TypeError,
578 "tzinfo argument must be None or of a tzinfo subclass, "
579 "not type '%s'",
580 p->ob_type->tp_name);
581 return -1;
582}
583
Tim Petersbad8ff02002-12-30 20:52:32 +0000584/* Return tzinfo.methname(tzinfoarg), without any checking of results.
Tim Peters855fe882002-12-22 03:43:39 +0000585 * If tzinfo is None, returns None.
586 */
587static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000588call_tzinfo_method(PyObject *tzinfo, char *methname, PyObject *tzinfoarg)
Tim Peters855fe882002-12-22 03:43:39 +0000589{
590 PyObject *result;
591
Tim Petersbad8ff02002-12-30 20:52:32 +0000592 assert(tzinfo && methname && tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000593 assert(check_tzinfo_subclass(tzinfo) >= 0);
594 if (tzinfo == Py_None) {
595 result = Py_None;
596 Py_INCREF(result);
597 }
598 else
Tim Petersbad8ff02002-12-30 20:52:32 +0000599 result = PyObject_CallMethod(tzinfo, methname, "O", tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000600 return result;
601}
602
Tim Peters2a799bf2002-12-16 20:18:38 +0000603/* If self has a tzinfo member, return a BORROWED reference to it. Else
604 * return NULL, which is NOT AN ERROR. There are no error returns here,
605 * and the caller must not decref the result.
606 */
607static PyObject *
608get_tzinfo_member(PyObject *self)
609{
610 PyObject *tzinfo = NULL;
611
612 if (PyDateTimeTZ_Check(self))
613 tzinfo = ((PyDateTime_DateTimeTZ *)self)->tzinfo;
Tim Petersa032d2e2003-01-11 00:15:54 +0000614 else if (PyTime_Check(self) && HASTZINFO(self))
Tim Peters37f39822003-01-10 03:49:02 +0000615 tzinfo = ((PyDateTime_Time *)self)->tzinfo;
Tim Peters2a799bf2002-12-16 20:18:38 +0000616
617 return tzinfo;
618}
619
Tim Peters80475bb2002-12-25 07:40:55 +0000620/* self is a datetimetz. Replace its tzinfo member. */
621void
622replace_tzinfo(PyObject *self, PyObject *newtzinfo)
623{
624 assert(self != NULL);
625 assert(PyDateTimeTZ_Check(self));
626 assert(check_tzinfo_subclass(newtzinfo) >= 0);
627 Py_INCREF(newtzinfo);
Tim Peters33e0f382003-01-10 02:05:14 +0000628 Py_XDECREF(((PyDateTime_DateTimeTZ *)self)->tzinfo);
Tim Peters80475bb2002-12-25 07:40:55 +0000629 ((PyDateTime_DateTimeTZ *)self)->tzinfo = newtzinfo;
630}
631
Tim Petersbad8ff02002-12-30 20:52:32 +0000632
633/* Call getattr(tzinfo, name)(tzinfoarg), and extract an int from the
Tim Peters2a799bf2002-12-16 20:18:38 +0000634 * result. tzinfo must be an instance of the tzinfo class. If the method
635 * returns None, this returns 0 and sets *none to 1. If the method doesn't
Tim Peters397301e2003-01-02 21:28:08 +0000636 * return None or timedelta, TypeError is raised and this returns -1. If it
637 * returnsa timedelta and the value is out of range or isn't a whole number
638 * of minutes, ValueError is raised and this returns -1.
Tim Peters2a799bf2002-12-16 20:18:38 +0000639 * Else *none is set to 0 and the integer method result is returned.
640 */
641static int
642call_utc_tzinfo_method(PyObject *tzinfo, char *name, PyObject *tzinfoarg,
643 int *none)
644{
645 PyObject *u;
Tim Peters397301e2003-01-02 21:28:08 +0000646 int result = -1;
Tim Peters2a799bf2002-12-16 20:18:38 +0000647
648 assert(tzinfo != NULL);
649 assert(PyTZInfo_Check(tzinfo));
650 assert(tzinfoarg != NULL);
651
652 *none = 0;
Tim Petersbad8ff02002-12-30 20:52:32 +0000653 u = call_tzinfo_method(tzinfo, name, tzinfoarg);
Tim Peters2a799bf2002-12-16 20:18:38 +0000654 if (u == NULL)
655 return -1;
656
Tim Peters27362852002-12-23 16:17:39 +0000657 else if (u == Py_None) {
Tim Peters2a799bf2002-12-16 20:18:38 +0000658 result = 0;
659 *none = 1;
Tim Peters2a799bf2002-12-16 20:18:38 +0000660 }
Tim Peters855fe882002-12-22 03:43:39 +0000661 else if (PyDelta_Check(u)) {
662 const int days = GET_TD_DAYS(u);
663 if (days < -1 || days > 0)
664 result = 24*60; /* trigger ValueError below */
665 else {
666 /* next line can't overflow because we know days
667 * is -1 or 0 now
668 */
669 int ss = days * 24 * 3600 + GET_TD_SECONDS(u);
670 result = divmod(ss, 60, &ss);
671 if (ss || GET_TD_MICROSECONDS(u)) {
672 PyErr_Format(PyExc_ValueError,
673 "tzinfo.%s() must return a "
674 "whole number of minutes",
675 name);
676 result = -1;
Tim Peters855fe882002-12-22 03:43:39 +0000677 }
678 }
679 }
Tim Peters2a799bf2002-12-16 20:18:38 +0000680 else {
681 PyErr_Format(PyExc_TypeError,
Tim Peters397301e2003-01-02 21:28:08 +0000682 "tzinfo.%s() must return None or "
Tim Peters855fe882002-12-22 03:43:39 +0000683 "timedelta, not '%s'",
684 name, u->ob_type->tp_name);
Tim Peters2a799bf2002-12-16 20:18:38 +0000685 }
686
Tim Peters2a799bf2002-12-16 20:18:38 +0000687 Py_DECREF(u);
688 if (result < -1439 || result > 1439) {
689 PyErr_Format(PyExc_ValueError,
Neal Norwitz506a2242003-01-04 01:02:25 +0000690 "tzinfo.%s() returned %d; must be in "
Tim Peters2a799bf2002-12-16 20:18:38 +0000691 "-1439 .. 1439",
692 name, result);
693 result = -1;
694 }
Tim Peters397301e2003-01-02 21:28:08 +0000695 return result;
Tim Peters2a799bf2002-12-16 20:18:38 +0000696}
697
698/* Call tzinfo.utcoffset(tzinfoarg), and extract an integer from the
699 * result. tzinfo must be an instance of the tzinfo class. If utcoffset()
700 * returns None, call_utcoffset returns 0 and sets *none to 1. If uctoffset()
Tim Peters397301e2003-01-02 21:28:08 +0000701 * doesn't return None or timedelta, TypeError is raised and this returns -1.
702 * If utcoffset() returns an invalid timedelta (out of range, or not a whole
703 * # of minutes), ValueError is raised and this returns -1. Else *none is
704 * set to 0 and the offset is returned (as int # of minutes east of UTC).
Tim Peters2a799bf2002-12-16 20:18:38 +0000705 */
706static int
707call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
708{
709 return call_utc_tzinfo_method(tzinfo, "utcoffset", tzinfoarg, none);
710}
711
Tim Peters855fe882002-12-22 03:43:39 +0000712static PyObject *new_delta(int d, int sec, int usec, int normalize);
713
Tim Petersbad8ff02002-12-30 20:52:32 +0000714/* Call tzinfo.name(tzinfoarg), and return the offset as a timedelta or None.
715 */
Tim Peters855fe882002-12-22 03:43:39 +0000716static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000717offset_as_timedelta(PyObject *tzinfo, char *name, PyObject *tzinfoarg) {
Tim Peters855fe882002-12-22 03:43:39 +0000718 PyObject *result;
719
Tim Petersbad8ff02002-12-30 20:52:32 +0000720 assert(tzinfo && name && tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000721 if (tzinfo == Py_None) {
722 result = Py_None;
723 Py_INCREF(result);
724 }
725 else {
726 int none;
Tim Petersbad8ff02002-12-30 20:52:32 +0000727 int offset = call_utc_tzinfo_method(tzinfo, name, tzinfoarg,
728 &none);
Tim Peters855fe882002-12-22 03:43:39 +0000729 if (offset < 0 && PyErr_Occurred())
730 return NULL;
731 if (none) {
732 result = Py_None;
733 Py_INCREF(result);
734 }
735 else
736 result = new_delta(0, offset * 60, 0, 1);
737 }
738 return result;
739}
740
Tim Peters2a799bf2002-12-16 20:18:38 +0000741/* Call tzinfo.dst(tzinfoarg), and extract an integer from the
742 * result. tzinfo must be an instance of the tzinfo class. If dst()
743 * returns None, call_dst returns 0 and sets *none to 1. If dst()
Tim Peters397301e2003-01-02 21:28:08 +0000744 & doesn't return None or timedelta, TypeError is raised and this
745 * returns -1. If dst() returns an invalid timedelta for for a UTC offset,
746 * ValueError is raised and this returns -1. Else *none is set to 0 and
747 * the offset is returned (as an int # of minutes east of UTC).
Tim Peters2a799bf2002-12-16 20:18:38 +0000748 */
749static int
750call_dst(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
751{
752 return call_utc_tzinfo_method(tzinfo, "dst", tzinfoarg, none);
753}
754
Tim Petersbad8ff02002-12-30 20:52:32 +0000755/* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be
Tim Peters855fe882002-12-22 03:43:39 +0000756 * an instance of the tzinfo class or None. If tzinfo isn't None, and
Tim Petersbad8ff02002-12-30 20:52:32 +0000757 * tzname() doesn't return None or a string, TypeError is raised and this
Tim Peters855fe882002-12-22 03:43:39 +0000758 * returns NULL.
Tim Peters2a799bf2002-12-16 20:18:38 +0000759 */
760static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000761call_tzname(PyObject *tzinfo, PyObject *tzinfoarg)
Tim Peters2a799bf2002-12-16 20:18:38 +0000762{
763 PyObject *result;
764
765 assert(tzinfo != NULL);
Tim Peters855fe882002-12-22 03:43:39 +0000766 assert(check_tzinfo_subclass(tzinfo) >= 0);
Tim Petersbad8ff02002-12-30 20:52:32 +0000767 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +0000768
Tim Peters855fe882002-12-22 03:43:39 +0000769 if (tzinfo == Py_None) {
770 result = Py_None;
771 Py_INCREF(result);
772 }
773 else
Tim Petersbad8ff02002-12-30 20:52:32 +0000774 result = PyObject_CallMethod(tzinfo, "tzname", "O", tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000775
776 if (result != NULL && result != Py_None && ! PyString_Check(result)) {
777 PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must "
Tim Peters2a799bf2002-12-16 20:18:38 +0000778 "return None or a string, not '%s'",
779 result->ob_type->tp_name);
780 Py_DECREF(result);
781 result = NULL;
782 }
783 return result;
784}
785
786typedef enum {
787 /* an exception has been set; the caller should pass it on */
788 OFFSET_ERROR,
789
Tim Peters37f39822003-01-10 03:49:02 +0000790 /* type isn't date, datetime, datetimetz subclass, or time
791 * subclass
Tim Peters2a799bf2002-12-16 20:18:38 +0000792 */
793 OFFSET_UNKNOWN,
794
795 /* date,
796 * datetime,
797 * datetimetz with None tzinfo,
Tim Peters855fe882002-12-22 03:43:39 +0000798 * datetimetz where utcoffset() returns None
Tim Peters37f39822003-01-10 03:49:02 +0000799 * time with !hastzinfo
800 * time with None tzinfo,
801 * time where utcoffset() returns None
Tim Peters2a799bf2002-12-16 20:18:38 +0000802 */
803 OFFSET_NAIVE,
804
Tim Peters37f39822003-01-10 03:49:02 +0000805 /* time where utcoffset() doesn't return None,
Tim Peters2a799bf2002-12-16 20:18:38 +0000806 * datetimetz where utcoffset() doesn't return None
807 */
808 OFFSET_AWARE,
809} naivety;
810
Tim Peters14b69412002-12-22 18:10:22 +0000811/* Classify an object as to whether it's naive or offset-aware. See
Tim Peters2a799bf2002-12-16 20:18:38 +0000812 * the "naivety" typedef for details. If the type is aware, *offset is set
813 * to minutes east of UTC (as returned by the tzinfo.utcoffset() method).
Tim Peters14b69412002-12-22 18:10:22 +0000814 * If the type is offset-naive (or unknown, or error), *offset is set to 0.
Tim Peterse39a80c2002-12-30 21:28:52 +0000815 * tzinfoarg is the argument to pass to the tzinfo.utcoffset() method.
Tim Peters2a799bf2002-12-16 20:18:38 +0000816 */
817static naivety
Tim Peterse39a80c2002-12-30 21:28:52 +0000818classify_utcoffset(PyObject *op, PyObject *tzinfoarg, int *offset)
Tim Peters2a799bf2002-12-16 20:18:38 +0000819{
820 int none;
821 PyObject *tzinfo;
822
Tim Peterse39a80c2002-12-30 21:28:52 +0000823 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +0000824 *offset = 0;
Tim Peters14b69412002-12-22 18:10:22 +0000825 tzinfo = get_tzinfo_member(op); /* NULL means no tzinfo, not error */
Tim Peters2a799bf2002-12-16 20:18:38 +0000826 if (tzinfo == Py_None)
827 return OFFSET_NAIVE;
Tim Peters14b69412002-12-22 18:10:22 +0000828 if (tzinfo == NULL) {
829 /* note that a datetime passes the PyDate_Check test */
830 return (PyTime_Check(op) || PyDate_Check(op)) ?
831 OFFSET_NAIVE : OFFSET_UNKNOWN;
832 }
Tim Peterse39a80c2002-12-30 21:28:52 +0000833 *offset = call_utcoffset(tzinfo, tzinfoarg, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +0000834 if (*offset == -1 && PyErr_Occurred())
835 return OFFSET_ERROR;
836 return none ? OFFSET_NAIVE : OFFSET_AWARE;
837}
838
Tim Peters00237032002-12-27 02:21:51 +0000839/* Classify two objects as to whether they're naive or offset-aware.
840 * This isn't quite the same as calling classify_utcoffset() twice: for
841 * binary operations (comparison and subtraction), we generally want to
842 * ignore the tzinfo members if they're identical. This is by design,
843 * so that results match "naive" expectations when mixing objects from a
844 * single timezone. So in that case, this sets both offsets to 0 and
845 * both naiveties to OFFSET_NAIVE.
846 * The function returns 0 if everything's OK, and -1 on error.
847 */
848static int
849classify_two_utcoffsets(PyObject *o1, int *offset1, naivety *n1,
Tim Peterse39a80c2002-12-30 21:28:52 +0000850 PyObject *tzinfoarg1,
851 PyObject *o2, int *offset2, naivety *n2,
852 PyObject *tzinfoarg2)
Tim Peters00237032002-12-27 02:21:51 +0000853{
854 if (get_tzinfo_member(o1) == get_tzinfo_member(o2)) {
855 *offset1 = *offset2 = 0;
856 *n1 = *n2 = OFFSET_NAIVE;
857 }
858 else {
Tim Peterse39a80c2002-12-30 21:28:52 +0000859 *n1 = classify_utcoffset(o1, tzinfoarg1, offset1);
Tim Peters00237032002-12-27 02:21:51 +0000860 if (*n1 == OFFSET_ERROR)
861 return -1;
Tim Peterse39a80c2002-12-30 21:28:52 +0000862 *n2 = classify_utcoffset(o2, tzinfoarg2, offset2);
Tim Peters00237032002-12-27 02:21:51 +0000863 if (*n2 == OFFSET_ERROR)
864 return -1;
865 }
866 return 0;
867}
868
Tim Peters2a799bf2002-12-16 20:18:38 +0000869/* repr is like "someclass(arg1, arg2)". If tzinfo isn't None,
870 * stuff
871 * ", tzinfo=" + repr(tzinfo)
872 * before the closing ")".
873 */
874static PyObject *
875append_keyword_tzinfo(PyObject *repr, PyObject *tzinfo)
876{
877 PyObject *temp;
878
879 assert(PyString_Check(repr));
880 assert(tzinfo);
881 if (tzinfo == Py_None)
882 return repr;
883 /* Get rid of the trailing ')'. */
884 assert(PyString_AsString(repr)[PyString_Size(repr)-1] == ')');
885 temp = PyString_FromStringAndSize(PyString_AsString(repr),
886 PyString_Size(repr) - 1);
887 Py_DECREF(repr);
888 if (temp == NULL)
889 return NULL;
890 repr = temp;
891
892 /* Append ", tzinfo=". */
893 PyString_ConcatAndDel(&repr, PyString_FromString(", tzinfo="));
894
895 /* Append repr(tzinfo). */
896 PyString_ConcatAndDel(&repr, PyObject_Repr(tzinfo));
897
898 /* Add a closing paren. */
899 PyString_ConcatAndDel(&repr, PyString_FromString(")"));
900 return repr;
901}
902
903/* ---------------------------------------------------------------------------
904 * String format helpers.
905 */
906
907static PyObject *
908format_ctime(PyDateTime_Date *date,
909 int hours, int minutes, int seconds)
910{
911 static char *DayNames[] = {
912 "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
913 };
914 static char *MonthNames[] = {
915 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
916 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
917 };
918
919 char buffer[128];
920 int wday = weekday(GET_YEAR(date), GET_MONTH(date), GET_DAY(date));
921
922 PyOS_snprintf(buffer, sizeof(buffer), "%s %s %2d %02d:%02d:%02d %04d",
923 DayNames[wday], MonthNames[GET_MONTH(date) - 1],
924 GET_DAY(date), hours, minutes, seconds,
925 GET_YEAR(date));
926 return PyString_FromString(buffer);
927}
928
929/* Add an hours & minutes UTC offset string to buf. buf has no more than
930 * buflen bytes remaining. The UTC offset is gotten by calling
931 * tzinfo.uctoffset(tzinfoarg). If that returns None, \0 is stored into
932 * *buf, and that's all. Else the returned value is checked for sanity (an
933 * integer in range), and if that's OK it's converted to an hours & minutes
934 * string of the form
935 * sign HH sep MM
936 * Returns 0 if everything is OK. If the return value from utcoffset() is
937 * bogus, an appropriate exception is set and -1 is returned.
938 */
939static int
Tim Peters328fff72002-12-20 01:31:27 +0000940format_utcoffset(char *buf, size_t buflen, const char *sep,
Tim Peters2a799bf2002-12-16 20:18:38 +0000941 PyObject *tzinfo, PyObject *tzinfoarg)
942{
943 int offset;
944 int hours;
945 int minutes;
946 char sign;
947 int none;
948
949 offset = call_utcoffset(tzinfo, tzinfoarg, &none);
950 if (offset == -1 && PyErr_Occurred())
951 return -1;
952 if (none) {
953 *buf = '\0';
954 return 0;
955 }
956 sign = '+';
957 if (offset < 0) {
958 sign = '-';
959 offset = - offset;
960 }
961 hours = divmod(offset, 60, &minutes);
962 PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes);
963 return 0;
964}
965
966/* I sure don't want to reproduce the strftime code from the time module,
967 * so this imports the module and calls it. All the hair is due to
968 * giving special meanings to the %z and %Z format codes via a preprocessing
969 * step on the format string.
Tim Petersbad8ff02002-12-30 20:52:32 +0000970 * tzinfoarg is the argument to pass to the object's tzinfo method, if
971 * needed.
Tim Peters2a799bf2002-12-16 20:18:38 +0000972 */
973static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000974wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
975 PyObject *tzinfoarg)
Tim Peters2a799bf2002-12-16 20:18:38 +0000976{
977 PyObject *result = NULL; /* guilty until proved innocent */
978
979 PyObject *zreplacement = NULL; /* py string, replacement for %z */
980 PyObject *Zreplacement = NULL; /* py string, replacement for %Z */
981
982 char *pin; /* pointer to next char in input format */
983 char ch; /* next char in input format */
984
985 PyObject *newfmt = NULL; /* py string, the output format */
986 char *pnew; /* pointer to available byte in output format */
987 char totalnew; /* number bytes total in output format buffer,
988 exclusive of trailing \0 */
989 char usednew; /* number bytes used so far in output format buffer */
990
991 char *ptoappend; /* pointer to string to append to output buffer */
992 int ntoappend; /* # of bytes to append to output buffer */
993
Tim Peters2a799bf2002-12-16 20:18:38 +0000994 assert(object && format && timetuple);
995 assert(PyString_Check(format));
996
Tim Petersd6844152002-12-22 20:58:42 +0000997 /* Give up if the year is before 1900.
998 * Python strftime() plays games with the year, and different
999 * games depending on whether envar PYTHON2K is set. This makes
1000 * years before 1900 a nightmare, even if the platform strftime
1001 * supports them (and not all do).
1002 * We could get a lot farther here by avoiding Python's strftime
1003 * wrapper and calling the C strftime() directly, but that isn't
1004 * an option in the Python implementation of this module.
1005 */
1006 {
1007 long year;
1008 PyObject *pyyear = PySequence_GetItem(timetuple, 0);
1009 if (pyyear == NULL) return NULL;
1010 assert(PyInt_Check(pyyear));
1011 year = PyInt_AsLong(pyyear);
1012 Py_DECREF(pyyear);
1013 if (year < 1900) {
1014 PyErr_Format(PyExc_ValueError, "year=%ld is before "
1015 "1900; the datetime strftime() "
1016 "methods require year >= 1900",
1017 year);
1018 return NULL;
1019 }
1020 }
1021
Tim Peters2a799bf2002-12-16 20:18:38 +00001022 /* Scan the input format, looking for %z and %Z escapes, building
Tim Peters328fff72002-12-20 01:31:27 +00001023 * a new format. Since computing the replacements for those codes
1024 * is expensive, don't unless they're actually used.
Tim Peters2a799bf2002-12-16 20:18:38 +00001025 */
1026 totalnew = PyString_Size(format); /* realistic if no %z/%Z */
1027 newfmt = PyString_FromStringAndSize(NULL, totalnew);
1028 if (newfmt == NULL) goto Done;
1029 pnew = PyString_AsString(newfmt);
1030 usednew = 0;
1031
1032 pin = PyString_AsString(format);
1033 while ((ch = *pin++) != '\0') {
1034 if (ch != '%') {
Tim Peters328fff72002-12-20 01:31:27 +00001035 ptoappend = pin - 1;
Tim Peters2a799bf2002-12-16 20:18:38 +00001036 ntoappend = 1;
1037 }
1038 else if ((ch = *pin++) == '\0') {
1039 /* There's a lone trailing %; doesn't make sense. */
1040 PyErr_SetString(PyExc_ValueError, "strftime format "
1041 "ends with raw %");
1042 goto Done;
1043 }
1044 /* A % has been seen and ch is the character after it. */
1045 else if (ch == 'z') {
1046 if (zreplacement == NULL) {
1047 /* format utcoffset */
Tim Peters328fff72002-12-20 01:31:27 +00001048 char buf[100];
Tim Peters2a799bf2002-12-16 20:18:38 +00001049 PyObject *tzinfo = get_tzinfo_member(object);
1050 zreplacement = PyString_FromString("");
1051 if (zreplacement == NULL) goto Done;
1052 if (tzinfo != Py_None && tzinfo != NULL) {
Tim Petersbad8ff02002-12-30 20:52:32 +00001053 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +00001054 if (format_utcoffset(buf,
Tim Peters328fff72002-12-20 01:31:27 +00001055 sizeof(buf),
Tim Peters2a799bf2002-12-16 20:18:38 +00001056 "",
1057 tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00001058 tzinfoarg) < 0)
Tim Peters2a799bf2002-12-16 20:18:38 +00001059 goto Done;
1060 Py_DECREF(zreplacement);
1061 zreplacement = PyString_FromString(buf);
1062 if (zreplacement == NULL) goto Done;
1063 }
1064 }
1065 assert(zreplacement != NULL);
1066 ptoappend = PyString_AsString(zreplacement);
1067 ntoappend = PyString_Size(zreplacement);
1068 }
1069 else if (ch == 'Z') {
1070 /* format tzname */
1071 if (Zreplacement == NULL) {
1072 PyObject *tzinfo = get_tzinfo_member(object);
1073 Zreplacement = PyString_FromString("");
1074 if (Zreplacement == NULL) goto Done;
1075 if (tzinfo != Py_None && tzinfo != NULL) {
Tim Petersbad8ff02002-12-30 20:52:32 +00001076 PyObject *temp;
1077 assert(tzinfoarg != NULL);
1078 temp = call_tzname(tzinfo, tzinfoarg);
Tim Peters2a799bf2002-12-16 20:18:38 +00001079 if (temp == NULL) goto Done;
1080 if (temp != Py_None) {
1081 assert(PyString_Check(temp));
1082 /* Since the tzname is getting
1083 * stuffed into the format, we
1084 * have to double any % signs
1085 * so that strftime doesn't
1086 * treat them as format codes.
1087 */
1088 Py_DECREF(Zreplacement);
1089 Zreplacement = PyObject_CallMethod(
1090 temp, "replace",
1091 "ss", "%", "%%");
1092 Py_DECREF(temp);
1093 if (Zreplacement == NULL)
1094 goto Done;
1095 }
1096 else
1097 Py_DECREF(temp);
1098 }
1099 }
1100 assert(Zreplacement != NULL);
1101 ptoappend = PyString_AsString(Zreplacement);
1102 ntoappend = PyString_Size(Zreplacement);
1103 }
1104 else {
Tim Peters328fff72002-12-20 01:31:27 +00001105 /* percent followed by neither z nor Z */
1106 ptoappend = pin - 2;
Tim Peters2a799bf2002-12-16 20:18:38 +00001107 ntoappend = 2;
1108 }
1109
1110 /* Append the ntoappend chars starting at ptoappend to
1111 * the new format.
1112 */
1113 assert(ntoappend >= 0);
1114 if (ntoappend == 0)
1115 continue;
1116 while (usednew + ntoappend > totalnew) {
1117 int bigger = totalnew << 1;
1118 if ((bigger >> 1) != totalnew) { /* overflow */
1119 PyErr_NoMemory();
1120 goto Done;
1121 }
1122 if (_PyString_Resize(&newfmt, bigger) < 0)
1123 goto Done;
1124 totalnew = bigger;
1125 pnew = PyString_AsString(newfmt) + usednew;
1126 }
1127 memcpy(pnew, ptoappend, ntoappend);
1128 pnew += ntoappend;
1129 usednew += ntoappend;
1130 assert(usednew <= totalnew);
1131 } /* end while() */
1132
1133 if (_PyString_Resize(&newfmt, usednew) < 0)
1134 goto Done;
1135 {
1136 PyObject *time = PyImport_ImportModule("time");
1137 if (time == NULL)
1138 goto Done;
1139 result = PyObject_CallMethod(time, "strftime", "OO",
1140 newfmt, timetuple);
1141 Py_DECREF(time);
1142 }
1143 Done:
1144 Py_XDECREF(zreplacement);
1145 Py_XDECREF(Zreplacement);
1146 Py_XDECREF(newfmt);
1147 return result;
1148}
1149
1150static char *
1151isoformat_date(PyDateTime_Date *dt, char buffer[], int bufflen)
1152{
1153 int x;
1154 x = PyOS_snprintf(buffer, bufflen,
1155 "%04d-%02d-%02d",
1156 GET_YEAR(dt), GET_MONTH(dt), GET_DAY(dt));
1157 return buffer + x;
1158}
1159
1160static void
1161isoformat_time(PyDateTime_DateTime *dt, char buffer[], int bufflen)
1162{
1163 int us = DATE_GET_MICROSECOND(dt);
1164
1165 PyOS_snprintf(buffer, bufflen,
1166 "%02d:%02d:%02d", /* 8 characters */
1167 DATE_GET_HOUR(dt),
1168 DATE_GET_MINUTE(dt),
1169 DATE_GET_SECOND(dt));
1170 if (us)
1171 PyOS_snprintf(buffer + 8, bufflen - 8, ".%06d", us);
1172}
1173
1174/* ---------------------------------------------------------------------------
1175 * Wrap functions from the time module. These aren't directly available
1176 * from C. Perhaps they should be.
1177 */
1178
1179/* Call time.time() and return its result (a Python float). */
1180static PyObject *
Guido van Rossumbd43e912002-12-16 20:34:55 +00001181time_time(void)
Tim Peters2a799bf2002-12-16 20:18:38 +00001182{
1183 PyObject *result = NULL;
1184 PyObject *time = PyImport_ImportModule("time");
1185
1186 if (time != NULL) {
1187 result = PyObject_CallMethod(time, "time", "()");
1188 Py_DECREF(time);
1189 }
1190 return result;
1191}
1192
1193/* Build a time.struct_time. The weekday and day number are automatically
1194 * computed from the y,m,d args.
1195 */
1196static PyObject *
1197build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
1198{
1199 PyObject *time;
1200 PyObject *result = NULL;
1201
1202 time = PyImport_ImportModule("time");
1203 if (time != NULL) {
1204 result = PyObject_CallMethod(time, "struct_time",
1205 "((iiiiiiiii))",
1206 y, m, d,
1207 hh, mm, ss,
1208 weekday(y, m, d),
1209 days_before_month(y, m) + d,
1210 dstflag);
1211 Py_DECREF(time);
1212 }
1213 return result;
1214}
1215
1216/* ---------------------------------------------------------------------------
1217 * Miscellaneous helpers.
1218 */
1219
1220/* For obscure reasons, we need to use tp_richcompare instead of tp_compare.
1221 * The comparisons here all most naturally compute a cmp()-like result.
1222 * This little helper turns that into a bool result for rich comparisons.
1223 */
1224static PyObject *
1225diff_to_bool(int diff, int op)
1226{
1227 PyObject *result;
1228 int istrue;
1229
1230 switch (op) {
1231 case Py_EQ: istrue = diff == 0; break;
1232 case Py_NE: istrue = diff != 0; break;
1233 case Py_LE: istrue = diff <= 0; break;
1234 case Py_GE: istrue = diff >= 0; break;
1235 case Py_LT: istrue = diff < 0; break;
1236 case Py_GT: istrue = diff > 0; break;
1237 default:
1238 assert(! "op unknown");
1239 istrue = 0; /* To shut up compiler */
1240 }
1241 result = istrue ? Py_True : Py_False;
1242 Py_INCREF(result);
1243 return result;
1244}
1245
1246/* ---------------------------------------------------------------------------
1247 * Helpers for setting object fields. These work on pointers to the
1248 * appropriate base class.
1249 */
1250
1251/* For date, datetime and datetimetz. */
1252static void
1253set_date_fields(PyDateTime_Date *self, int y, int m, int d)
1254{
1255 self->hashcode = -1;
1256 SET_YEAR(self, y);
1257 SET_MONTH(self, m);
1258 SET_DAY(self, d);
1259}
1260
1261/* For datetime and datetimetz. */
1262static void
1263set_datetime_time_fields(PyDateTime_Date *self, int h, int m, int s, int us)
1264{
1265 DATE_SET_HOUR(self, h);
1266 DATE_SET_MINUTE(self, m);
1267 DATE_SET_SECOND(self, s);
1268 DATE_SET_MICROSECOND(self, us);
1269}
1270
Tim Peters37f39822003-01-10 03:49:02 +00001271/* For time. */
Tim Peters2a799bf2002-12-16 20:18:38 +00001272static void
1273set_time_fields(PyDateTime_Time *self, int h, int m, int s, int us)
1274{
1275 self->hashcode = -1;
1276 TIME_SET_HOUR(self, h);
1277 TIME_SET_MINUTE(self, m);
1278 TIME_SET_SECOND(self, s);
1279 TIME_SET_MICROSECOND(self, us);
1280}
1281
1282/* ---------------------------------------------------------------------------
1283 * Create various objects, mostly without range checking.
1284 */
1285
1286/* Create a date instance with no range checking. */
1287static PyObject *
1288new_date(int year, int month, int day)
1289{
1290 PyDateTime_Date *self;
1291
1292 self = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
1293 if (self != NULL)
1294 set_date_fields(self, year, month, day);
1295 return (PyObject *) self;
1296}
1297
1298/* Create a datetime instance with no range checking. */
1299static PyObject *
1300new_datetime(int year, int month, int day, int hour, int minute,
1301 int second, int usecond)
1302{
1303 PyDateTime_DateTime *self;
1304
1305 self = PyObject_New(PyDateTime_DateTime, &PyDateTime_DateTimeType);
1306 if (self != NULL) {
1307 set_date_fields((PyDateTime_Date *)self, year, month, day);
1308 set_datetime_time_fields((PyDateTime_Date *)self,
1309 hour, minute, second, usecond);
1310 }
1311 return (PyObject *) self;
1312}
1313
1314/* Create a datetimetz instance with no range checking. */
1315static PyObject *
1316new_datetimetz(int year, int month, int day, int hour, int minute,
1317 int second, int usecond, PyObject *tzinfo)
1318{
1319 PyDateTime_DateTimeTZ *self;
1320
1321 self = PyObject_New(PyDateTime_DateTimeTZ, &PyDateTime_DateTimeTZType);
1322 if (self != NULL) {
1323 set_date_fields((PyDateTime_Date *)self, year, month, day);
1324 set_datetime_time_fields((PyDateTime_Date *)self,
1325 hour, minute, second, usecond);
1326 Py_INCREF(tzinfo);
1327 self->tzinfo = tzinfo;
1328 }
1329 return (PyObject *) self;
1330}
1331
1332/* Create a time instance with no range checking. */
1333static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00001334new_time(int hour, int minute, int second, int usecond, PyObject *tzinfo)
Tim Peters2a799bf2002-12-16 20:18:38 +00001335{
1336 PyDateTime_Time *self;
Tim Peters37f39822003-01-10 03:49:02 +00001337 char aware = tzinfo != Py_None;
Tim Peters2a799bf2002-12-16 20:18:38 +00001338
Tim Peters37f39822003-01-10 03:49:02 +00001339 self = (PyDateTime_Time *)PyObject_MALLOC(aware ?
1340 sizeof(PyDateTime_Time) :
1341 sizeof(_PyDateTime_BaseTime));
1342 if (self == NULL)
1343 return PyErr_NoMemory();
1344 self->hastzinfo = aware;
1345 set_time_fields(self, hour, minute, second, usecond);
1346 if (aware) {
Tim Peters2a799bf2002-12-16 20:18:38 +00001347 Py_INCREF(tzinfo);
1348 self->tzinfo = tzinfo;
1349 }
Tim Peters37f39822003-01-10 03:49:02 +00001350 return (PyObject *)PyObject_INIT(self, &PyDateTime_TimeType);
Tim Peters2a799bf2002-12-16 20:18:38 +00001351}
1352
1353/* Create a timedelta instance. Normalize the members iff normalize is
1354 * true. Passing false is a speed optimization, if you know for sure
1355 * that seconds and microseconds are already in their proper ranges. In any
1356 * case, raises OverflowError and returns NULL if the normalized days is out
1357 * of range).
1358 */
1359static PyObject *
1360new_delta(int days, int seconds, int microseconds, int normalize)
1361{
1362 PyDateTime_Delta *self;
1363
1364 if (normalize)
1365 normalize_d_s_us(&days, &seconds, &microseconds);
1366 assert(0 <= seconds && seconds < 24*3600);
1367 assert(0 <= microseconds && microseconds < 1000000);
1368
1369 if (check_delta_day_range(days) < 0)
1370 return NULL;
1371
1372 self = PyObject_New(PyDateTime_Delta, &PyDateTime_DeltaType);
1373 if (self != NULL) {
1374 self->hashcode = -1;
1375 SET_TD_DAYS(self, days);
1376 SET_TD_SECONDS(self, seconds);
1377 SET_TD_MICROSECONDS(self, microseconds);
1378 }
1379 return (PyObject *) self;
1380}
1381
1382
1383/* ---------------------------------------------------------------------------
1384 * Cached Python objects; these are set by the module init function.
1385 */
1386
1387/* Conversion factors. */
1388static PyObject *us_per_us = NULL; /* 1 */
1389static PyObject *us_per_ms = NULL; /* 1000 */
1390static PyObject *us_per_second = NULL; /* 1000000 */
1391static PyObject *us_per_minute = NULL; /* 1e6 * 60 as Python int */
1392static PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python long */
1393static PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python long */
1394static PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python long */
1395static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */
1396
1397/* Callables to support unpickling. */
1398static PyObject *date_unpickler_object = NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00001399static PyObject *datetimetz_unpickler_object = NULL;
1400static PyObject *tzinfo_unpickler_object = NULL;
Tim Peters37f39822003-01-10 03:49:02 +00001401static PyObject *time_unpickler_object = NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00001402
1403/* ---------------------------------------------------------------------------
1404 * Class implementations.
1405 */
1406
1407/*
1408 * PyDateTime_Delta implementation.
1409 */
1410
1411/* Convert a timedelta to a number of us,
1412 * (24*3600*self.days + self.seconds)*1000000 + self.microseconds
1413 * as a Python int or long.
1414 * Doing mixed-radix arithmetic by hand instead is excruciating in C,
1415 * due to ubiquitous overflow possibilities.
1416 */
1417static PyObject *
1418delta_to_microseconds(PyDateTime_Delta *self)
1419{
1420 PyObject *x1 = NULL;
1421 PyObject *x2 = NULL;
1422 PyObject *x3 = NULL;
1423 PyObject *result = NULL;
1424
1425 x1 = PyInt_FromLong(GET_TD_DAYS(self));
1426 if (x1 == NULL)
1427 goto Done;
1428 x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */
1429 if (x2 == NULL)
1430 goto Done;
1431 Py_DECREF(x1);
1432 x1 = NULL;
1433
1434 /* x2 has days in seconds */
1435 x1 = PyInt_FromLong(GET_TD_SECONDS(self)); /* seconds */
1436 if (x1 == NULL)
1437 goto Done;
1438 x3 = PyNumber_Add(x1, x2); /* days and seconds in seconds */
1439 if (x3 == NULL)
1440 goto Done;
1441 Py_DECREF(x1);
1442 Py_DECREF(x2);
1443 x1 = x2 = NULL;
1444
1445 /* x3 has days+seconds in seconds */
1446 x1 = PyNumber_Multiply(x3, us_per_second); /* us */
1447 if (x1 == NULL)
1448 goto Done;
1449 Py_DECREF(x3);
1450 x3 = NULL;
1451
1452 /* x1 has days+seconds in us */
1453 x2 = PyInt_FromLong(GET_TD_MICROSECONDS(self));
1454 if (x2 == NULL)
1455 goto Done;
1456 result = PyNumber_Add(x1, x2);
1457
1458Done:
1459 Py_XDECREF(x1);
1460 Py_XDECREF(x2);
1461 Py_XDECREF(x3);
1462 return result;
1463}
1464
1465/* Convert a number of us (as a Python int or long) to a timedelta.
1466 */
1467static PyObject *
1468microseconds_to_delta(PyObject *pyus)
1469{
1470 int us;
1471 int s;
1472 int d;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001473 long temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001474
1475 PyObject *tuple = NULL;
1476 PyObject *num = NULL;
1477 PyObject *result = NULL;
1478
1479 tuple = PyNumber_Divmod(pyus, us_per_second);
1480 if (tuple == NULL)
1481 goto Done;
1482
1483 num = PyTuple_GetItem(tuple, 1); /* us */
1484 if (num == NULL)
1485 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001486 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001487 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001488 if (temp == -1 && PyErr_Occurred())
1489 goto Done;
1490 assert(0 <= temp && temp < 1000000);
1491 us = (int)temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001492 if (us < 0) {
1493 /* The divisor was positive, so this must be an error. */
1494 assert(PyErr_Occurred());
1495 goto Done;
1496 }
1497
1498 num = PyTuple_GetItem(tuple, 0); /* leftover seconds */
1499 if (num == NULL)
1500 goto Done;
1501 Py_INCREF(num);
1502 Py_DECREF(tuple);
1503
1504 tuple = PyNumber_Divmod(num, seconds_per_day);
1505 if (tuple == NULL)
1506 goto Done;
1507 Py_DECREF(num);
1508
1509 num = PyTuple_GetItem(tuple, 1); /* seconds */
1510 if (num == NULL)
1511 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001512 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001513 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001514 if (temp == -1 && PyErr_Occurred())
1515 goto Done;
1516 assert(0 <= temp && temp < 24*3600);
1517 s = (int)temp;
1518
Tim Peters2a799bf2002-12-16 20:18:38 +00001519 if (s < 0) {
1520 /* The divisor was positive, so this must be an error. */
1521 assert(PyErr_Occurred());
1522 goto Done;
1523 }
1524
1525 num = PyTuple_GetItem(tuple, 0); /* leftover days */
1526 if (num == NULL)
1527 goto Done;
1528 Py_INCREF(num);
Tim Peters0b0f41c2002-12-19 01:44:38 +00001529 temp = PyLong_AsLong(num);
1530 if (temp == -1 && PyErr_Occurred())
Tim Peters2a799bf2002-12-16 20:18:38 +00001531 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001532 d = (int)temp;
1533 if ((long)d != temp) {
1534 PyErr_SetString(PyExc_OverflowError, "normalized days too "
1535 "large to fit in a C int");
1536 goto Done;
1537 }
Tim Peters2a799bf2002-12-16 20:18:38 +00001538 result = new_delta(d, s, us, 0);
1539
1540Done:
1541 Py_XDECREF(tuple);
1542 Py_XDECREF(num);
1543 return result;
1544}
1545
1546static PyObject *
1547multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
1548{
1549 PyObject *pyus_in;
1550 PyObject *pyus_out;
1551 PyObject *result;
1552
1553 pyus_in = delta_to_microseconds(delta);
1554 if (pyus_in == NULL)
1555 return NULL;
1556
1557 pyus_out = PyNumber_Multiply(pyus_in, intobj);
1558 Py_DECREF(pyus_in);
1559 if (pyus_out == NULL)
1560 return NULL;
1561
1562 result = microseconds_to_delta(pyus_out);
1563 Py_DECREF(pyus_out);
1564 return result;
1565}
1566
1567static PyObject *
1568divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj)
1569{
1570 PyObject *pyus_in;
1571 PyObject *pyus_out;
1572 PyObject *result;
1573
1574 pyus_in = delta_to_microseconds(delta);
1575 if (pyus_in == NULL)
1576 return NULL;
1577
1578 pyus_out = PyNumber_FloorDivide(pyus_in, intobj);
1579 Py_DECREF(pyus_in);
1580 if (pyus_out == NULL)
1581 return NULL;
1582
1583 result = microseconds_to_delta(pyus_out);
1584 Py_DECREF(pyus_out);
1585 return result;
1586}
1587
1588static PyObject *
1589delta_add(PyObject *left, PyObject *right)
1590{
1591 PyObject *result = Py_NotImplemented;
1592
1593 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1594 /* delta + delta */
1595 /* The C-level additions can't overflow because of the
1596 * invariant bounds.
1597 */
1598 int days = GET_TD_DAYS(left) + GET_TD_DAYS(right);
1599 int seconds = GET_TD_SECONDS(left) + GET_TD_SECONDS(right);
1600 int microseconds = GET_TD_MICROSECONDS(left) +
1601 GET_TD_MICROSECONDS(right);
1602 result = new_delta(days, seconds, microseconds, 1);
1603 }
1604
1605 if (result == Py_NotImplemented)
1606 Py_INCREF(result);
1607 return result;
1608}
1609
1610static PyObject *
1611delta_negative(PyDateTime_Delta *self)
1612{
1613 return new_delta(-GET_TD_DAYS(self),
1614 -GET_TD_SECONDS(self),
1615 -GET_TD_MICROSECONDS(self),
1616 1);
1617}
1618
1619static PyObject *
1620delta_positive(PyDateTime_Delta *self)
1621{
1622 /* Could optimize this (by returning self) if this isn't a
1623 * subclass -- but who uses unary + ? Approximately nobody.
1624 */
1625 return new_delta(GET_TD_DAYS(self),
1626 GET_TD_SECONDS(self),
1627 GET_TD_MICROSECONDS(self),
1628 0);
1629}
1630
1631static PyObject *
1632delta_abs(PyDateTime_Delta *self)
1633{
1634 PyObject *result;
1635
1636 assert(GET_TD_MICROSECONDS(self) >= 0);
1637 assert(GET_TD_SECONDS(self) >= 0);
1638
1639 if (GET_TD_DAYS(self) < 0)
1640 result = delta_negative(self);
1641 else
1642 result = delta_positive(self);
1643
1644 return result;
1645}
1646
1647static PyObject *
1648delta_subtract(PyObject *left, PyObject *right)
1649{
1650 PyObject *result = Py_NotImplemented;
1651
1652 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1653 /* delta - delta */
1654 PyObject *minus_right = PyNumber_Negative(right);
1655 if (minus_right) {
1656 result = delta_add(left, minus_right);
1657 Py_DECREF(minus_right);
1658 }
1659 else
1660 result = NULL;
1661 }
1662
1663 if (result == Py_NotImplemented)
1664 Py_INCREF(result);
1665 return result;
1666}
1667
1668/* This is more natural as a tp_compare, but doesn't work then: for whatever
1669 * reason, Python's try_3way_compare ignores tp_compare unless
1670 * PyInstance_Check returns true, but these aren't old-style classes.
1671 */
1672static PyObject *
1673delta_richcompare(PyDateTime_Delta *self, PyObject *other, int op)
1674{
1675 int diff;
1676
1677 if (! PyDelta_CheckExact(other)) {
1678 PyErr_Format(PyExc_TypeError,
1679 "can't compare %s to %s instance",
1680 self->ob_type->tp_name, other->ob_type->tp_name);
1681 return NULL;
1682 }
1683 diff = GET_TD_DAYS(self) - GET_TD_DAYS(other);
1684 if (diff == 0) {
1685 diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other);
1686 if (diff == 0)
1687 diff = GET_TD_MICROSECONDS(self) -
1688 GET_TD_MICROSECONDS(other);
1689 }
1690 return diff_to_bool(diff, op);
1691}
1692
1693static PyObject *delta_getstate(PyDateTime_Delta *self);
1694
1695static long
1696delta_hash(PyDateTime_Delta *self)
1697{
1698 if (self->hashcode == -1) {
1699 PyObject *temp = delta_getstate(self);
1700 if (temp != NULL) {
1701 self->hashcode = PyObject_Hash(temp);
1702 Py_DECREF(temp);
1703 }
1704 }
1705 return self->hashcode;
1706}
1707
1708static PyObject *
1709delta_multiply(PyObject *left, PyObject *right)
1710{
1711 PyObject *result = Py_NotImplemented;
1712
1713 if (PyDelta_Check(left)) {
1714 /* delta * ??? */
1715 if (PyInt_Check(right) || PyLong_Check(right))
1716 result = multiply_int_timedelta(right,
1717 (PyDateTime_Delta *) left);
1718 }
1719 else if (PyInt_Check(left) || PyLong_Check(left))
1720 result = multiply_int_timedelta(left,
1721 (PyDateTime_Delta *) right);
1722
1723 if (result == Py_NotImplemented)
1724 Py_INCREF(result);
1725 return result;
1726}
1727
1728static PyObject *
1729delta_divide(PyObject *left, PyObject *right)
1730{
1731 PyObject *result = Py_NotImplemented;
1732
1733 if (PyDelta_Check(left)) {
1734 /* delta * ??? */
1735 if (PyInt_Check(right) || PyLong_Check(right))
1736 result = divide_timedelta_int(
1737 (PyDateTime_Delta *)left,
1738 right);
1739 }
1740
1741 if (result == Py_NotImplemented)
1742 Py_INCREF(result);
1743 return result;
1744}
1745
1746/* Fold in the value of the tag ("seconds", "weeks", etc) component of a
1747 * timedelta constructor. sofar is the # of microseconds accounted for
1748 * so far, and there are factor microseconds per current unit, the number
1749 * of which is given by num. num * factor is added to sofar in a
1750 * numerically careful way, and that's the result. Any fractional
1751 * microseconds left over (this can happen if num is a float type) are
1752 * added into *leftover.
1753 * Note that there are many ways this can give an error (NULL) return.
1754 */
1755static PyObject *
1756accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
1757 double *leftover)
1758{
1759 PyObject *prod;
1760 PyObject *sum;
1761
1762 assert(num != NULL);
1763
1764 if (PyInt_Check(num) || PyLong_Check(num)) {
1765 prod = PyNumber_Multiply(num, factor);
1766 if (prod == NULL)
1767 return NULL;
1768 sum = PyNumber_Add(sofar, prod);
1769 Py_DECREF(prod);
1770 return sum;
1771 }
1772
1773 if (PyFloat_Check(num)) {
1774 double dnum;
1775 double fracpart;
1776 double intpart;
1777 PyObject *x;
1778 PyObject *y;
1779
1780 /* The Plan: decompose num into an integer part and a
1781 * fractional part, num = intpart + fracpart.
1782 * Then num * factor ==
1783 * intpart * factor + fracpart * factor
1784 * and the LHS can be computed exactly in long arithmetic.
1785 * The RHS is again broken into an int part and frac part.
1786 * and the frac part is added into *leftover.
1787 */
1788 dnum = PyFloat_AsDouble(num);
1789 if (dnum == -1.0 && PyErr_Occurred())
1790 return NULL;
1791 fracpart = modf(dnum, &intpart);
1792 x = PyLong_FromDouble(intpart);
1793 if (x == NULL)
1794 return NULL;
1795
1796 prod = PyNumber_Multiply(x, factor);
1797 Py_DECREF(x);
1798 if (prod == NULL)
1799 return NULL;
1800
1801 sum = PyNumber_Add(sofar, prod);
1802 Py_DECREF(prod);
1803 if (sum == NULL)
1804 return NULL;
1805
1806 if (fracpart == 0.0)
1807 return sum;
1808 /* So far we've lost no information. Dealing with the
1809 * fractional part requires float arithmetic, and may
1810 * lose a little info.
1811 */
1812 assert(PyInt_Check(factor) || PyLong_Check(factor));
1813 if (PyInt_Check(factor))
1814 dnum = (double)PyInt_AsLong(factor);
1815 else
1816 dnum = PyLong_AsDouble(factor);
1817
1818 dnum *= fracpart;
1819 fracpart = modf(dnum, &intpart);
1820 x = PyLong_FromDouble(intpart);
1821 if (x == NULL) {
1822 Py_DECREF(sum);
1823 return NULL;
1824 }
1825
1826 y = PyNumber_Add(sum, x);
1827 Py_DECREF(sum);
1828 Py_DECREF(x);
1829 *leftover += fracpart;
1830 return y;
1831 }
1832
1833 PyErr_Format(PyExc_TypeError,
1834 "unsupported type for timedelta %s component: %s",
1835 tag, num->ob_type->tp_name);
1836 return NULL;
1837}
1838
1839static PyObject *
1840delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1841{
1842 PyObject *self = NULL;
1843
1844 /* Argument objects. */
1845 PyObject *day = NULL;
1846 PyObject *second = NULL;
1847 PyObject *us = NULL;
1848 PyObject *ms = NULL;
1849 PyObject *minute = NULL;
1850 PyObject *hour = NULL;
1851 PyObject *week = NULL;
1852
1853 PyObject *x = NULL; /* running sum of microseconds */
1854 PyObject *y = NULL; /* temp sum of microseconds */
1855 double leftover_us = 0.0;
1856
1857 static char *keywords[] = {
1858 "days", "seconds", "microseconds", "milliseconds",
1859 "minutes", "hours", "weeks", NULL
1860 };
1861
1862 if (PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOO:__new__",
1863 keywords,
1864 &day, &second, &us,
1865 &ms, &minute, &hour, &week) == 0)
1866 goto Done;
1867
1868 x = PyInt_FromLong(0);
1869 if (x == NULL)
1870 goto Done;
1871
1872#define CLEANUP \
1873 Py_DECREF(x); \
1874 x = y; \
1875 if (x == NULL) \
1876 goto Done
1877
1878 if (us) {
1879 y = accum("microseconds", x, us, us_per_us, &leftover_us);
1880 CLEANUP;
1881 }
1882 if (ms) {
1883 y = accum("milliseconds", x, ms, us_per_ms, &leftover_us);
1884 CLEANUP;
1885 }
1886 if (second) {
1887 y = accum("seconds", x, second, us_per_second, &leftover_us);
1888 CLEANUP;
1889 }
1890 if (minute) {
1891 y = accum("minutes", x, minute, us_per_minute, &leftover_us);
1892 CLEANUP;
1893 }
1894 if (hour) {
1895 y = accum("hours", x, hour, us_per_hour, &leftover_us);
1896 CLEANUP;
1897 }
1898 if (day) {
1899 y = accum("days", x, day, us_per_day, &leftover_us);
1900 CLEANUP;
1901 }
1902 if (week) {
1903 y = accum("weeks", x, week, us_per_week, &leftover_us);
1904 CLEANUP;
1905 }
1906 if (leftover_us) {
1907 /* Round to nearest whole # of us, and add into x. */
Tim Peters5d644dd2003-01-02 16:32:54 +00001908 PyObject *temp = PyLong_FromLong(round_to_long(leftover_us));
Tim Peters2a799bf2002-12-16 20:18:38 +00001909 if (temp == NULL) {
1910 Py_DECREF(x);
1911 goto Done;
1912 }
1913 y = PyNumber_Add(x, temp);
1914 Py_DECREF(temp);
1915 CLEANUP;
1916 }
1917
1918 self = microseconds_to_delta(x);
1919 Py_DECREF(x);
1920Done:
1921 return self;
1922
1923#undef CLEANUP
1924}
1925
1926static int
1927delta_nonzero(PyDateTime_Delta *self)
1928{
1929 return (GET_TD_DAYS(self) != 0
1930 || GET_TD_SECONDS(self) != 0
1931 || GET_TD_MICROSECONDS(self) != 0);
1932}
1933
1934static PyObject *
1935delta_repr(PyDateTime_Delta *self)
1936{
1937 if (GET_TD_MICROSECONDS(self) != 0)
1938 return PyString_FromFormat("%s(%d, %d, %d)",
1939 self->ob_type->tp_name,
1940 GET_TD_DAYS(self),
1941 GET_TD_SECONDS(self),
1942 GET_TD_MICROSECONDS(self));
1943 if (GET_TD_SECONDS(self) != 0)
1944 return PyString_FromFormat("%s(%d, %d)",
1945 self->ob_type->tp_name,
1946 GET_TD_DAYS(self),
1947 GET_TD_SECONDS(self));
1948
1949 return PyString_FromFormat("%s(%d)",
1950 self->ob_type->tp_name,
1951 GET_TD_DAYS(self));
1952}
1953
1954static PyObject *
1955delta_str(PyDateTime_Delta *self)
1956{
1957 int days = GET_TD_DAYS(self);
1958 int seconds = GET_TD_SECONDS(self);
1959 int us = GET_TD_MICROSECONDS(self);
1960 int hours;
1961 int minutes;
Tim Petersba873472002-12-18 20:19:21 +00001962 char buf[100];
1963 char *pbuf = buf;
1964 size_t buflen = sizeof(buf);
1965 int n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001966
1967 minutes = divmod(seconds, 60, &seconds);
1968 hours = divmod(minutes, 60, &minutes);
1969
1970 if (days) {
Tim Petersba873472002-12-18 20:19:21 +00001971 n = PyOS_snprintf(pbuf, buflen, "%d day%s, ", days,
1972 (days == 1 || days == -1) ? "" : "s");
1973 if (n < 0 || (size_t)n >= buflen)
1974 goto Fail;
1975 pbuf += n;
1976 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001977 }
1978
Tim Petersba873472002-12-18 20:19:21 +00001979 n = PyOS_snprintf(pbuf, buflen, "%d:%02d:%02d",
1980 hours, minutes, seconds);
1981 if (n < 0 || (size_t)n >= buflen)
1982 goto Fail;
1983 pbuf += n;
1984 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001985
1986 if (us) {
Tim Petersba873472002-12-18 20:19:21 +00001987 n = PyOS_snprintf(pbuf, buflen, ".%06d", us);
1988 if (n < 0 || (size_t)n >= buflen)
1989 goto Fail;
1990 pbuf += n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001991 }
1992
Tim Petersba873472002-12-18 20:19:21 +00001993 return PyString_FromStringAndSize(buf, pbuf - buf);
1994
1995 Fail:
1996 PyErr_SetString(PyExc_SystemError, "goofy result from PyOS_snprintf");
1997 return NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00001998}
1999
2000/* Pickle support. Quite a maze! While __getstate__/__setstate__ sufficed
2001 * in the Python implementation, the C implementation also requires
2002 * __reduce__, and a __safe_for_unpickling__ attr in the type object.
2003 */
2004static PyObject *
2005delta_getstate(PyDateTime_Delta *self)
2006{
2007 return Py_BuildValue("iii", GET_TD_DAYS(self),
2008 GET_TD_SECONDS(self),
2009 GET_TD_MICROSECONDS(self));
2010}
2011
2012static PyObject *
2013delta_setstate(PyDateTime_Delta *self, PyObject *state)
2014{
2015 int day;
2016 int second;
2017 int us;
2018
2019 if (!PyArg_ParseTuple(state, "iii:__setstate__", &day, &second, &us))
2020 return NULL;
2021
2022 self->hashcode = -1;
2023 SET_TD_DAYS(self, day);
2024 SET_TD_SECONDS(self, second);
2025 SET_TD_MICROSECONDS(self, us);
2026
2027 Py_INCREF(Py_None);
2028 return Py_None;
2029}
2030
2031static PyObject *
2032delta_reduce(PyDateTime_Delta* self)
2033{
2034 PyObject* result = NULL;
2035 PyObject* state = delta_getstate(self);
2036
2037 if (state != NULL) {
2038 /* The funky "()" in the format string creates an empty
2039 * tuple as the 2nd component of the result 3-tuple.
2040 */
2041 result = Py_BuildValue("O()O", self->ob_type, state);
2042 Py_DECREF(state);
2043 }
2044 return result;
2045}
2046
2047#define OFFSET(field) offsetof(PyDateTime_Delta, field)
2048
2049static PyMemberDef delta_members[] = {
Neal Norwitzdfb80862002-12-19 02:30:56 +00002050 {"days", T_INT, OFFSET(days), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002051 PyDoc_STR("Number of days.")},
2052
Neal Norwitzdfb80862002-12-19 02:30:56 +00002053 {"seconds", T_INT, OFFSET(seconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002054 PyDoc_STR("Number of seconds (>= 0 and less than 1 day).")},
2055
Neal Norwitzdfb80862002-12-19 02:30:56 +00002056 {"microseconds", T_INT, OFFSET(microseconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002057 PyDoc_STR("Number of microseconds (>= 0 and less than 1 second).")},
2058 {NULL}
2059};
2060
2061static PyMethodDef delta_methods[] = {
2062 {"__setstate__", (PyCFunction)delta_setstate, METH_O,
2063 PyDoc_STR("__setstate__(state)")},
2064
2065 {"__reduce__", (PyCFunction)delta_reduce, METH_NOARGS,
2066 PyDoc_STR("__setstate__(state)")},
2067
2068 {"__getstate__", (PyCFunction)delta_getstate, METH_NOARGS,
2069 PyDoc_STR("__getstate__() -> state")},
2070 {NULL, NULL},
2071};
2072
2073static char delta_doc[] =
2074PyDoc_STR("Difference between two datetime values.");
2075
2076static PyNumberMethods delta_as_number = {
2077 delta_add, /* nb_add */
2078 delta_subtract, /* nb_subtract */
2079 delta_multiply, /* nb_multiply */
2080 delta_divide, /* nb_divide */
2081 0, /* nb_remainder */
2082 0, /* nb_divmod */
2083 0, /* nb_power */
2084 (unaryfunc)delta_negative, /* nb_negative */
2085 (unaryfunc)delta_positive, /* nb_positive */
2086 (unaryfunc)delta_abs, /* nb_absolute */
2087 (inquiry)delta_nonzero, /* nb_nonzero */
2088 0, /*nb_invert*/
2089 0, /*nb_lshift*/
2090 0, /*nb_rshift*/
2091 0, /*nb_and*/
2092 0, /*nb_xor*/
2093 0, /*nb_or*/
2094 0, /*nb_coerce*/
2095 0, /*nb_int*/
2096 0, /*nb_long*/
2097 0, /*nb_float*/
2098 0, /*nb_oct*/
2099 0, /*nb_hex*/
2100 0, /*nb_inplace_add*/
2101 0, /*nb_inplace_subtract*/
2102 0, /*nb_inplace_multiply*/
2103 0, /*nb_inplace_divide*/
2104 0, /*nb_inplace_remainder*/
2105 0, /*nb_inplace_power*/
2106 0, /*nb_inplace_lshift*/
2107 0, /*nb_inplace_rshift*/
2108 0, /*nb_inplace_and*/
2109 0, /*nb_inplace_xor*/
2110 0, /*nb_inplace_or*/
2111 delta_divide, /* nb_floor_divide */
2112 0, /* nb_true_divide */
2113 0, /* nb_inplace_floor_divide */
2114 0, /* nb_inplace_true_divide */
2115};
2116
2117static PyTypeObject PyDateTime_DeltaType = {
2118 PyObject_HEAD_INIT(NULL)
2119 0, /* ob_size */
2120 "datetime.timedelta", /* tp_name */
2121 sizeof(PyDateTime_Delta), /* tp_basicsize */
2122 0, /* tp_itemsize */
2123 0, /* tp_dealloc */
2124 0, /* tp_print */
2125 0, /* tp_getattr */
2126 0, /* tp_setattr */
2127 0, /* tp_compare */
2128 (reprfunc)delta_repr, /* tp_repr */
2129 &delta_as_number, /* tp_as_number */
2130 0, /* tp_as_sequence */
2131 0, /* tp_as_mapping */
2132 (hashfunc)delta_hash, /* tp_hash */
2133 0, /* tp_call */
2134 (reprfunc)delta_str, /* tp_str */
2135 PyObject_GenericGetAttr, /* tp_getattro */
2136 0, /* tp_setattro */
2137 0, /* tp_as_buffer */
2138 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
2139 delta_doc, /* tp_doc */
2140 0, /* tp_traverse */
2141 0, /* tp_clear */
2142 (richcmpfunc)delta_richcompare, /* tp_richcompare */
2143 0, /* tp_weaklistoffset */
2144 0, /* tp_iter */
2145 0, /* tp_iternext */
2146 delta_methods, /* tp_methods */
2147 delta_members, /* tp_members */
2148 0, /* tp_getset */
2149 0, /* tp_base */
2150 0, /* tp_dict */
2151 0, /* tp_descr_get */
2152 0, /* tp_descr_set */
2153 0, /* tp_dictoffset */
2154 0, /* tp_init */
2155 0, /* tp_alloc */
2156 delta_new, /* tp_new */
2157 _PyObject_Del, /* tp_free */
2158};
2159
2160/*
2161 * PyDateTime_Date implementation.
2162 */
2163
2164/* Accessor properties. */
2165
2166static PyObject *
2167date_year(PyDateTime_Date *self, void *unused)
2168{
2169 return PyInt_FromLong(GET_YEAR(self));
2170}
2171
2172static PyObject *
2173date_month(PyDateTime_Date *self, void *unused)
2174{
2175 return PyInt_FromLong(GET_MONTH(self));
2176}
2177
2178static PyObject *
2179date_day(PyDateTime_Date *self, void *unused)
2180{
2181 return PyInt_FromLong(GET_DAY(self));
2182}
2183
2184static PyGetSetDef date_getset[] = {
2185 {"year", (getter)date_year},
2186 {"month", (getter)date_month},
2187 {"day", (getter)date_day},
2188 {NULL}
2189};
2190
2191/* Constructors. */
2192
Tim Peters12bf3392002-12-24 05:41:27 +00002193static char *date_kws[] = {"year", "month", "day", NULL};
2194
Tim Peters2a799bf2002-12-16 20:18:38 +00002195static PyObject *
2196date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2197{
2198 PyObject *self = NULL;
2199 int year;
2200 int month;
2201 int day;
2202
Tim Peters12bf3392002-12-24 05:41:27 +00002203 if (PyArg_ParseTupleAndKeywords(args, kw, "iii", date_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002204 &year, &month, &day)) {
2205 if (check_date_args(year, month, day) < 0)
2206 return NULL;
2207 self = new_date(year, month, day);
2208 }
2209 return self;
2210}
2211
2212/* Return new date from localtime(t). */
2213static PyObject *
2214date_local_from_time_t(PyObject *cls, time_t t)
2215{
2216 struct tm *tm;
2217 PyObject *result = NULL;
2218
2219 tm = localtime(&t);
2220 if (tm)
2221 result = PyObject_CallFunction(cls, "iii",
2222 tm->tm_year + 1900,
2223 tm->tm_mon + 1,
2224 tm->tm_mday);
2225 else
2226 PyErr_SetString(PyExc_ValueError,
2227 "timestamp out of range for "
2228 "platform localtime() function");
2229 return result;
2230}
2231
2232/* Return new date from current time.
2233 * We say this is equivalent to fromtimestamp(time.time()), and the
2234 * only way to be sure of that is to *call* time.time(). That's not
2235 * generally the same as calling C's time.
2236 */
2237static PyObject *
2238date_today(PyObject *cls, PyObject *dummy)
2239{
2240 PyObject *time;
2241 PyObject *result;
2242
2243 time = time_time();
2244 if (time == NULL)
2245 return NULL;
2246
2247 /* Note well: today() is a class method, so this may not call
2248 * date.fromtimestamp. For example, it may call
2249 * datetime.fromtimestamp. That's why we need all the accuracy
2250 * time.time() delivers; if someone were gonzo about optimization,
2251 * date.today() could get away with plain C time().
2252 */
2253 result = PyObject_CallMethod(cls, "fromtimestamp", "O", time);
2254 Py_DECREF(time);
2255 return result;
2256}
2257
2258/* Return new date from given timestamp (Python timestamp -- a double). */
2259static PyObject *
2260date_fromtimestamp(PyObject *cls, PyObject *args)
2261{
2262 double timestamp;
2263 PyObject *result = NULL;
2264
2265 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2266 result = date_local_from_time_t(cls, (time_t)timestamp);
2267 return result;
2268}
2269
2270/* Return new date from proleptic Gregorian ordinal. Raises ValueError if
2271 * the ordinal is out of range.
2272 */
2273static PyObject *
2274date_fromordinal(PyObject *cls, PyObject *args)
2275{
2276 PyObject *result = NULL;
2277 int ordinal;
2278
2279 if (PyArg_ParseTuple(args, "i:fromordinal", &ordinal)) {
2280 int year;
2281 int month;
2282 int day;
2283
2284 if (ordinal < 1)
2285 PyErr_SetString(PyExc_ValueError, "ordinal must be "
2286 ">= 1");
2287 else {
2288 ord_to_ymd(ordinal, &year, &month, &day);
2289 result = PyObject_CallFunction(cls, "iii",
2290 year, month, day);
2291 }
2292 }
2293 return result;
2294}
2295
2296/*
2297 * Date arithmetic.
2298 */
2299
2300/* date + timedelta -> date. If arg negate is true, subtract the timedelta
2301 * instead.
2302 */
2303static PyObject *
2304add_date_timedelta(PyDateTime_Date *date, PyDateTime_Delta *delta, int negate)
2305{
2306 PyObject *result = NULL;
2307 int year = GET_YEAR(date);
2308 int month = GET_MONTH(date);
2309 int deltadays = GET_TD_DAYS(delta);
2310 /* C-level overflow is impossible because |deltadays| < 1e9. */
2311 int day = GET_DAY(date) + (negate ? -deltadays : deltadays);
2312
2313 if (normalize_date(&year, &month, &day) >= 0)
2314 result = new_date(year, month, day);
2315 return result;
2316}
2317
2318static PyObject *
2319date_add(PyObject *left, PyObject *right)
2320{
2321 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2322 Py_INCREF(Py_NotImplemented);
2323 return Py_NotImplemented;
2324 }
2325 if (PyDate_CheckExact(left)) {
2326 /* date + ??? */
2327 if (PyDelta_Check(right))
2328 /* date + delta */
2329 return add_date_timedelta((PyDateTime_Date *) left,
2330 (PyDateTime_Delta *) right,
2331 0);
2332 }
2333 else {
2334 /* ??? + date
2335 * 'right' must be one of us, or we wouldn't have been called
2336 */
2337 if (PyDelta_Check(left))
2338 /* delta + date */
2339 return add_date_timedelta((PyDateTime_Date *) right,
2340 (PyDateTime_Delta *) left,
2341 0);
2342 }
2343 Py_INCREF(Py_NotImplemented);
2344 return Py_NotImplemented;
2345}
2346
2347static PyObject *
2348date_subtract(PyObject *left, PyObject *right)
2349{
2350 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2351 Py_INCREF(Py_NotImplemented);
2352 return Py_NotImplemented;
2353 }
2354 if (PyDate_CheckExact(left)) {
2355 if (PyDate_CheckExact(right)) {
2356 /* date - date */
2357 int left_ord = ymd_to_ord(GET_YEAR(left),
2358 GET_MONTH(left),
2359 GET_DAY(left));
2360 int right_ord = ymd_to_ord(GET_YEAR(right),
2361 GET_MONTH(right),
2362 GET_DAY(right));
2363 return new_delta(left_ord - right_ord, 0, 0, 0);
2364 }
2365 if (PyDelta_Check(right)) {
2366 /* date - delta */
2367 return add_date_timedelta((PyDateTime_Date *) left,
2368 (PyDateTime_Delta *) right,
2369 1);
2370 }
2371 }
2372 Py_INCREF(Py_NotImplemented);
2373 return Py_NotImplemented;
2374}
2375
2376
2377/* Various ways to turn a date into a string. */
2378
2379static PyObject *
2380date_repr(PyDateTime_Date *self)
2381{
2382 char buffer[1028];
2383 char *typename;
2384
2385 typename = self->ob_type->tp_name;
2386 PyOS_snprintf(buffer, sizeof(buffer), "%s(%d, %d, %d)",
2387 typename,
2388 GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2389
2390 return PyString_FromString(buffer);
2391}
2392
2393static PyObject *
2394date_isoformat(PyDateTime_Date *self)
2395{
2396 char buffer[128];
2397
2398 isoformat_date(self, buffer, sizeof(buffer));
2399 return PyString_FromString(buffer);
2400}
2401
2402/* str() calls the appropriate isofomat() method. */
2403static PyObject *
2404date_str(PyDateTime_Date *self)
2405{
2406 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
2407}
2408
2409
2410static PyObject *
2411date_ctime(PyDateTime_Date *self)
2412{
2413 return format_ctime(self, 0, 0, 0);
2414}
2415
2416static PyObject *
2417date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2418{
2419 /* This method can be inherited, and needs to call the
2420 * timetuple() method appropriate to self's class.
2421 */
2422 PyObject *result;
2423 PyObject *format;
2424 PyObject *tuple;
2425 static char *keywords[] = {"format", NULL};
2426
2427 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
2428 &PyString_Type, &format))
2429 return NULL;
2430
2431 tuple = PyObject_CallMethod((PyObject *)self, "timetuple", "()");
2432 if (tuple == NULL)
2433 return NULL;
Tim Petersbad8ff02002-12-30 20:52:32 +00002434 result = wrap_strftime((PyObject *)self, format, tuple,
2435 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00002436 Py_DECREF(tuple);
2437 return result;
2438}
2439
2440/* ISO methods. */
2441
2442static PyObject *
2443date_isoweekday(PyDateTime_Date *self)
2444{
2445 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2446
2447 return PyInt_FromLong(dow + 1);
2448}
2449
2450static PyObject *
2451date_isocalendar(PyDateTime_Date *self)
2452{
2453 int year = GET_YEAR(self);
2454 int week1_monday = iso_week1_monday(year);
2455 int today = ymd_to_ord(year, GET_MONTH(self), GET_DAY(self));
2456 int week;
2457 int day;
2458
2459 week = divmod(today - week1_monday, 7, &day);
2460 if (week < 0) {
2461 --year;
2462 week1_monday = iso_week1_monday(year);
2463 week = divmod(today - week1_monday, 7, &day);
2464 }
2465 else if (week >= 52 && today >= iso_week1_monday(year + 1)) {
2466 ++year;
2467 week = 0;
2468 }
2469 return Py_BuildValue("iii", year, week + 1, day + 1);
2470}
2471
2472/* Miscellaneous methods. */
2473
2474/* This is more natural as a tp_compare, but doesn't work then: for whatever
2475 * reason, Python's try_3way_compare ignores tp_compare unless
2476 * PyInstance_Check returns true, but these aren't old-style classes.
2477 */
2478static PyObject *
2479date_richcompare(PyDateTime_Date *self, PyObject *other, int op)
2480{
2481 int diff;
2482
2483 if (! PyDate_Check(other)) {
2484 PyErr_Format(PyExc_TypeError,
2485 "can't compare date to %s instance",
2486 other->ob_type->tp_name);
2487 return NULL;
2488 }
2489 diff = memcmp(self->data, ((PyDateTime_Date *)other)->data,
2490 _PyDateTime_DATE_DATASIZE);
2491 return diff_to_bool(diff, op);
2492}
2493
2494static PyObject *
2495date_timetuple(PyDateTime_Date *self)
2496{
2497 return build_struct_time(GET_YEAR(self),
2498 GET_MONTH(self),
2499 GET_DAY(self),
2500 0, 0, 0, -1);
2501}
2502
Tim Peters12bf3392002-12-24 05:41:27 +00002503static PyObject *
2504date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2505{
2506 PyObject *clone;
2507 PyObject *tuple;
2508 int year = GET_YEAR(self);
2509 int month = GET_MONTH(self);
2510 int day = GET_DAY(self);
2511
2512 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iii:replace", date_kws,
2513 &year, &month, &day))
2514 return NULL;
2515 tuple = Py_BuildValue("iii", year, month, day);
2516 if (tuple == NULL)
2517 return NULL;
2518 clone = date_new(self->ob_type, tuple, NULL);
2519 Py_DECREF(tuple);
2520 return clone;
2521}
2522
Tim Peters2a799bf2002-12-16 20:18:38 +00002523static PyObject *date_getstate(PyDateTime_Date *self);
2524
2525static long
2526date_hash(PyDateTime_Date *self)
2527{
2528 if (self->hashcode == -1) {
2529 PyObject *temp = date_getstate(self);
2530 if (temp != NULL) {
2531 self->hashcode = PyObject_Hash(temp);
2532 Py_DECREF(temp);
2533 }
2534 }
2535 return self->hashcode;
2536}
2537
2538static PyObject *
2539date_toordinal(PyDateTime_Date *self)
2540{
2541 return PyInt_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self),
2542 GET_DAY(self)));
2543}
2544
2545static PyObject *
2546date_weekday(PyDateTime_Date *self)
2547{
2548 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2549
2550 return PyInt_FromLong(dow);
2551}
2552
2553/* Pickle support. Quite a maze! */
2554
2555static PyObject *
2556date_getstate(PyDateTime_Date *self)
2557{
Jack Jansenb8941f22003-01-08 16:28:45 +00002558 return PyString_FromStringAndSize((char *)self->data,
Tim Peters2a799bf2002-12-16 20:18:38 +00002559 _PyDateTime_DATE_DATASIZE);
2560}
2561
2562static PyObject *
2563date_setstate(PyDateTime_Date *self, PyObject *state)
2564{
2565 const int len = PyString_Size(state);
2566 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
2567
2568 if (! PyString_Check(state) ||
2569 len != _PyDateTime_DATE_DATASIZE) {
2570 PyErr_SetString(PyExc_TypeError,
2571 "bad argument to date.__setstate__");
2572 return NULL;
2573 }
2574 memcpy(self->data, pdata, _PyDateTime_DATE_DATASIZE);
2575 self->hashcode = -1;
2576
2577 Py_INCREF(Py_None);
2578 return Py_None;
2579}
2580
2581/* XXX This seems a ridiculously inefficient way to pickle a short string. */
2582static PyObject *
2583date_pickler(PyObject *module, PyDateTime_Date *date)
2584{
2585 PyObject *state;
2586 PyObject *result = NULL;
2587
2588 if (! PyDate_CheckExact(date)) {
2589 PyErr_Format(PyExc_TypeError,
2590 "bad type passed to date pickler: %s",
2591 date->ob_type->tp_name);
2592 return NULL;
2593 }
2594 state = date_getstate(date);
2595 if (state) {
2596 result = Py_BuildValue("O(O)", date_unpickler_object, state);
2597 Py_DECREF(state);
2598 }
2599 return result;
2600}
2601
2602static PyObject *
2603date_unpickler(PyObject *module, PyObject *arg)
2604{
2605 PyDateTime_Date *self;
2606
2607 if (! PyString_CheckExact(arg)) {
2608 PyErr_Format(PyExc_TypeError,
2609 "bad type passed to date unpickler: %s",
2610 arg->ob_type->tp_name);
2611 return NULL;
2612 }
2613 self = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
2614 if (self != NULL) {
2615 PyObject *res = date_setstate(self, arg);
2616 if (res == NULL) {
2617 Py_DECREF(self);
2618 return NULL;
2619 }
2620 Py_DECREF(res);
2621 }
2622 return (PyObject *)self;
2623}
2624
2625static PyMethodDef date_methods[] = {
2626 /* Class methods: */
2627 {"fromtimestamp", (PyCFunction)date_fromtimestamp, METH_VARARGS |
2628 METH_CLASS,
2629 PyDoc_STR("timestamp -> local date from a POSIX timestamp (like "
2630 "time.time()).")},
2631
2632 {"fromordinal", (PyCFunction)date_fromordinal, METH_VARARGS |
2633 METH_CLASS,
2634 PyDoc_STR("int -> date corresponding to a proleptic Gregorian "
2635 "ordinal.")},
2636
2637 {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS,
2638 PyDoc_STR("Current date or datetime: same as "
2639 "self.__class__.fromtimestamp(time.time()).")},
2640
2641 /* Instance methods: */
2642
2643 {"ctime", (PyCFunction)date_ctime, METH_NOARGS,
2644 PyDoc_STR("Return ctime() style string.")},
2645
2646 {"strftime", (PyCFunction)date_strftime, METH_KEYWORDS,
2647 PyDoc_STR("format -> strftime() style string.")},
2648
2649 {"timetuple", (PyCFunction)date_timetuple, METH_NOARGS,
2650 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
2651
2652 {"isocalendar", (PyCFunction)date_isocalendar, METH_NOARGS,
2653 PyDoc_STR("Return a 3-tuple containing ISO year, week number, and "
2654 "weekday.")},
2655
2656 {"isoformat", (PyCFunction)date_isoformat, METH_NOARGS,
2657 PyDoc_STR("Return string in ISO 8601 format, YYYY-MM-DD.")},
2658
2659 {"isoweekday", (PyCFunction)date_isoweekday, METH_NOARGS,
2660 PyDoc_STR("Return the day of the week represented by the date.\n"
2661 "Monday == 1 ... Sunday == 7")},
2662
2663 {"toordinal", (PyCFunction)date_toordinal, METH_NOARGS,
2664 PyDoc_STR("Return proleptic Gregorian ordinal. January 1 of year "
2665 "1 is day 1.")},
2666
2667 {"weekday", (PyCFunction)date_weekday, METH_NOARGS,
2668 PyDoc_STR("Return the day of the week represented by the date.\n"
2669 "Monday == 0 ... Sunday == 6")},
2670
Tim Peters12bf3392002-12-24 05:41:27 +00002671 {"replace", (PyCFunction)date_replace, METH_KEYWORDS,
2672 PyDoc_STR("Return date with new specified fields.")},
2673
Tim Peters2a799bf2002-12-16 20:18:38 +00002674 {"__setstate__", (PyCFunction)date_setstate, METH_O,
2675 PyDoc_STR("__setstate__(state)")},
2676
2677 {"__getstate__", (PyCFunction)date_getstate, METH_NOARGS,
2678 PyDoc_STR("__getstate__() -> state")},
2679
2680 {NULL, NULL}
2681};
2682
2683static char date_doc[] =
2684PyDoc_STR("Basic date type.");
2685
2686static PyNumberMethods date_as_number = {
2687 date_add, /* nb_add */
2688 date_subtract, /* nb_subtract */
2689 0, /* nb_multiply */
2690 0, /* nb_divide */
2691 0, /* nb_remainder */
2692 0, /* nb_divmod */
2693 0, /* nb_power */
2694 0, /* nb_negative */
2695 0, /* nb_positive */
2696 0, /* nb_absolute */
2697 0, /* nb_nonzero */
2698};
2699
2700static PyTypeObject PyDateTime_DateType = {
2701 PyObject_HEAD_INIT(NULL)
2702 0, /* ob_size */
2703 "datetime.date", /* tp_name */
2704 sizeof(PyDateTime_Date), /* tp_basicsize */
2705 0, /* tp_itemsize */
2706 (destructor)PyObject_Del, /* tp_dealloc */
2707 0, /* tp_print */
2708 0, /* tp_getattr */
2709 0, /* tp_setattr */
2710 0, /* tp_compare */
2711 (reprfunc)date_repr, /* tp_repr */
2712 &date_as_number, /* tp_as_number */
2713 0, /* tp_as_sequence */
2714 0, /* tp_as_mapping */
2715 (hashfunc)date_hash, /* tp_hash */
2716 0, /* tp_call */
2717 (reprfunc)date_str, /* tp_str */
2718 PyObject_GenericGetAttr, /* tp_getattro */
2719 0, /* tp_setattro */
2720 0, /* tp_as_buffer */
2721 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
2722 Py_TPFLAGS_BASETYPE, /* tp_flags */
2723 date_doc, /* tp_doc */
2724 0, /* tp_traverse */
2725 0, /* tp_clear */
2726 (richcmpfunc)date_richcompare, /* tp_richcompare */
2727 0, /* tp_weaklistoffset */
2728 0, /* tp_iter */
2729 0, /* tp_iternext */
2730 date_methods, /* tp_methods */
2731 0, /* tp_members */
2732 date_getset, /* tp_getset */
2733 0, /* tp_base */
2734 0, /* tp_dict */
2735 0, /* tp_descr_get */
2736 0, /* tp_descr_set */
2737 0, /* tp_dictoffset */
2738 0, /* tp_init */
2739 0, /* tp_alloc */
2740 date_new, /* tp_new */
2741 _PyObject_Del, /* tp_free */
2742};
2743
2744/*
2745 * PyDateTime_DateTime implementation.
2746 */
2747
2748/* Accessor properties. */
2749
2750static PyObject *
2751datetime_hour(PyDateTime_DateTime *self, void *unused)
2752{
2753 return PyInt_FromLong(DATE_GET_HOUR(self));
2754}
2755
2756static PyObject *
2757datetime_minute(PyDateTime_DateTime *self, void *unused)
2758{
2759 return PyInt_FromLong(DATE_GET_MINUTE(self));
2760}
2761
2762static PyObject *
2763datetime_second(PyDateTime_DateTime *self, void *unused)
2764{
2765 return PyInt_FromLong(DATE_GET_SECOND(self));
2766}
2767
2768static PyObject *
2769datetime_microsecond(PyDateTime_DateTime *self, void *unused)
2770{
2771 return PyInt_FromLong(DATE_GET_MICROSECOND(self));
2772}
2773
2774static PyGetSetDef datetime_getset[] = {
2775 {"hour", (getter)datetime_hour},
2776 {"minute", (getter)datetime_minute},
2777 {"second", (getter)datetime_second},
2778 {"microsecond", (getter)datetime_microsecond},
2779 {NULL}
2780};
2781
2782/* Constructors. */
2783
Tim Peters12bf3392002-12-24 05:41:27 +00002784
2785static char *datetime_kws[] = {"year", "month", "day",
2786 "hour", "minute", "second", "microsecond",
2787 NULL};
2788
Tim Peters2a799bf2002-12-16 20:18:38 +00002789static PyObject *
2790datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2791{
2792 PyObject *self = NULL;
2793 int year;
2794 int month;
2795 int day;
2796 int hour = 0;
2797 int minute = 0;
2798 int second = 0;
2799 int usecond = 0;
2800
Tim Peters12bf3392002-12-24 05:41:27 +00002801 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiii", datetime_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002802 &year, &month, &day, &hour, &minute,
2803 &second, &usecond)) {
2804 if (check_date_args(year, month, day) < 0)
2805 return NULL;
2806 if (check_time_args(hour, minute, second, usecond) < 0)
2807 return NULL;
2808 self = new_datetime(year, month, day,
2809 hour, minute, second, usecond);
2810 }
2811 return self;
2812}
2813
2814
2815/* TM_FUNC is the shared type of localtime() and gmtime(). */
2816typedef struct tm *(*TM_FUNC)(const time_t *timer);
2817
2818/* Internal helper.
2819 * Build datetime from a time_t and a distinct count of microseconds.
2820 * Pass localtime or gmtime for f, to control the interpretation of timet.
2821 */
2822static PyObject *
2823datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us)
2824{
2825 struct tm *tm;
2826 PyObject *result = NULL;
2827
2828 tm = f(&timet);
Tim Peters75a6e3b2003-01-04 18:17:36 +00002829 if (tm) {
2830 /* The platform localtime/gmtime may insert leap seconds,
2831 * indicated by tm->tm_sec > 59. We don't care about them,
2832 * except to the extent that passing them on to the datetime
2833 * constructor would raise ValueError for a reason that
2834 * made no sense to the user.
2835 */
2836 if (tm->tm_sec > 59)
2837 tm->tm_sec = 59;
Tim Peters2a799bf2002-12-16 20:18:38 +00002838 result = PyObject_CallFunction(cls, "iiiiiii",
2839 tm->tm_year + 1900,
2840 tm->tm_mon + 1,
2841 tm->tm_mday,
2842 tm->tm_hour,
2843 tm->tm_min,
2844 tm->tm_sec,
2845 us);
Tim Peters75a6e3b2003-01-04 18:17:36 +00002846 }
Tim Peters2a799bf2002-12-16 20:18:38 +00002847 else
2848 PyErr_SetString(PyExc_ValueError,
2849 "timestamp out of range for "
2850 "platform localtime()/gmtime() function");
2851 return result;
2852}
2853
2854/* Internal helper.
2855 * Build datetime from a Python timestamp. Pass localtime or gmtime for f,
2856 * to control the interpretation of the timestamp. Since a double doesn't
2857 * have enough bits to cover a datetime's full range of precision, it's
2858 * better to call datetime_from_timet_and_us provided you have a way
2859 * to get that much precision (e.g., C time() isn't good enough).
2860 */
2861static PyObject *
2862datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp)
2863{
2864 time_t timet = (time_t)timestamp;
Tim Peters5d644dd2003-01-02 16:32:54 +00002865 double fraction = timestamp - (double)timet;
2866 int us = (int)round_to_long(fraction * 1e6);
Tim Peters2a799bf2002-12-16 20:18:38 +00002867
2868 return datetime_from_timet_and_us(cls, f, timet, us);
2869}
2870
2871/* Internal helper.
2872 * Build most accurate possible datetime for current time. Pass localtime or
2873 * gmtime for f as appropriate.
2874 */
2875static PyObject *
2876datetime_best_possible(PyObject *cls, TM_FUNC f)
2877{
2878#ifdef HAVE_GETTIMEOFDAY
2879 struct timeval t;
2880
2881#ifdef GETTIMEOFDAY_NO_TZ
2882 gettimeofday(&t);
2883#else
2884 gettimeofday(&t, (struct timezone *)NULL);
2885#endif
2886 return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec);
2887
2888#else /* ! HAVE_GETTIMEOFDAY */
2889 /* No flavor of gettimeofday exists on this platform. Python's
2890 * time.time() does a lot of other platform tricks to get the
2891 * best time it can on the platform, and we're not going to do
2892 * better than that (if we could, the better code would belong
2893 * in time.time()!) We're limited by the precision of a double,
2894 * though.
2895 */
2896 PyObject *time;
2897 double dtime;
2898
2899 time = time_time();
2900 if (time == NULL)
2901 return NULL;
2902 dtime = PyFloat_AsDouble(time);
2903 Py_DECREF(time);
2904 if (dtime == -1.0 && PyErr_Occurred())
2905 return NULL;
2906 return datetime_from_timestamp(cls, f, dtime);
2907#endif /* ! HAVE_GETTIMEOFDAY */
2908}
2909
2910/* Return new local datetime from timestamp (Python timestamp -- a double). */
2911static PyObject *
2912datetime_fromtimestamp(PyObject *cls, PyObject *args)
2913{
2914 double timestamp;
2915 PyObject *result = NULL;
2916
2917 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2918 result = datetime_from_timestamp(cls, localtime, timestamp);
2919 return result;
2920}
2921
2922/* Return new UTC datetime from timestamp (Python timestamp -- a double). */
2923static PyObject *
2924datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
2925{
2926 double timestamp;
2927 PyObject *result = NULL;
2928
2929 if (PyArg_ParseTuple(args, "d:utcfromtimestamp", &timestamp))
2930 result = datetime_from_timestamp(cls, gmtime, timestamp);
2931 return result;
2932}
2933
2934/* Return best possible local time -- this isn't constrained by the
2935 * precision of a timestamp.
2936 */
2937static PyObject *
2938datetime_now(PyObject *cls, PyObject *dummy)
2939{
2940 return datetime_best_possible(cls, localtime);
2941}
2942
2943/* Return best possible UTC time -- this isn't constrained by the
2944 * precision of a timestamp.
2945 */
2946static PyObject *
2947datetime_utcnow(PyObject *cls, PyObject *dummy)
2948{
2949 return datetime_best_possible(cls, gmtime);
2950}
2951
2952/* Return new datetime or datetimetz from date/datetime/datetimetz and
Tim Peters37f39822003-01-10 03:49:02 +00002953 * time arguments.
Tim Peters2a799bf2002-12-16 20:18:38 +00002954 */
2955static PyObject *
2956datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
2957{
2958 static char *keywords[] = {"date", "time", NULL};
2959 PyObject *date;
2960 PyObject *time;
2961 PyObject *result = NULL;
2962
2963 if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!:combine", keywords,
2964 &PyDateTime_DateType, &date,
2965 &PyDateTime_TimeType, &time))
2966 result = PyObject_CallFunction(cls, "iiiiiii",
2967 GET_YEAR(date),
2968 GET_MONTH(date),
2969 GET_DAY(date),
2970 TIME_GET_HOUR(time),
2971 TIME_GET_MINUTE(time),
2972 TIME_GET_SECOND(time),
2973 TIME_GET_MICROSECOND(time));
Tim Petersa032d2e2003-01-11 00:15:54 +00002974 if (result && HASTZINFO(time) && PyDateTimeTZ_Check(result)) {
Tim Peters2a799bf2002-12-16 20:18:38 +00002975 /* Copy the tzinfo field. */
Tim Peters37f39822003-01-10 03:49:02 +00002976 replace_tzinfo(result, ((PyDateTime_Time *)time)->tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00002977 }
2978 return result;
2979}
2980
2981/* datetime arithmetic. */
2982
2983static PyObject *
2984add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
2985{
2986 /* Note that the C-level additions can't overflow, because of
2987 * invariant bounds on the member values.
2988 */
2989 int year = GET_YEAR(date);
2990 int month = GET_MONTH(date);
2991 int day = GET_DAY(date) + GET_TD_DAYS(delta);
2992 int hour = DATE_GET_HOUR(date);
2993 int minute = DATE_GET_MINUTE(date);
2994 int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta);
2995 int microsecond = DATE_GET_MICROSECOND(date) +
2996 GET_TD_MICROSECONDS(delta);
2997
2998 if (normalize_datetime(&year, &month, &day,
2999 &hour, &minute, &second, &microsecond) < 0)
3000 return NULL;
3001 else
3002 return new_datetime(year, month, day,
3003 hour, minute, second, microsecond);
3004}
3005
3006static PyObject *
3007sub_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
3008{
3009 /* Note that the C-level subtractions can't overflow, because of
3010 * invariant bounds on the member values.
3011 */
3012 int year = GET_YEAR(date);
3013 int month = GET_MONTH(date);
3014 int day = GET_DAY(date) - GET_TD_DAYS(delta);
3015 int hour = DATE_GET_HOUR(date);
3016 int minute = DATE_GET_MINUTE(date);
3017 int second = DATE_GET_SECOND(date) - GET_TD_SECONDS(delta);
3018 int microsecond = DATE_GET_MICROSECOND(date) -
3019 GET_TD_MICROSECONDS(delta);
3020
3021 if (normalize_datetime(&year, &month, &day,
3022 &hour, &minute, &second, &microsecond) < 0)
3023 return NULL;
3024 else
3025 return new_datetime(year, month, day,
3026 hour, minute, second, microsecond);
3027}
3028
3029static PyObject *
3030sub_datetime_datetime(PyDateTime_DateTime *left, PyDateTime_DateTime *right)
3031{
3032 int days1 = ymd_to_ord(GET_YEAR(left), GET_MONTH(left), GET_DAY(left));
3033 int days2 = ymd_to_ord(GET_YEAR(right),
3034 GET_MONTH(right),
3035 GET_DAY(right));
3036 /* These can't overflow, since the values are normalized. At most
3037 * this gives the number of seconds in one day.
3038 */
3039 int delta_s = (DATE_GET_HOUR(left) - DATE_GET_HOUR(right)) * 3600 +
3040 (DATE_GET_MINUTE(left) - DATE_GET_MINUTE(right)) * 60 +
3041 DATE_GET_SECOND(left) - DATE_GET_SECOND(right);
3042 int delta_us = DATE_GET_MICROSECOND(left) -
3043 DATE_GET_MICROSECOND(right);
3044
3045 return new_delta(days1 - days2, delta_s, delta_us, 1);
3046}
3047
3048static PyObject *
3049datetime_add(PyObject *left, PyObject *right)
3050{
3051 if (PyDateTime_Check(left)) {
3052 /* datetime + ??? */
3053 if (PyDelta_Check(right))
3054 /* datetime + delta */
3055 return add_datetime_timedelta(
3056 (PyDateTime_DateTime *)left,
3057 (PyDateTime_Delta *)right);
3058 }
3059 else if (PyDelta_Check(left)) {
3060 /* delta + datetime */
3061 return add_datetime_timedelta((PyDateTime_DateTime *) right,
3062 (PyDateTime_Delta *) left);
3063 }
3064 Py_INCREF(Py_NotImplemented);
3065 return Py_NotImplemented;
3066}
3067
3068static PyObject *
3069datetime_subtract(PyObject *left, PyObject *right)
3070{
3071 PyObject *result = Py_NotImplemented;
3072
3073 if (PyDateTime_Check(left)) {
3074 /* datetime - ??? */
3075 if (PyDateTime_Check(right)) {
3076 /* datetime - datetime */
3077 result = sub_datetime_datetime(
3078 (PyDateTime_DateTime *)left,
3079 (PyDateTime_DateTime *)right);
3080 }
3081 else if (PyDelta_Check(right)) {
3082 /* datetime - delta */
3083 result = sub_datetime_timedelta(
3084 (PyDateTime_DateTime *)left,
3085 (PyDateTime_Delta *)right);
3086 }
3087 }
3088
3089 if (result == Py_NotImplemented)
3090 Py_INCREF(result);
3091 return result;
3092}
3093
3094/* Various ways to turn a datetime into a string. */
3095
3096static PyObject *
3097datetime_repr(PyDateTime_DateTime *self)
3098{
3099 char buffer[1000];
3100 char *typename = self->ob_type->tp_name;
3101
3102 if (DATE_GET_MICROSECOND(self)) {
3103 PyOS_snprintf(buffer, sizeof(buffer),
3104 "%s(%d, %d, %d, %d, %d, %d, %d)",
3105 typename,
3106 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3107 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3108 DATE_GET_SECOND(self),
3109 DATE_GET_MICROSECOND(self));
3110 }
3111 else if (DATE_GET_SECOND(self)) {
3112 PyOS_snprintf(buffer, sizeof(buffer),
3113 "%s(%d, %d, %d, %d, %d, %d)",
3114 typename,
3115 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3116 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3117 DATE_GET_SECOND(self));
3118 }
3119 else {
3120 PyOS_snprintf(buffer, sizeof(buffer),
3121 "%s(%d, %d, %d, %d, %d)",
3122 typename,
3123 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3124 DATE_GET_HOUR(self), DATE_GET_MINUTE(self));
3125 }
3126 return PyString_FromString(buffer);
3127}
3128
3129static PyObject *
3130datetime_str(PyDateTime_DateTime *self)
3131{
3132 return PyObject_CallMethod((PyObject *)self, "isoformat", "(s)", " ");
3133}
3134
3135static PyObject *
3136datetime_isoformat(PyDateTime_DateTime *self,
3137 PyObject *args, PyObject *kw)
3138{
3139 char sep = 'T';
3140 static char *keywords[] = {"sep", NULL};
3141 char buffer[100];
3142 char *cp;
3143
3144 if (!PyArg_ParseTupleAndKeywords(args, kw, "|c:isoformat", keywords,
3145 &sep))
3146 return NULL;
3147 cp = isoformat_date((PyDateTime_Date *)self, buffer, sizeof(buffer));
3148 assert(cp != NULL);
3149 *cp++ = sep;
3150 isoformat_time(self, cp, sizeof(buffer) - (cp - buffer));
3151 return PyString_FromString(buffer);
3152}
3153
3154static PyObject *
3155datetime_ctime(PyDateTime_DateTime *self)
3156{
3157 return format_ctime((PyDateTime_Date *)self,
3158 DATE_GET_HOUR(self),
3159 DATE_GET_MINUTE(self),
3160 DATE_GET_SECOND(self));
3161}
3162
3163/* Miscellaneous methods. */
3164
3165/* This is more natural as a tp_compare, but doesn't work then: for whatever
3166 * reason, Python's try_3way_compare ignores tp_compare unless
3167 * PyInstance_Check returns true, but these aren't old-style classes.
3168 * Note that this routine handles all comparisons for datetime and datetimetz.
3169 */
3170static PyObject *
3171datetime_richcompare(PyDateTime_DateTime *self, PyObject *other, int op)
3172{
3173 int diff;
3174 naivety n1, n2;
3175 int offset1, offset2;
3176
3177 if (! PyDateTime_Check(other)) {
3178 /* Stop this from falling back to address comparison. */
3179 PyErr_Format(PyExc_TypeError,
3180 "can't compare '%s' to '%s'",
3181 self->ob_type->tp_name,
3182 other->ob_type->tp_name);
3183 return NULL;
3184 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003185
Tim Peters00237032002-12-27 02:21:51 +00003186 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1,
Tim Peterse39a80c2002-12-30 21:28:52 +00003187 (PyObject *)self,
3188 other, &offset2, &n2,
3189 other) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003190 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003191 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters60c76e42002-12-27 00:41:11 +00003192 /* If they're both naive, or both aware and have the same offsets,
Tim Peters2a799bf2002-12-16 20:18:38 +00003193 * we get off cheap. Note that if they're both naive, offset1 ==
3194 * offset2 == 0 at this point.
3195 */
3196 if (n1 == n2 && offset1 == offset2) {
3197 diff = memcmp(self->data, ((PyDateTime_DateTime *)other)->data,
3198 _PyDateTime_DATETIME_DATASIZE);
3199 return diff_to_bool(diff, op);
3200 }
3201
3202 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3203 /* We want the sign of
3204 * (self - offset1 minutes) - (other - offset2 minutes) =
3205 * (self - other) + (offset2 - offset1) minutes.
3206 */
3207 PyDateTime_Delta *delta;
3208 int days, seconds, us;
3209
3210 assert(offset1 != offset2); /* else last "if" handled it */
3211 delta = (PyDateTime_Delta *)sub_datetime_datetime(self,
3212 (PyDateTime_DateTime *)other);
3213 if (delta == NULL)
3214 return NULL;
3215 days = delta->days;
3216 seconds = delta->seconds + (offset2 - offset1) * 60;
3217 us = delta->microseconds;
3218 Py_DECREF(delta);
3219 normalize_d_s_us(&days, &seconds, &us);
3220 diff = days;
3221 if (diff == 0)
3222 diff = seconds | us;
3223 return diff_to_bool(diff, op);
3224 }
3225
3226 assert(n1 != n2);
3227 PyErr_SetString(PyExc_TypeError,
3228 "can't compare offset-naive and "
3229 "offset-aware datetimes");
3230 return NULL;
3231}
3232
Tim Peters2a799bf2002-12-16 20:18:38 +00003233static long
3234datetime_hash(PyDateTime_DateTime *self)
3235{
3236 if (self->hashcode == -1) {
3237 naivety n;
3238 int offset;
3239 PyObject *temp;
3240
Tim Peterse39a80c2002-12-30 21:28:52 +00003241 n = classify_utcoffset((PyObject *)self, (PyObject *)self,
3242 &offset);
Tim Peters2a799bf2002-12-16 20:18:38 +00003243 assert(n != OFFSET_UNKNOWN);
3244 if (n == OFFSET_ERROR)
3245 return -1;
3246
3247 /* Reduce this to a hash of another object. */
3248 if (n == OFFSET_NAIVE)
Tim Peters33e0f382003-01-10 02:05:14 +00003249 temp = PyString_FromStringAndSize(
3250 (char *)self->data,
3251 _PyDateTime_DATETIME_DATASIZE);
Tim Peters2a799bf2002-12-16 20:18:38 +00003252 else {
3253 int days;
3254 int seconds;
3255
3256 assert(n == OFFSET_AWARE);
3257 assert(PyDateTimeTZ_Check(self));
3258 days = ymd_to_ord(GET_YEAR(self),
3259 GET_MONTH(self),
3260 GET_DAY(self));
3261 seconds = DATE_GET_HOUR(self) * 3600 +
3262 (DATE_GET_MINUTE(self) - offset) * 60 +
3263 DATE_GET_SECOND(self);
3264 temp = new_delta(days,
3265 seconds,
3266 DATE_GET_MICROSECOND(self),
3267 1);
3268 }
3269 if (temp != NULL) {
3270 self->hashcode = PyObject_Hash(temp);
3271 Py_DECREF(temp);
3272 }
3273 }
3274 return self->hashcode;
3275}
3276
3277static PyObject *
Tim Peters12bf3392002-12-24 05:41:27 +00003278datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
3279{
3280 PyObject *clone;
3281 PyObject *tuple;
3282 int y = GET_YEAR(self);
3283 int m = GET_MONTH(self);
3284 int d = GET_DAY(self);
3285 int hh = DATE_GET_HOUR(self);
3286 int mm = DATE_GET_MINUTE(self);
3287 int ss = DATE_GET_SECOND(self);
3288 int us = DATE_GET_MICROSECOND(self);
3289
3290 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiii:replace",
3291 datetime_kws,
3292 &y, &m, &d, &hh, &mm, &ss, &us))
3293 return NULL;
3294 tuple = Py_BuildValue("iiiiiii", y, m, d, hh, mm, ss, us);
3295 if (tuple == NULL)
3296 return NULL;
3297 clone = datetime_new(self->ob_type, tuple, NULL);
3298 Py_DECREF(tuple);
3299 return clone;
3300}
3301
3302static PyObject *
Tim Peters80475bb2002-12-25 07:40:55 +00003303datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
3304{
3305 PyObject *tzinfo;
3306 static char *keywords[] = {"tz", NULL};
3307
3308 if (! PyArg_ParseTupleAndKeywords(args, kw, "O:astimezone", keywords,
3309 &tzinfo))
3310 return NULL;
3311 if (check_tzinfo_subclass(tzinfo) < 0)
3312 return NULL;
3313 return new_datetimetz(GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3314 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3315 DATE_GET_SECOND(self),
3316 DATE_GET_MICROSECOND(self),
3317 tzinfo);
3318}
3319
3320static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00003321datetime_timetuple(PyDateTime_DateTime *self)
3322{
3323 return build_struct_time(GET_YEAR(self),
3324 GET_MONTH(self),
3325 GET_DAY(self),
3326 DATE_GET_HOUR(self),
3327 DATE_GET_MINUTE(self),
3328 DATE_GET_SECOND(self),
3329 -1);
3330}
3331
3332static PyObject *
3333datetime_getdate(PyDateTime_DateTime *self)
3334{
3335 return new_date(GET_YEAR(self),
3336 GET_MONTH(self),
3337 GET_DAY(self));
3338}
3339
3340static PyObject *
3341datetime_gettime(PyDateTime_DateTime *self)
3342{
Tim Peters37f39822003-01-10 03:49:02 +00003343 return new_time(DATE_GET_HOUR(self),
3344 DATE_GET_MINUTE(self),
3345 DATE_GET_SECOND(self),
3346 DATE_GET_MICROSECOND(self),
3347 Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003348}
3349
Tim Peters2a799bf2002-12-16 20:18:38 +00003350static PyMethodDef datetime_methods[] = {
3351 /* Class methods: */
3352 {"now", (PyCFunction)datetime_now,
3353 METH_NOARGS | METH_CLASS,
3354 PyDoc_STR("Return a new datetime representing local day and time.")},
3355
3356 {"utcnow", (PyCFunction)datetime_utcnow,
3357 METH_NOARGS | METH_CLASS,
3358 PyDoc_STR("Return a new datetime representing UTC day and time.")},
3359
3360 {"fromtimestamp", (PyCFunction)datetime_fromtimestamp,
3361 METH_VARARGS | METH_CLASS,
3362 PyDoc_STR("timestamp -> local datetime from a POSIX timestamp "
3363 "(like time.time()).")},
3364
3365 {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
3366 METH_VARARGS | METH_CLASS,
3367 PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp "
3368 "(like time.time()).")},
3369
3370 {"combine", (PyCFunction)datetime_combine,
3371 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
3372 PyDoc_STR("date, time -> datetime with same date and time fields")},
3373
3374 /* Instance methods: */
3375 {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS,
3376 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
3377
3378 {"date", (PyCFunction)datetime_getdate, METH_NOARGS,
3379 PyDoc_STR("Return date object with same year, month and day.")},
3380
3381 {"time", (PyCFunction)datetime_gettime, METH_NOARGS,
Tim Peters0bf60bd2003-01-08 20:40:01 +00003382 PyDoc_STR("Return time object with same time but with tzinfo=None.")},
Tim Peters2a799bf2002-12-16 20:18:38 +00003383
3384 {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
3385 PyDoc_STR("Return ctime() style string.")},
3386
3387 {"isoformat", (PyCFunction)datetime_isoformat, METH_KEYWORDS,
3388 PyDoc_STR("[sep] -> string in ISO 8601 format, "
3389 "YYYY-MM-DDTHH:MM:SS[.mmmmmm].\n\n"
3390 "sep is used to separate the year from the time, and "
3391 "defaults\n"
3392 "to 'T'.")},
3393
Tim Peters12bf3392002-12-24 05:41:27 +00003394 {"replace", (PyCFunction)datetime_replace, METH_KEYWORDS,
3395 PyDoc_STR("Return datetime with new specified fields.")},
3396
Tim Peters80475bb2002-12-25 07:40:55 +00003397 {"astimezone", (PyCFunction)datetime_astimezone, METH_KEYWORDS,
Tim Peters37f39822003-01-10 03:49:02 +00003398 PyDoc_STR("tz -> datetime with same date & time, and tzinfo=tz\n")},
Tim Peters80475bb2002-12-25 07:40:55 +00003399
Tim Peters2a799bf2002-12-16 20:18:38 +00003400 {NULL, NULL}
3401};
3402
3403static char datetime_doc[] =
3404PyDoc_STR("Basic date/time type.");
3405
3406static PyNumberMethods datetime_as_number = {
3407 datetime_add, /* nb_add */
3408 datetime_subtract, /* nb_subtract */
3409 0, /* nb_multiply */
3410 0, /* nb_divide */
3411 0, /* nb_remainder */
3412 0, /* nb_divmod */
3413 0, /* nb_power */
3414 0, /* nb_negative */
3415 0, /* nb_positive */
3416 0, /* nb_absolute */
3417 0, /* nb_nonzero */
3418};
3419
3420statichere PyTypeObject PyDateTime_DateTimeType = {
3421 PyObject_HEAD_INIT(NULL)
3422 0, /* ob_size */
3423 "datetime.datetime", /* tp_name */
3424 sizeof(PyDateTime_DateTime), /* tp_basicsize */
3425 0, /* tp_itemsize */
3426 (destructor)PyObject_Del, /* tp_dealloc */
3427 0, /* tp_print */
3428 0, /* tp_getattr */
3429 0, /* tp_setattr */
3430 0, /* tp_compare */
3431 (reprfunc)datetime_repr, /* tp_repr */
3432 &datetime_as_number, /* tp_as_number */
3433 0, /* tp_as_sequence */
3434 0, /* tp_as_mapping */
3435 (hashfunc)datetime_hash, /* tp_hash */
3436 0, /* tp_call */
3437 (reprfunc)datetime_str, /* tp_str */
3438 PyObject_GenericGetAttr, /* tp_getattro */
3439 0, /* tp_setattro */
3440 0, /* tp_as_buffer */
3441 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3442 Py_TPFLAGS_BASETYPE, /* tp_flags */
3443 datetime_doc, /* tp_doc */
3444 0, /* tp_traverse */
3445 0, /* tp_clear */
3446 (richcmpfunc)datetime_richcompare, /* tp_richcompare */
3447 0, /* tp_weaklistoffset */
3448 0, /* tp_iter */
3449 0, /* tp_iternext */
3450 datetime_methods, /* tp_methods */
3451 0, /* tp_members */
3452 datetime_getset, /* tp_getset */
3453 &PyDateTime_DateType, /* tp_base */
3454 0, /* tp_dict */
3455 0, /* tp_descr_get */
3456 0, /* tp_descr_set */
3457 0, /* tp_dictoffset */
3458 0, /* tp_init */
3459 0, /* tp_alloc */
3460 datetime_new, /* tp_new */
3461 _PyObject_Del, /* tp_free */
3462};
3463
3464/*
Tim Peters2a799bf2002-12-16 20:18:38 +00003465 * PyDateTime_TZInfo implementation.
3466 */
3467
3468/* This is a pure abstract base class, so doesn't do anything beyond
3469 * raising NotImplemented exceptions. Real tzinfo classes need
3470 * to derive from this. This is mostly for clarity, and for efficiency in
Tim Peters37f39822003-01-10 03:49:02 +00003471 * datetimetz and time constructors (their tzinfo arguments need to
Tim Peters2a799bf2002-12-16 20:18:38 +00003472 * be subclasses of this tzinfo class, which is easy and quick to check).
3473 *
3474 * Note: For reasons having to do with pickling of subclasses, we have
3475 * to allow tzinfo objects to be instantiated. This wasn't an issue
3476 * in the Python implementation (__init__() could raise NotImplementedError
3477 * there without ill effect), but doing so in the C implementation hit a
3478 * brick wall.
3479 */
3480
3481static PyObject *
3482tzinfo_nogo(const char* methodname)
3483{
3484 PyErr_Format(PyExc_NotImplementedError,
3485 "a tzinfo subclass must implement %s()",
3486 methodname);
3487 return NULL;
3488}
3489
3490/* Methods. A subclass must implement these. */
3491
3492static PyObject*
3493tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt)
3494{
3495 return tzinfo_nogo("tzname");
3496}
3497
3498static PyObject*
3499tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt)
3500{
3501 return tzinfo_nogo("utcoffset");
3502}
3503
3504static PyObject*
3505tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
3506{
3507 return tzinfo_nogo("dst");
3508}
3509
3510/*
3511 * Pickle support. This is solely so that tzinfo subclasses can use
3512 * pickling -- tzinfo itself is supposed to be uninstantiable. The
3513 * pickler and unpickler functions are given module-level private
3514 * names, and registered with copy_reg, by the module init function.
3515 */
3516
3517static PyObject*
3518tzinfo_pickler(PyDateTime_TZInfo *self) {
3519 return Py_BuildValue("O()", tzinfo_unpickler_object);
3520}
3521
3522static PyObject*
3523tzinfo_unpickler(PyObject * unused) {
3524 return PyType_GenericNew(&PyDateTime_TZInfoType, NULL, NULL);
3525}
3526
3527
3528static PyMethodDef tzinfo_methods[] = {
3529 {"tzname", (PyCFunction)tzinfo_tzname, METH_O,
3530 PyDoc_STR("datetime -> string name of time zone.")},
3531
3532 {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
3533 PyDoc_STR("datetime -> minutes east of UTC (negative for "
3534 "west of UTC).")},
3535
3536 {"dst", (PyCFunction)tzinfo_dst, METH_O,
3537 PyDoc_STR("datetime -> DST offset in minutes east of UTC.")},
3538
3539 {NULL, NULL}
3540};
3541
3542static char tzinfo_doc[] =
3543PyDoc_STR("Abstract base class for time zone info objects.");
3544
3545 statichere PyTypeObject PyDateTime_TZInfoType = {
3546 PyObject_HEAD_INIT(NULL)
3547 0, /* ob_size */
3548 "datetime.tzinfo", /* tp_name */
3549 sizeof(PyDateTime_TZInfo), /* tp_basicsize */
3550 0, /* tp_itemsize */
3551 0, /* tp_dealloc */
3552 0, /* tp_print */
3553 0, /* tp_getattr */
3554 0, /* tp_setattr */
3555 0, /* tp_compare */
3556 0, /* tp_repr */
3557 0, /* tp_as_number */
3558 0, /* tp_as_sequence */
3559 0, /* tp_as_mapping */
3560 0, /* tp_hash */
3561 0, /* tp_call */
3562 0, /* tp_str */
3563 PyObject_GenericGetAttr, /* tp_getattro */
3564 0, /* tp_setattro */
3565 0, /* tp_as_buffer */
3566 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3567 Py_TPFLAGS_BASETYPE, /* tp_flags */
3568 tzinfo_doc, /* tp_doc */
3569 0, /* tp_traverse */
3570 0, /* tp_clear */
3571 0, /* tp_richcompare */
3572 0, /* tp_weaklistoffset */
3573 0, /* tp_iter */
3574 0, /* tp_iternext */
3575 tzinfo_methods, /* tp_methods */
3576 0, /* tp_members */
3577 0, /* tp_getset */
3578 0, /* tp_base */
3579 0, /* tp_dict */
3580 0, /* tp_descr_get */
3581 0, /* tp_descr_set */
3582 0, /* tp_dictoffset */
3583 0, /* tp_init */
3584 0, /* tp_alloc */
3585 PyType_GenericNew, /* tp_new */
3586 0, /* tp_free */
3587};
3588
3589/*
Tim Peters37f39822003-01-10 03:49:02 +00003590 * PyDateTime_Time implementation.
Tim Peters2a799bf2002-12-16 20:18:38 +00003591 */
3592
Tim Peters37f39822003-01-10 03:49:02 +00003593/* Accessor properties.
Tim Peters2a799bf2002-12-16 20:18:38 +00003594 */
3595
3596static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003597time_hour(PyDateTime_Time *self, void *unused)
Tim Peters2a799bf2002-12-16 20:18:38 +00003598{
Tim Peters37f39822003-01-10 03:49:02 +00003599 return PyInt_FromLong(TIME_GET_HOUR(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00003600}
3601
Tim Peters37f39822003-01-10 03:49:02 +00003602static PyObject *
3603time_minute(PyDateTime_Time *self, void *unused)
3604{
3605 return PyInt_FromLong(TIME_GET_MINUTE(self));
3606}
3607
3608/* The name time_second conflicted with some platform header file. */
3609static PyObject *
3610py_time_second(PyDateTime_Time *self, void *unused)
3611{
3612 return PyInt_FromLong(TIME_GET_SECOND(self));
3613}
3614
3615static PyObject *
3616time_microsecond(PyDateTime_Time *self, void *unused)
3617{
3618 return PyInt_FromLong(TIME_GET_MICROSECOND(self));
3619}
3620
3621static PyObject *
3622time_tzinfo(PyDateTime_Time *self, void *unused)
3623{
Tim Petersa032d2e2003-01-11 00:15:54 +00003624 PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
Tim Peters37f39822003-01-10 03:49:02 +00003625 Py_INCREF(result);
3626 return result;
3627}
3628
3629static PyGetSetDef time_getset[] = {
3630 {"hour", (getter)time_hour},
3631 {"minute", (getter)time_minute},
3632 {"second", (getter)py_time_second},
3633 {"microsecond", (getter)time_microsecond},
3634 {"tzinfo", (getter)time_tzinfo},
Tim Peters2a799bf2002-12-16 20:18:38 +00003635 {NULL}
3636};
3637
3638/*
3639 * Constructors.
3640 */
3641
Tim Peters37f39822003-01-10 03:49:02 +00003642static char *time_kws[] = {"hour", "minute", "second", "microsecond",
3643 "tzinfo", NULL};
Tim Peters12bf3392002-12-24 05:41:27 +00003644
Tim Peters2a799bf2002-12-16 20:18:38 +00003645static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003646time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003647{
3648 PyObject *self = NULL;
3649 int hour = 0;
3650 int minute = 0;
3651 int second = 0;
3652 int usecond = 0;
3653 PyObject *tzinfo = Py_None;
3654
Tim Peters37f39822003-01-10 03:49:02 +00003655 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", time_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00003656 &hour, &minute, &second, &usecond,
3657 &tzinfo)) {
3658 if (check_time_args(hour, minute, second, usecond) < 0)
3659 return NULL;
3660 if (check_tzinfo_subclass(tzinfo) < 0)
3661 return NULL;
Tim Peters37f39822003-01-10 03:49:02 +00003662 self = new_time(hour, minute, second, usecond, tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00003663 }
3664 return self;
3665}
3666
3667/*
3668 * Destructor.
3669 */
3670
3671static void
Tim Peters37f39822003-01-10 03:49:02 +00003672time_dealloc(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003673{
Tim Petersa032d2e2003-01-11 00:15:54 +00003674 if (HASTZINFO(self)) {
Tim Peters37f39822003-01-10 03:49:02 +00003675 Py_XDECREF(self->tzinfo);
Neal Norwitz8e914d92003-01-10 15:29:16 +00003676 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003677 self->ob_type->tp_free((PyObject *)self);
3678}
3679
3680/*
Tim Peters855fe882002-12-22 03:43:39 +00003681 * Indirect access to tzinfo methods.
Tim Peters2a799bf2002-12-16 20:18:38 +00003682 */
3683
Tim Peters2a799bf2002-12-16 20:18:38 +00003684/* These are all METH_NOARGS, so don't need to check the arglist. */
3685static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003686time_utcoffset(PyDateTime_Time *self, PyObject *unused) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003687 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
Tim Peters37f39822003-01-10 03:49:02 +00003688 "utcoffset", Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003689}
3690
3691static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003692time_dst(PyDateTime_Time *self, PyObject *unused) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003693 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
Tim Peters37f39822003-01-10 03:49:02 +00003694 "dst", Py_None);
Tim Peters855fe882002-12-22 03:43:39 +00003695}
3696
3697static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003698time_tzname(PyDateTime_Time *self, PyObject *unused) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003699 return call_tzname(HASTZINFO(self) ? self->tzinfo : Py_None,
Tim Peters37f39822003-01-10 03:49:02 +00003700 Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003701}
3702
3703/*
Tim Peters37f39822003-01-10 03:49:02 +00003704 * Various ways to turn a time into a string.
Tim Peters2a799bf2002-12-16 20:18:38 +00003705 */
3706
3707static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003708time_repr(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003709{
Tim Peters37f39822003-01-10 03:49:02 +00003710 char buffer[100];
3711 char *typename = self->ob_type->tp_name;
3712 int h = TIME_GET_HOUR(self);
3713 int m = TIME_GET_MINUTE(self);
3714 int s = TIME_GET_SECOND(self);
3715 int us = TIME_GET_MICROSECOND(self);
3716 PyObject *result = NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00003717
Tim Peters37f39822003-01-10 03:49:02 +00003718 if (us)
3719 PyOS_snprintf(buffer, sizeof(buffer),
3720 "%s(%d, %d, %d, %d)", typename, h, m, s, us);
3721 else if (s)
3722 PyOS_snprintf(buffer, sizeof(buffer),
3723 "%s(%d, %d, %d)", typename, h, m, s);
3724 else
3725 PyOS_snprintf(buffer, sizeof(buffer),
3726 "%s(%d, %d)", typename, h, m);
3727 result = PyString_FromString(buffer);
Tim Petersa032d2e2003-01-11 00:15:54 +00003728 if (result != NULL && HASTZINFO(self))
Tim Peters37f39822003-01-10 03:49:02 +00003729 result = append_keyword_tzinfo(result, self->tzinfo);
3730 return result;
Tim Peters2a799bf2002-12-16 20:18:38 +00003731}
3732
Tim Peters37f39822003-01-10 03:49:02 +00003733static PyObject *
3734time_str(PyDateTime_Time *self)
3735{
3736 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
3737}
Tim Peters2a799bf2002-12-16 20:18:38 +00003738
3739static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003740time_isoformat(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003741{
3742 char buf[100];
Tim Peters37f39822003-01-10 03:49:02 +00003743 PyObject *result;
3744 /* Reuse the time format code from the datetime type. */
3745 PyDateTime_DateTime datetime;
3746 PyDateTime_DateTime *pdatetime = &datetime;
Tim Peters2a799bf2002-12-16 20:18:38 +00003747
Tim Peters37f39822003-01-10 03:49:02 +00003748 /* Copy over just the time bytes. */
3749 memcpy(pdatetime->data + _PyDateTime_DATE_DATASIZE,
3750 self->data,
3751 _PyDateTime_TIME_DATASIZE);
3752
3753 isoformat_time(pdatetime, buf, sizeof(buf));
3754 result = PyString_FromString(buf);
Tim Petersa032d2e2003-01-11 00:15:54 +00003755 if (result == NULL || ! HASTZINFO(self) || self->tzinfo == Py_None)
Tim Peters2a799bf2002-12-16 20:18:38 +00003756 return result;
3757
3758 /* We need to append the UTC offset. */
3759 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00003760 Py_None) < 0) {
Tim Peters2a799bf2002-12-16 20:18:38 +00003761 Py_DECREF(result);
3762 return NULL;
3763 }
3764 PyString_ConcatAndDel(&result, PyString_FromString(buf));
3765 return result;
3766}
3767
Tim Peters37f39822003-01-10 03:49:02 +00003768static PyObject *
3769time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3770{
3771 PyObject *result;
3772 PyObject *format;
3773 PyObject *tuple;
3774 static char *keywords[] = {"format", NULL};
3775
3776 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
3777 &PyString_Type, &format))
3778 return NULL;
3779
3780 /* Python's strftime does insane things with the year part of the
3781 * timetuple. The year is forced to (the otherwise nonsensical)
3782 * 1900 to worm around that.
3783 */
3784 tuple = Py_BuildValue("iiiiiiiii",
3785 1900, 0, 0, /* year, month, day */
3786 TIME_GET_HOUR(self),
3787 TIME_GET_MINUTE(self),
3788 TIME_GET_SECOND(self),
3789 0, 0, -1); /* weekday, daynum, dst */
3790 if (tuple == NULL)
3791 return NULL;
3792 assert(PyTuple_Size(tuple) == 9);
3793 result = wrap_strftime((PyObject *)self, format, tuple, Py_None);
3794 Py_DECREF(tuple);
3795 return result;
3796}
Tim Peters2a799bf2002-12-16 20:18:38 +00003797
3798/*
3799 * Miscellaneous methods.
3800 */
3801
Tim Peters37f39822003-01-10 03:49:02 +00003802/* This is more natural as a tp_compare, but doesn't work then: for whatever
3803 * reason, Python's try_3way_compare ignores tp_compare unless
3804 * PyInstance_Check returns true, but these aren't old-style classes.
3805 */
3806static PyObject *
3807time_richcompare(PyDateTime_Time *self, PyObject *other, int op)
3808{
3809 int diff;
3810 naivety n1, n2;
3811 int offset1, offset2;
3812
3813 if (! PyTime_Check(other)) {
3814 /* Stop this from falling back to address comparison. */
3815 PyErr_Format(PyExc_TypeError,
3816 "can't compare '%s' to '%s'",
3817 self->ob_type->tp_name,
3818 other->ob_type->tp_name);
3819 return NULL;
3820 }
3821 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1, Py_None,
3822 other, &offset2, &n2, Py_None) < 0)
3823 return NULL;
3824 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
3825 /* If they're both naive, or both aware and have the same offsets,
3826 * we get off cheap. Note that if they're both naive, offset1 ==
3827 * offset2 == 0 at this point.
3828 */
3829 if (n1 == n2 && offset1 == offset2) {
3830 diff = memcmp(self->data, ((PyDateTime_Time *)other)->data,
3831 _PyDateTime_TIME_DATASIZE);
3832 return diff_to_bool(diff, op);
3833 }
3834
3835 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3836 assert(offset1 != offset2); /* else last "if" handled it */
3837 /* Convert everything except microseconds to seconds. These
3838 * can't overflow (no more than the # of seconds in 2 days).
3839 */
3840 offset1 = TIME_GET_HOUR(self) * 3600 +
3841 (TIME_GET_MINUTE(self) - offset1) * 60 +
3842 TIME_GET_SECOND(self);
3843 offset2 = TIME_GET_HOUR(other) * 3600 +
3844 (TIME_GET_MINUTE(other) - offset2) * 60 +
3845 TIME_GET_SECOND(other);
3846 diff = offset1 - offset2;
3847 if (diff == 0)
3848 diff = TIME_GET_MICROSECOND(self) -
3849 TIME_GET_MICROSECOND(other);
3850 return diff_to_bool(diff, op);
3851 }
3852
3853 assert(n1 != n2);
3854 PyErr_SetString(PyExc_TypeError,
3855 "can't compare offset-naive and "
3856 "offset-aware times");
3857 return NULL;
3858}
3859
3860static long
3861time_hash(PyDateTime_Time *self)
3862{
3863 if (self->hashcode == -1) {
3864 naivety n;
3865 int offset;
3866 PyObject *temp;
3867
3868 n = classify_utcoffset((PyObject *)self, Py_None, &offset);
3869 assert(n != OFFSET_UNKNOWN);
3870 if (n == OFFSET_ERROR)
3871 return -1;
3872
3873 /* Reduce this to a hash of another object. */
3874 if (offset == 0)
3875 temp = PyString_FromStringAndSize((char *)self->data,
3876 _PyDateTime_TIME_DATASIZE);
3877 else {
3878 int hour;
3879 int minute;
3880
3881 assert(n == OFFSET_AWARE);
Tim Petersa032d2e2003-01-11 00:15:54 +00003882 assert(HASTZINFO(self));
Tim Peters37f39822003-01-10 03:49:02 +00003883 hour = divmod(TIME_GET_HOUR(self) * 60 +
3884 TIME_GET_MINUTE(self) - offset,
3885 60,
3886 &minute);
3887 if (0 <= hour && hour < 24)
3888 temp = new_time(hour, minute,
3889 TIME_GET_SECOND(self),
3890 TIME_GET_MICROSECOND(self),
3891 Py_None);
3892 else
3893 temp = Py_BuildValue("iiii",
3894 hour, minute,
3895 TIME_GET_SECOND(self),
3896 TIME_GET_MICROSECOND(self));
3897 }
3898 if (temp != NULL) {
3899 self->hashcode = PyObject_Hash(temp);
3900 Py_DECREF(temp);
3901 }
3902 }
3903 return self->hashcode;
3904}
Tim Peters2a799bf2002-12-16 20:18:38 +00003905
Tim Peters12bf3392002-12-24 05:41:27 +00003906static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003907time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
Tim Peters12bf3392002-12-24 05:41:27 +00003908{
3909 PyObject *clone;
3910 PyObject *tuple;
3911 int hh = TIME_GET_HOUR(self);
3912 int mm = TIME_GET_MINUTE(self);
3913 int ss = TIME_GET_SECOND(self);
3914 int us = TIME_GET_MICROSECOND(self);
Tim Petersa032d2e2003-01-11 00:15:54 +00003915 PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
Tim Peters12bf3392002-12-24 05:41:27 +00003916
3917 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
Tim Peters37f39822003-01-10 03:49:02 +00003918 time_kws,
Tim Peters12bf3392002-12-24 05:41:27 +00003919 &hh, &mm, &ss, &us, &tzinfo))
3920 return NULL;
3921 tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
3922 if (tuple == NULL)
3923 return NULL;
Tim Peters37f39822003-01-10 03:49:02 +00003924 clone = time_new(self->ob_type, tuple, NULL);
Tim Peters12bf3392002-12-24 05:41:27 +00003925 Py_DECREF(tuple);
3926 return clone;
3927}
3928
Tim Peters2a799bf2002-12-16 20:18:38 +00003929static int
Tim Peters37f39822003-01-10 03:49:02 +00003930time_nonzero(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003931{
3932 int offset;
3933 int none;
3934
3935 if (TIME_GET_SECOND(self) || TIME_GET_MICROSECOND(self)) {
3936 /* Since utcoffset is in whole minutes, nothing can
3937 * alter the conclusion that this is nonzero.
3938 */
3939 return 1;
3940 }
3941 offset = 0;
Tim Petersa032d2e2003-01-11 00:15:54 +00003942 if (HASTZINFO(self) && self->tzinfo != Py_None) {
Tim Petersbad8ff02002-12-30 20:52:32 +00003943 offset = call_utcoffset(self->tzinfo, Py_None, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +00003944 if (offset == -1 && PyErr_Occurred())
3945 return -1;
3946 }
3947 return (TIME_GET_MINUTE(self) - offset + TIME_GET_HOUR(self)*60) != 0;
3948}
3949
3950/*
3951 * Pickle support. Quite a maze!
3952 */
3953
Tim Peters33e0f382003-01-10 02:05:14 +00003954/* Let basestate be the non-tzinfo data string.
Tim Peters2a799bf2002-12-16 20:18:38 +00003955 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
3956 * So it's a tuple in any (non-error) case.
3957 */
3958static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003959time_getstate(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003960{
3961 PyObject *basestate;
3962 PyObject *result = NULL;
3963
Tim Peters33e0f382003-01-10 02:05:14 +00003964 basestate = PyString_FromStringAndSize((char *)self->data,
3965 _PyDateTime_TIME_DATASIZE);
Tim Peters2a799bf2002-12-16 20:18:38 +00003966 if (basestate != NULL) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003967 if (! HASTZINFO(self) || self->tzinfo == Py_None)
Tim Peters2a799bf2002-12-16 20:18:38 +00003968 result = Py_BuildValue("(O)", basestate);
3969 else
3970 result = Py_BuildValue("OO", basestate, self->tzinfo);
3971 Py_DECREF(basestate);
3972 }
3973 return result;
3974}
3975
3976static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003977time_setstate(PyDateTime_Time *self, PyObject *state)
Tim Peters2a799bf2002-12-16 20:18:38 +00003978{
Tim Peters2a799bf2002-12-16 20:18:38 +00003979 PyObject *basestate;
3980 PyObject *tzinfo = Py_None;
3981
3982 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
3983 &PyString_Type, &basestate,
3984 &tzinfo))
3985 return NULL;
Tim Peters33e0f382003-01-10 02:05:14 +00003986 if (PyString_Size(basestate) != _PyDateTime_TIME_DATASIZE ||
3987 check_tzinfo_subclass(tzinfo) < 0) {
3988 PyErr_SetString(PyExc_TypeError,
3989 "bad argument to time.__setstate__");
Tim Peters2a799bf2002-12-16 20:18:38 +00003990 return NULL;
Tim Peters33e0f382003-01-10 02:05:14 +00003991 }
Tim Petersa032d2e2003-01-11 00:15:54 +00003992 if (tzinfo != Py_None && ! HASTZINFO(self)) {
Tim Peters37f39822003-01-10 03:49:02 +00003993 PyErr_SetString(PyExc_ValueError, "time.__setstate__ can't "
3994 "add a non-None tzinfo to a time object that "
3995 "doesn't have one already");
3996 return NULL;
3997 }
Tim Peters33e0f382003-01-10 02:05:14 +00003998 memcpy((char *)self->data,
3999 PyString_AsString(basestate),
4000 _PyDateTime_TIME_DATASIZE);
4001 self->hashcode = -1;
Tim Petersa032d2e2003-01-11 00:15:54 +00004002 if (HASTZINFO(self)) {
Tim Peters37f39822003-01-10 03:49:02 +00004003 Py_INCREF(tzinfo);
4004 Py_XDECREF(self->tzinfo);
4005 self->tzinfo = tzinfo;
4006 }
Tim Peters2a799bf2002-12-16 20:18:38 +00004007 Py_INCREF(Py_None);
4008 return Py_None;
4009}
4010
4011static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00004012time_pickler(PyObject *module, PyDateTime_Time *time)
Tim Peters2a799bf2002-12-16 20:18:38 +00004013{
4014 PyObject *state;
4015 PyObject *result = NULL;
4016
Tim Peters37f39822003-01-10 03:49:02 +00004017 if (! PyTime_CheckExact(time)) {
Tim Peters2a799bf2002-12-16 20:18:38 +00004018 PyErr_Format(PyExc_TypeError,
Tim Peters37f39822003-01-10 03:49:02 +00004019 "bad type passed to time pickler: %s",
4020 time->ob_type->tp_name);
Tim Peters2a799bf2002-12-16 20:18:38 +00004021 return NULL;
4022 }
Tim Peters37f39822003-01-10 03:49:02 +00004023 state = time_getstate(time);
Tim Peters2a799bf2002-12-16 20:18:38 +00004024 if (state) {
4025 result = Py_BuildValue("O(O)",
Tim Peters37f39822003-01-10 03:49:02 +00004026 time_unpickler_object,
Tim Peters2a799bf2002-12-16 20:18:38 +00004027 state);
4028 Py_DECREF(state);
4029 }
4030 return result;
4031}
4032
4033static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00004034time_unpickler(PyObject *module, PyObject *arg)
Tim Peters2a799bf2002-12-16 20:18:38 +00004035{
Tim Peters37f39822003-01-10 03:49:02 +00004036 PyDateTime_Time *self;
Tim Peters2a799bf2002-12-16 20:18:38 +00004037
Tim Peters37f39822003-01-10 03:49:02 +00004038 /* We don't want to allocate space for tzinfo if it's not needed.
4039 * Figuring that out in advance is irritating, so for now we
4040 * realloc later.
4041 */
4042 self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
Tim Peters2a799bf2002-12-16 20:18:38 +00004043 if (self != NULL) {
4044 PyObject *res;
4045
Tim Peters37f39822003-01-10 03:49:02 +00004046 self->tzinfo = Py_None;
4047 Py_INCREF(self->tzinfo);
4048 self->hastzinfo = (char)1; /* true */
4049 res = time_setstate(self, arg);
Tim Peters2a799bf2002-12-16 20:18:38 +00004050 if (res == NULL) {
4051 Py_DECREF(self);
4052 return NULL;
4053 }
4054 Py_DECREF(res);
Tim Peters37f39822003-01-10 03:49:02 +00004055 if (self->tzinfo == Py_None) {
4056 /* shrinking; can't fail */
4057 Py_DECREF(self->tzinfo);
4058 PyObject_Realloc(self, sizeof(_PyDateTime_BaseTime));
4059 self->hastzinfo = (char)0;
4060 }
Tim Peters2a799bf2002-12-16 20:18:38 +00004061 }
4062 return (PyObject *)self;
4063}
4064
Tim Peters37f39822003-01-10 03:49:02 +00004065static PyMethodDef time_methods[] = {
4066 {"isoformat", (PyCFunction)time_isoformat, METH_KEYWORDS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004067 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]"
4068 "[+HH:MM].")},
4069
Tim Peters37f39822003-01-10 03:49:02 +00004070 {"strftime", (PyCFunction)time_strftime, METH_KEYWORDS,
4071 PyDoc_STR("format -> strftime() style string.")},
4072
4073 {"utcoffset", (PyCFunction)time_utcoffset, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004074 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
4075
Tim Peters37f39822003-01-10 03:49:02 +00004076 {"tzname", (PyCFunction)time_tzname, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004077 PyDoc_STR("Return self.tzinfo.tzname(self).")},
4078
Tim Peters37f39822003-01-10 03:49:02 +00004079 {"dst", (PyCFunction)time_dst, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004080 PyDoc_STR("Return self.tzinfo.dst(self).")},
4081
Tim Peters37f39822003-01-10 03:49:02 +00004082 {"replace", (PyCFunction)time_replace, METH_KEYWORDS,
4083 PyDoc_STR("Return time with new specified fields.")},
Tim Peters12bf3392002-12-24 05:41:27 +00004084
Tim Peters37f39822003-01-10 03:49:02 +00004085 {"__setstate__", (PyCFunction)time_setstate, METH_O,
Tim Peters2a799bf2002-12-16 20:18:38 +00004086 PyDoc_STR("__setstate__(state)")},
4087
Tim Peters37f39822003-01-10 03:49:02 +00004088 {"__getstate__", (PyCFunction)time_getstate, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004089 PyDoc_STR("__getstate__() -> state")},
4090 {NULL, NULL}
Tim Peters2a799bf2002-12-16 20:18:38 +00004091};
4092
Tim Peters37f39822003-01-10 03:49:02 +00004093static char time_doc[] =
Tim Peters2a799bf2002-12-16 20:18:38 +00004094PyDoc_STR("Time type.");
4095
Tim Peters37f39822003-01-10 03:49:02 +00004096static PyNumberMethods time_as_number = {
Tim Peters2a799bf2002-12-16 20:18:38 +00004097 0, /* nb_add */
4098 0, /* nb_subtract */
4099 0, /* nb_multiply */
4100 0, /* nb_divide */
4101 0, /* nb_remainder */
4102 0, /* nb_divmod */
4103 0, /* nb_power */
4104 0, /* nb_negative */
4105 0, /* nb_positive */
4106 0, /* nb_absolute */
Tim Peters37f39822003-01-10 03:49:02 +00004107 (inquiry)time_nonzero, /* nb_nonzero */
Tim Peters2a799bf2002-12-16 20:18:38 +00004108};
4109
Tim Peters37f39822003-01-10 03:49:02 +00004110statichere PyTypeObject PyDateTime_TimeType = {
Tim Peters2a799bf2002-12-16 20:18:38 +00004111 PyObject_HEAD_INIT(NULL)
4112 0, /* ob_size */
Tim Peters0bf60bd2003-01-08 20:40:01 +00004113 "datetime.time", /* tp_name */
Tim Peters37f39822003-01-10 03:49:02 +00004114 sizeof(PyDateTime_Time), /* tp_basicsize */
Tim Peters2a799bf2002-12-16 20:18:38 +00004115 0, /* tp_itemsize */
Tim Peters37f39822003-01-10 03:49:02 +00004116 (destructor)time_dealloc, /* tp_dealloc */
Tim Peters2a799bf2002-12-16 20:18:38 +00004117 0, /* tp_print */
4118 0, /* tp_getattr */
4119 0, /* tp_setattr */
4120 0, /* tp_compare */
Tim Peters37f39822003-01-10 03:49:02 +00004121 (reprfunc)time_repr, /* tp_repr */
4122 &time_as_number, /* tp_as_number */
Tim Peters2a799bf2002-12-16 20:18:38 +00004123 0, /* tp_as_sequence */
4124 0, /* tp_as_mapping */
Tim Peters37f39822003-01-10 03:49:02 +00004125 (hashfunc)time_hash, /* tp_hash */
Tim Peters2a799bf2002-12-16 20:18:38 +00004126 0, /* tp_call */
Tim Peters37f39822003-01-10 03:49:02 +00004127 (reprfunc)time_str, /* tp_str */
Tim Peters2a799bf2002-12-16 20:18:38 +00004128 PyObject_GenericGetAttr, /* tp_getattro */
4129 0, /* tp_setattro */
4130 0, /* tp_as_buffer */
4131 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4132 Py_TPFLAGS_BASETYPE, /* tp_flags */
Tim Peters37f39822003-01-10 03:49:02 +00004133 time_doc, /* tp_doc */
Tim Peters2a799bf2002-12-16 20:18:38 +00004134 0, /* tp_traverse */
4135 0, /* tp_clear */
Tim Peters37f39822003-01-10 03:49:02 +00004136 (richcmpfunc)time_richcompare, /* tp_richcompare */
Tim Peters2a799bf2002-12-16 20:18:38 +00004137 0, /* tp_weaklistoffset */
4138 0, /* tp_iter */
4139 0, /* tp_iternext */
Tim Peters37f39822003-01-10 03:49:02 +00004140 time_methods, /* tp_methods */
Tim Peters2a799bf2002-12-16 20:18:38 +00004141 0, /* tp_members */
Tim Peters37f39822003-01-10 03:49:02 +00004142 time_getset, /* tp_getset */
4143 0, /* tp_base */
Tim Peters2a799bf2002-12-16 20:18:38 +00004144 0, /* tp_dict */
4145 0, /* tp_descr_get */
4146 0, /* tp_descr_set */
4147 0, /* tp_dictoffset */
4148 0, /* tp_init */
4149 0, /* tp_alloc */
Tim Peters37f39822003-01-10 03:49:02 +00004150 time_new, /* tp_new */
Tim Peters2a799bf2002-12-16 20:18:38 +00004151 _PyObject_Del, /* tp_free */
4152};
4153
4154/*
4155 * PyDateTime_DateTimeTZ implementation.
4156 */
4157
4158/* Accessor properties. Properties for day, month, year, hour, minute,
4159 * second and microsecond are inherited from datetime.
4160 */
4161
4162static PyObject *
4163datetimetz_tzinfo(PyDateTime_DateTimeTZ *self, void *unused)
4164{
4165 Py_INCREF(self->tzinfo);
4166 return self->tzinfo;
4167}
4168
4169static PyGetSetDef datetimetz_getset[] = {
4170 {"tzinfo", (getter)datetimetz_tzinfo},
4171 {NULL}
4172};
4173
4174/*
4175 * Constructors.
4176 * These are like the datetime methods of the same names, but allow an
4177 * optional tzinfo argument.
4178 */
4179
Tim Peters12bf3392002-12-24 05:41:27 +00004180static char *datetimetz_kws[] = {
4181 "year", "month", "day", "hour", "minute", "second",
4182 "microsecond", "tzinfo", NULL
4183};
4184
Tim Peters2a799bf2002-12-16 20:18:38 +00004185static PyObject *
4186datetimetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4187{
4188 PyObject *self = NULL;
4189 int year;
4190 int month;
4191 int day;
4192 int hour = 0;
4193 int minute = 0;
4194 int second = 0;
4195 int usecond = 0;
4196 PyObject *tzinfo = Py_None;
4197
Tim Peters12bf3392002-12-24 05:41:27 +00004198 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO", datetimetz_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00004199 &year, &month, &day, &hour, &minute,
4200 &second, &usecond, &tzinfo)) {
4201 if (check_date_args(year, month, day) < 0)
4202 return NULL;
4203 if (check_time_args(hour, minute, second, usecond) < 0)
4204 return NULL;
4205 if (check_tzinfo_subclass(tzinfo) < 0)
4206 return NULL;
4207 self = new_datetimetz(year, month, day,
4208 hour, minute, second, usecond,
4209 tzinfo);
4210 }
4211 return self;
4212}
4213
4214/* Return best possible local time -- this isn't constrained by the
4215 * precision of a timestamp.
4216 */
4217static PyObject *
4218datetimetz_now(PyObject *cls, PyObject *args, PyObject *kw)
4219{
4220 PyObject *self = NULL;
4221 PyObject *tzinfo = Py_None;
4222 static char *keywords[] = {"tzinfo", NULL};
4223
4224 if (PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords,
4225 &tzinfo)) {
4226 if (check_tzinfo_subclass(tzinfo) < 0)
4227 return NULL;
4228 self = datetime_best_possible(cls, localtime);
4229 if (self != NULL)
4230 replace_tzinfo(self, tzinfo);
4231 }
4232 return self;
4233}
4234
4235/* Return new local datetime from timestamp (Python timestamp -- a double). */
4236static PyObject *
4237datetimetz_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
4238{
4239 PyObject *self = NULL;
4240 double timestamp;
4241 PyObject *tzinfo = Py_None;
4242 static char *keywords[] = {"timestamp", "tzinfo", NULL};
4243
4244 if (PyArg_ParseTupleAndKeywords(args, kw, "d|O:fromtimestamp",
4245 keywords, &timestamp, &tzinfo)) {
4246 if (check_tzinfo_subclass(tzinfo) < 0)
4247 return NULL;
4248 self = datetime_from_timestamp(cls, localtime, timestamp);
4249 if (self != NULL)
4250 replace_tzinfo(self, tzinfo);
4251 }
4252 return self;
4253}
4254
4255/* Note: utcnow() is inherited, and doesn't accept tzinfo.
4256 * Ditto utcfromtimestamp(). Ditto combine().
4257 */
4258
4259
4260/*
4261 * Destructor.
4262 */
4263
4264static void
4265datetimetz_dealloc(PyDateTime_DateTimeTZ *self)
4266{
4267 Py_XDECREF(self->tzinfo);
4268 self->ob_type->tp_free((PyObject *)self);
4269}
4270
4271/*
4272 * Indirect access to tzinfo methods.
4273 */
4274
Tim Peters2a799bf2002-12-16 20:18:38 +00004275/* These are all METH_NOARGS, so don't need to check the arglist. */
4276static PyObject *
4277datetimetz_utcoffset(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004278 return offset_as_timedelta(self->tzinfo, "utcoffset",
4279 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00004280}
4281
4282static PyObject *
4283datetimetz_dst(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004284 return offset_as_timedelta(self->tzinfo, "dst", (PyObject *)self);
Tim Peters855fe882002-12-22 03:43:39 +00004285}
4286
4287static PyObject *
4288datetimetz_tzname(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004289 return call_tzname(self->tzinfo, (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00004290}
4291
4292/*
4293 * datetimetz arithmetic.
4294 */
4295
4296/* If base is Py_NotImplemented or NULL, just return it.
4297 * Else base is a datetime, exactly one of {left, right} is a datetimetz,
4298 * and we want to create a datetimetz with the same date and time fields
4299 * as base, and with the tzinfo field from left or right. Do that,
4300 * return it, and decref base. This is used to transform the result of
4301 * a binary datetime operation (base) into a datetimetz result.
4302 */
4303static PyObject *
4304attach_tzinfo(PyObject *base, PyObject *left, PyObject *right)
4305{
4306 PyDateTime_DateTimeTZ *self;
4307 PyDateTime_DateTimeTZ *result;
4308
4309 if (base == NULL || base == Py_NotImplemented)
4310 return base;
4311
4312 assert(PyDateTime_CheckExact(base));
4313
4314 if (PyDateTimeTZ_Check(left)) {
4315 assert(! PyDateTimeTZ_Check(right));
4316 self = (PyDateTime_DateTimeTZ *)left;
4317 }
4318 else {
4319 assert(PyDateTimeTZ_Check(right));
4320 self = (PyDateTime_DateTimeTZ *)right;
4321 }
4322 result = PyObject_New(PyDateTime_DateTimeTZ,
4323 &PyDateTime_DateTimeTZType);
4324 if (result != NULL) {
4325 memcpy(result->data, ((PyDateTime_DateTime *)base)->data,
4326 _PyDateTime_DATETIME_DATASIZE);
4327 Py_INCREF(self->tzinfo);
4328 result->tzinfo = self->tzinfo;
4329 }
4330 Py_DECREF(base);
4331 return (PyObject *)result;
4332}
4333
4334static PyObject *
4335datetimetz_add(PyObject *left, PyObject *right)
4336{
4337 return attach_tzinfo(datetime_add(left, right), left, right);
4338}
4339
4340static PyObject *
4341datetimetz_subtract(PyObject *left, PyObject *right)
4342{
4343 PyObject *result = Py_NotImplemented;
4344
4345 if (PyDateTime_Check(left)) {
4346 /* datetime - ??? */
4347 if (PyDateTime_Check(right)) {
4348 /* datetime - datetime */
4349 naivety n1, n2;
4350 int offset1, offset2;
4351 PyDateTime_Delta *delta;
4352
Tim Peterse39a80c2002-12-30 21:28:52 +00004353 if (classify_two_utcoffsets(left, &offset1, &n1, left,
4354 right, &offset2, &n2,
4355 right) < 0)
Tim Peters00237032002-12-27 02:21:51 +00004356 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00004357 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00004358 if (n1 != n2) {
4359 PyErr_SetString(PyExc_TypeError,
4360 "can't subtract offset-naive and "
4361 "offset-aware datetimes");
4362 return NULL;
4363 }
4364 delta = (PyDateTime_Delta *)sub_datetime_datetime(
4365 (PyDateTime_DateTime *)left,
4366 (PyDateTime_DateTime *)right);
4367 if (delta == NULL || offset1 == offset2)
4368 return (PyObject *)delta;
4369 /* (left - offset1) - (right - offset2) =
4370 * (left - right) + (offset2 - offset1)
4371 */
4372 result = new_delta(delta->days,
4373 delta->seconds +
4374 (offset2 - offset1) * 60,
4375 delta->microseconds,
4376 1);
4377 Py_DECREF(delta);
4378 }
4379 else if (PyDelta_Check(right)) {
4380 /* datetimetz - delta */
4381 result = sub_datetime_timedelta(
4382 (PyDateTime_DateTime *)left,
4383 (PyDateTime_Delta *)right);
4384 result = attach_tzinfo(result, left, right);
4385 }
4386 }
4387
4388 if (result == Py_NotImplemented)
4389 Py_INCREF(result);
4390 return result;
4391}
4392
4393/* Various ways to turn a datetime into a string. */
4394
4395static PyObject *
4396datetimetz_repr(PyDateTime_DateTimeTZ *self)
4397{
4398 PyObject *baserepr = datetime_repr((PyDateTime_DateTime *)self);
4399
4400 if (baserepr == NULL)
4401 return NULL;
4402 return append_keyword_tzinfo(baserepr, self->tzinfo);
4403}
4404
4405/* Note: tp_str is inherited from datetime. */
4406
4407static PyObject *
4408datetimetz_isoformat(PyDateTime_DateTimeTZ *self,
4409 PyObject *args, PyObject *kw)
4410{
4411 char buf[100];
4412 PyObject *result = datetime_isoformat((PyDateTime_DateTime *)self,
4413 args, kw);
4414
4415 if (result == NULL || self->tzinfo == Py_None)
4416 return result;
4417
4418 /* We need to append the UTC offset. */
4419 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
4420 (PyObject *)self) < 0) {
4421 Py_DECREF(result);
4422 return NULL;
4423 }
4424 PyString_ConcatAndDel(&result, PyString_FromString(buf));
4425 return result;
4426}
4427
4428/* Miscellaneous methods. */
4429
4430/* Note: tp_richcompare and tp_hash are inherited from datetime. */
4431
4432static PyObject *
Tim Peters12bf3392002-12-24 05:41:27 +00004433datetimetz_replace(PyDateTime_DateTimeTZ *self, PyObject *args, PyObject *kw)
4434{
4435 PyObject *clone;
4436 PyObject *tuple;
4437 int y = GET_YEAR(self);
4438 int m = GET_MONTH(self);
4439 int d = GET_DAY(self);
4440 int hh = DATE_GET_HOUR(self);
4441 int mm = DATE_GET_MINUTE(self);
4442 int ss = DATE_GET_SECOND(self);
4443 int us = DATE_GET_MICROSECOND(self);
4444 PyObject *tzinfo = self->tzinfo;
4445
4446 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO:replace",
4447 datetimetz_kws,
4448 &y, &m, &d, &hh, &mm, &ss, &us,
4449 &tzinfo))
4450 return NULL;
4451 tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
4452 if (tuple == NULL)
4453 return NULL;
4454 clone = datetimetz_new(self->ob_type, tuple, NULL);
4455 Py_DECREF(tuple);
4456 return clone;
4457}
4458
4459static PyObject *
Tim Peters80475bb2002-12-25 07:40:55 +00004460datetimetz_astimezone(PyDateTime_DateTimeTZ *self, PyObject *args,
4461 PyObject *kw)
4462{
4463 int y = GET_YEAR(self);
4464 int m = GET_MONTH(self);
4465 int d = GET_DAY(self);
4466 int hh = DATE_GET_HOUR(self);
4467 int mm = DATE_GET_MINUTE(self);
4468 int ss = DATE_GET_SECOND(self);
4469 int us = DATE_GET_MICROSECOND(self);
4470
Tim Peters521fc152002-12-31 17:36:56 +00004471 PyObject *result;
4472 PyObject *temp;
Tim Petersadf64202003-01-04 06:03:15 +00004473 int selfoff, resoff, dst1, dst2;
Tim Peters521fc152002-12-31 17:36:56 +00004474 int none;
Tim Petersf3615152003-01-01 21:51:37 +00004475 int delta;
Tim Peters521fc152002-12-31 17:36:56 +00004476
Tim Peters80475bb2002-12-25 07:40:55 +00004477 PyObject *tzinfo;
4478 static char *keywords[] = {"tz", NULL};
4479
4480 if (! PyArg_ParseTupleAndKeywords(args, kw, "O:astimezone", keywords,
4481 &tzinfo))
4482 return NULL;
4483 if (check_tzinfo_subclass(tzinfo) < 0)
4484 return NULL;
4485
Tim Peters521fc152002-12-31 17:36:56 +00004486 /* Don't call utcoffset unless necessary. */
4487 result = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4488 if (result == NULL ||
4489 tzinfo == Py_None ||
4490 self->tzinfo == Py_None ||
4491 self->tzinfo == tzinfo)
4492 return result;
4493
4494 /* Get the offsets. If either object turns out to be naive, again
4495 * there's no conversion of date or time fields.
4496 */
Tim Petersb5a16f32003-01-01 04:48:01 +00004497 selfoff = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4498 if (selfoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004499 goto Fail;
4500 if (none)
4501 return result;
4502
Tim Petersb5a16f32003-01-01 04:48:01 +00004503 resoff = call_utcoffset(tzinfo, result, &none);
4504 if (resoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004505 goto Fail;
4506 if (none)
4507 return result;
4508
Tim Petersf3615152003-01-01 21:51:37 +00004509 /* See the long comment block at the end of this file for an
4510 * explanation of this algorithm. That it always works requires a
Tim Petersadf64202003-01-04 06:03:15 +00004511 * pretty intricate proof. There are many equivalent ways to code
4512 * up the proof as an algorithm. This way favors calling dst() over
4513 * calling utcoffset(), because "the usual" utcoffset() calls dst()
4514 * itself, and calling the latter instead saves a Python-level
4515 * function call. This way of coding it also follows the proof
4516 * closely, w/ x=self, y=result, z=result, and z'=temp.
Tim Peters521fc152002-12-31 17:36:56 +00004517 */
Tim Petersadf64202003-01-04 06:03:15 +00004518 dst1 = call_dst(tzinfo, result, &none);
4519 if (dst1 == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004520 goto Fail;
Tim Peters710fb152003-01-02 19:35:54 +00004521 if (none) {
4522 PyErr_SetString(PyExc_ValueError, "astimezone(): utcoffset() "
4523 "returned a duration but dst() returned None");
4524 goto Fail;
4525 }
Tim Petersadf64202003-01-04 06:03:15 +00004526 delta = resoff - dst1 - selfoff;
4527 if (delta) {
4528 mm += delta;
Tim Petersb5a16f32003-01-01 04:48:01 +00004529 if ((mm < 0 || mm >= 60) &&
4530 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters521fc152002-12-31 17:36:56 +00004531 goto Fail;
4532 temp = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4533 if (temp == NULL)
4534 goto Fail;
4535 Py_DECREF(result);
4536 result = temp;
4537
Tim Petersadf64202003-01-04 06:03:15 +00004538 dst1 = call_dst(tzinfo, result, &none);
4539 if (dst1 == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004540 goto Fail;
4541 if (none)
4542 goto Inconsistent;
Tim Petersf3615152003-01-01 21:51:37 +00004543 }
Tim Petersadf64202003-01-04 06:03:15 +00004544 if (dst1 == 0)
Tim Petersf3615152003-01-01 21:51:37 +00004545 return result;
4546
Tim Petersadf64202003-01-04 06:03:15 +00004547 mm += dst1;
Tim Petersf3615152003-01-01 21:51:37 +00004548 if ((mm < 0 || mm >= 60) &&
4549 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters521fc152002-12-31 17:36:56 +00004550 goto Fail;
4551 temp = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4552 if (temp == NULL)
4553 goto Fail;
Tim Peters521fc152002-12-31 17:36:56 +00004554
Tim Petersadf64202003-01-04 06:03:15 +00004555 dst2 = call_dst(tzinfo, temp, &none);
4556 if (dst2 == -1 && PyErr_Occurred()) {
4557 Py_DECREF(temp);
Tim Petersf3615152003-01-01 21:51:37 +00004558 goto Fail;
Tim Petersadf64202003-01-04 06:03:15 +00004559 }
4560 if (none) {
4561 Py_DECREF(temp);
Tim Petersf3615152003-01-01 21:51:37 +00004562 goto Inconsistent;
Tim Petersadf64202003-01-04 06:03:15 +00004563 }
Tim Petersf3615152003-01-01 21:51:37 +00004564
Tim Petersadf64202003-01-04 06:03:15 +00004565 if (dst1 == dst2) {
4566 /* The normal case: we want temp, not result. */
4567 Py_DECREF(result);
4568 result = temp;
4569 }
4570 else {
4571 /* The "unspellable hour" at the end of DST. */
4572 Py_DECREF(temp);
4573 }
4574 return result;
Tim Peters521fc152002-12-31 17:36:56 +00004575
4576Inconsistent:
Tim Petersadf64202003-01-04 06:03:15 +00004577 PyErr_SetString(PyExc_ValueError, "astimezone(): tz.dst() gave"
4578 "inconsistent results; cannot convert");
Tim Peters521fc152002-12-31 17:36:56 +00004579
4580 /* fall thru to failure */
4581Fail:
4582 Py_DECREF(result);
4583 return NULL;
Tim Peters80475bb2002-12-25 07:40:55 +00004584}
4585
4586static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00004587datetimetz_timetuple(PyDateTime_DateTimeTZ *self)
4588{
4589 int dstflag = -1;
4590
4591 if (self->tzinfo != Py_None) {
4592 int none;
4593
4594 dstflag = call_dst(self->tzinfo, (PyObject *)self, &none);
4595 if (dstflag == -1 && PyErr_Occurred())
4596 return NULL;
4597
4598 if (none)
4599 dstflag = -1;
4600 else if (dstflag != 0)
4601 dstflag = 1;
4602
4603 }
4604 return build_struct_time(GET_YEAR(self),
4605 GET_MONTH(self),
4606 GET_DAY(self),
4607 DATE_GET_HOUR(self),
4608 DATE_GET_MINUTE(self),
4609 DATE_GET_SECOND(self),
4610 dstflag);
4611}
4612
4613static PyObject *
4614datetimetz_utctimetuple(PyDateTime_DateTimeTZ *self)
4615{
4616 int y = GET_YEAR(self);
4617 int m = GET_MONTH(self);
4618 int d = GET_DAY(self);
4619 int hh = DATE_GET_HOUR(self);
4620 int mm = DATE_GET_MINUTE(self);
4621 int ss = DATE_GET_SECOND(self);
4622 int us = 0; /* microseconds are ignored in a timetuple */
4623 int offset = 0;
4624
4625 if (self->tzinfo != Py_None) {
4626 int none;
4627
4628 offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4629 if (offset == -1 && PyErr_Occurred())
4630 return NULL;
4631 }
4632 /* Even if offset is 0, don't call timetuple() -- tm_isdst should be
4633 * 0 in a UTC timetuple regardless of what dst() says.
4634 */
4635 if (offset) {
4636 /* Subtract offset minutes & normalize. */
4637 int stat;
4638
4639 mm -= offset;
4640 stat = normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us);
4641 if (stat < 0) {
4642 /* At the edges, it's possible we overflowed
4643 * beyond MINYEAR or MAXYEAR.
4644 */
4645 if (PyErr_ExceptionMatches(PyExc_OverflowError))
4646 PyErr_Clear();
4647 else
4648 return NULL;
4649 }
4650 }
4651 return build_struct_time(y, m, d, hh, mm, ss, 0);
4652}
4653
4654static PyObject *
4655datetimetz_gettimetz(PyDateTime_DateTimeTZ *self)
4656{
Tim Peters37f39822003-01-10 03:49:02 +00004657 return new_time(DATE_GET_HOUR(self),
4658 DATE_GET_MINUTE(self),
4659 DATE_GET_SECOND(self),
4660 DATE_GET_MICROSECOND(self),
4661 self->tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00004662}
4663
4664/*
4665 * Pickle support. Quite a maze!
4666 */
4667
Tim Peters33e0f382003-01-10 02:05:14 +00004668
4669/* Pickle support. Quite a maze! */
4670
4671/* Let basestate be the state string returned by the date & time fields.
Tim Peters2a799bf2002-12-16 20:18:38 +00004672 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4673 * So it's a tuple in any (non-error) case.
4674 */
4675static PyObject *
4676datetimetz_getstate(PyDateTime_DateTimeTZ *self)
4677{
4678 PyObject *basestate;
4679 PyObject *result = NULL;
4680
Tim Peters33e0f382003-01-10 02:05:14 +00004681 basestate = PyString_FromStringAndSize((char *)self->data,
4682 _PyDateTime_DATETIME_DATASIZE);
Tim Peters2a799bf2002-12-16 20:18:38 +00004683 if (basestate != NULL) {
4684 if (self->tzinfo == Py_None)
4685 result = Py_BuildValue("(O)", basestate);
4686 else
4687 result = Py_BuildValue("OO", basestate, self->tzinfo);
4688 Py_DECREF(basestate);
4689 }
4690 return result;
4691}
4692
4693static PyObject *
4694datetimetz_setstate(PyDateTime_DateTimeTZ *self, PyObject *state)
4695{
Tim Peters2a799bf2002-12-16 20:18:38 +00004696 PyObject *basestate;
4697 PyObject *tzinfo = Py_None;
4698
4699 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
4700 &PyString_Type, &basestate,
4701 &tzinfo))
4702 return NULL;
Tim Peters33e0f382003-01-10 02:05:14 +00004703 if (PyString_Size(basestate) != _PyDateTime_DATETIME_DATASIZE ||
4704 check_tzinfo_subclass(tzinfo) < 0) {
4705 PyErr_SetString(PyExc_TypeError,
4706 "bad argument to datetime.__setstate__");
Tim Peters2a799bf2002-12-16 20:18:38 +00004707 return NULL;
Tim Peters33e0f382003-01-10 02:05:14 +00004708 }
4709 memcpy((char *)self->data,
4710 PyString_AsString(basestate),
4711 _PyDateTime_DATETIME_DATASIZE);
4712 self->hashcode = -1;
4713 replace_tzinfo((PyObject *)self, tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00004714 Py_INCREF(Py_None);
4715 return Py_None;
4716}
4717
4718static PyObject *
4719datetimetz_pickler(PyObject *module, PyDateTime_DateTimeTZ *datetimetz)
4720{
4721 PyObject *state;
4722 PyObject *result = NULL;
4723
4724 if (! PyDateTimeTZ_CheckExact(datetimetz)) {
4725 PyErr_Format(PyExc_TypeError,
4726 "bad type passed to datetimetz pickler: %s",
4727 datetimetz->ob_type->tp_name);
4728 return NULL;
4729 }
4730 state = datetimetz_getstate(datetimetz);
4731 if (state) {
4732 result = Py_BuildValue("O(O)",
4733 datetimetz_unpickler_object,
4734 state);
4735 Py_DECREF(state);
4736 }
4737 return result;
4738}
4739
4740static PyObject *
4741datetimetz_unpickler(PyObject *module, PyObject *arg)
4742{
4743 PyDateTime_DateTimeTZ *self;
4744
4745 self = PyObject_New(PyDateTime_DateTimeTZ, &PyDateTime_DateTimeTZType);
4746 if (self != NULL) {
4747 PyObject *res;
4748
4749 self->tzinfo = NULL;
4750 res = datetimetz_setstate(self, arg);
4751 if (res == NULL) {
4752 Py_DECREF(self);
4753 return NULL;
4754 }
4755 Py_DECREF(res);
4756 }
4757 return (PyObject *)self;
4758}
4759
4760
4761static PyMethodDef datetimetz_methods[] = {
4762 /* Class methods: */
4763 /* Inherited: combine(), utcnow(), utcfromtimestamp() */
4764
4765 {"now", (PyCFunction)datetimetz_now,
4766 METH_KEYWORDS | METH_CLASS,
4767 PyDoc_STR("[tzinfo] -> new datetimetz with local day and time.")},
4768
4769 {"fromtimestamp", (PyCFunction)datetimetz_fromtimestamp,
4770 METH_KEYWORDS | METH_CLASS,
4771 PyDoc_STR("timestamp[, tzinfo] -> local time from POSIX timestamp.")},
4772
4773 /* Instance methods: */
4774 /* Inherited: date(), time(), ctime(). */
4775 {"timetuple", (PyCFunction)datetimetz_timetuple, METH_NOARGS,
4776 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
4777
4778 {"utctimetuple", (PyCFunction)datetimetz_utctimetuple, METH_NOARGS,
4779 PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")},
4780
4781 {"timetz", (PyCFunction)datetimetz_gettimetz, METH_NOARGS,
4782 PyDoc_STR("Return timetz object with same hour, minute, second, "
4783 "microsecond, and tzinfo.")},
4784
4785 {"isoformat", (PyCFunction)datetimetz_isoformat, METH_KEYWORDS,
4786 PyDoc_STR("[sep] -> string in ISO 8601 format, "
4787 "YYYY-MM-DDTHH:MM:SS[.mmmmmm][+HH:MM].\n\n"
4788 "sep is used to separate the year from the time, and "
4789 "defaults to 'T'.")},
4790
4791 {"utcoffset", (PyCFunction)datetimetz_utcoffset, METH_NOARGS,
4792 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
4793
4794 {"tzname", (PyCFunction)datetimetz_tzname, METH_NOARGS,
4795 PyDoc_STR("Return self.tzinfo.tzname(self).")},
4796
4797 {"dst", (PyCFunction)datetimetz_dst, METH_NOARGS,
4798 PyDoc_STR("Return self.tzinfo.dst(self).")},
4799
Tim Peters12bf3392002-12-24 05:41:27 +00004800 {"replace", (PyCFunction)datetimetz_replace, METH_KEYWORDS,
4801 PyDoc_STR("Return datetimetz with new specified fields.")},
4802
Tim Peters80475bb2002-12-25 07:40:55 +00004803 {"astimezone", (PyCFunction)datetimetz_astimezone, METH_KEYWORDS,
4804 PyDoc_STR("tz -> convert to local time in new timezone tz\n")},
4805
Tim Peters2a799bf2002-12-16 20:18:38 +00004806 {"__setstate__", (PyCFunction)datetimetz_setstate, METH_O,
4807 PyDoc_STR("__setstate__(state)")},
4808
4809 {"__getstate__", (PyCFunction)datetimetz_getstate, METH_NOARGS,
4810 PyDoc_STR("__getstate__() -> state")},
4811 {NULL, NULL}
4812};
4813
4814static char datetimetz_doc[] =
4815PyDoc_STR("date/time type.");
4816
4817static PyNumberMethods datetimetz_as_number = {
4818 datetimetz_add, /* nb_add */
4819 datetimetz_subtract, /* nb_subtract */
4820 0, /* nb_multiply */
4821 0, /* nb_divide */
4822 0, /* nb_remainder */
4823 0, /* nb_divmod */
4824 0, /* nb_power */
4825 0, /* nb_negative */
4826 0, /* nb_positive */
4827 0, /* nb_absolute */
4828 0, /* nb_nonzero */
4829};
4830
4831statichere PyTypeObject PyDateTime_DateTimeTZType = {
4832 PyObject_HEAD_INIT(NULL)
4833 0, /* ob_size */
Tim Peters0bf60bd2003-01-08 20:40:01 +00004834 "datetime.datetime", /* tp_name */
Tim Peters2a799bf2002-12-16 20:18:38 +00004835 sizeof(PyDateTime_DateTimeTZ), /* tp_basicsize */
4836 0, /* tp_itemsize */
4837 (destructor)datetimetz_dealloc, /* tp_dealloc */
4838 0, /* tp_print */
4839 0, /* tp_getattr */
4840 0, /* tp_setattr */
4841 0, /* tp_compare */
4842 (reprfunc)datetimetz_repr, /* tp_repr */
4843 &datetimetz_as_number, /* tp_as_number */
4844 0, /* tp_as_sequence */
4845 0, /* tp_as_mapping */
4846 0, /* tp_hash */
4847 0, /* tp_call */
4848 0, /* tp_str */
4849 PyObject_GenericGetAttr, /* tp_getattro */
4850 0, /* tp_setattro */
4851 0, /* tp_as_buffer */
4852 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4853 Py_TPFLAGS_BASETYPE, /* tp_flags */
4854 datetimetz_doc, /* tp_doc */
4855 0, /* tp_traverse */
4856 0, /* tp_clear */
4857 0, /* tp_richcompare */
4858 0, /* tp_weaklistoffset */
4859 0, /* tp_iter */
4860 0, /* tp_iternext */
4861 datetimetz_methods, /* tp_methods */
4862 0, /* tp_members */
4863 datetimetz_getset, /* tp_getset */
4864 &PyDateTime_DateTimeType, /* tp_base */
4865 0, /* tp_dict */
4866 0, /* tp_descr_get */
4867 0, /* tp_descr_set */
4868 0, /* tp_dictoffset */
4869 0, /* tp_init */
4870 0, /* tp_alloc */
4871 datetimetz_new, /* tp_new */
4872 _PyObject_Del, /* tp_free */
4873};
4874
4875/* ---------------------------------------------------------------------------
4876 * Module methods and initialization.
4877 */
4878
4879static PyMethodDef module_methods[] = {
4880 /* Private functions for pickling support, registered with the
4881 * copy_reg module by the module init function.
4882 */
4883 {"_date_pickler", (PyCFunction)date_pickler, METH_O, NULL},
4884 {"_date_unpickler", (PyCFunction)date_unpickler, METH_O, NULL},
Tim Peters2a799bf2002-12-16 20:18:38 +00004885 {"_datetimetz_pickler", (PyCFunction)datetimetz_pickler,METH_O, NULL},
4886 {"_datetimetz_unpickler",(PyCFunction)datetimetz_unpickler,METH_O, NULL},
Tim Peters37f39822003-01-10 03:49:02 +00004887 {"_time_pickler", (PyCFunction)time_pickler, METH_O, NULL},
4888 {"_time_unpickler", (PyCFunction)time_unpickler, METH_O, NULL},
Tim Peters2a799bf2002-12-16 20:18:38 +00004889 {"_tzinfo_pickler", (PyCFunction)tzinfo_pickler, METH_O, NULL},
4890 {"_tzinfo_unpickler", (PyCFunction)tzinfo_unpickler, METH_NOARGS,
4891 NULL},
4892 {NULL, NULL}
4893};
4894
4895PyMODINIT_FUNC
4896initdatetime(void)
4897{
4898 PyObject *m; /* a module object */
4899 PyObject *d; /* its dict */
4900 PyObject *x;
4901
4902 /* Types that use __reduce__ for pickling need to set the following
4903 * magical attr in the type dict, with a true value.
4904 */
4905 PyObject *safepickle = PyString_FromString("__safe_for_unpickling__");
4906 if (safepickle == NULL)
4907 return;
4908
4909 m = Py_InitModule3("datetime", module_methods,
4910 "Fast implementation of the datetime type.");
4911
4912 if (PyType_Ready(&PyDateTime_DateType) < 0)
4913 return;
4914 if (PyType_Ready(&PyDateTime_DateTimeType) < 0)
4915 return;
4916 if (PyType_Ready(&PyDateTime_DeltaType) < 0)
4917 return;
4918 if (PyType_Ready(&PyDateTime_TimeType) < 0)
4919 return;
4920 if (PyType_Ready(&PyDateTime_TZInfoType) < 0)
4921 return;
Tim Peters2a799bf2002-12-16 20:18:38 +00004922 if (PyType_Ready(&PyDateTime_DateTimeTZType) < 0)
4923 return;
4924
4925 /* Pickling support, via registering functions with copy_reg. */
4926 {
4927 PyObject *pickler;
4928 PyObject *copyreg = PyImport_ImportModule("copy_reg");
4929
4930 if (copyreg == NULL) return;
4931
4932 pickler = PyObject_GetAttrString(m, "_date_pickler");
4933 if (pickler == NULL) return;
4934 date_unpickler_object = PyObject_GetAttrString(m,
4935 "_date_unpickler");
4936 if (date_unpickler_object == NULL) return;
4937 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
4938 &PyDateTime_DateType,
4939 pickler,
4940 date_unpickler_object);
4941 if (x == NULL) return;
4942 Py_DECREF(x);
4943 Py_DECREF(pickler);
4944
Tim Peters37f39822003-01-10 03:49:02 +00004945 pickler = PyObject_GetAttrString(m, "_time_pickler");
Tim Peters2a799bf2002-12-16 20:18:38 +00004946 if (pickler == NULL) return;
Tim Peters37f39822003-01-10 03:49:02 +00004947 time_unpickler_object = PyObject_GetAttrString(m,
4948 "_time_unpickler");
4949 if (time_unpickler_object == NULL) return;
Tim Peters2a799bf2002-12-16 20:18:38 +00004950 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
Tim Peters37f39822003-01-10 03:49:02 +00004951 &PyDateTime_TimeType,
Tim Peters2a799bf2002-12-16 20:18:38 +00004952 pickler,
Tim Peters37f39822003-01-10 03:49:02 +00004953 time_unpickler_object);
Tim Peters2a799bf2002-12-16 20:18:38 +00004954 if (x == NULL) return;
4955 Py_DECREF(x);
4956 Py_DECREF(pickler);
4957
4958 pickler = PyObject_GetAttrString(m, "_tzinfo_pickler");
4959 if (pickler == NULL) return;
4960 tzinfo_unpickler_object = PyObject_GetAttrString(m,
4961 "_tzinfo_unpickler");
4962 if (tzinfo_unpickler_object == NULL) return;
4963 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
4964 &PyDateTime_TZInfoType,
4965 pickler,
4966 tzinfo_unpickler_object);
4967 if (x== NULL) return;
4968 Py_DECREF(x);
4969 Py_DECREF(pickler);
4970
4971 pickler = PyObject_GetAttrString(m, "_datetimetz_pickler");
4972 if (pickler == NULL) return;
4973 datetimetz_unpickler_object = PyObject_GetAttrString(m,
4974 "_datetimetz_unpickler");
4975 if (datetimetz_unpickler_object == NULL) return;
4976 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
4977 &PyDateTime_DateTimeTZType,
4978 pickler,
4979 datetimetz_unpickler_object);
4980 if (x== NULL) return;
4981 Py_DECREF(x);
4982 Py_DECREF(pickler);
4983
4984 Py_DECREF(copyreg);
4985 }
4986
4987 /* timedelta values */
4988 d = PyDateTime_DeltaType.tp_dict;
4989
4990 if (PyDict_SetItem(d, safepickle, Py_True) < 0)
4991 return;
4992
4993 x = new_delta(0, 0, 1, 0);
4994 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
4995 return;
4996 Py_DECREF(x);
4997
4998 x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0);
4999 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5000 return;
5001 Py_DECREF(x);
5002
5003 x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0);
5004 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5005 return;
5006 Py_DECREF(x);
5007
5008 /* date values */
5009 d = PyDateTime_DateType.tp_dict;
5010
5011 x = new_date(1, 1, 1);
5012 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5013 return;
5014 Py_DECREF(x);
5015
5016 x = new_date(MAXYEAR, 12, 31);
5017 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5018 return;
5019 Py_DECREF(x);
5020
5021 x = new_delta(1, 0, 0, 0);
5022 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5023 return;
5024 Py_DECREF(x);
5025
Tim Peters37f39822003-01-10 03:49:02 +00005026 /* time values */
5027 d = PyDateTime_TimeType.tp_dict;
Tim Peters2a799bf2002-12-16 20:18:38 +00005028
Tim Peters37f39822003-01-10 03:49:02 +00005029 x = new_time(0, 0, 0, 0, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00005030 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5031 return;
5032 Py_DECREF(x);
5033
Tim Peters37f39822003-01-10 03:49:02 +00005034 x = new_time(23, 59, 59, 999999, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00005035 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5036 return;
5037 Py_DECREF(x);
5038
5039 x = new_delta(0, 0, 1, 0);
5040 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5041 return;
5042 Py_DECREF(x);
5043
5044 /* datetimetz values */
5045 d = PyDateTime_DateTimeTZType.tp_dict;
5046
5047 x = new_datetimetz(1, 1, 1, 0, 0, 0, 0, Py_None);
5048 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5049 return;
5050 Py_DECREF(x);
5051
5052 x = new_datetimetz(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None);
5053 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5054 return;
5055 Py_DECREF(x);
5056
5057 x = new_delta(0, 0, 1, 0);
5058 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5059 return;
5060 Py_DECREF(x);
5061
5062 Py_DECREF(safepickle);
5063
5064 /* module initialization */
5065 PyModule_AddIntConstant(m, "MINYEAR", MINYEAR);
5066 PyModule_AddIntConstant(m, "MAXYEAR", MAXYEAR);
5067
5068 Py_INCREF(&PyDateTime_DateType);
5069 PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType);
5070
Tim Peters2a799bf2002-12-16 20:18:38 +00005071 Py_INCREF(&PyDateTime_DeltaType);
5072 PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType);
5073
Tim Peters2a799bf2002-12-16 20:18:38 +00005074 Py_INCREF(&PyDateTime_TZInfoType);
5075 PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
5076
Tim Peters37f39822003-01-10 03:49:02 +00005077 Py_INCREF(&PyDateTime_TimeType);
5078 PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType);
Tim Peters2a799bf2002-12-16 20:18:38 +00005079
5080 Py_INCREF(&PyDateTime_DateTimeTZType);
Tim Peters0bf60bd2003-01-08 20:40:01 +00005081 PyModule_AddObject(m, "datetime",
Tim Peters2a799bf2002-12-16 20:18:38 +00005082 (PyObject *)&PyDateTime_DateTimeTZType);
5083
5084 /* A 4-year cycle has an extra leap day over what we'd get from
5085 * pasting together 4 single years.
5086 */
5087 assert(DI4Y == 4 * 365 + 1);
5088 assert(DI4Y == days_before_year(4+1));
5089
5090 /* Similarly, a 400-year cycle has an extra leap day over what we'd
5091 * get from pasting together 4 100-year cycles.
5092 */
5093 assert(DI400Y == 4 * DI100Y + 1);
5094 assert(DI400Y == days_before_year(400+1));
5095
5096 /* OTOH, a 100-year cycle has one fewer leap day than we'd get from
5097 * pasting together 25 4-year cycles.
5098 */
5099 assert(DI100Y == 25 * DI4Y - 1);
5100 assert(DI100Y == days_before_year(100+1));
5101
5102 us_per_us = PyInt_FromLong(1);
5103 us_per_ms = PyInt_FromLong(1000);
5104 us_per_second = PyInt_FromLong(1000000);
5105 us_per_minute = PyInt_FromLong(60000000);
5106 seconds_per_day = PyInt_FromLong(24 * 3600);
5107 if (us_per_us == NULL || us_per_ms == NULL || us_per_second == NULL ||
5108 us_per_minute == NULL || seconds_per_day == NULL)
5109 return;
5110
5111 /* The rest are too big for 32-bit ints, but even
5112 * us_per_week fits in 40 bits, so doubles should be exact.
5113 */
5114 us_per_hour = PyLong_FromDouble(3600000000.0);
5115 us_per_day = PyLong_FromDouble(86400000000.0);
5116 us_per_week = PyLong_FromDouble(604800000000.0);
5117 if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL)
5118 return;
5119}
Tim Petersf3615152003-01-01 21:51:37 +00005120
5121/* ---------------------------------------------------------------------------
5122Some time zone algebra. For a datetimetz x, let
5123 x.n = x stripped of its timezone -- its naive time.
5124 x.o = x.utcoffset(), and assuming that doesn't raise an exception or
5125 return None
5126 x.d = x.dst(), and assuming that doesn't raise an exception or
5127 return None
5128 x.s = x's standard offset, x.o - x.d
5129
5130Now some derived rules, where k is a duration (timedelta).
5131
51321. x.o = x.s + x.d
5133 This follows from the definition of x.s.
5134
Tim Petersc5dc4da2003-01-02 17:55:03 +000051352. If x and y have the same tzinfo member, x.s = y.s.
Tim Petersf3615152003-01-01 21:51:37 +00005136 This is actually a requirement, an assumption we need to make about
5137 sane tzinfo classes.
5138
51393. The naive UTC time corresponding to x is x.n - x.o.
5140 This is again a requirement for a sane tzinfo class.
5141
51424. (x+k).s = x.s
5143 This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
5144
Tim Petersc5dc4da2003-01-02 17:55:03 +000051455. (x+k).n = x.n + k
Tim Petersf3615152003-01-01 21:51:37 +00005146 Again follows from how arithmetic is defined.
5147
5148Now we can explain x.astimezone(tz). Let's assume it's an interesting case
5149(meaning that the various tzinfo methods exist, and don't blow up or return
5150None when called).
5151
5152The function wants to return a datetimetz y with timezone tz, equivalent to x.
5153
5154By #3, we want
5155
5156 y.n - y.o = x.n - x.o [1]
5157
5158The algorithm starts by attaching tz to x.n, and calling that y. So
5159x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
5160becomes true; in effect, we want to solve [2] for k:
5161
5162 (y+k).n - (y+k).o = x.n - x.o [2]
5163
5164By #1, this is the same as
5165
5166 (y+k).n - ((y+k).s + (y+k).d) = x.n - x.o [3]
5167
5168By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
5169Substituting that into [3],
5170
5171 x.n + k - (y+k).s - (y+k).d = x.n - x.o; the x.n terms cancel, leaving
5172 k - (y+k).s - (y+k).d = - x.o; rearranging,
5173 k = (y+k).s - x.o - (y+k).d; by #4, (y+k).s == y.s, so
5174 k = y.s - x.o - (y+k).d; then by #1, y.s = y.o - y.d, so
5175 k = y.o - y.d - x.o - (y+k).d
5176
5177On the RHS, (y+k).d can't be computed directly, but all the rest can be, and
5178we approximate k by ignoring the (y+k).d term at first. Note that k can't
5179be very large, since all offset-returning methods return a duration of
5180magnitude less than 24 hours. For that reason, if y is firmly in std time,
5181(y+k).d must be 0, so ignoring it has no consequence then.
5182
5183In any case, the new value is
5184
Tim Petersc5dc4da2003-01-02 17:55:03 +00005185 z = y + y.o - y.d - x.o [4]
Tim Petersf3615152003-01-01 21:51:37 +00005186
Tim Petersc5dc4da2003-01-02 17:55:03 +00005187It's helpful to step back at look at [4] from a higher level: rewrite it as
Tim Petersf3615152003-01-01 21:51:37 +00005188
Tim Petersc5dc4da2003-01-02 17:55:03 +00005189 z = (y - x.o) + (y.o - y.d)
5190
5191(y - x.o).n = [by #5] y.n - x.o = [since y.n=x.n] x.n - x.o = [by #3] x's
5192UTC equivalent time. So the y-x.o part essentially converts x to UTC. Then
5193the y.o-y.d part essentially converts x's UTC equivalent into tz's standard
5194time (y.o-y.d=y.s by #1).
5195
5196At this point, if
5197
5198 z.n - z.o = x.n - x.o [5]
5199
5200we have an equivalent time, and are almost done. The insecurity here is
Tim Petersf3615152003-01-01 21:51:37 +00005201at the start of daylight time. Picture US Eastern for concreteness. The wall
5202time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
5203sense then. A sensible Eastern tzinfo class will consider such a time to be
5204EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST on the
5205day DST starts. We want to return the 1:MM EST spelling because that's
5206the only spelling that makes sense on the local wall clock.
5207
Tim Petersc5dc4da2003-01-02 17:55:03 +00005208In fact, if [5] holds at this point, we do have the standard-time spelling,
5209but that takes a bit of proof. We first prove a stronger result. What's the
5210difference between the LHS and RHS of [5]? Let
Tim Petersf3615152003-01-01 21:51:37 +00005211
Tim Petersc5dc4da2003-01-02 17:55:03 +00005212 diff = (x.n - x.o) - (z.n - z.o) [6]
Tim Petersf3615152003-01-01 21:51:37 +00005213
Tim Petersc5dc4da2003-01-02 17:55:03 +00005214Now
5215 z.n = by [4]
5216 (y + y.o - y.d - x.o).n = by #5
5217 y.n + y.o - y.d - x.o = since y.n = x.n
5218 x.n + y.o - y.d - x.o = since y.o = y.s + y.d by #1
5219 x.n + (y.s + y.d) - y.d - x.o = cancelling the y.d terms
5220 x.n + y.s - x.o = since z and y are have the same tzinfo member,
5221 y.s = z.s by #2
5222 x.n + z.s - x.o
Tim Petersf3615152003-01-01 21:51:37 +00005223
Tim Petersc5dc4da2003-01-02 17:55:03 +00005224Plugging that back into [6] gives
Tim Petersf3615152003-01-01 21:51:37 +00005225
Tim Petersc5dc4da2003-01-02 17:55:03 +00005226 diff =
5227 (x.n - x.o) - ((x.n + z.s - x.o) - z.o) = expanding
5228 x.n - x.o - x.n - z.s + x.o + z.o = cancelling
5229 - z.s + z.o = by #2
5230 z.d
Tim Petersf3615152003-01-01 21:51:37 +00005231
Tim Petersc5dc4da2003-01-02 17:55:03 +00005232So diff = z.d.
Tim Petersf3615152003-01-01 21:51:37 +00005233
Tim Petersc5dc4da2003-01-02 17:55:03 +00005234If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
5235spelling we wanted in the endcase described above. We're done.
Tim Petersf3615152003-01-01 21:51:37 +00005236
Tim Petersc5dc4da2003-01-02 17:55:03 +00005237If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
5238add to z (in effect, z is in tz's standard time, and we need to shift the
5239offset into tz's daylight time).
Tim Petersf3615152003-01-01 21:51:37 +00005240
Tim Petersc5dc4da2003-01-02 17:55:03 +00005241Let
Tim Petersf3615152003-01-01 21:51:37 +00005242
Tim Peters4fede1a2003-01-04 00:26:59 +00005243 z' = z + z.d = z + diff [7]
Tim Petersc3bb26a2003-01-02 03:14:59 +00005244
Tim Peters4fede1a2003-01-04 00:26:59 +00005245and we can again ask whether
Tim Petersc3bb26a2003-01-02 03:14:59 +00005246
Tim Peters4fede1a2003-01-04 00:26:59 +00005247 z'.n - z'.o = x.n - x.o [8]
Tim Petersc3bb26a2003-01-02 03:14:59 +00005248
5249If so, we're done. If not, the tzinfo class is insane, or we're trying to
Tim Peters4fede1a2003-01-04 00:26:59 +00005250convert to the hour that can't be spelled in tz. This also requires a
5251bit of proof. As before, let's compute the difference between the LHS and
5252RHS of [8] (and skipping some of the justifications for the kinds of
5253substitutions we've done several times already):
5254
5255 diff' = (x.n - x.o) - (z'.n - z'.o) = replacing z'.n via [7]
5256 (x.n - x.o) - (z.n + diff - z'.o) = replacing diff via [6]
5257 (x.n - x.o) - (z.n + (x.n - x.o) - (z.n - z.o) - z'.o) =
5258 x.n - x.o - z.n - x.n + x.o + z.n - z.o + z'.o = cancel x.n
5259 - x.o - z.n + x.o + z.n - z.o + z'.o = cancel x.o
5260 - z.n + z.n - z.o + z'.o = cancel z.n
5261 - z.o + z'.o = #1 twice
5262 -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
5263 z'.d - z.d
5264
5265So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
5266we've found the UTC-equivalent so are done.
5267
5268How could they differ? z' = z + z.d [7], so merely moving z' by a dst()
5269offset, and starting *from* a time already in DST (we know z.d != 0), would
5270have to change the result dst() returns: we start in DST, and moving a
5271little further into it takes us out of DST.
5272
5273There's (only) one sane case where this can happen: at the end of DST,
5274there's an hour in UTC with no spelling in a hybrid tzinfo class. In US
5275Eastern, that's 6:MM UTC = 1:MM EST = 2:MM EDT. During that hour, on an
5276Eastern clock 1:MM is taken as being in daylight time (5:MM UTC), but 2:MM is
5277taken as being in standard time (7:MM UTC). There is no local time mapping to
52786:MM UTC. The local clock jumps from 1:59 back to 1:00 again, and repeats the
52791:MM hour in standard time. Since that's what the local clock *does*, we want
5280to map both UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
5281in local time, but so it goes -- it's the way the local clock works.
5282
5283When x = 6:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
5284so z=1:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
5285z' = z + z.d = 2:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
5286(correctly) concludes that z' is not UTC-equivalent to x.
5287
5288Because we know z.d said z was in daylight time (else [5] would have held and
5289we would have stopped then), and we know z.d != z'.d (else [8] would have held
5290and we we have stopped then), and there are only 2 possible values dst() can
5291return in Eastern, it follows that z'.d must be 0 (which it is in the example,
5292but the reasoning doesn't depend on the example -- it depends on there being
5293two possible dst() outcomes, one zero and the other non-zero). Therefore
5294z' must be in standard time, and is not the spelling we want in this case.
5295z is in daylight time, and is the spelling we want. Note again that z is
5296not UTC-equivalent as far as the hybrid tzinfo class is concerned (because
5297it takes z as being in standard time rather than the daylight time we intend
5298here), but returning it gives the real-life "local clock repeats an hour"
5299behavior when mapping the "unspellable" UTC hour into tz.
Tim Petersf3615152003-01-01 21:51:37 +00005300--------------------------------------------------------------------------- */