blob: 2755f72f6aaf239db87d68494e856c13a01221f1 [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
78/* Forward declarations. */
79static PyTypeObject PyDateTime_DateType;
80static PyTypeObject PyDateTime_DateTimeType;
81static PyTypeObject PyDateTime_DateTimeTZType;
82static PyTypeObject PyDateTime_DeltaType;
83static PyTypeObject PyDateTime_TimeType;
84static PyTypeObject PyDateTime_TZInfoType;
85static PyTypeObject PyDateTime_TimeTZType;
86
87/* ---------------------------------------------------------------------------
88 * Math utilities.
89 */
90
91/* k = i+j overflows iff k differs in sign from both inputs,
92 * iff k^i has sign bit set and k^j has sign bit set,
93 * iff (k^i)&(k^j) has sign bit set.
94 */
95#define SIGNED_ADD_OVERFLOWED(RESULT, I, J) \
96 ((((RESULT) ^ (I)) & ((RESULT) ^ (J))) < 0)
97
98/* Compute Python divmod(x, y), returning the quotient and storing the
99 * remainder into *r. The quotient is the floor of x/y, and that's
100 * the real point of this. C will probably truncate instead (C99
101 * requires truncation; C89 left it implementation-defined).
102 * Simplification: we *require* that y > 0 here. That's appropriate
103 * for all the uses made of it. This simplifies the code and makes
104 * the overflow case impossible (divmod(LONG_MIN, -1) is the only
105 * overflow case).
106 */
107static int
108divmod(int x, int y, int *r)
109{
110 int quo;
111
112 assert(y > 0);
113 quo = x / y;
114 *r = x - quo * y;
115 if (*r < 0) {
116 --quo;
117 *r += y;
118 }
119 assert(0 <= *r && *r < y);
120 return quo;
121}
122
123/* ---------------------------------------------------------------------------
124 * General calendrical helper functions
125 */
126
127/* For each month ordinal in 1..12, the number of days in that month,
128 * and the number of days before that month in the same year. These
129 * are correct for non-leap years only.
130 */
131static int _days_in_month[] = {
132 0, /* unused; this vector uses 1-based indexing */
133 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
134};
135
136static int _days_before_month[] = {
137 0, /* unused; this vector uses 1-based indexing */
138 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
139};
140
141/* year -> 1 if leap year, else 0. */
142static int
143is_leap(int year)
144{
145 /* Cast year to unsigned. The result is the same either way, but
146 * C can generate faster code for unsigned mod than for signed
147 * mod (especially for % 4 -- a good compiler should just grab
148 * the last 2 bits when the LHS is unsigned).
149 */
150 const unsigned int ayear = (unsigned int)year;
151 return ayear % 4 == 0 && (ayear % 100 != 0 || ayear % 400 == 0);
152}
153
154/* year, month -> number of days in that month in that year */
155static int
156days_in_month(int year, int month)
157{
158 assert(month >= 1);
159 assert(month <= 12);
160 if (month == 2 && is_leap(year))
161 return 29;
162 else
163 return _days_in_month[month];
164}
165
166/* year, month -> number of days in year preceeding first day of month */
167static int
168days_before_month(int year, int month)
169{
170 int days;
171
172 assert(month >= 1);
173 assert(month <= 12);
174 days = _days_before_month[month];
175 if (month > 2 && is_leap(year))
176 ++days;
177 return days;
178}
179
180/* year -> number of days before January 1st of year. Remember that we
181 * start with year 1, so days_before_year(1) == 0.
182 */
183static int
184days_before_year(int year)
185{
186 int y = year - 1;
187 /* This is incorrect if year <= 0; we really want the floor
188 * here. But so long as MINYEAR is 1, the smallest year this
189 * can see is 0 (this can happen in some normalization endcases),
190 * so we'll just special-case that.
191 */
192 assert (year >= 0);
193 if (y >= 0)
194 return y*365 + y/4 - y/100 + y/400;
195 else {
196 assert(y == -1);
197 return -366;
198 }
199}
200
201/* Number of days in 4, 100, and 400 year cycles. That these have
202 * the correct values is asserted in the module init function.
203 */
204#define DI4Y 1461 /* days_before_year(5); days in 4 years */
205#define DI100Y 36524 /* days_before_year(101); days in 100 years */
206#define DI400Y 146097 /* days_before_year(401); days in 400 years */
207
208/* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */
209static void
210ord_to_ymd(int ordinal, int *year, int *month, int *day)
211{
212 int n, n1, n4, n100, n400, leapyear, preceding;
213
214 /* ordinal is a 1-based index, starting at 1-Jan-1. The pattern of
215 * leap years repeats exactly every 400 years. The basic strategy is
216 * to find the closest 400-year boundary at or before ordinal, then
217 * work with the offset from that boundary to ordinal. Life is much
218 * clearer if we subtract 1 from ordinal first -- then the values
219 * of ordinal at 400-year boundaries are exactly those divisible
220 * by DI400Y:
221 *
222 * D M Y n n-1
223 * -- --- ---- ---------- ----------------
224 * 31 Dec -400 -DI400Y -DI400Y -1
225 * 1 Jan -399 -DI400Y +1 -DI400Y 400-year boundary
226 * ...
227 * 30 Dec 000 -1 -2
228 * 31 Dec 000 0 -1
229 * 1 Jan 001 1 0 400-year boundary
230 * 2 Jan 001 2 1
231 * 3 Jan 001 3 2
232 * ...
233 * 31 Dec 400 DI400Y DI400Y -1
234 * 1 Jan 401 DI400Y +1 DI400Y 400-year boundary
235 */
236 assert(ordinal >= 1);
237 --ordinal;
238 n400 = ordinal / DI400Y;
239 n = ordinal % DI400Y;
240 *year = n400 * 400 + 1;
241
242 /* Now n is the (non-negative) offset, in days, from January 1 of
243 * year, to the desired date. Now compute how many 100-year cycles
244 * precede n.
245 * Note that it's possible for n100 to equal 4! In that case 4 full
246 * 100-year cycles precede the desired day, which implies the
247 * desired day is December 31 at the end of a 400-year cycle.
248 */
249 n100 = n / DI100Y;
250 n = n % DI100Y;
251
252 /* Now compute how many 4-year cycles precede it. */
253 n4 = n / DI4Y;
254 n = n % DI4Y;
255
256 /* And now how many single years. Again n1 can be 4, and again
257 * meaning that the desired day is December 31 at the end of the
258 * 4-year cycle.
259 */
260 n1 = n / 365;
261 n = n % 365;
262
263 *year += n100 * 100 + n4 * 4 + n1;
264 if (n1 == 4 || n100 == 4) {
265 assert(n == 0);
266 *year -= 1;
267 *month = 12;
268 *day = 31;
269 return;
270 }
271
272 /* Now the year is correct, and n is the offset from January 1. We
273 * find the month via an estimate that's either exact or one too
274 * large.
275 */
276 leapyear = n1 == 3 && (n4 != 24 || n100 == 3);
277 assert(leapyear == is_leap(*year));
278 *month = (n + 50) >> 5;
279 preceding = (_days_before_month[*month] + (*month > 2 && leapyear));
280 if (preceding > n) {
281 /* estimate is too large */
282 *month -= 1;
283 preceding -= days_in_month(*year, *month);
284 }
285 n -= preceding;
286 assert(0 <= n);
287 assert(n < days_in_month(*year, *month));
288
289 *day = n + 1;
290}
291
292/* year, month, day -> ordinal, considering 01-Jan-0001 as day 1. */
293static int
294ymd_to_ord(int year, int month, int day)
295{
296 return days_before_year(year) + days_before_month(year, month) + day;
297}
298
299/* Day of week, where Monday==0, ..., Sunday==6. 1/1/1 was a Monday. */
300static int
301weekday(int year, int month, int day)
302{
303 return (ymd_to_ord(year, month, day) + 6) % 7;
304}
305
306/* Ordinal of the Monday starting week 1 of the ISO year. Week 1 is the
307 * first calendar week containing a Thursday.
308 */
309static int
310iso_week1_monday(int year)
311{
312 int first_day = ymd_to_ord(year, 1, 1); /* ord of 1/1 */
313 /* 0 if 1/1 is a Monday, 1 if a Tue, etc. */
314 int first_weekday = (first_day + 6) % 7;
315 /* ordinal of closest Monday at or before 1/1 */
316 int week1_monday = first_day - first_weekday;
317
318 if (first_weekday > 3) /* if 1/1 was Fri, Sat, Sun */
319 week1_monday += 7;
320 return week1_monday;
321}
322
323/* ---------------------------------------------------------------------------
324 * Range checkers.
325 */
326
327/* Check that -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS. If so, return 0.
328 * If not, raise OverflowError and return -1.
329 */
330static int
331check_delta_day_range(int days)
332{
333 if (-MAX_DELTA_DAYS <= days && days <= MAX_DELTA_DAYS)
334 return 0;
335 PyErr_Format(PyExc_OverflowError,
336 "days=%d; must have magnitude <= %d",
Guido van Rossumbd43e912002-12-16 20:34:55 +0000337 days, MAX_DELTA_DAYS);
Tim Peters2a799bf2002-12-16 20:18:38 +0000338 return -1;
339}
340
341/* Check that date arguments are in range. Return 0 if they are. If they
342 * aren't, raise ValueError and return -1.
343 */
344static int
345check_date_args(int year, int month, int day)
346{
347
348 if (year < MINYEAR || year > MAXYEAR) {
349 PyErr_SetString(PyExc_ValueError,
350 "year is out of range");
351 return -1;
352 }
353 if (month < 1 || month > 12) {
354 PyErr_SetString(PyExc_ValueError,
355 "month must be in 1..12");
356 return -1;
357 }
358 if (day < 1 || day > days_in_month(year, month)) {
359 PyErr_SetString(PyExc_ValueError,
360 "day is out of range for month");
361 return -1;
362 }
363 return 0;
364}
365
366/* Check that time arguments are in range. Return 0 if they are. If they
367 * aren't, raise ValueError and return -1.
368 */
369static int
370check_time_args(int h, int m, int s, int us)
371{
372 if (h < 0 || h > 23) {
373 PyErr_SetString(PyExc_ValueError,
374 "hour must be in 0..23");
375 return -1;
376 }
377 if (m < 0 || m > 59) {
378 PyErr_SetString(PyExc_ValueError,
379 "minute must be in 0..59");
380 return -1;
381 }
382 if (s < 0 || s > 59) {
383 PyErr_SetString(PyExc_ValueError,
384 "second must be in 0..59");
385 return -1;
386 }
387 if (us < 0 || us > 999999) {
388 PyErr_SetString(PyExc_ValueError,
389 "microsecond must be in 0..999999");
390 return -1;
391 }
392 return 0;
393}
394
395/* ---------------------------------------------------------------------------
396 * Normalization utilities.
397 */
398
399/* One step of a mixed-radix conversion. A "hi" unit is equivalent to
400 * factor "lo" units. factor must be > 0. If *lo is less than 0, or
401 * at least factor, enough of *lo is converted into "hi" units so that
402 * 0 <= *lo < factor. The input values must be such that int overflow
403 * is impossible.
404 */
405static void
406normalize_pair(int *hi, int *lo, int factor)
407{
408 assert(factor > 0);
409 assert(lo != hi);
410 if (*lo < 0 || *lo >= factor) {
411 const int num_hi = divmod(*lo, factor, lo);
412 const int new_hi = *hi + num_hi;
413 assert(! SIGNED_ADD_OVERFLOWED(new_hi, *hi, num_hi));
414 *hi = new_hi;
415 }
416 assert(0 <= *lo && *lo < factor);
417}
418
419/* Fiddle days (d), seconds (s), and microseconds (us) so that
420 * 0 <= *s < 24*3600
421 * 0 <= *us < 1000000
422 * The input values must be such that the internals don't overflow.
423 * The way this routine is used, we don't get close.
424 */
425static void
426normalize_d_s_us(int *d, int *s, int *us)
427{
428 if (*us < 0 || *us >= 1000000) {
429 normalize_pair(s, us, 1000000);
430 /* |s| can't be bigger than about
431 * |original s| + |original us|/1000000 now.
432 */
433
434 }
435 if (*s < 0 || *s >= 24*3600) {
436 normalize_pair(d, s, 24*3600);
437 /* |d| can't be bigger than about
438 * |original d| +
439 * (|original s| + |original us|/1000000) / (24*3600) now.
440 */
441 }
442 assert(0 <= *s && *s < 24*3600);
443 assert(0 <= *us && *us < 1000000);
444}
445
446/* Fiddle years (y), months (m), and days (d) so that
447 * 1 <= *m <= 12
448 * 1 <= *d <= days_in_month(*y, *m)
449 * The input values must be such that the internals don't overflow.
450 * The way this routine is used, we don't get close.
451 */
452static void
453normalize_y_m_d(int *y, int *m, int *d)
454{
455 int dim; /* # of days in month */
456
457 /* This gets muddy: the proper range for day can't be determined
458 * without knowing the correct month and year, but if day is, e.g.,
459 * plus or minus a million, the current month and year values make
460 * no sense (and may also be out of bounds themselves).
461 * Saying 12 months == 1 year should be non-controversial.
462 */
463 if (*m < 1 || *m > 12) {
464 --*m;
465 normalize_pair(y, m, 12);
466 ++*m;
467 /* |y| can't be bigger than about
468 * |original y| + |original m|/12 now.
469 */
470 }
471 assert(1 <= *m && *m <= 12);
472
473 /* Now only day can be out of bounds (year may also be out of bounds
474 * for a datetime object, but we don't care about that here).
475 * If day is out of bounds, what to do is arguable, but at least the
476 * method here is principled and explainable.
477 */
478 dim = days_in_month(*y, *m);
479 if (*d < 1 || *d > dim) {
480 /* Move day-1 days from the first of the month. First try to
481 * get off cheap if we're only one day out of range
482 * (adjustments for timezone alone can't be worse than that).
483 */
484 if (*d == 0) {
485 --*m;
486 if (*m > 0)
487 *d = days_in_month(*y, *m);
488 else {
489 --*y;
490 *m = 12;
491 *d = 31;
492 }
493 }
494 else if (*d == dim + 1) {
495 /* move forward a day */
496 ++*m;
497 *d = 1;
498 if (*m > 12) {
499 *m = 1;
500 ++*y;
501 }
502 }
503 else {
504 int ordinal = ymd_to_ord(*y, *m, 1) +
505 *d - 1;
506 ord_to_ymd(ordinal, y, m, d);
507 }
508 }
509 assert(*m > 0);
510 assert(*d > 0);
511}
512
513/* Fiddle out-of-bounds months and days so that the result makes some kind
514 * of sense. The parameters are both inputs and outputs. Returns < 0 on
515 * failure, where failure means the adjusted year is out of bounds.
516 */
517static int
518normalize_date(int *year, int *month, int *day)
519{
520 int result;
521
522 normalize_y_m_d(year, month, day);
523 if (MINYEAR <= *year && *year <= MAXYEAR)
524 result = 0;
525 else {
526 PyErr_SetString(PyExc_OverflowError,
527 "date value out of range");
528 result = -1;
529 }
530 return result;
531}
532
533/* Force all the datetime fields into range. The parameters are both
534 * inputs and outputs. Returns < 0 on error.
535 */
536static int
537normalize_datetime(int *year, int *month, int *day,
538 int *hour, int *minute, int *second,
539 int *microsecond)
540{
541 normalize_pair(second, microsecond, 1000000);
542 normalize_pair(minute, second, 60);
543 normalize_pair(hour, minute, 60);
544 normalize_pair(day, hour, 24);
545 return normalize_date(year, month, day);
546}
547
548/* ---------------------------------------------------------------------------
549 * tzinfo helpers.
550 */
551
Tim Peters855fe882002-12-22 03:43:39 +0000552/* Ensure that p is None or of a tzinfo subclass. Return 0 if OK; if not
553 * raise TypeError and return -1.
554 */
555static int
556check_tzinfo_subclass(PyObject *p)
557{
558 if (p == Py_None || PyTZInfo_Check(p))
559 return 0;
560 PyErr_Format(PyExc_TypeError,
561 "tzinfo argument must be None or of a tzinfo subclass, "
562 "not type '%s'",
563 p->ob_type->tp_name);
564 return -1;
565}
566
Tim Petersbad8ff02002-12-30 20:52:32 +0000567/* Return tzinfo.methname(tzinfoarg), without any checking of results.
Tim Peters855fe882002-12-22 03:43:39 +0000568 * If tzinfo is None, returns None.
569 */
570static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000571call_tzinfo_method(PyObject *tzinfo, char *methname, PyObject *tzinfoarg)
Tim Peters855fe882002-12-22 03:43:39 +0000572{
573 PyObject *result;
574
Tim Petersbad8ff02002-12-30 20:52:32 +0000575 assert(tzinfo && methname && tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000576 assert(check_tzinfo_subclass(tzinfo) >= 0);
577 if (tzinfo == Py_None) {
578 result = Py_None;
579 Py_INCREF(result);
580 }
581 else
Tim Petersbad8ff02002-12-30 20:52:32 +0000582 result = PyObject_CallMethod(tzinfo, methname, "O", tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000583 return result;
584}
585
Tim Peters2a799bf2002-12-16 20:18:38 +0000586/* If self has a tzinfo member, return a BORROWED reference to it. Else
587 * return NULL, which is NOT AN ERROR. There are no error returns here,
588 * and the caller must not decref the result.
589 */
590static PyObject *
591get_tzinfo_member(PyObject *self)
592{
593 PyObject *tzinfo = NULL;
594
595 if (PyDateTimeTZ_Check(self))
596 tzinfo = ((PyDateTime_DateTimeTZ *)self)->tzinfo;
597 else if (PyTimeTZ_Check(self))
598 tzinfo = ((PyDateTime_TimeTZ *)self)->tzinfo;
599
600 return tzinfo;
601}
602
Tim Peters80475bb2002-12-25 07:40:55 +0000603/* self is a datetimetz. Replace its tzinfo member. */
604void
605replace_tzinfo(PyObject *self, PyObject *newtzinfo)
606{
607 assert(self != NULL);
608 assert(PyDateTimeTZ_Check(self));
609 assert(check_tzinfo_subclass(newtzinfo) >= 0);
610 Py_INCREF(newtzinfo);
611 Py_DECREF(((PyDateTime_DateTimeTZ *)self)->tzinfo);
612 ((PyDateTime_DateTimeTZ *)self)->tzinfo = newtzinfo;
613}
614
Tim Petersbad8ff02002-12-30 20:52:32 +0000615
616/* Call getattr(tzinfo, name)(tzinfoarg), and extract an int from the
Tim Peters2a799bf2002-12-16 20:18:38 +0000617 * result. tzinfo must be an instance of the tzinfo class. If the method
618 * returns None, this returns 0 and sets *none to 1. If the method doesn't
Tim Peters855fe882002-12-22 03:43:39 +0000619 * return a Python int or long or timedelta, TypeError is raised and this
620 * returns -1. If it returns an int or long, but is outside the valid
621 * range for a UTC minute offset, or it returns a timedelta and the value is
622 * out of range or isn't a whole number of minutes, ValueError is raised and
623 * this returns -1.
Tim Peters2a799bf2002-12-16 20:18:38 +0000624 * Else *none is set to 0 and the integer method result is returned.
625 */
626static int
627call_utc_tzinfo_method(PyObject *tzinfo, char *name, PyObject *tzinfoarg,
628 int *none)
629{
630 PyObject *u;
631 long result = -1; /* Py{Int,Long}_AsLong return long */
632
633 assert(tzinfo != NULL);
634 assert(PyTZInfo_Check(tzinfo));
635 assert(tzinfoarg != NULL);
636
637 *none = 0;
Tim Petersbad8ff02002-12-30 20:52:32 +0000638 u = call_tzinfo_method(tzinfo, name, tzinfoarg);
Tim Peters2a799bf2002-12-16 20:18:38 +0000639 if (u == NULL)
640 return -1;
641
Tim Peters27362852002-12-23 16:17:39 +0000642 else if (u == Py_None) {
Tim Peters2a799bf2002-12-16 20:18:38 +0000643 result = 0;
644 *none = 1;
Tim Peters2a799bf2002-12-16 20:18:38 +0000645 }
Tim Peters27362852002-12-23 16:17:39 +0000646 else if (PyInt_Check(u))
Tim Peters2a799bf2002-12-16 20:18:38 +0000647 result = PyInt_AS_LONG(u);
Tim Peters855fe882002-12-22 03:43:39 +0000648
Tim Peters2a799bf2002-12-16 20:18:38 +0000649 else if (PyLong_Check(u))
650 result = PyLong_AsLong(u);
Tim Peters855fe882002-12-22 03:43:39 +0000651
652 else if (PyDelta_Check(u)) {
653 const int days = GET_TD_DAYS(u);
654 if (days < -1 || days > 0)
655 result = 24*60; /* trigger ValueError below */
656 else {
657 /* next line can't overflow because we know days
658 * is -1 or 0 now
659 */
660 int ss = days * 24 * 3600 + GET_TD_SECONDS(u);
661 result = divmod(ss, 60, &ss);
662 if (ss || GET_TD_MICROSECONDS(u)) {
663 PyErr_Format(PyExc_ValueError,
664 "tzinfo.%s() must return a "
665 "whole number of minutes",
666 name);
667 result = -1;
Tim Peters855fe882002-12-22 03:43:39 +0000668 }
669 }
670 }
Tim Peters2a799bf2002-12-16 20:18:38 +0000671 else {
672 PyErr_Format(PyExc_TypeError,
Tim Peters855fe882002-12-22 03:43:39 +0000673 "tzinfo.%s() must return None, integer or "
674 "timedelta, not '%s'",
675 name, u->ob_type->tp_name);
Tim Peters2a799bf2002-12-16 20:18:38 +0000676 }
677
Tim Peters2a799bf2002-12-16 20:18:38 +0000678 Py_DECREF(u);
679 if (result < -1439 || result > 1439) {
680 PyErr_Format(PyExc_ValueError,
681 "tzinfo.%s() returned %ld; must be in "
682 "-1439 .. 1439",
683 name, result);
684 result = -1;
685 }
686 return (int)result;
687}
688
689/* Call tzinfo.utcoffset(tzinfoarg), and extract an integer from the
690 * result. tzinfo must be an instance of the tzinfo class. If utcoffset()
691 * returns None, call_utcoffset returns 0 and sets *none to 1. If uctoffset()
692 & doesn't return a Python int or long, TypeError is raised and this
693 * returns -1. If utcoffset() returns an int outside the legitimate range
694 * for a UTC offset, ValueError is raised and this returns -1. Else
695 * *none is set to 0 and the offset is returned.
696 */
697static int
698call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
699{
700 return call_utc_tzinfo_method(tzinfo, "utcoffset", tzinfoarg, none);
701}
702
Tim Peters855fe882002-12-22 03:43:39 +0000703static PyObject *new_delta(int d, int sec, int usec, int normalize);
704
Tim Petersbad8ff02002-12-30 20:52:32 +0000705/* Call tzinfo.name(tzinfoarg), and return the offset as a timedelta or None.
706 */
Tim Peters855fe882002-12-22 03:43:39 +0000707static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000708offset_as_timedelta(PyObject *tzinfo, char *name, PyObject *tzinfoarg) {
Tim Peters855fe882002-12-22 03:43:39 +0000709 PyObject *result;
710
Tim Petersbad8ff02002-12-30 20:52:32 +0000711 assert(tzinfo && name && tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000712 if (tzinfo == Py_None) {
713 result = Py_None;
714 Py_INCREF(result);
715 }
716 else {
717 int none;
Tim Petersbad8ff02002-12-30 20:52:32 +0000718 int offset = call_utc_tzinfo_method(tzinfo, name, tzinfoarg,
719 &none);
Tim Peters855fe882002-12-22 03:43:39 +0000720 if (offset < 0 && PyErr_Occurred())
721 return NULL;
722 if (none) {
723 result = Py_None;
724 Py_INCREF(result);
725 }
726 else
727 result = new_delta(0, offset * 60, 0, 1);
728 }
729 return result;
730}
731
Tim Peters2a799bf2002-12-16 20:18:38 +0000732/* Call tzinfo.dst(tzinfoarg), and extract an integer from the
733 * result. tzinfo must be an instance of the tzinfo class. If dst()
734 * returns None, call_dst returns 0 and sets *none to 1. If dst()
735 & doesn't return a Python int or long, TypeError is raised and this
736 * returns -1. If dst() returns an int outside the legitimate range
737 * for a UTC offset, ValueError is raised and this returns -1. Else
738 * *none is set to 0 and the offset is returned.
739 */
740static int
741call_dst(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
742{
743 return call_utc_tzinfo_method(tzinfo, "dst", tzinfoarg, none);
744}
745
Tim Petersbad8ff02002-12-30 20:52:32 +0000746/* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be
Tim Peters855fe882002-12-22 03:43:39 +0000747 * an instance of the tzinfo class or None. If tzinfo isn't None, and
Tim Petersbad8ff02002-12-30 20:52:32 +0000748 * tzname() doesn't return None or a string, TypeError is raised and this
Tim Peters855fe882002-12-22 03:43:39 +0000749 * returns NULL.
Tim Peters2a799bf2002-12-16 20:18:38 +0000750 */
751static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000752call_tzname(PyObject *tzinfo, PyObject *tzinfoarg)
Tim Peters2a799bf2002-12-16 20:18:38 +0000753{
754 PyObject *result;
755
756 assert(tzinfo != NULL);
Tim Peters855fe882002-12-22 03:43:39 +0000757 assert(check_tzinfo_subclass(tzinfo) >= 0);
Tim Petersbad8ff02002-12-30 20:52:32 +0000758 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +0000759
Tim Peters855fe882002-12-22 03:43:39 +0000760 if (tzinfo == Py_None) {
761 result = Py_None;
762 Py_INCREF(result);
763 }
764 else
Tim Petersbad8ff02002-12-30 20:52:32 +0000765 result = PyObject_CallMethod(tzinfo, "tzname", "O", tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000766
767 if (result != NULL && result != Py_None && ! PyString_Check(result)) {
768 PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must "
Tim Peters2a799bf2002-12-16 20:18:38 +0000769 "return None or a string, not '%s'",
770 result->ob_type->tp_name);
771 Py_DECREF(result);
772 result = NULL;
773 }
774 return result;
775}
776
777typedef enum {
778 /* an exception has been set; the caller should pass it on */
779 OFFSET_ERROR,
780
781 /* type isn't date, datetime, datetimetz subclass, time, or
782 * timetz subclass
783 */
784 OFFSET_UNKNOWN,
785
786 /* date,
787 * datetime,
788 * datetimetz with None tzinfo,
Tim Peters855fe882002-12-22 03:43:39 +0000789 * datetimetz where utcoffset() returns None
Tim Peters2a799bf2002-12-16 20:18:38 +0000790 * time,
791 * timetz with None tzinfo,
792 * timetz where utcoffset() returns None
793 */
794 OFFSET_NAIVE,
795
796 /* timetz where utcoffset() doesn't return None,
797 * datetimetz where utcoffset() doesn't return None
798 */
799 OFFSET_AWARE,
800} naivety;
801
Tim Peters14b69412002-12-22 18:10:22 +0000802/* Classify an object as to whether it's naive or offset-aware. See
Tim Peters2a799bf2002-12-16 20:18:38 +0000803 * the "naivety" typedef for details. If the type is aware, *offset is set
804 * to minutes east of UTC (as returned by the tzinfo.utcoffset() method).
Tim Peters14b69412002-12-22 18:10:22 +0000805 * If the type is offset-naive (or unknown, or error), *offset is set to 0.
Tim Peterse39a80c2002-12-30 21:28:52 +0000806 * tzinfoarg is the argument to pass to the tzinfo.utcoffset() method.
Tim Peters2a799bf2002-12-16 20:18:38 +0000807 */
808static naivety
Tim Peterse39a80c2002-12-30 21:28:52 +0000809classify_utcoffset(PyObject *op, PyObject *tzinfoarg, int *offset)
Tim Peters2a799bf2002-12-16 20:18:38 +0000810{
811 int none;
812 PyObject *tzinfo;
813
Tim Peterse39a80c2002-12-30 21:28:52 +0000814 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +0000815 *offset = 0;
Tim Peters14b69412002-12-22 18:10:22 +0000816 tzinfo = get_tzinfo_member(op); /* NULL means no tzinfo, not error */
Tim Peters2a799bf2002-12-16 20:18:38 +0000817 if (tzinfo == Py_None)
818 return OFFSET_NAIVE;
Tim Peters14b69412002-12-22 18:10:22 +0000819 if (tzinfo == NULL) {
820 /* note that a datetime passes the PyDate_Check test */
821 return (PyTime_Check(op) || PyDate_Check(op)) ?
822 OFFSET_NAIVE : OFFSET_UNKNOWN;
823 }
Tim Peterse39a80c2002-12-30 21:28:52 +0000824 *offset = call_utcoffset(tzinfo, tzinfoarg, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +0000825 if (*offset == -1 && PyErr_Occurred())
826 return OFFSET_ERROR;
827 return none ? OFFSET_NAIVE : OFFSET_AWARE;
828}
829
Tim Peters00237032002-12-27 02:21:51 +0000830/* Classify two objects as to whether they're naive or offset-aware.
831 * This isn't quite the same as calling classify_utcoffset() twice: for
832 * binary operations (comparison and subtraction), we generally want to
833 * ignore the tzinfo members if they're identical. This is by design,
834 * so that results match "naive" expectations when mixing objects from a
835 * single timezone. So in that case, this sets both offsets to 0 and
836 * both naiveties to OFFSET_NAIVE.
837 * The function returns 0 if everything's OK, and -1 on error.
838 */
839static int
840classify_two_utcoffsets(PyObject *o1, int *offset1, naivety *n1,
Tim Peterse39a80c2002-12-30 21:28:52 +0000841 PyObject *tzinfoarg1,
842 PyObject *o2, int *offset2, naivety *n2,
843 PyObject *tzinfoarg2)
Tim Peters00237032002-12-27 02:21:51 +0000844{
845 if (get_tzinfo_member(o1) == get_tzinfo_member(o2)) {
846 *offset1 = *offset2 = 0;
847 *n1 = *n2 = OFFSET_NAIVE;
848 }
849 else {
Tim Peterse39a80c2002-12-30 21:28:52 +0000850 *n1 = classify_utcoffset(o1, tzinfoarg1, offset1);
Tim Peters00237032002-12-27 02:21:51 +0000851 if (*n1 == OFFSET_ERROR)
852 return -1;
Tim Peterse39a80c2002-12-30 21:28:52 +0000853 *n2 = classify_utcoffset(o2, tzinfoarg2, offset2);
Tim Peters00237032002-12-27 02:21:51 +0000854 if (*n2 == OFFSET_ERROR)
855 return -1;
856 }
857 return 0;
858}
859
Tim Peters2a799bf2002-12-16 20:18:38 +0000860/* repr is like "someclass(arg1, arg2)". If tzinfo isn't None,
861 * stuff
862 * ", tzinfo=" + repr(tzinfo)
863 * before the closing ")".
864 */
865static PyObject *
866append_keyword_tzinfo(PyObject *repr, PyObject *tzinfo)
867{
868 PyObject *temp;
869
870 assert(PyString_Check(repr));
871 assert(tzinfo);
872 if (tzinfo == Py_None)
873 return repr;
874 /* Get rid of the trailing ')'. */
875 assert(PyString_AsString(repr)[PyString_Size(repr)-1] == ')');
876 temp = PyString_FromStringAndSize(PyString_AsString(repr),
877 PyString_Size(repr) - 1);
878 Py_DECREF(repr);
879 if (temp == NULL)
880 return NULL;
881 repr = temp;
882
883 /* Append ", tzinfo=". */
884 PyString_ConcatAndDel(&repr, PyString_FromString(", tzinfo="));
885
886 /* Append repr(tzinfo). */
887 PyString_ConcatAndDel(&repr, PyObject_Repr(tzinfo));
888
889 /* Add a closing paren. */
890 PyString_ConcatAndDel(&repr, PyString_FromString(")"));
891 return repr;
892}
893
894/* ---------------------------------------------------------------------------
895 * String format helpers.
896 */
897
898static PyObject *
899format_ctime(PyDateTime_Date *date,
900 int hours, int minutes, int seconds)
901{
902 static char *DayNames[] = {
903 "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
904 };
905 static char *MonthNames[] = {
906 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
907 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
908 };
909
910 char buffer[128];
911 int wday = weekday(GET_YEAR(date), GET_MONTH(date), GET_DAY(date));
912
913 PyOS_snprintf(buffer, sizeof(buffer), "%s %s %2d %02d:%02d:%02d %04d",
914 DayNames[wday], MonthNames[GET_MONTH(date) - 1],
915 GET_DAY(date), hours, minutes, seconds,
916 GET_YEAR(date));
917 return PyString_FromString(buffer);
918}
919
920/* Add an hours & minutes UTC offset string to buf. buf has no more than
921 * buflen bytes remaining. The UTC offset is gotten by calling
922 * tzinfo.uctoffset(tzinfoarg). If that returns None, \0 is stored into
923 * *buf, and that's all. Else the returned value is checked for sanity (an
924 * integer in range), and if that's OK it's converted to an hours & minutes
925 * string of the form
926 * sign HH sep MM
927 * Returns 0 if everything is OK. If the return value from utcoffset() is
928 * bogus, an appropriate exception is set and -1 is returned.
929 */
930static int
Tim Peters328fff72002-12-20 01:31:27 +0000931format_utcoffset(char *buf, size_t buflen, const char *sep,
Tim Peters2a799bf2002-12-16 20:18:38 +0000932 PyObject *tzinfo, PyObject *tzinfoarg)
933{
934 int offset;
935 int hours;
936 int minutes;
937 char sign;
938 int none;
939
940 offset = call_utcoffset(tzinfo, tzinfoarg, &none);
941 if (offset == -1 && PyErr_Occurred())
942 return -1;
943 if (none) {
944 *buf = '\0';
945 return 0;
946 }
947 sign = '+';
948 if (offset < 0) {
949 sign = '-';
950 offset = - offset;
951 }
952 hours = divmod(offset, 60, &minutes);
953 PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes);
954 return 0;
955}
956
957/* I sure don't want to reproduce the strftime code from the time module,
958 * so this imports the module and calls it. All the hair is due to
959 * giving special meanings to the %z and %Z format codes via a preprocessing
960 * step on the format string.
Tim Petersbad8ff02002-12-30 20:52:32 +0000961 * tzinfoarg is the argument to pass to the object's tzinfo method, if
962 * needed.
Tim Peters2a799bf2002-12-16 20:18:38 +0000963 */
964static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000965wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
966 PyObject *tzinfoarg)
Tim Peters2a799bf2002-12-16 20:18:38 +0000967{
968 PyObject *result = NULL; /* guilty until proved innocent */
969
970 PyObject *zreplacement = NULL; /* py string, replacement for %z */
971 PyObject *Zreplacement = NULL; /* py string, replacement for %Z */
972
973 char *pin; /* pointer to next char in input format */
974 char ch; /* next char in input format */
975
976 PyObject *newfmt = NULL; /* py string, the output format */
977 char *pnew; /* pointer to available byte in output format */
978 char totalnew; /* number bytes total in output format buffer,
979 exclusive of trailing \0 */
980 char usednew; /* number bytes used so far in output format buffer */
981
982 char *ptoappend; /* pointer to string to append to output buffer */
983 int ntoappend; /* # of bytes to append to output buffer */
984
Tim Peters2a799bf2002-12-16 20:18:38 +0000985 assert(object && format && timetuple);
986 assert(PyString_Check(format));
987
Tim Petersd6844152002-12-22 20:58:42 +0000988 /* Give up if the year is before 1900.
989 * Python strftime() plays games with the year, and different
990 * games depending on whether envar PYTHON2K is set. This makes
991 * years before 1900 a nightmare, even if the platform strftime
992 * supports them (and not all do).
993 * We could get a lot farther here by avoiding Python's strftime
994 * wrapper and calling the C strftime() directly, but that isn't
995 * an option in the Python implementation of this module.
996 */
997 {
998 long year;
999 PyObject *pyyear = PySequence_GetItem(timetuple, 0);
1000 if (pyyear == NULL) return NULL;
1001 assert(PyInt_Check(pyyear));
1002 year = PyInt_AsLong(pyyear);
1003 Py_DECREF(pyyear);
1004 if (year < 1900) {
1005 PyErr_Format(PyExc_ValueError, "year=%ld is before "
1006 "1900; the datetime strftime() "
1007 "methods require year >= 1900",
1008 year);
1009 return NULL;
1010 }
1011 }
1012
Tim Peters2a799bf2002-12-16 20:18:38 +00001013 /* Scan the input format, looking for %z and %Z escapes, building
Tim Peters328fff72002-12-20 01:31:27 +00001014 * a new format. Since computing the replacements for those codes
1015 * is expensive, don't unless they're actually used.
Tim Peters2a799bf2002-12-16 20:18:38 +00001016 */
1017 totalnew = PyString_Size(format); /* realistic if no %z/%Z */
1018 newfmt = PyString_FromStringAndSize(NULL, totalnew);
1019 if (newfmt == NULL) goto Done;
1020 pnew = PyString_AsString(newfmt);
1021 usednew = 0;
1022
1023 pin = PyString_AsString(format);
1024 while ((ch = *pin++) != '\0') {
1025 if (ch != '%') {
Tim Peters328fff72002-12-20 01:31:27 +00001026 ptoappend = pin - 1;
Tim Peters2a799bf2002-12-16 20:18:38 +00001027 ntoappend = 1;
1028 }
1029 else if ((ch = *pin++) == '\0') {
1030 /* There's a lone trailing %; doesn't make sense. */
1031 PyErr_SetString(PyExc_ValueError, "strftime format "
1032 "ends with raw %");
1033 goto Done;
1034 }
1035 /* A % has been seen and ch is the character after it. */
1036 else if (ch == 'z') {
1037 if (zreplacement == NULL) {
1038 /* format utcoffset */
Tim Peters328fff72002-12-20 01:31:27 +00001039 char buf[100];
Tim Peters2a799bf2002-12-16 20:18:38 +00001040 PyObject *tzinfo = get_tzinfo_member(object);
1041 zreplacement = PyString_FromString("");
1042 if (zreplacement == NULL) goto Done;
1043 if (tzinfo != Py_None && tzinfo != NULL) {
Tim Petersbad8ff02002-12-30 20:52:32 +00001044 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +00001045 if (format_utcoffset(buf,
Tim Peters328fff72002-12-20 01:31:27 +00001046 sizeof(buf),
Tim Peters2a799bf2002-12-16 20:18:38 +00001047 "",
1048 tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00001049 tzinfoarg) < 0)
Tim Peters2a799bf2002-12-16 20:18:38 +00001050 goto Done;
1051 Py_DECREF(zreplacement);
1052 zreplacement = PyString_FromString(buf);
1053 if (zreplacement == NULL) goto Done;
1054 }
1055 }
1056 assert(zreplacement != NULL);
1057 ptoappend = PyString_AsString(zreplacement);
1058 ntoappend = PyString_Size(zreplacement);
1059 }
1060 else if (ch == 'Z') {
1061 /* format tzname */
1062 if (Zreplacement == NULL) {
1063 PyObject *tzinfo = get_tzinfo_member(object);
1064 Zreplacement = PyString_FromString("");
1065 if (Zreplacement == NULL) goto Done;
1066 if (tzinfo != Py_None && tzinfo != NULL) {
Tim Petersbad8ff02002-12-30 20:52:32 +00001067 PyObject *temp;
1068 assert(tzinfoarg != NULL);
1069 temp = call_tzname(tzinfo, tzinfoarg);
Tim Peters2a799bf2002-12-16 20:18:38 +00001070 if (temp == NULL) goto Done;
1071 if (temp != Py_None) {
1072 assert(PyString_Check(temp));
1073 /* Since the tzname is getting
1074 * stuffed into the format, we
1075 * have to double any % signs
1076 * so that strftime doesn't
1077 * treat them as format codes.
1078 */
1079 Py_DECREF(Zreplacement);
1080 Zreplacement = PyObject_CallMethod(
1081 temp, "replace",
1082 "ss", "%", "%%");
1083 Py_DECREF(temp);
1084 if (Zreplacement == NULL)
1085 goto Done;
1086 }
1087 else
1088 Py_DECREF(temp);
1089 }
1090 }
1091 assert(Zreplacement != NULL);
1092 ptoappend = PyString_AsString(Zreplacement);
1093 ntoappend = PyString_Size(Zreplacement);
1094 }
1095 else {
Tim Peters328fff72002-12-20 01:31:27 +00001096 /* percent followed by neither z nor Z */
1097 ptoappend = pin - 2;
Tim Peters2a799bf2002-12-16 20:18:38 +00001098 ntoappend = 2;
1099 }
1100
1101 /* Append the ntoappend chars starting at ptoappend to
1102 * the new format.
1103 */
1104 assert(ntoappend >= 0);
1105 if (ntoappend == 0)
1106 continue;
1107 while (usednew + ntoappend > totalnew) {
1108 int bigger = totalnew << 1;
1109 if ((bigger >> 1) != totalnew) { /* overflow */
1110 PyErr_NoMemory();
1111 goto Done;
1112 }
1113 if (_PyString_Resize(&newfmt, bigger) < 0)
1114 goto Done;
1115 totalnew = bigger;
1116 pnew = PyString_AsString(newfmt) + usednew;
1117 }
1118 memcpy(pnew, ptoappend, ntoappend);
1119 pnew += ntoappend;
1120 usednew += ntoappend;
1121 assert(usednew <= totalnew);
1122 } /* end while() */
1123
1124 if (_PyString_Resize(&newfmt, usednew) < 0)
1125 goto Done;
1126 {
1127 PyObject *time = PyImport_ImportModule("time");
1128 if (time == NULL)
1129 goto Done;
1130 result = PyObject_CallMethod(time, "strftime", "OO",
1131 newfmt, timetuple);
1132 Py_DECREF(time);
1133 }
1134 Done:
1135 Py_XDECREF(zreplacement);
1136 Py_XDECREF(Zreplacement);
1137 Py_XDECREF(newfmt);
1138 return result;
1139}
1140
1141static char *
1142isoformat_date(PyDateTime_Date *dt, char buffer[], int bufflen)
1143{
1144 int x;
1145 x = PyOS_snprintf(buffer, bufflen,
1146 "%04d-%02d-%02d",
1147 GET_YEAR(dt), GET_MONTH(dt), GET_DAY(dt));
1148 return buffer + x;
1149}
1150
1151static void
1152isoformat_time(PyDateTime_DateTime *dt, char buffer[], int bufflen)
1153{
1154 int us = DATE_GET_MICROSECOND(dt);
1155
1156 PyOS_snprintf(buffer, bufflen,
1157 "%02d:%02d:%02d", /* 8 characters */
1158 DATE_GET_HOUR(dt),
1159 DATE_GET_MINUTE(dt),
1160 DATE_GET_SECOND(dt));
1161 if (us)
1162 PyOS_snprintf(buffer + 8, bufflen - 8, ".%06d", us);
1163}
1164
1165/* ---------------------------------------------------------------------------
1166 * Wrap functions from the time module. These aren't directly available
1167 * from C. Perhaps they should be.
1168 */
1169
1170/* Call time.time() and return its result (a Python float). */
1171static PyObject *
Guido van Rossumbd43e912002-12-16 20:34:55 +00001172time_time(void)
Tim Peters2a799bf2002-12-16 20:18:38 +00001173{
1174 PyObject *result = NULL;
1175 PyObject *time = PyImport_ImportModule("time");
1176
1177 if (time != NULL) {
1178 result = PyObject_CallMethod(time, "time", "()");
1179 Py_DECREF(time);
1180 }
1181 return result;
1182}
1183
1184/* Build a time.struct_time. The weekday and day number are automatically
1185 * computed from the y,m,d args.
1186 */
1187static PyObject *
1188build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
1189{
1190 PyObject *time;
1191 PyObject *result = NULL;
1192
1193 time = PyImport_ImportModule("time");
1194 if (time != NULL) {
1195 result = PyObject_CallMethod(time, "struct_time",
1196 "((iiiiiiiii))",
1197 y, m, d,
1198 hh, mm, ss,
1199 weekday(y, m, d),
1200 days_before_month(y, m) + d,
1201 dstflag);
1202 Py_DECREF(time);
1203 }
1204 return result;
1205}
1206
1207/* ---------------------------------------------------------------------------
1208 * Miscellaneous helpers.
1209 */
1210
1211/* For obscure reasons, we need to use tp_richcompare instead of tp_compare.
1212 * The comparisons here all most naturally compute a cmp()-like result.
1213 * This little helper turns that into a bool result for rich comparisons.
1214 */
1215static PyObject *
1216diff_to_bool(int diff, int op)
1217{
1218 PyObject *result;
1219 int istrue;
1220
1221 switch (op) {
1222 case Py_EQ: istrue = diff == 0; break;
1223 case Py_NE: istrue = diff != 0; break;
1224 case Py_LE: istrue = diff <= 0; break;
1225 case Py_GE: istrue = diff >= 0; break;
1226 case Py_LT: istrue = diff < 0; break;
1227 case Py_GT: istrue = diff > 0; break;
1228 default:
1229 assert(! "op unknown");
1230 istrue = 0; /* To shut up compiler */
1231 }
1232 result = istrue ? Py_True : Py_False;
1233 Py_INCREF(result);
1234 return result;
1235}
1236
1237/* ---------------------------------------------------------------------------
1238 * Helpers for setting object fields. These work on pointers to the
1239 * appropriate base class.
1240 */
1241
1242/* For date, datetime and datetimetz. */
1243static void
1244set_date_fields(PyDateTime_Date *self, int y, int m, int d)
1245{
1246 self->hashcode = -1;
1247 SET_YEAR(self, y);
1248 SET_MONTH(self, m);
1249 SET_DAY(self, d);
1250}
1251
1252/* For datetime and datetimetz. */
1253static void
1254set_datetime_time_fields(PyDateTime_Date *self, int h, int m, int s, int us)
1255{
1256 DATE_SET_HOUR(self, h);
1257 DATE_SET_MINUTE(self, m);
1258 DATE_SET_SECOND(self, s);
1259 DATE_SET_MICROSECOND(self, us);
1260}
1261
1262/* For time and timetz. */
1263static void
1264set_time_fields(PyDateTime_Time *self, int h, int m, int s, int us)
1265{
1266 self->hashcode = -1;
1267 TIME_SET_HOUR(self, h);
1268 TIME_SET_MINUTE(self, m);
1269 TIME_SET_SECOND(self, s);
1270 TIME_SET_MICROSECOND(self, us);
1271}
1272
1273/* ---------------------------------------------------------------------------
1274 * Create various objects, mostly without range checking.
1275 */
1276
1277/* Create a date instance with no range checking. */
1278static PyObject *
1279new_date(int year, int month, int day)
1280{
1281 PyDateTime_Date *self;
1282
1283 self = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
1284 if (self != NULL)
1285 set_date_fields(self, year, month, day);
1286 return (PyObject *) self;
1287}
1288
1289/* Create a datetime instance with no range checking. */
1290static PyObject *
1291new_datetime(int year, int month, int day, int hour, int minute,
1292 int second, int usecond)
1293{
1294 PyDateTime_DateTime *self;
1295
1296 self = PyObject_New(PyDateTime_DateTime, &PyDateTime_DateTimeType);
1297 if (self != NULL) {
1298 set_date_fields((PyDateTime_Date *)self, year, month, day);
1299 set_datetime_time_fields((PyDateTime_Date *)self,
1300 hour, minute, second, usecond);
1301 }
1302 return (PyObject *) self;
1303}
1304
1305/* Create a datetimetz instance with no range checking. */
1306static PyObject *
1307new_datetimetz(int year, int month, int day, int hour, int minute,
1308 int second, int usecond, PyObject *tzinfo)
1309{
1310 PyDateTime_DateTimeTZ *self;
1311
1312 self = PyObject_New(PyDateTime_DateTimeTZ, &PyDateTime_DateTimeTZType);
1313 if (self != NULL) {
1314 set_date_fields((PyDateTime_Date *)self, year, month, day);
1315 set_datetime_time_fields((PyDateTime_Date *)self,
1316 hour, minute, second, usecond);
1317 Py_INCREF(tzinfo);
1318 self->tzinfo = tzinfo;
1319 }
1320 return (PyObject *) self;
1321}
1322
1323/* Create a time instance with no range checking. */
1324static PyObject *
1325new_time(int hour, int minute, int second, int usecond)
1326{
1327 PyDateTime_Time *self;
1328
1329 self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
1330 if (self != NULL)
1331 set_time_fields(self, hour, minute, second, usecond);
1332 return (PyObject *) self;
1333}
1334
1335/* Create a timetz instance with no range checking. */
1336static PyObject *
1337new_timetz(int hour, int minute, int second, int usecond, PyObject *tzinfo)
1338{
1339 PyDateTime_TimeTZ *self;
1340
1341 self = PyObject_New(PyDateTime_TimeTZ, &PyDateTime_TimeTZType);
1342 if (self != NULL) {
1343 set_time_fields((PyDateTime_Time *)self,
1344 hour, minute, second, usecond);
1345 Py_INCREF(tzinfo);
1346 self->tzinfo = tzinfo;
1347 }
1348 return (PyObject *) self;
1349}
1350
1351/* Create a timedelta instance. Normalize the members iff normalize is
1352 * true. Passing false is a speed optimization, if you know for sure
1353 * that seconds and microseconds are already in their proper ranges. In any
1354 * case, raises OverflowError and returns NULL if the normalized days is out
1355 * of range).
1356 */
1357static PyObject *
1358new_delta(int days, int seconds, int microseconds, int normalize)
1359{
1360 PyDateTime_Delta *self;
1361
1362 if (normalize)
1363 normalize_d_s_us(&days, &seconds, &microseconds);
1364 assert(0 <= seconds && seconds < 24*3600);
1365 assert(0 <= microseconds && microseconds < 1000000);
1366
1367 if (check_delta_day_range(days) < 0)
1368 return NULL;
1369
1370 self = PyObject_New(PyDateTime_Delta, &PyDateTime_DeltaType);
1371 if (self != NULL) {
1372 self->hashcode = -1;
1373 SET_TD_DAYS(self, days);
1374 SET_TD_SECONDS(self, seconds);
1375 SET_TD_MICROSECONDS(self, microseconds);
1376 }
1377 return (PyObject *) self;
1378}
1379
1380
1381/* ---------------------------------------------------------------------------
1382 * Cached Python objects; these are set by the module init function.
1383 */
1384
1385/* Conversion factors. */
1386static PyObject *us_per_us = NULL; /* 1 */
1387static PyObject *us_per_ms = NULL; /* 1000 */
1388static PyObject *us_per_second = NULL; /* 1000000 */
1389static PyObject *us_per_minute = NULL; /* 1e6 * 60 as Python int */
1390static PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python long */
1391static PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python long */
1392static PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python long */
1393static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */
1394
1395/* Callables to support unpickling. */
1396static PyObject *date_unpickler_object = NULL;
1397static PyObject *datetime_unpickler_object = NULL;
1398static PyObject *datetimetz_unpickler_object = NULL;
1399static PyObject *tzinfo_unpickler_object = NULL;
1400static PyObject *time_unpickler_object = NULL;
1401static PyObject *timetz_unpickler_object = NULL;
1402
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. */
1908 PyObject *temp;
1909 if (leftover_us >= 0.0)
1910 leftover_us = floor(leftover_us + 0.5);
1911 else
1912 leftover_us = ceil(leftover_us - 0.5);
1913 temp = PyLong_FromDouble(leftover_us);
1914 if (temp == NULL) {
1915 Py_DECREF(x);
1916 goto Done;
1917 }
1918 y = PyNumber_Add(x, temp);
1919 Py_DECREF(temp);
1920 CLEANUP;
1921 }
1922
1923 self = microseconds_to_delta(x);
1924 Py_DECREF(x);
1925Done:
1926 return self;
1927
1928#undef CLEANUP
1929}
1930
1931static int
1932delta_nonzero(PyDateTime_Delta *self)
1933{
1934 return (GET_TD_DAYS(self) != 0
1935 || GET_TD_SECONDS(self) != 0
1936 || GET_TD_MICROSECONDS(self) != 0);
1937}
1938
1939static PyObject *
1940delta_repr(PyDateTime_Delta *self)
1941{
1942 if (GET_TD_MICROSECONDS(self) != 0)
1943 return PyString_FromFormat("%s(%d, %d, %d)",
1944 self->ob_type->tp_name,
1945 GET_TD_DAYS(self),
1946 GET_TD_SECONDS(self),
1947 GET_TD_MICROSECONDS(self));
1948 if (GET_TD_SECONDS(self) != 0)
1949 return PyString_FromFormat("%s(%d, %d)",
1950 self->ob_type->tp_name,
1951 GET_TD_DAYS(self),
1952 GET_TD_SECONDS(self));
1953
1954 return PyString_FromFormat("%s(%d)",
1955 self->ob_type->tp_name,
1956 GET_TD_DAYS(self));
1957}
1958
1959static PyObject *
1960delta_str(PyDateTime_Delta *self)
1961{
1962 int days = GET_TD_DAYS(self);
1963 int seconds = GET_TD_SECONDS(self);
1964 int us = GET_TD_MICROSECONDS(self);
1965 int hours;
1966 int minutes;
Tim Petersba873472002-12-18 20:19:21 +00001967 char buf[100];
1968 char *pbuf = buf;
1969 size_t buflen = sizeof(buf);
1970 int n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001971
1972 minutes = divmod(seconds, 60, &seconds);
1973 hours = divmod(minutes, 60, &minutes);
1974
1975 if (days) {
Tim Petersba873472002-12-18 20:19:21 +00001976 n = PyOS_snprintf(pbuf, buflen, "%d day%s, ", days,
1977 (days == 1 || days == -1) ? "" : "s");
1978 if (n < 0 || (size_t)n >= buflen)
1979 goto Fail;
1980 pbuf += n;
1981 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001982 }
1983
Tim Petersba873472002-12-18 20:19:21 +00001984 n = PyOS_snprintf(pbuf, buflen, "%d:%02d:%02d",
1985 hours, minutes, seconds);
1986 if (n < 0 || (size_t)n >= buflen)
1987 goto Fail;
1988 pbuf += n;
1989 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001990
1991 if (us) {
Tim Petersba873472002-12-18 20:19:21 +00001992 n = PyOS_snprintf(pbuf, buflen, ".%06d", us);
1993 if (n < 0 || (size_t)n >= buflen)
1994 goto Fail;
1995 pbuf += n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001996 }
1997
Tim Petersba873472002-12-18 20:19:21 +00001998 return PyString_FromStringAndSize(buf, pbuf - buf);
1999
2000 Fail:
2001 PyErr_SetString(PyExc_SystemError, "goofy result from PyOS_snprintf");
2002 return NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00002003}
2004
2005/* Pickle support. Quite a maze! While __getstate__/__setstate__ sufficed
2006 * in the Python implementation, the C implementation also requires
2007 * __reduce__, and a __safe_for_unpickling__ attr in the type object.
2008 */
2009static PyObject *
2010delta_getstate(PyDateTime_Delta *self)
2011{
2012 return Py_BuildValue("iii", GET_TD_DAYS(self),
2013 GET_TD_SECONDS(self),
2014 GET_TD_MICROSECONDS(self));
2015}
2016
2017static PyObject *
2018delta_setstate(PyDateTime_Delta *self, PyObject *state)
2019{
2020 int day;
2021 int second;
2022 int us;
2023
2024 if (!PyArg_ParseTuple(state, "iii:__setstate__", &day, &second, &us))
2025 return NULL;
2026
2027 self->hashcode = -1;
2028 SET_TD_DAYS(self, day);
2029 SET_TD_SECONDS(self, second);
2030 SET_TD_MICROSECONDS(self, us);
2031
2032 Py_INCREF(Py_None);
2033 return Py_None;
2034}
2035
2036static PyObject *
2037delta_reduce(PyDateTime_Delta* self)
2038{
2039 PyObject* result = NULL;
2040 PyObject* state = delta_getstate(self);
2041
2042 if (state != NULL) {
2043 /* The funky "()" in the format string creates an empty
2044 * tuple as the 2nd component of the result 3-tuple.
2045 */
2046 result = Py_BuildValue("O()O", self->ob_type, state);
2047 Py_DECREF(state);
2048 }
2049 return result;
2050}
2051
2052#define OFFSET(field) offsetof(PyDateTime_Delta, field)
2053
2054static PyMemberDef delta_members[] = {
Neal Norwitzdfb80862002-12-19 02:30:56 +00002055 {"days", T_INT, OFFSET(days), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002056 PyDoc_STR("Number of days.")},
2057
Neal Norwitzdfb80862002-12-19 02:30:56 +00002058 {"seconds", T_INT, OFFSET(seconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002059 PyDoc_STR("Number of seconds (>= 0 and less than 1 day).")},
2060
Neal Norwitzdfb80862002-12-19 02:30:56 +00002061 {"microseconds", T_INT, OFFSET(microseconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002062 PyDoc_STR("Number of microseconds (>= 0 and less than 1 second).")},
2063 {NULL}
2064};
2065
2066static PyMethodDef delta_methods[] = {
2067 {"__setstate__", (PyCFunction)delta_setstate, METH_O,
2068 PyDoc_STR("__setstate__(state)")},
2069
2070 {"__reduce__", (PyCFunction)delta_reduce, METH_NOARGS,
2071 PyDoc_STR("__setstate__(state)")},
2072
2073 {"__getstate__", (PyCFunction)delta_getstate, METH_NOARGS,
2074 PyDoc_STR("__getstate__() -> state")},
2075 {NULL, NULL},
2076};
2077
2078static char delta_doc[] =
2079PyDoc_STR("Difference between two datetime values.");
2080
2081static PyNumberMethods delta_as_number = {
2082 delta_add, /* nb_add */
2083 delta_subtract, /* nb_subtract */
2084 delta_multiply, /* nb_multiply */
2085 delta_divide, /* nb_divide */
2086 0, /* nb_remainder */
2087 0, /* nb_divmod */
2088 0, /* nb_power */
2089 (unaryfunc)delta_negative, /* nb_negative */
2090 (unaryfunc)delta_positive, /* nb_positive */
2091 (unaryfunc)delta_abs, /* nb_absolute */
2092 (inquiry)delta_nonzero, /* nb_nonzero */
2093 0, /*nb_invert*/
2094 0, /*nb_lshift*/
2095 0, /*nb_rshift*/
2096 0, /*nb_and*/
2097 0, /*nb_xor*/
2098 0, /*nb_or*/
2099 0, /*nb_coerce*/
2100 0, /*nb_int*/
2101 0, /*nb_long*/
2102 0, /*nb_float*/
2103 0, /*nb_oct*/
2104 0, /*nb_hex*/
2105 0, /*nb_inplace_add*/
2106 0, /*nb_inplace_subtract*/
2107 0, /*nb_inplace_multiply*/
2108 0, /*nb_inplace_divide*/
2109 0, /*nb_inplace_remainder*/
2110 0, /*nb_inplace_power*/
2111 0, /*nb_inplace_lshift*/
2112 0, /*nb_inplace_rshift*/
2113 0, /*nb_inplace_and*/
2114 0, /*nb_inplace_xor*/
2115 0, /*nb_inplace_or*/
2116 delta_divide, /* nb_floor_divide */
2117 0, /* nb_true_divide */
2118 0, /* nb_inplace_floor_divide */
2119 0, /* nb_inplace_true_divide */
2120};
2121
2122static PyTypeObject PyDateTime_DeltaType = {
2123 PyObject_HEAD_INIT(NULL)
2124 0, /* ob_size */
2125 "datetime.timedelta", /* tp_name */
2126 sizeof(PyDateTime_Delta), /* tp_basicsize */
2127 0, /* tp_itemsize */
2128 0, /* tp_dealloc */
2129 0, /* tp_print */
2130 0, /* tp_getattr */
2131 0, /* tp_setattr */
2132 0, /* tp_compare */
2133 (reprfunc)delta_repr, /* tp_repr */
2134 &delta_as_number, /* tp_as_number */
2135 0, /* tp_as_sequence */
2136 0, /* tp_as_mapping */
2137 (hashfunc)delta_hash, /* tp_hash */
2138 0, /* tp_call */
2139 (reprfunc)delta_str, /* tp_str */
2140 PyObject_GenericGetAttr, /* tp_getattro */
2141 0, /* tp_setattro */
2142 0, /* tp_as_buffer */
2143 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
2144 delta_doc, /* tp_doc */
2145 0, /* tp_traverse */
2146 0, /* tp_clear */
2147 (richcmpfunc)delta_richcompare, /* tp_richcompare */
2148 0, /* tp_weaklistoffset */
2149 0, /* tp_iter */
2150 0, /* tp_iternext */
2151 delta_methods, /* tp_methods */
2152 delta_members, /* tp_members */
2153 0, /* tp_getset */
2154 0, /* tp_base */
2155 0, /* tp_dict */
2156 0, /* tp_descr_get */
2157 0, /* tp_descr_set */
2158 0, /* tp_dictoffset */
2159 0, /* tp_init */
2160 0, /* tp_alloc */
2161 delta_new, /* tp_new */
2162 _PyObject_Del, /* tp_free */
2163};
2164
2165/*
2166 * PyDateTime_Date implementation.
2167 */
2168
2169/* Accessor properties. */
2170
2171static PyObject *
2172date_year(PyDateTime_Date *self, void *unused)
2173{
2174 return PyInt_FromLong(GET_YEAR(self));
2175}
2176
2177static PyObject *
2178date_month(PyDateTime_Date *self, void *unused)
2179{
2180 return PyInt_FromLong(GET_MONTH(self));
2181}
2182
2183static PyObject *
2184date_day(PyDateTime_Date *self, void *unused)
2185{
2186 return PyInt_FromLong(GET_DAY(self));
2187}
2188
2189static PyGetSetDef date_getset[] = {
2190 {"year", (getter)date_year},
2191 {"month", (getter)date_month},
2192 {"day", (getter)date_day},
2193 {NULL}
2194};
2195
2196/* Constructors. */
2197
Tim Peters12bf3392002-12-24 05:41:27 +00002198static char *date_kws[] = {"year", "month", "day", NULL};
2199
Tim Peters2a799bf2002-12-16 20:18:38 +00002200static PyObject *
2201date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2202{
2203 PyObject *self = NULL;
2204 int year;
2205 int month;
2206 int day;
2207
Tim Peters12bf3392002-12-24 05:41:27 +00002208 if (PyArg_ParseTupleAndKeywords(args, kw, "iii", date_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002209 &year, &month, &day)) {
2210 if (check_date_args(year, month, day) < 0)
2211 return NULL;
2212 self = new_date(year, month, day);
2213 }
2214 return self;
2215}
2216
2217/* Return new date from localtime(t). */
2218static PyObject *
2219date_local_from_time_t(PyObject *cls, time_t t)
2220{
2221 struct tm *tm;
2222 PyObject *result = NULL;
2223
2224 tm = localtime(&t);
2225 if (tm)
2226 result = PyObject_CallFunction(cls, "iii",
2227 tm->tm_year + 1900,
2228 tm->tm_mon + 1,
2229 tm->tm_mday);
2230 else
2231 PyErr_SetString(PyExc_ValueError,
2232 "timestamp out of range for "
2233 "platform localtime() function");
2234 return result;
2235}
2236
2237/* Return new date from current time.
2238 * We say this is equivalent to fromtimestamp(time.time()), and the
2239 * only way to be sure of that is to *call* time.time(). That's not
2240 * generally the same as calling C's time.
2241 */
2242static PyObject *
2243date_today(PyObject *cls, PyObject *dummy)
2244{
2245 PyObject *time;
2246 PyObject *result;
2247
2248 time = time_time();
2249 if (time == NULL)
2250 return NULL;
2251
2252 /* Note well: today() is a class method, so this may not call
2253 * date.fromtimestamp. For example, it may call
2254 * datetime.fromtimestamp. That's why we need all the accuracy
2255 * time.time() delivers; if someone were gonzo about optimization,
2256 * date.today() could get away with plain C time().
2257 */
2258 result = PyObject_CallMethod(cls, "fromtimestamp", "O", time);
2259 Py_DECREF(time);
2260 return result;
2261}
2262
2263/* Return new date from given timestamp (Python timestamp -- a double). */
2264static PyObject *
2265date_fromtimestamp(PyObject *cls, PyObject *args)
2266{
2267 double timestamp;
2268 PyObject *result = NULL;
2269
2270 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2271 result = date_local_from_time_t(cls, (time_t)timestamp);
2272 return result;
2273}
2274
2275/* Return new date from proleptic Gregorian ordinal. Raises ValueError if
2276 * the ordinal is out of range.
2277 */
2278static PyObject *
2279date_fromordinal(PyObject *cls, PyObject *args)
2280{
2281 PyObject *result = NULL;
2282 int ordinal;
2283
2284 if (PyArg_ParseTuple(args, "i:fromordinal", &ordinal)) {
2285 int year;
2286 int month;
2287 int day;
2288
2289 if (ordinal < 1)
2290 PyErr_SetString(PyExc_ValueError, "ordinal must be "
2291 ">= 1");
2292 else {
2293 ord_to_ymd(ordinal, &year, &month, &day);
2294 result = PyObject_CallFunction(cls, "iii",
2295 year, month, day);
2296 }
2297 }
2298 return result;
2299}
2300
2301/*
2302 * Date arithmetic.
2303 */
2304
2305/* date + timedelta -> date. If arg negate is true, subtract the timedelta
2306 * instead.
2307 */
2308static PyObject *
2309add_date_timedelta(PyDateTime_Date *date, PyDateTime_Delta *delta, int negate)
2310{
2311 PyObject *result = NULL;
2312 int year = GET_YEAR(date);
2313 int month = GET_MONTH(date);
2314 int deltadays = GET_TD_DAYS(delta);
2315 /* C-level overflow is impossible because |deltadays| < 1e9. */
2316 int day = GET_DAY(date) + (negate ? -deltadays : deltadays);
2317
2318 if (normalize_date(&year, &month, &day) >= 0)
2319 result = new_date(year, month, day);
2320 return result;
2321}
2322
2323static PyObject *
2324date_add(PyObject *left, PyObject *right)
2325{
2326 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2327 Py_INCREF(Py_NotImplemented);
2328 return Py_NotImplemented;
2329 }
2330 if (PyDate_CheckExact(left)) {
2331 /* date + ??? */
2332 if (PyDelta_Check(right))
2333 /* date + delta */
2334 return add_date_timedelta((PyDateTime_Date *) left,
2335 (PyDateTime_Delta *) right,
2336 0);
2337 }
2338 else {
2339 /* ??? + date
2340 * 'right' must be one of us, or we wouldn't have been called
2341 */
2342 if (PyDelta_Check(left))
2343 /* delta + date */
2344 return add_date_timedelta((PyDateTime_Date *) right,
2345 (PyDateTime_Delta *) left,
2346 0);
2347 }
2348 Py_INCREF(Py_NotImplemented);
2349 return Py_NotImplemented;
2350}
2351
2352static PyObject *
2353date_subtract(PyObject *left, PyObject *right)
2354{
2355 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2356 Py_INCREF(Py_NotImplemented);
2357 return Py_NotImplemented;
2358 }
2359 if (PyDate_CheckExact(left)) {
2360 if (PyDate_CheckExact(right)) {
2361 /* date - date */
2362 int left_ord = ymd_to_ord(GET_YEAR(left),
2363 GET_MONTH(left),
2364 GET_DAY(left));
2365 int right_ord = ymd_to_ord(GET_YEAR(right),
2366 GET_MONTH(right),
2367 GET_DAY(right));
2368 return new_delta(left_ord - right_ord, 0, 0, 0);
2369 }
2370 if (PyDelta_Check(right)) {
2371 /* date - delta */
2372 return add_date_timedelta((PyDateTime_Date *) left,
2373 (PyDateTime_Delta *) right,
2374 1);
2375 }
2376 }
2377 Py_INCREF(Py_NotImplemented);
2378 return Py_NotImplemented;
2379}
2380
2381
2382/* Various ways to turn a date into a string. */
2383
2384static PyObject *
2385date_repr(PyDateTime_Date *self)
2386{
2387 char buffer[1028];
2388 char *typename;
2389
2390 typename = self->ob_type->tp_name;
2391 PyOS_snprintf(buffer, sizeof(buffer), "%s(%d, %d, %d)",
2392 typename,
2393 GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2394
2395 return PyString_FromString(buffer);
2396}
2397
2398static PyObject *
2399date_isoformat(PyDateTime_Date *self)
2400{
2401 char buffer[128];
2402
2403 isoformat_date(self, buffer, sizeof(buffer));
2404 return PyString_FromString(buffer);
2405}
2406
2407/* str() calls the appropriate isofomat() method. */
2408static PyObject *
2409date_str(PyDateTime_Date *self)
2410{
2411 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
2412}
2413
2414
2415static PyObject *
2416date_ctime(PyDateTime_Date *self)
2417{
2418 return format_ctime(self, 0, 0, 0);
2419}
2420
2421static PyObject *
2422date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2423{
2424 /* This method can be inherited, and needs to call the
2425 * timetuple() method appropriate to self's class.
2426 */
2427 PyObject *result;
2428 PyObject *format;
2429 PyObject *tuple;
2430 static char *keywords[] = {"format", NULL};
2431
2432 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
2433 &PyString_Type, &format))
2434 return NULL;
2435
2436 tuple = PyObject_CallMethod((PyObject *)self, "timetuple", "()");
2437 if (tuple == NULL)
2438 return NULL;
Tim Petersbad8ff02002-12-30 20:52:32 +00002439 result = wrap_strftime((PyObject *)self, format, tuple,
2440 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00002441 Py_DECREF(tuple);
2442 return result;
2443}
2444
2445/* ISO methods. */
2446
2447static PyObject *
2448date_isoweekday(PyDateTime_Date *self)
2449{
2450 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2451
2452 return PyInt_FromLong(dow + 1);
2453}
2454
2455static PyObject *
2456date_isocalendar(PyDateTime_Date *self)
2457{
2458 int year = GET_YEAR(self);
2459 int week1_monday = iso_week1_monday(year);
2460 int today = ymd_to_ord(year, GET_MONTH(self), GET_DAY(self));
2461 int week;
2462 int day;
2463
2464 week = divmod(today - week1_monday, 7, &day);
2465 if (week < 0) {
2466 --year;
2467 week1_monday = iso_week1_monday(year);
2468 week = divmod(today - week1_monday, 7, &day);
2469 }
2470 else if (week >= 52 && today >= iso_week1_monday(year + 1)) {
2471 ++year;
2472 week = 0;
2473 }
2474 return Py_BuildValue("iii", year, week + 1, day + 1);
2475}
2476
2477/* Miscellaneous methods. */
2478
2479/* This is more natural as a tp_compare, but doesn't work then: for whatever
2480 * reason, Python's try_3way_compare ignores tp_compare unless
2481 * PyInstance_Check returns true, but these aren't old-style classes.
2482 */
2483static PyObject *
2484date_richcompare(PyDateTime_Date *self, PyObject *other, int op)
2485{
2486 int diff;
2487
2488 if (! PyDate_Check(other)) {
2489 PyErr_Format(PyExc_TypeError,
2490 "can't compare date to %s instance",
2491 other->ob_type->tp_name);
2492 return NULL;
2493 }
2494 diff = memcmp(self->data, ((PyDateTime_Date *)other)->data,
2495 _PyDateTime_DATE_DATASIZE);
2496 return diff_to_bool(diff, op);
2497}
2498
2499static PyObject *
2500date_timetuple(PyDateTime_Date *self)
2501{
2502 return build_struct_time(GET_YEAR(self),
2503 GET_MONTH(self),
2504 GET_DAY(self),
2505 0, 0, 0, -1);
2506}
2507
Tim Peters12bf3392002-12-24 05:41:27 +00002508static PyObject *
2509date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2510{
2511 PyObject *clone;
2512 PyObject *tuple;
2513 int year = GET_YEAR(self);
2514 int month = GET_MONTH(self);
2515 int day = GET_DAY(self);
2516
2517 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iii:replace", date_kws,
2518 &year, &month, &day))
2519 return NULL;
2520 tuple = Py_BuildValue("iii", year, month, day);
2521 if (tuple == NULL)
2522 return NULL;
2523 clone = date_new(self->ob_type, tuple, NULL);
2524 Py_DECREF(tuple);
2525 return clone;
2526}
2527
Tim Peters2a799bf2002-12-16 20:18:38 +00002528static PyObject *date_getstate(PyDateTime_Date *self);
2529
2530static long
2531date_hash(PyDateTime_Date *self)
2532{
2533 if (self->hashcode == -1) {
2534 PyObject *temp = date_getstate(self);
2535 if (temp != NULL) {
2536 self->hashcode = PyObject_Hash(temp);
2537 Py_DECREF(temp);
2538 }
2539 }
2540 return self->hashcode;
2541}
2542
2543static PyObject *
2544date_toordinal(PyDateTime_Date *self)
2545{
2546 return PyInt_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self),
2547 GET_DAY(self)));
2548}
2549
2550static PyObject *
2551date_weekday(PyDateTime_Date *self)
2552{
2553 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2554
2555 return PyInt_FromLong(dow);
2556}
2557
2558/* Pickle support. Quite a maze! */
2559
2560static PyObject *
2561date_getstate(PyDateTime_Date *self)
2562{
2563 return PyString_FromStringAndSize(self->data,
2564 _PyDateTime_DATE_DATASIZE);
2565}
2566
2567static PyObject *
2568date_setstate(PyDateTime_Date *self, PyObject *state)
2569{
2570 const int len = PyString_Size(state);
2571 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
2572
2573 if (! PyString_Check(state) ||
2574 len != _PyDateTime_DATE_DATASIZE) {
2575 PyErr_SetString(PyExc_TypeError,
2576 "bad argument to date.__setstate__");
2577 return NULL;
2578 }
2579 memcpy(self->data, pdata, _PyDateTime_DATE_DATASIZE);
2580 self->hashcode = -1;
2581
2582 Py_INCREF(Py_None);
2583 return Py_None;
2584}
2585
2586/* XXX This seems a ridiculously inefficient way to pickle a short string. */
2587static PyObject *
2588date_pickler(PyObject *module, PyDateTime_Date *date)
2589{
2590 PyObject *state;
2591 PyObject *result = NULL;
2592
2593 if (! PyDate_CheckExact(date)) {
2594 PyErr_Format(PyExc_TypeError,
2595 "bad type passed to date pickler: %s",
2596 date->ob_type->tp_name);
2597 return NULL;
2598 }
2599 state = date_getstate(date);
2600 if (state) {
2601 result = Py_BuildValue("O(O)", date_unpickler_object, state);
2602 Py_DECREF(state);
2603 }
2604 return result;
2605}
2606
2607static PyObject *
2608date_unpickler(PyObject *module, PyObject *arg)
2609{
2610 PyDateTime_Date *self;
2611
2612 if (! PyString_CheckExact(arg)) {
2613 PyErr_Format(PyExc_TypeError,
2614 "bad type passed to date unpickler: %s",
2615 arg->ob_type->tp_name);
2616 return NULL;
2617 }
2618 self = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
2619 if (self != NULL) {
2620 PyObject *res = date_setstate(self, arg);
2621 if (res == NULL) {
2622 Py_DECREF(self);
2623 return NULL;
2624 }
2625 Py_DECREF(res);
2626 }
2627 return (PyObject *)self;
2628}
2629
2630static PyMethodDef date_methods[] = {
2631 /* Class methods: */
2632 {"fromtimestamp", (PyCFunction)date_fromtimestamp, METH_VARARGS |
2633 METH_CLASS,
2634 PyDoc_STR("timestamp -> local date from a POSIX timestamp (like "
2635 "time.time()).")},
2636
2637 {"fromordinal", (PyCFunction)date_fromordinal, METH_VARARGS |
2638 METH_CLASS,
2639 PyDoc_STR("int -> date corresponding to a proleptic Gregorian "
2640 "ordinal.")},
2641
2642 {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS,
2643 PyDoc_STR("Current date or datetime: same as "
2644 "self.__class__.fromtimestamp(time.time()).")},
2645
2646 /* Instance methods: */
2647
2648 {"ctime", (PyCFunction)date_ctime, METH_NOARGS,
2649 PyDoc_STR("Return ctime() style string.")},
2650
2651 {"strftime", (PyCFunction)date_strftime, METH_KEYWORDS,
2652 PyDoc_STR("format -> strftime() style string.")},
2653
2654 {"timetuple", (PyCFunction)date_timetuple, METH_NOARGS,
2655 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
2656
2657 {"isocalendar", (PyCFunction)date_isocalendar, METH_NOARGS,
2658 PyDoc_STR("Return a 3-tuple containing ISO year, week number, and "
2659 "weekday.")},
2660
2661 {"isoformat", (PyCFunction)date_isoformat, METH_NOARGS,
2662 PyDoc_STR("Return string in ISO 8601 format, YYYY-MM-DD.")},
2663
2664 {"isoweekday", (PyCFunction)date_isoweekday, METH_NOARGS,
2665 PyDoc_STR("Return the day of the week represented by the date.\n"
2666 "Monday == 1 ... Sunday == 7")},
2667
2668 {"toordinal", (PyCFunction)date_toordinal, METH_NOARGS,
2669 PyDoc_STR("Return proleptic Gregorian ordinal. January 1 of year "
2670 "1 is day 1.")},
2671
2672 {"weekday", (PyCFunction)date_weekday, METH_NOARGS,
2673 PyDoc_STR("Return the day of the week represented by the date.\n"
2674 "Monday == 0 ... Sunday == 6")},
2675
Tim Peters12bf3392002-12-24 05:41:27 +00002676 {"replace", (PyCFunction)date_replace, METH_KEYWORDS,
2677 PyDoc_STR("Return date with new specified fields.")},
2678
Tim Peters2a799bf2002-12-16 20:18:38 +00002679 {"__setstate__", (PyCFunction)date_setstate, METH_O,
2680 PyDoc_STR("__setstate__(state)")},
2681
2682 {"__getstate__", (PyCFunction)date_getstate, METH_NOARGS,
2683 PyDoc_STR("__getstate__() -> state")},
2684
2685 {NULL, NULL}
2686};
2687
2688static char date_doc[] =
2689PyDoc_STR("Basic date type.");
2690
2691static PyNumberMethods date_as_number = {
2692 date_add, /* nb_add */
2693 date_subtract, /* nb_subtract */
2694 0, /* nb_multiply */
2695 0, /* nb_divide */
2696 0, /* nb_remainder */
2697 0, /* nb_divmod */
2698 0, /* nb_power */
2699 0, /* nb_negative */
2700 0, /* nb_positive */
2701 0, /* nb_absolute */
2702 0, /* nb_nonzero */
2703};
2704
2705static PyTypeObject PyDateTime_DateType = {
2706 PyObject_HEAD_INIT(NULL)
2707 0, /* ob_size */
2708 "datetime.date", /* tp_name */
2709 sizeof(PyDateTime_Date), /* tp_basicsize */
2710 0, /* tp_itemsize */
2711 (destructor)PyObject_Del, /* tp_dealloc */
2712 0, /* tp_print */
2713 0, /* tp_getattr */
2714 0, /* tp_setattr */
2715 0, /* tp_compare */
2716 (reprfunc)date_repr, /* tp_repr */
2717 &date_as_number, /* tp_as_number */
2718 0, /* tp_as_sequence */
2719 0, /* tp_as_mapping */
2720 (hashfunc)date_hash, /* tp_hash */
2721 0, /* tp_call */
2722 (reprfunc)date_str, /* tp_str */
2723 PyObject_GenericGetAttr, /* tp_getattro */
2724 0, /* tp_setattro */
2725 0, /* tp_as_buffer */
2726 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
2727 Py_TPFLAGS_BASETYPE, /* tp_flags */
2728 date_doc, /* tp_doc */
2729 0, /* tp_traverse */
2730 0, /* tp_clear */
2731 (richcmpfunc)date_richcompare, /* tp_richcompare */
2732 0, /* tp_weaklistoffset */
2733 0, /* tp_iter */
2734 0, /* tp_iternext */
2735 date_methods, /* tp_methods */
2736 0, /* tp_members */
2737 date_getset, /* tp_getset */
2738 0, /* tp_base */
2739 0, /* tp_dict */
2740 0, /* tp_descr_get */
2741 0, /* tp_descr_set */
2742 0, /* tp_dictoffset */
2743 0, /* tp_init */
2744 0, /* tp_alloc */
2745 date_new, /* tp_new */
2746 _PyObject_Del, /* tp_free */
2747};
2748
2749/*
2750 * PyDateTime_DateTime implementation.
2751 */
2752
2753/* Accessor properties. */
2754
2755static PyObject *
2756datetime_hour(PyDateTime_DateTime *self, void *unused)
2757{
2758 return PyInt_FromLong(DATE_GET_HOUR(self));
2759}
2760
2761static PyObject *
2762datetime_minute(PyDateTime_DateTime *self, void *unused)
2763{
2764 return PyInt_FromLong(DATE_GET_MINUTE(self));
2765}
2766
2767static PyObject *
2768datetime_second(PyDateTime_DateTime *self, void *unused)
2769{
2770 return PyInt_FromLong(DATE_GET_SECOND(self));
2771}
2772
2773static PyObject *
2774datetime_microsecond(PyDateTime_DateTime *self, void *unused)
2775{
2776 return PyInt_FromLong(DATE_GET_MICROSECOND(self));
2777}
2778
2779static PyGetSetDef datetime_getset[] = {
2780 {"hour", (getter)datetime_hour},
2781 {"minute", (getter)datetime_minute},
2782 {"second", (getter)datetime_second},
2783 {"microsecond", (getter)datetime_microsecond},
2784 {NULL}
2785};
2786
2787/* Constructors. */
2788
Tim Peters12bf3392002-12-24 05:41:27 +00002789
2790static char *datetime_kws[] = {"year", "month", "day",
2791 "hour", "minute", "second", "microsecond",
2792 NULL};
2793
Tim Peters2a799bf2002-12-16 20:18:38 +00002794static PyObject *
2795datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2796{
2797 PyObject *self = NULL;
2798 int year;
2799 int month;
2800 int day;
2801 int hour = 0;
2802 int minute = 0;
2803 int second = 0;
2804 int usecond = 0;
2805
Tim Peters12bf3392002-12-24 05:41:27 +00002806 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiii", datetime_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002807 &year, &month, &day, &hour, &minute,
2808 &second, &usecond)) {
2809 if (check_date_args(year, month, day) < 0)
2810 return NULL;
2811 if (check_time_args(hour, minute, second, usecond) < 0)
2812 return NULL;
2813 self = new_datetime(year, month, day,
2814 hour, minute, second, usecond);
2815 }
2816 return self;
2817}
2818
2819
2820/* TM_FUNC is the shared type of localtime() and gmtime(). */
2821typedef struct tm *(*TM_FUNC)(const time_t *timer);
2822
2823/* Internal helper.
2824 * Build datetime from a time_t and a distinct count of microseconds.
2825 * Pass localtime or gmtime for f, to control the interpretation of timet.
2826 */
2827static PyObject *
2828datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us)
2829{
2830 struct tm *tm;
2831 PyObject *result = NULL;
2832
2833 tm = f(&timet);
2834 if (tm)
2835 result = PyObject_CallFunction(cls, "iiiiiii",
2836 tm->tm_year + 1900,
2837 tm->tm_mon + 1,
2838 tm->tm_mday,
2839 tm->tm_hour,
2840 tm->tm_min,
2841 tm->tm_sec,
2842 us);
2843 else
2844 PyErr_SetString(PyExc_ValueError,
2845 "timestamp out of range for "
2846 "platform localtime()/gmtime() function");
2847 return result;
2848}
2849
2850/* Internal helper.
2851 * Build datetime from a Python timestamp. Pass localtime or gmtime for f,
2852 * to control the interpretation of the timestamp. Since a double doesn't
2853 * have enough bits to cover a datetime's full range of precision, it's
2854 * better to call datetime_from_timet_and_us provided you have a way
2855 * to get that much precision (e.g., C time() isn't good enough).
2856 */
2857static PyObject *
2858datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp)
2859{
2860 time_t timet = (time_t)timestamp;
2861 int us = (int)((timestamp - (double)timet) * 1e6);
2862
2863 return datetime_from_timet_and_us(cls, f, timet, us);
2864}
2865
2866/* Internal helper.
2867 * Build most accurate possible datetime for current time. Pass localtime or
2868 * gmtime for f as appropriate.
2869 */
2870static PyObject *
2871datetime_best_possible(PyObject *cls, TM_FUNC f)
2872{
2873#ifdef HAVE_GETTIMEOFDAY
2874 struct timeval t;
2875
2876#ifdef GETTIMEOFDAY_NO_TZ
2877 gettimeofday(&t);
2878#else
2879 gettimeofday(&t, (struct timezone *)NULL);
2880#endif
2881 return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec);
2882
2883#else /* ! HAVE_GETTIMEOFDAY */
2884 /* No flavor of gettimeofday exists on this platform. Python's
2885 * time.time() does a lot of other platform tricks to get the
2886 * best time it can on the platform, and we're not going to do
2887 * better than that (if we could, the better code would belong
2888 * in time.time()!) We're limited by the precision of a double,
2889 * though.
2890 */
2891 PyObject *time;
2892 double dtime;
2893
2894 time = time_time();
2895 if (time == NULL)
2896 return NULL;
2897 dtime = PyFloat_AsDouble(time);
2898 Py_DECREF(time);
2899 if (dtime == -1.0 && PyErr_Occurred())
2900 return NULL;
2901 return datetime_from_timestamp(cls, f, dtime);
2902#endif /* ! HAVE_GETTIMEOFDAY */
2903}
2904
2905/* Return new local datetime from timestamp (Python timestamp -- a double). */
2906static PyObject *
2907datetime_fromtimestamp(PyObject *cls, PyObject *args)
2908{
2909 double timestamp;
2910 PyObject *result = NULL;
2911
2912 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2913 result = datetime_from_timestamp(cls, localtime, timestamp);
2914 return result;
2915}
2916
2917/* Return new UTC datetime from timestamp (Python timestamp -- a double). */
2918static PyObject *
2919datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
2920{
2921 double timestamp;
2922 PyObject *result = NULL;
2923
2924 if (PyArg_ParseTuple(args, "d:utcfromtimestamp", &timestamp))
2925 result = datetime_from_timestamp(cls, gmtime, timestamp);
2926 return result;
2927}
2928
2929/* Return best possible local time -- this isn't constrained by the
2930 * precision of a timestamp.
2931 */
2932static PyObject *
2933datetime_now(PyObject *cls, PyObject *dummy)
2934{
2935 return datetime_best_possible(cls, localtime);
2936}
2937
2938/* Return best possible UTC time -- this isn't constrained by the
2939 * precision of a timestamp.
2940 */
2941static PyObject *
2942datetime_utcnow(PyObject *cls, PyObject *dummy)
2943{
2944 return datetime_best_possible(cls, gmtime);
2945}
2946
2947/* Return new datetime or datetimetz from date/datetime/datetimetz and
2948 * time/timetz arguments.
2949 */
2950static PyObject *
2951datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
2952{
2953 static char *keywords[] = {"date", "time", NULL};
2954 PyObject *date;
2955 PyObject *time;
2956 PyObject *result = NULL;
2957
2958 if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!:combine", keywords,
2959 &PyDateTime_DateType, &date,
2960 &PyDateTime_TimeType, &time))
2961 result = PyObject_CallFunction(cls, "iiiiiii",
2962 GET_YEAR(date),
2963 GET_MONTH(date),
2964 GET_DAY(date),
2965 TIME_GET_HOUR(time),
2966 TIME_GET_MINUTE(time),
2967 TIME_GET_SECOND(time),
2968 TIME_GET_MICROSECOND(time));
2969 if (result && PyTimeTZ_Check(time) && PyDateTimeTZ_Check(result)) {
2970 /* Copy the tzinfo field. */
Tim Peters80475bb2002-12-25 07:40:55 +00002971 replace_tzinfo(result, ((PyDateTime_TimeTZ *)time)->tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00002972 }
2973 return result;
2974}
2975
2976/* datetime arithmetic. */
2977
2978static PyObject *
2979add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
2980{
2981 /* Note that the C-level additions can't overflow, because of
2982 * invariant bounds on the member values.
2983 */
2984 int year = GET_YEAR(date);
2985 int month = GET_MONTH(date);
2986 int day = GET_DAY(date) + GET_TD_DAYS(delta);
2987 int hour = DATE_GET_HOUR(date);
2988 int minute = DATE_GET_MINUTE(date);
2989 int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta);
2990 int microsecond = DATE_GET_MICROSECOND(date) +
2991 GET_TD_MICROSECONDS(delta);
2992
2993 if (normalize_datetime(&year, &month, &day,
2994 &hour, &minute, &second, &microsecond) < 0)
2995 return NULL;
2996 else
2997 return new_datetime(year, month, day,
2998 hour, minute, second, microsecond);
2999}
3000
3001static PyObject *
3002sub_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
3003{
3004 /* Note that the C-level subtractions can't overflow, because of
3005 * invariant bounds on the member values.
3006 */
3007 int year = GET_YEAR(date);
3008 int month = GET_MONTH(date);
3009 int day = GET_DAY(date) - GET_TD_DAYS(delta);
3010 int hour = DATE_GET_HOUR(date);
3011 int minute = DATE_GET_MINUTE(date);
3012 int second = DATE_GET_SECOND(date) - GET_TD_SECONDS(delta);
3013 int microsecond = DATE_GET_MICROSECOND(date) -
3014 GET_TD_MICROSECONDS(delta);
3015
3016 if (normalize_datetime(&year, &month, &day,
3017 &hour, &minute, &second, &microsecond) < 0)
3018 return NULL;
3019 else
3020 return new_datetime(year, month, day,
3021 hour, minute, second, microsecond);
3022}
3023
3024static PyObject *
3025sub_datetime_datetime(PyDateTime_DateTime *left, PyDateTime_DateTime *right)
3026{
3027 int days1 = ymd_to_ord(GET_YEAR(left), GET_MONTH(left), GET_DAY(left));
3028 int days2 = ymd_to_ord(GET_YEAR(right),
3029 GET_MONTH(right),
3030 GET_DAY(right));
3031 /* These can't overflow, since the values are normalized. At most
3032 * this gives the number of seconds in one day.
3033 */
3034 int delta_s = (DATE_GET_HOUR(left) - DATE_GET_HOUR(right)) * 3600 +
3035 (DATE_GET_MINUTE(left) - DATE_GET_MINUTE(right)) * 60 +
3036 DATE_GET_SECOND(left) - DATE_GET_SECOND(right);
3037 int delta_us = DATE_GET_MICROSECOND(left) -
3038 DATE_GET_MICROSECOND(right);
3039
3040 return new_delta(days1 - days2, delta_s, delta_us, 1);
3041}
3042
3043static PyObject *
3044datetime_add(PyObject *left, PyObject *right)
3045{
3046 if (PyDateTime_Check(left)) {
3047 /* datetime + ??? */
3048 if (PyDelta_Check(right))
3049 /* datetime + delta */
3050 return add_datetime_timedelta(
3051 (PyDateTime_DateTime *)left,
3052 (PyDateTime_Delta *)right);
3053 }
3054 else if (PyDelta_Check(left)) {
3055 /* delta + datetime */
3056 return add_datetime_timedelta((PyDateTime_DateTime *) right,
3057 (PyDateTime_Delta *) left);
3058 }
3059 Py_INCREF(Py_NotImplemented);
3060 return Py_NotImplemented;
3061}
3062
3063static PyObject *
3064datetime_subtract(PyObject *left, PyObject *right)
3065{
3066 PyObject *result = Py_NotImplemented;
3067
3068 if (PyDateTime_Check(left)) {
3069 /* datetime - ??? */
3070 if (PyDateTime_Check(right)) {
3071 /* datetime - datetime */
3072 result = sub_datetime_datetime(
3073 (PyDateTime_DateTime *)left,
3074 (PyDateTime_DateTime *)right);
3075 }
3076 else if (PyDelta_Check(right)) {
3077 /* datetime - delta */
3078 result = sub_datetime_timedelta(
3079 (PyDateTime_DateTime *)left,
3080 (PyDateTime_Delta *)right);
3081 }
3082 }
3083
3084 if (result == Py_NotImplemented)
3085 Py_INCREF(result);
3086 return result;
3087}
3088
3089/* Various ways to turn a datetime into a string. */
3090
3091static PyObject *
3092datetime_repr(PyDateTime_DateTime *self)
3093{
3094 char buffer[1000];
3095 char *typename = self->ob_type->tp_name;
3096
3097 if (DATE_GET_MICROSECOND(self)) {
3098 PyOS_snprintf(buffer, sizeof(buffer),
3099 "%s(%d, %d, %d, %d, %d, %d, %d)",
3100 typename,
3101 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3102 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3103 DATE_GET_SECOND(self),
3104 DATE_GET_MICROSECOND(self));
3105 }
3106 else if (DATE_GET_SECOND(self)) {
3107 PyOS_snprintf(buffer, sizeof(buffer),
3108 "%s(%d, %d, %d, %d, %d, %d)",
3109 typename,
3110 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3111 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3112 DATE_GET_SECOND(self));
3113 }
3114 else {
3115 PyOS_snprintf(buffer, sizeof(buffer),
3116 "%s(%d, %d, %d, %d, %d)",
3117 typename,
3118 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3119 DATE_GET_HOUR(self), DATE_GET_MINUTE(self));
3120 }
3121 return PyString_FromString(buffer);
3122}
3123
3124static PyObject *
3125datetime_str(PyDateTime_DateTime *self)
3126{
3127 return PyObject_CallMethod((PyObject *)self, "isoformat", "(s)", " ");
3128}
3129
3130static PyObject *
3131datetime_isoformat(PyDateTime_DateTime *self,
3132 PyObject *args, PyObject *kw)
3133{
3134 char sep = 'T';
3135 static char *keywords[] = {"sep", NULL};
3136 char buffer[100];
3137 char *cp;
3138
3139 if (!PyArg_ParseTupleAndKeywords(args, kw, "|c:isoformat", keywords,
3140 &sep))
3141 return NULL;
3142 cp = isoformat_date((PyDateTime_Date *)self, buffer, sizeof(buffer));
3143 assert(cp != NULL);
3144 *cp++ = sep;
3145 isoformat_time(self, cp, sizeof(buffer) - (cp - buffer));
3146 return PyString_FromString(buffer);
3147}
3148
3149static PyObject *
3150datetime_ctime(PyDateTime_DateTime *self)
3151{
3152 return format_ctime((PyDateTime_Date *)self,
3153 DATE_GET_HOUR(self),
3154 DATE_GET_MINUTE(self),
3155 DATE_GET_SECOND(self));
3156}
3157
3158/* Miscellaneous methods. */
3159
3160/* This is more natural as a tp_compare, but doesn't work then: for whatever
3161 * reason, Python's try_3way_compare ignores tp_compare unless
3162 * PyInstance_Check returns true, but these aren't old-style classes.
3163 * Note that this routine handles all comparisons for datetime and datetimetz.
3164 */
3165static PyObject *
3166datetime_richcompare(PyDateTime_DateTime *self, PyObject *other, int op)
3167{
3168 int diff;
3169 naivety n1, n2;
3170 int offset1, offset2;
3171
3172 if (! PyDateTime_Check(other)) {
3173 /* Stop this from falling back to address comparison. */
3174 PyErr_Format(PyExc_TypeError,
3175 "can't compare '%s' to '%s'",
3176 self->ob_type->tp_name,
3177 other->ob_type->tp_name);
3178 return NULL;
3179 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003180
Tim Peters00237032002-12-27 02:21:51 +00003181 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1,
Tim Peterse39a80c2002-12-30 21:28:52 +00003182 (PyObject *)self,
3183 other, &offset2, &n2,
3184 other) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003185 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003186 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters60c76e42002-12-27 00:41:11 +00003187 /* If they're both naive, or both aware and have the same offsets,
Tim Peters2a799bf2002-12-16 20:18:38 +00003188 * we get off cheap. Note that if they're both naive, offset1 ==
3189 * offset2 == 0 at this point.
3190 */
3191 if (n1 == n2 && offset1 == offset2) {
3192 diff = memcmp(self->data, ((PyDateTime_DateTime *)other)->data,
3193 _PyDateTime_DATETIME_DATASIZE);
3194 return diff_to_bool(diff, op);
3195 }
3196
3197 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3198 /* We want the sign of
3199 * (self - offset1 minutes) - (other - offset2 minutes) =
3200 * (self - other) + (offset2 - offset1) minutes.
3201 */
3202 PyDateTime_Delta *delta;
3203 int days, seconds, us;
3204
3205 assert(offset1 != offset2); /* else last "if" handled it */
3206 delta = (PyDateTime_Delta *)sub_datetime_datetime(self,
3207 (PyDateTime_DateTime *)other);
3208 if (delta == NULL)
3209 return NULL;
3210 days = delta->days;
3211 seconds = delta->seconds + (offset2 - offset1) * 60;
3212 us = delta->microseconds;
3213 Py_DECREF(delta);
3214 normalize_d_s_us(&days, &seconds, &us);
3215 diff = days;
3216 if (diff == 0)
3217 diff = seconds | us;
3218 return diff_to_bool(diff, op);
3219 }
3220
3221 assert(n1 != n2);
3222 PyErr_SetString(PyExc_TypeError,
3223 "can't compare offset-naive and "
3224 "offset-aware datetimes");
3225 return NULL;
3226}
3227
3228static PyObject *datetime_getstate(PyDateTime_DateTime *self);
3229
3230static long
3231datetime_hash(PyDateTime_DateTime *self)
3232{
3233 if (self->hashcode == -1) {
3234 naivety n;
3235 int offset;
3236 PyObject *temp;
3237
Tim Peterse39a80c2002-12-30 21:28:52 +00003238 n = classify_utcoffset((PyObject *)self, (PyObject *)self,
3239 &offset);
Tim Peters2a799bf2002-12-16 20:18:38 +00003240 assert(n != OFFSET_UNKNOWN);
3241 if (n == OFFSET_ERROR)
3242 return -1;
3243
3244 /* Reduce this to a hash of another object. */
3245 if (n == OFFSET_NAIVE)
3246 temp = datetime_getstate(self);
3247 else {
3248 int days;
3249 int seconds;
3250
3251 assert(n == OFFSET_AWARE);
3252 assert(PyDateTimeTZ_Check(self));
3253 days = ymd_to_ord(GET_YEAR(self),
3254 GET_MONTH(self),
3255 GET_DAY(self));
3256 seconds = DATE_GET_HOUR(self) * 3600 +
3257 (DATE_GET_MINUTE(self) - offset) * 60 +
3258 DATE_GET_SECOND(self);
3259 temp = new_delta(days,
3260 seconds,
3261 DATE_GET_MICROSECOND(self),
3262 1);
3263 }
3264 if (temp != NULL) {
3265 self->hashcode = PyObject_Hash(temp);
3266 Py_DECREF(temp);
3267 }
3268 }
3269 return self->hashcode;
3270}
3271
3272static PyObject *
Tim Peters12bf3392002-12-24 05:41:27 +00003273datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
3274{
3275 PyObject *clone;
3276 PyObject *tuple;
3277 int y = GET_YEAR(self);
3278 int m = GET_MONTH(self);
3279 int d = GET_DAY(self);
3280 int hh = DATE_GET_HOUR(self);
3281 int mm = DATE_GET_MINUTE(self);
3282 int ss = DATE_GET_SECOND(self);
3283 int us = DATE_GET_MICROSECOND(self);
3284
3285 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiii:replace",
3286 datetime_kws,
3287 &y, &m, &d, &hh, &mm, &ss, &us))
3288 return NULL;
3289 tuple = Py_BuildValue("iiiiiii", y, m, d, hh, mm, ss, us);
3290 if (tuple == NULL)
3291 return NULL;
3292 clone = datetime_new(self->ob_type, tuple, NULL);
3293 Py_DECREF(tuple);
3294 return clone;
3295}
3296
3297static PyObject *
Tim Peters80475bb2002-12-25 07:40:55 +00003298datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
3299{
3300 PyObject *tzinfo;
3301 static char *keywords[] = {"tz", NULL};
3302
3303 if (! PyArg_ParseTupleAndKeywords(args, kw, "O:astimezone", keywords,
3304 &tzinfo))
3305 return NULL;
3306 if (check_tzinfo_subclass(tzinfo) < 0)
3307 return NULL;
3308 return new_datetimetz(GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3309 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3310 DATE_GET_SECOND(self),
3311 DATE_GET_MICROSECOND(self),
3312 tzinfo);
3313}
3314
3315static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00003316datetime_timetuple(PyDateTime_DateTime *self)
3317{
3318 return build_struct_time(GET_YEAR(self),
3319 GET_MONTH(self),
3320 GET_DAY(self),
3321 DATE_GET_HOUR(self),
3322 DATE_GET_MINUTE(self),
3323 DATE_GET_SECOND(self),
3324 -1);
3325}
3326
3327static PyObject *
3328datetime_getdate(PyDateTime_DateTime *self)
3329{
3330 return new_date(GET_YEAR(self),
3331 GET_MONTH(self),
3332 GET_DAY(self));
3333}
3334
3335static PyObject *
3336datetime_gettime(PyDateTime_DateTime *self)
3337{
3338 return new_time(DATE_GET_HOUR(self),
3339 DATE_GET_MINUTE(self),
3340 DATE_GET_SECOND(self),
3341 DATE_GET_MICROSECOND(self));
3342}
3343
3344/* Pickle support. Quite a maze! */
3345
3346static PyObject *
3347datetime_getstate(PyDateTime_DateTime *self)
3348{
3349 return PyString_FromStringAndSize(self->data,
3350 _PyDateTime_DATETIME_DATASIZE);
3351}
3352
3353static PyObject *
3354datetime_setstate(PyDateTime_DateTime *self, PyObject *state)
3355{
3356 const int len = PyString_Size(state);
3357 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
3358
3359 if (! PyString_Check(state) ||
3360 len != _PyDateTime_DATETIME_DATASIZE) {
3361 PyErr_SetString(PyExc_TypeError,
3362 "bad argument to datetime.__setstate__");
3363 return NULL;
3364 }
3365 memcpy(self->data, pdata, _PyDateTime_DATETIME_DATASIZE);
3366 self->hashcode = -1;
3367
3368 Py_INCREF(Py_None);
3369 return Py_None;
3370}
3371
3372/* XXX This seems a ridiculously inefficient way to pickle a short string. */
3373static PyObject *
3374datetime_pickler(PyObject *module, PyDateTime_DateTime *datetime)
3375{
3376 PyObject *state;
3377 PyObject *result = NULL;
3378
3379 if (! PyDateTime_CheckExact(datetime)) {
3380 PyErr_Format(PyExc_TypeError,
3381 "bad type passed to datetime pickler: %s",
3382 datetime->ob_type->tp_name);
3383 return NULL;
3384 }
3385 state = datetime_getstate(datetime);
3386 if (state) {
3387 result = Py_BuildValue("O(O)",
3388 datetime_unpickler_object,
3389 state);
3390 Py_DECREF(state);
3391 }
3392 return result;
3393}
3394
3395static PyObject *
3396datetime_unpickler(PyObject *module, PyObject *arg)
3397{
3398 PyDateTime_DateTime *self;
3399
3400 if (! PyString_CheckExact(arg)) {
3401 PyErr_Format(PyExc_TypeError,
3402 "bad type passed to datetime unpickler: %s",
3403 arg->ob_type->tp_name);
3404 return NULL;
3405 }
3406 self = PyObject_New(PyDateTime_DateTime, &PyDateTime_DateTimeType);
3407 if (self != NULL) {
3408 PyObject *res = datetime_setstate(self, arg);
3409 if (res == NULL) {
3410 Py_DECREF(self);
3411 return NULL;
3412 }
3413 Py_DECREF(res);
3414 }
3415 return (PyObject *)self;
3416}
3417
3418static PyMethodDef datetime_methods[] = {
3419 /* Class methods: */
3420 {"now", (PyCFunction)datetime_now,
3421 METH_NOARGS | METH_CLASS,
3422 PyDoc_STR("Return a new datetime representing local day and time.")},
3423
3424 {"utcnow", (PyCFunction)datetime_utcnow,
3425 METH_NOARGS | METH_CLASS,
3426 PyDoc_STR("Return a new datetime representing UTC day and time.")},
3427
3428 {"fromtimestamp", (PyCFunction)datetime_fromtimestamp,
3429 METH_VARARGS | METH_CLASS,
3430 PyDoc_STR("timestamp -> local datetime from a POSIX timestamp "
3431 "(like time.time()).")},
3432
3433 {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
3434 METH_VARARGS | METH_CLASS,
3435 PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp "
3436 "(like time.time()).")},
3437
3438 {"combine", (PyCFunction)datetime_combine,
3439 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
3440 PyDoc_STR("date, time -> datetime with same date and time fields")},
3441
3442 /* Instance methods: */
3443 {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS,
3444 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
3445
3446 {"date", (PyCFunction)datetime_getdate, METH_NOARGS,
3447 PyDoc_STR("Return date object with same year, month and day.")},
3448
3449 {"time", (PyCFunction)datetime_gettime, METH_NOARGS,
3450 PyDoc_STR("Return time object with same hour, minute, second and "
3451 "microsecond.")},
3452
3453 {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
3454 PyDoc_STR("Return ctime() style string.")},
3455
3456 {"isoformat", (PyCFunction)datetime_isoformat, METH_KEYWORDS,
3457 PyDoc_STR("[sep] -> string in ISO 8601 format, "
3458 "YYYY-MM-DDTHH:MM:SS[.mmmmmm].\n\n"
3459 "sep is used to separate the year from the time, and "
3460 "defaults\n"
3461 "to 'T'.")},
3462
Tim Peters12bf3392002-12-24 05:41:27 +00003463 {"replace", (PyCFunction)datetime_replace, METH_KEYWORDS,
3464 PyDoc_STR("Return datetime with new specified fields.")},
3465
Tim Peters80475bb2002-12-25 07:40:55 +00003466 {"astimezone", (PyCFunction)datetime_astimezone, METH_KEYWORDS,
3467 PyDoc_STR("tz -> datetimetz with same date & time, and tzinfo=tz\n")},
3468
Tim Peters2a799bf2002-12-16 20:18:38 +00003469 {"__setstate__", (PyCFunction)datetime_setstate, METH_O,
3470 PyDoc_STR("__setstate__(state)")},
3471
3472 {"__getstate__", (PyCFunction)datetime_getstate, METH_NOARGS,
3473 PyDoc_STR("__getstate__() -> state")},
3474 {NULL, NULL}
3475};
3476
3477static char datetime_doc[] =
3478PyDoc_STR("Basic date/time type.");
3479
3480static PyNumberMethods datetime_as_number = {
3481 datetime_add, /* nb_add */
3482 datetime_subtract, /* nb_subtract */
3483 0, /* nb_multiply */
3484 0, /* nb_divide */
3485 0, /* nb_remainder */
3486 0, /* nb_divmod */
3487 0, /* nb_power */
3488 0, /* nb_negative */
3489 0, /* nb_positive */
3490 0, /* nb_absolute */
3491 0, /* nb_nonzero */
3492};
3493
3494statichere PyTypeObject PyDateTime_DateTimeType = {
3495 PyObject_HEAD_INIT(NULL)
3496 0, /* ob_size */
3497 "datetime.datetime", /* tp_name */
3498 sizeof(PyDateTime_DateTime), /* tp_basicsize */
3499 0, /* tp_itemsize */
3500 (destructor)PyObject_Del, /* tp_dealloc */
3501 0, /* tp_print */
3502 0, /* tp_getattr */
3503 0, /* tp_setattr */
3504 0, /* tp_compare */
3505 (reprfunc)datetime_repr, /* tp_repr */
3506 &datetime_as_number, /* tp_as_number */
3507 0, /* tp_as_sequence */
3508 0, /* tp_as_mapping */
3509 (hashfunc)datetime_hash, /* tp_hash */
3510 0, /* tp_call */
3511 (reprfunc)datetime_str, /* tp_str */
3512 PyObject_GenericGetAttr, /* tp_getattro */
3513 0, /* tp_setattro */
3514 0, /* tp_as_buffer */
3515 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3516 Py_TPFLAGS_BASETYPE, /* tp_flags */
3517 datetime_doc, /* tp_doc */
3518 0, /* tp_traverse */
3519 0, /* tp_clear */
3520 (richcmpfunc)datetime_richcompare, /* tp_richcompare */
3521 0, /* tp_weaklistoffset */
3522 0, /* tp_iter */
3523 0, /* tp_iternext */
3524 datetime_methods, /* tp_methods */
3525 0, /* tp_members */
3526 datetime_getset, /* tp_getset */
3527 &PyDateTime_DateType, /* tp_base */
3528 0, /* tp_dict */
3529 0, /* tp_descr_get */
3530 0, /* tp_descr_set */
3531 0, /* tp_dictoffset */
3532 0, /* tp_init */
3533 0, /* tp_alloc */
3534 datetime_new, /* tp_new */
3535 _PyObject_Del, /* tp_free */
3536};
3537
3538/*
3539 * PyDateTime_Time implementation.
3540 */
3541
3542/* Accessor properties. */
3543
3544static PyObject *
3545time_hour(PyDateTime_Time *self, void *unused)
3546{
3547 return PyInt_FromLong(TIME_GET_HOUR(self));
3548}
3549
3550static PyObject *
3551time_minute(PyDateTime_Time *self, void *unused)
3552{
3553 return PyInt_FromLong(TIME_GET_MINUTE(self));
3554}
3555
3556static PyObject *
Jack Jansen51cd8a22002-12-17 20:57:24 +00003557py_time_second(PyDateTime_Time *self, void *unused)
Tim Peters2a799bf2002-12-16 20:18:38 +00003558{
3559 return PyInt_FromLong(TIME_GET_SECOND(self));
3560}
3561
3562static PyObject *
3563time_microsecond(PyDateTime_Time *self, void *unused)
3564{
3565 return PyInt_FromLong(TIME_GET_MICROSECOND(self));
3566}
3567
3568static PyGetSetDef time_getset[] = {
3569 {"hour", (getter)time_hour},
3570 {"minute", (getter)time_minute},
Jack Jansen51cd8a22002-12-17 20:57:24 +00003571 {"second", (getter)py_time_second},
Tim Peters2a799bf2002-12-16 20:18:38 +00003572 {"microsecond", (getter)time_microsecond},
3573 {NULL}
3574};
3575
3576/* Constructors. */
3577
Tim Peters12bf3392002-12-24 05:41:27 +00003578static char *time_kws[] = {"hour", "minute", "second", "microsecond", NULL};
3579
Tim Peters2a799bf2002-12-16 20:18:38 +00003580static PyObject *
3581time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
3582{
3583 PyObject *self = NULL;
3584 int hour = 0;
3585 int minute = 0;
3586 int second = 0;
3587 int usecond = 0;
3588
Tim Peters2a799bf2002-12-16 20:18:38 +00003589
Tim Peters12bf3392002-12-24 05:41:27 +00003590 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiii", time_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00003591 &hour, &minute, &second, &usecond)) {
3592 if (check_time_args(hour, minute, second, usecond) < 0)
3593 return NULL;
3594 self = new_time(hour, minute, second, usecond);
3595 }
3596 return self;
3597}
3598
3599/* Various ways to turn a time into a string. */
3600
3601static PyObject *
3602time_repr(PyDateTime_Time *self)
3603{
3604 char buffer[100];
3605 char *typename = self->ob_type->tp_name;
3606 int h = TIME_GET_HOUR(self);
3607 int m = TIME_GET_MINUTE(self);
3608 int s = TIME_GET_SECOND(self);
3609 int us = TIME_GET_MICROSECOND(self);
3610
3611 if (us)
3612 PyOS_snprintf(buffer, sizeof(buffer),
3613 "%s(%d, %d, %d, %d)", typename, h, m, s, us);
3614 else if (s)
3615 PyOS_snprintf(buffer, sizeof(buffer),
3616 "%s(%d, %d, %d)", typename, h, m, s);
3617 else
3618 PyOS_snprintf(buffer, sizeof(buffer),
3619 "%s(%d, %d)", typename, h, m);
3620 return PyString_FromString(buffer);
3621}
3622
3623static PyObject *
3624time_str(PyDateTime_Time *self)
3625{
3626 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
3627}
3628
3629static PyObject *
3630time_isoformat(PyDateTime_Time *self)
3631{
3632 char buffer[100];
3633 /* Reuse the time format code from the datetime type. */
3634 PyDateTime_DateTime datetime;
3635 PyDateTime_DateTime *pdatetime = &datetime;
3636
3637 /* Copy over just the time bytes. */
3638 memcpy(pdatetime->data + _PyDateTime_DATE_DATASIZE,
3639 self->data,
3640 _PyDateTime_TIME_DATASIZE);
3641
3642 isoformat_time(pdatetime, buffer, sizeof(buffer));
3643 return PyString_FromString(buffer);
3644}
3645
3646static PyObject *
3647time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3648{
3649 PyObject *result;
3650 PyObject *format;
3651 PyObject *tuple;
3652 static char *keywords[] = {"format", NULL};
3653
3654 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
3655 &PyString_Type, &format))
3656 return NULL;
3657
Tim Peters83b85f12002-12-22 20:34:46 +00003658 /* Python's strftime does insane things with the year part of the
3659 * timetuple. The year is forced to (the otherwise nonsensical)
3660 * 1900 to worm around that.
3661 */
Tim Peters2a799bf2002-12-16 20:18:38 +00003662 tuple = Py_BuildValue("iiiiiiiii",
Tim Peters83b85f12002-12-22 20:34:46 +00003663 1900, 0, 0, /* year, month, day */
Tim Peters2a799bf2002-12-16 20:18:38 +00003664 TIME_GET_HOUR(self),
3665 TIME_GET_MINUTE(self),
3666 TIME_GET_SECOND(self),
3667 0, 0, -1); /* weekday, daynum, dst */
3668 if (tuple == NULL)
3669 return NULL;
3670 assert(PyTuple_Size(tuple) == 9);
Tim Petersbad8ff02002-12-30 20:52:32 +00003671 result = wrap_strftime((PyObject *)self, format, tuple, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003672 Py_DECREF(tuple);
3673 return result;
3674}
3675
3676/* Miscellaneous methods. */
3677
3678/* This is more natural as a tp_compare, but doesn't work then: for whatever
3679 * reason, Python's try_3way_compare ignores tp_compare unless
3680 * PyInstance_Check returns true, but these aren't old-style classes.
3681 * Note that this routine handles all comparisons for time and timetz.
3682 */
3683static PyObject *
3684time_richcompare(PyDateTime_Time *self, PyObject *other, int op)
3685{
3686 int diff;
3687 naivety n1, n2;
3688 int offset1, offset2;
3689
3690 if (! PyTime_Check(other)) {
3691 /* Stop this from falling back to address comparison. */
3692 PyErr_Format(PyExc_TypeError,
3693 "can't compare '%s' to '%s'",
3694 self->ob_type->tp_name,
3695 other->ob_type->tp_name);
3696 return NULL;
3697 }
Tim Peterse39a80c2002-12-30 21:28:52 +00003698 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1, Py_None,
3699 other, &offset2, &n2, Py_None) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003700 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003701 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00003702 /* If they're both naive, or both aware and have the same offsets,
3703 * we get off cheap. Note that if they're both naive, offset1 ==
3704 * offset2 == 0 at this point.
3705 */
3706 if (n1 == n2 && offset1 == offset2) {
3707 diff = memcmp(self->data, ((PyDateTime_Time *)other)->data,
3708 _PyDateTime_TIME_DATASIZE);
3709 return diff_to_bool(diff, op);
3710 }
3711
3712 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3713 assert(offset1 != offset2); /* else last "if" handled it */
3714 /* Convert everything except microseconds to seconds. These
3715 * can't overflow (no more than the # of seconds in 2 days).
3716 */
3717 offset1 = TIME_GET_HOUR(self) * 3600 +
3718 (TIME_GET_MINUTE(self) - offset1) * 60 +
3719 TIME_GET_SECOND(self);
3720 offset2 = TIME_GET_HOUR(other) * 3600 +
3721 (TIME_GET_MINUTE(other) - offset2) * 60 +
3722 TIME_GET_SECOND(other);
3723 diff = offset1 - offset2;
3724 if (diff == 0)
3725 diff = TIME_GET_MICROSECOND(self) -
3726 TIME_GET_MICROSECOND(other);
3727 return diff_to_bool(diff, op);
3728 }
3729
3730 assert(n1 != n2);
3731 PyErr_SetString(PyExc_TypeError,
3732 "can't compare offset-naive and "
3733 "offset-aware times");
3734 return NULL;
3735}
3736
3737static PyObject *time_getstate(PyDateTime_Time *self);
3738
3739static long
3740time_hash(PyDateTime_Time *self)
3741{
3742 if (self->hashcode == -1) {
3743 naivety n;
3744 int offset;
3745 PyObject *temp;
3746
Tim Peterse39a80c2002-12-30 21:28:52 +00003747 n = classify_utcoffset((PyObject *)self, Py_None, &offset);
Tim Peters2a799bf2002-12-16 20:18:38 +00003748 assert(n != OFFSET_UNKNOWN);
3749 if (n == OFFSET_ERROR)
3750 return -1;
3751
3752 /* Reduce this to a hash of another object. */
3753 if (offset == 0)
3754 temp = time_getstate(self);
3755 else {
3756 int hour;
3757 int minute;
3758
3759 assert(n == OFFSET_AWARE);
3760 assert(PyTimeTZ_Check(self));
3761 hour = divmod(TIME_GET_HOUR(self) * 60 +
3762 TIME_GET_MINUTE(self) - offset,
3763 60,
3764 &minute);
3765 if (0 <= hour && hour < 24)
3766 temp = new_time(hour, minute,
3767 TIME_GET_SECOND(self),
3768 TIME_GET_MICROSECOND(self));
3769 else
3770 temp = Py_BuildValue("iiii",
3771 hour, minute,
3772 TIME_GET_SECOND(self),
3773 TIME_GET_MICROSECOND(self));
3774 }
3775 if (temp != NULL) {
3776 self->hashcode = PyObject_Hash(temp);
3777 Py_DECREF(temp);
3778 }
3779 }
3780 return self->hashcode;
3781}
3782
Tim Peters12bf3392002-12-24 05:41:27 +00003783static PyObject *
3784time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3785{
3786 PyObject *clone;
3787 PyObject *tuple;
3788 int hh = TIME_GET_HOUR(self);
3789 int mm = TIME_GET_MINUTE(self);
3790 int ss = TIME_GET_SECOND(self);
3791 int us = TIME_GET_MICROSECOND(self);
3792
3793 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiii:replace",
3794 time_kws,
3795 &hh, &mm, &ss, &us))
3796 return NULL;
3797 tuple = Py_BuildValue("iiii", hh, mm, ss, us);
3798 if (tuple == NULL)
3799 return NULL;
3800 clone = time_new(self->ob_type, tuple, NULL);
3801 Py_DECREF(tuple);
3802 return clone;
3803}
3804
Tim Peters2a799bf2002-12-16 20:18:38 +00003805static int
3806time_nonzero(PyDateTime_Time *self)
3807{
3808 return TIME_GET_HOUR(self) ||
3809 TIME_GET_MINUTE(self) ||
3810 TIME_GET_SECOND(self) ||
3811 TIME_GET_MICROSECOND(self);
3812}
3813
3814/* Pickle support. Quite a maze! */
3815
3816static PyObject *
3817time_getstate(PyDateTime_Time *self)
3818{
3819 return PyString_FromStringAndSize(self->data,
3820 _PyDateTime_TIME_DATASIZE);
3821}
3822
3823static PyObject *
3824time_setstate(PyDateTime_Time *self, PyObject *state)
3825{
3826 const int len = PyString_Size(state);
3827 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
3828
3829 if (! PyString_Check(state) ||
3830 len != _PyDateTime_TIME_DATASIZE) {
3831 PyErr_SetString(PyExc_TypeError,
3832 "bad argument to time.__setstate__");
3833 return NULL;
3834 }
3835 memcpy(self->data, pdata, _PyDateTime_TIME_DATASIZE);
3836 self->hashcode = -1;
3837
3838 Py_INCREF(Py_None);
3839 return Py_None;
3840}
3841
3842/* XXX This seems a ridiculously inefficient way to pickle a short string. */
3843static PyObject *
3844time_pickler(PyObject *module, PyDateTime_Time *time)
3845{
3846 PyObject *state;
3847 PyObject *result = NULL;
3848
3849 if (! PyTime_CheckExact(time)) {
3850 PyErr_Format(PyExc_TypeError,
3851 "bad type passed to time pickler: %s",
3852 time->ob_type->tp_name);
3853 return NULL;
3854 }
3855 state = time_getstate(time);
3856 if (state) {
3857 result = Py_BuildValue("O(O)",
3858 time_unpickler_object,
3859 state);
3860 Py_DECREF(state);
3861 }
3862 return result;
3863}
3864
3865static PyObject *
3866time_unpickler(PyObject *module, PyObject *arg)
3867{
3868 PyDateTime_Time *self;
3869
3870 if (! PyString_CheckExact(arg)) {
3871 PyErr_Format(PyExc_TypeError,
3872 "bad type passed to time unpickler: %s",
3873 arg->ob_type->tp_name);
3874 return NULL;
3875 }
3876 self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
3877 if (self != NULL) {
3878 PyObject *res = time_setstate(self, arg);
3879 if (res == NULL) {
3880 Py_DECREF(self);
3881 return NULL;
3882 }
3883 Py_DECREF(res);
3884 }
3885 return (PyObject *)self;
3886}
3887
3888static PyMethodDef time_methods[] = {
3889 {"isoformat", (PyCFunction)time_isoformat, METH_KEYWORDS,
3890 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm].")},
3891
3892 {"strftime", (PyCFunction)time_strftime, METH_KEYWORDS,
3893 PyDoc_STR("format -> strftime() style string.")},
3894
Tim Peters12bf3392002-12-24 05:41:27 +00003895 {"replace", (PyCFunction)time_replace, METH_KEYWORDS,
3896 PyDoc_STR("Return datetime with new specified fields.")},
3897
Tim Peters2a799bf2002-12-16 20:18:38 +00003898 {"__setstate__", (PyCFunction)time_setstate, METH_O,
3899 PyDoc_STR("__setstate__(state)")},
3900
3901 {"__getstate__", (PyCFunction)time_getstate, METH_NOARGS,
3902 PyDoc_STR("__getstate__() -> state")},
3903 {NULL, NULL}
3904};
3905
3906static char time_doc[] =
3907PyDoc_STR("Basic time type.");
3908
3909static PyNumberMethods time_as_number = {
3910 0, /* nb_add */
3911 0, /* nb_subtract */
3912 0, /* nb_multiply */
3913 0, /* nb_divide */
3914 0, /* nb_remainder */
3915 0, /* nb_divmod */
3916 0, /* nb_power */
3917 0, /* nb_negative */
3918 0, /* nb_positive */
3919 0, /* nb_absolute */
3920 (inquiry)time_nonzero, /* nb_nonzero */
3921};
3922
3923statichere PyTypeObject PyDateTime_TimeType = {
3924 PyObject_HEAD_INIT(NULL)
3925 0, /* ob_size */
3926 "datetime.time", /* tp_name */
3927 sizeof(PyDateTime_Time), /* tp_basicsize */
3928 0, /* tp_itemsize */
3929 (destructor)PyObject_Del, /* tp_dealloc */
3930 0, /* tp_print */
3931 0, /* tp_getattr */
3932 0, /* tp_setattr */
3933 0, /* tp_compare */
3934 (reprfunc)time_repr, /* tp_repr */
3935 &time_as_number, /* tp_as_number */
3936 0, /* tp_as_sequence */
3937 0, /* tp_as_mapping */
3938 (hashfunc)time_hash, /* tp_hash */
3939 0, /* tp_call */
3940 (reprfunc)time_str, /* tp_str */
3941 PyObject_GenericGetAttr, /* tp_getattro */
3942 0, /* tp_setattro */
3943 0, /* tp_as_buffer */
3944 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3945 Py_TPFLAGS_BASETYPE, /* tp_flags */
3946 time_doc, /* tp_doc */
3947 0, /* tp_traverse */
3948 0, /* tp_clear */
3949 (richcmpfunc)time_richcompare, /* tp_richcompare */
3950 0, /* tp_weaklistoffset */
3951 0, /* tp_iter */
3952 0, /* tp_iternext */
3953 time_methods, /* tp_methods */
3954 0, /* tp_members */
3955 time_getset, /* tp_getset */
3956 0, /* tp_base */
3957 0, /* tp_dict */
3958 0, /* tp_descr_get */
3959 0, /* tp_descr_set */
3960 0, /* tp_dictoffset */
3961 0, /* tp_init */
3962 0, /* tp_alloc */
3963 time_new, /* tp_new */
3964 _PyObject_Del, /* tp_free */
3965};
3966
3967/*
3968 * PyDateTime_TZInfo implementation.
3969 */
3970
3971/* This is a pure abstract base class, so doesn't do anything beyond
3972 * raising NotImplemented exceptions. Real tzinfo classes need
3973 * to derive from this. This is mostly for clarity, and for efficiency in
3974 * datetimetz and timetz constructors (their tzinfo arguments need to
3975 * be subclasses of this tzinfo class, which is easy and quick to check).
3976 *
3977 * Note: For reasons having to do with pickling of subclasses, we have
3978 * to allow tzinfo objects to be instantiated. This wasn't an issue
3979 * in the Python implementation (__init__() could raise NotImplementedError
3980 * there without ill effect), but doing so in the C implementation hit a
3981 * brick wall.
3982 */
3983
3984static PyObject *
3985tzinfo_nogo(const char* methodname)
3986{
3987 PyErr_Format(PyExc_NotImplementedError,
3988 "a tzinfo subclass must implement %s()",
3989 methodname);
3990 return NULL;
3991}
3992
3993/* Methods. A subclass must implement these. */
3994
3995static PyObject*
3996tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt)
3997{
3998 return tzinfo_nogo("tzname");
3999}
4000
4001static PyObject*
4002tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt)
4003{
4004 return tzinfo_nogo("utcoffset");
4005}
4006
4007static PyObject*
4008tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
4009{
4010 return tzinfo_nogo("dst");
4011}
4012
4013/*
4014 * Pickle support. This is solely so that tzinfo subclasses can use
4015 * pickling -- tzinfo itself is supposed to be uninstantiable. The
4016 * pickler and unpickler functions are given module-level private
4017 * names, and registered with copy_reg, by the module init function.
4018 */
4019
4020static PyObject*
4021tzinfo_pickler(PyDateTime_TZInfo *self) {
4022 return Py_BuildValue("O()", tzinfo_unpickler_object);
4023}
4024
4025static PyObject*
4026tzinfo_unpickler(PyObject * unused) {
4027 return PyType_GenericNew(&PyDateTime_TZInfoType, NULL, NULL);
4028}
4029
4030
4031static PyMethodDef tzinfo_methods[] = {
4032 {"tzname", (PyCFunction)tzinfo_tzname, METH_O,
4033 PyDoc_STR("datetime -> string name of time zone.")},
4034
4035 {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
4036 PyDoc_STR("datetime -> minutes east of UTC (negative for "
4037 "west of UTC).")},
4038
4039 {"dst", (PyCFunction)tzinfo_dst, METH_O,
4040 PyDoc_STR("datetime -> DST offset in minutes east of UTC.")},
4041
4042 {NULL, NULL}
4043};
4044
4045static char tzinfo_doc[] =
4046PyDoc_STR("Abstract base class for time zone info objects.");
4047
4048 statichere PyTypeObject PyDateTime_TZInfoType = {
4049 PyObject_HEAD_INIT(NULL)
4050 0, /* ob_size */
4051 "datetime.tzinfo", /* tp_name */
4052 sizeof(PyDateTime_TZInfo), /* tp_basicsize */
4053 0, /* tp_itemsize */
4054 0, /* tp_dealloc */
4055 0, /* tp_print */
4056 0, /* tp_getattr */
4057 0, /* tp_setattr */
4058 0, /* tp_compare */
4059 0, /* tp_repr */
4060 0, /* tp_as_number */
4061 0, /* tp_as_sequence */
4062 0, /* tp_as_mapping */
4063 0, /* tp_hash */
4064 0, /* tp_call */
4065 0, /* tp_str */
4066 PyObject_GenericGetAttr, /* tp_getattro */
4067 0, /* tp_setattro */
4068 0, /* tp_as_buffer */
4069 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4070 Py_TPFLAGS_BASETYPE, /* tp_flags */
4071 tzinfo_doc, /* tp_doc */
4072 0, /* tp_traverse */
4073 0, /* tp_clear */
4074 0, /* tp_richcompare */
4075 0, /* tp_weaklistoffset */
4076 0, /* tp_iter */
4077 0, /* tp_iternext */
4078 tzinfo_methods, /* tp_methods */
4079 0, /* tp_members */
4080 0, /* tp_getset */
4081 0, /* tp_base */
4082 0, /* tp_dict */
4083 0, /* tp_descr_get */
4084 0, /* tp_descr_set */
4085 0, /* tp_dictoffset */
4086 0, /* tp_init */
4087 0, /* tp_alloc */
4088 PyType_GenericNew, /* tp_new */
4089 0, /* tp_free */
4090};
4091
4092/*
4093 * PyDateTime_TimeTZ implementation.
4094 */
4095
4096/* Accessor properties. Properties for hour, minute, second and microsecond
4097 * are inherited from time.
4098 */
4099
4100static PyObject *
4101timetz_tzinfo(PyDateTime_TimeTZ *self, void *unused)
4102{
4103 Py_INCREF(self->tzinfo);
4104 return self->tzinfo;
4105}
4106
4107static PyGetSetDef timetz_getset[] = {
4108 {"tzinfo", (getter)timetz_tzinfo},
4109 {NULL}
4110};
4111
4112/*
4113 * Constructors.
4114 */
4115
Tim Peters12bf3392002-12-24 05:41:27 +00004116static char *timetz_kws[] = {"hour", "minute", "second", "microsecond",
4117 "tzinfo", NULL};
4118
Tim Peters2a799bf2002-12-16 20:18:38 +00004119static PyObject *
4120timetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4121{
4122 PyObject *self = NULL;
4123 int hour = 0;
4124 int minute = 0;
4125 int second = 0;
4126 int usecond = 0;
4127 PyObject *tzinfo = Py_None;
4128
Tim Peters12bf3392002-12-24 05:41:27 +00004129 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", timetz_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00004130 &hour, &minute, &second, &usecond,
4131 &tzinfo)) {
4132 if (check_time_args(hour, minute, second, usecond) < 0)
4133 return NULL;
4134 if (check_tzinfo_subclass(tzinfo) < 0)
4135 return NULL;
4136 self = new_timetz(hour, minute, second, usecond, tzinfo);
4137 }
4138 return self;
4139}
4140
4141/*
4142 * Destructor.
4143 */
4144
4145static void
4146timetz_dealloc(PyDateTime_TimeTZ *self)
4147{
4148 Py_XDECREF(self->tzinfo);
4149 self->ob_type->tp_free((PyObject *)self);
4150}
4151
4152/*
Tim Peters855fe882002-12-22 03:43:39 +00004153 * Indirect access to tzinfo methods.
Tim Peters2a799bf2002-12-16 20:18:38 +00004154 */
4155
Tim Peters2a799bf2002-12-16 20:18:38 +00004156/* These are all METH_NOARGS, so don't need to check the arglist. */
4157static PyObject *
4158timetz_utcoffset(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004159 return offset_as_timedelta(self->tzinfo, "utcoffset", Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004160}
4161
4162static PyObject *
4163timetz_dst(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004164 return offset_as_timedelta(self->tzinfo, "dst", Py_None);
Tim Peters855fe882002-12-22 03:43:39 +00004165}
4166
4167static PyObject *
4168timetz_tzname(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004169 return call_tzname(self->tzinfo, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004170}
4171
4172/*
4173 * Various ways to turn a timetz into a string.
4174 */
4175
4176static PyObject *
4177timetz_repr(PyDateTime_TimeTZ *self)
4178{
4179 PyObject *baserepr = time_repr((PyDateTime_Time *)self);
4180
4181 if (baserepr == NULL)
4182 return NULL;
4183 return append_keyword_tzinfo(baserepr, self->tzinfo);
4184}
4185
4186/* Note: tp_str is inherited from time. */
4187
4188static PyObject *
4189timetz_isoformat(PyDateTime_TimeTZ *self)
4190{
4191 char buf[100];
4192 PyObject *result = time_isoformat((PyDateTime_Time *)self);
4193
4194 if (result == NULL || self->tzinfo == Py_None)
4195 return result;
4196
4197 /* We need to append the UTC offset. */
4198 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00004199 Py_None) < 0) {
Tim Peters2a799bf2002-12-16 20:18:38 +00004200 Py_DECREF(result);
4201 return NULL;
4202 }
4203 PyString_ConcatAndDel(&result, PyString_FromString(buf));
4204 return result;
4205}
4206
4207/* Note: strftime() is inherited from time. */
4208
4209/*
4210 * Miscellaneous methods.
4211 */
4212
4213/* Note: tp_richcompare and tp_hash are inherited from time. */
4214
Tim Peters12bf3392002-12-24 05:41:27 +00004215static PyObject *
4216timetz_replace(PyDateTime_TimeTZ *self, PyObject *args, PyObject *kw)
4217{
4218 PyObject *clone;
4219 PyObject *tuple;
4220 int hh = TIME_GET_HOUR(self);
4221 int mm = TIME_GET_MINUTE(self);
4222 int ss = TIME_GET_SECOND(self);
4223 int us = TIME_GET_MICROSECOND(self);
4224 PyObject *tzinfo = self->tzinfo;
4225
4226 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
4227 timetz_kws,
4228 &hh, &mm, &ss, &us, &tzinfo))
4229 return NULL;
4230 tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
4231 if (tuple == NULL)
4232 return NULL;
4233 clone = timetz_new(self->ob_type, tuple, NULL);
4234 Py_DECREF(tuple);
4235 return clone;
4236}
4237
Tim Peters2a799bf2002-12-16 20:18:38 +00004238static int
4239timetz_nonzero(PyDateTime_TimeTZ *self)
4240{
4241 int offset;
4242 int none;
4243
4244 if (TIME_GET_SECOND(self) || TIME_GET_MICROSECOND(self)) {
4245 /* Since utcoffset is in whole minutes, nothing can
4246 * alter the conclusion that this is nonzero.
4247 */
4248 return 1;
4249 }
4250 offset = 0;
4251 if (self->tzinfo != Py_None) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004252 offset = call_utcoffset(self->tzinfo, Py_None, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +00004253 if (offset == -1 && PyErr_Occurred())
4254 return -1;
4255 }
4256 return (TIME_GET_MINUTE(self) - offset + TIME_GET_HOUR(self)*60) != 0;
4257}
4258
4259/*
4260 * Pickle support. Quite a maze!
4261 */
4262
4263/* Let basestate be the state string returned by time_getstate.
4264 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4265 * So it's a tuple in any (non-error) case.
4266 */
4267static PyObject *
4268timetz_getstate(PyDateTime_TimeTZ *self)
4269{
4270 PyObject *basestate;
4271 PyObject *result = NULL;
4272
4273 basestate = time_getstate((PyDateTime_Time *)self);
4274 if (basestate != NULL) {
4275 if (self->tzinfo == Py_None)
4276 result = Py_BuildValue("(O)", basestate);
4277 else
4278 result = Py_BuildValue("OO", basestate, self->tzinfo);
4279 Py_DECREF(basestate);
4280 }
4281 return result;
4282}
4283
4284static PyObject *
4285timetz_setstate(PyDateTime_TimeTZ *self, PyObject *state)
4286{
4287 PyObject *temp;
4288 PyObject *basestate;
4289 PyObject *tzinfo = Py_None;
4290
4291 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
4292 &PyString_Type, &basestate,
4293 &tzinfo))
4294 return NULL;
4295 temp = time_setstate((PyDateTime_Time *)self, basestate);
4296 if (temp == NULL)
4297 return NULL;
4298 Py_DECREF(temp);
4299
4300 Py_INCREF(tzinfo);
4301 Py_XDECREF(self->tzinfo);
4302 self->tzinfo = tzinfo;
4303
4304 Py_INCREF(Py_None);
4305 return Py_None;
4306}
4307
4308static PyObject *
4309timetz_pickler(PyObject *module, PyDateTime_TimeTZ *timetz)
4310{
4311 PyObject *state;
4312 PyObject *result = NULL;
4313
4314 if (! PyTimeTZ_CheckExact(timetz)) {
4315 PyErr_Format(PyExc_TypeError,
4316 "bad type passed to timetz pickler: %s",
4317 timetz->ob_type->tp_name);
4318 return NULL;
4319 }
4320 state = timetz_getstate(timetz);
4321 if (state) {
4322 result = Py_BuildValue("O(O)",
4323 timetz_unpickler_object,
4324 state);
4325 Py_DECREF(state);
4326 }
4327 return result;
4328}
4329
4330static PyObject *
4331timetz_unpickler(PyObject *module, PyObject *arg)
4332{
4333 PyDateTime_TimeTZ *self;
4334
4335 self = PyObject_New(PyDateTime_TimeTZ, &PyDateTime_TimeTZType);
4336 if (self != NULL) {
4337 PyObject *res;
4338
4339 self->tzinfo = NULL;
4340 res = timetz_setstate(self, arg);
4341 if (res == NULL) {
4342 Py_DECREF(self);
4343 return NULL;
4344 }
4345 Py_DECREF(res);
4346 }
4347 return (PyObject *)self;
4348}
4349
4350static PyMethodDef timetz_methods[] = {
4351 {"isoformat", (PyCFunction)timetz_isoformat, METH_KEYWORDS,
4352 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]"
4353 "[+HH:MM].")},
4354
4355 {"utcoffset", (PyCFunction)timetz_utcoffset, METH_NOARGS,
4356 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
4357
4358 {"tzname", (PyCFunction)timetz_tzname, METH_NOARGS,
4359 PyDoc_STR("Return self.tzinfo.tzname(self).")},
4360
4361 {"dst", (PyCFunction)timetz_dst, METH_NOARGS,
4362 PyDoc_STR("Return self.tzinfo.dst(self).")},
4363
Tim Peters12bf3392002-12-24 05:41:27 +00004364 {"replace", (PyCFunction)timetz_replace, METH_KEYWORDS,
4365 PyDoc_STR("Return timetz with new specified fields.")},
4366
Tim Peters2a799bf2002-12-16 20:18:38 +00004367 {"__setstate__", (PyCFunction)timetz_setstate, METH_O,
4368 PyDoc_STR("__setstate__(state)")},
4369
4370 {"__getstate__", (PyCFunction)timetz_getstate, METH_NOARGS,
4371 PyDoc_STR("__getstate__() -> state")},
4372 {NULL, NULL}
4373
4374};
4375
4376static char timetz_doc[] =
4377PyDoc_STR("Time type.");
4378
4379static PyNumberMethods timetz_as_number = {
4380 0, /* nb_add */
4381 0, /* nb_subtract */
4382 0, /* nb_multiply */
4383 0, /* nb_divide */
4384 0, /* nb_remainder */
4385 0, /* nb_divmod */
4386 0, /* nb_power */
4387 0, /* nb_negative */
4388 0, /* nb_positive */
4389 0, /* nb_absolute */
4390 (inquiry)timetz_nonzero, /* nb_nonzero */
4391};
4392
4393statichere PyTypeObject PyDateTime_TimeTZType = {
4394 PyObject_HEAD_INIT(NULL)
4395 0, /* ob_size */
4396 "datetime.timetz", /* tp_name */
4397 sizeof(PyDateTime_TimeTZ), /* tp_basicsize */
4398 0, /* tp_itemsize */
4399 (destructor)timetz_dealloc, /* tp_dealloc */
4400 0, /* tp_print */
4401 0, /* tp_getattr */
4402 0, /* tp_setattr */
4403 0, /* tp_compare */
4404 (reprfunc)timetz_repr, /* tp_repr */
4405 &timetz_as_number, /* tp_as_number */
4406 0, /* tp_as_sequence */
4407 0, /* tp_as_mapping */
4408 0, /* tp_hash */
4409 0, /* tp_call */
4410 0, /* tp_str */
4411 PyObject_GenericGetAttr, /* tp_getattro */
4412 0, /* tp_setattro */
4413 0, /* tp_as_buffer */
4414 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4415 Py_TPFLAGS_BASETYPE, /* tp_flags */
Guido van Rossumbd43e912002-12-16 20:34:55 +00004416 timetz_doc, /* tp_doc */
Tim Peters2a799bf2002-12-16 20:18:38 +00004417 0, /* tp_traverse */
4418 0, /* tp_clear */
4419 0, /* tp_richcompare */
4420 0, /* tp_weaklistoffset */
4421 0, /* tp_iter */
4422 0, /* tp_iternext */
4423 timetz_methods, /* tp_methods */
4424 0, /* tp_members */
4425 timetz_getset, /* tp_getset */
4426 &PyDateTime_TimeType, /* tp_base */
4427 0, /* tp_dict */
4428 0, /* tp_descr_get */
4429 0, /* tp_descr_set */
4430 0, /* tp_dictoffset */
4431 0, /* tp_init */
4432 0, /* tp_alloc */
4433 timetz_new, /* tp_new */
4434 _PyObject_Del, /* tp_free */
4435};
4436
4437/*
4438 * PyDateTime_DateTimeTZ implementation.
4439 */
4440
4441/* Accessor properties. Properties for day, month, year, hour, minute,
4442 * second and microsecond are inherited from datetime.
4443 */
4444
4445static PyObject *
4446datetimetz_tzinfo(PyDateTime_DateTimeTZ *self, void *unused)
4447{
4448 Py_INCREF(self->tzinfo);
4449 return self->tzinfo;
4450}
4451
4452static PyGetSetDef datetimetz_getset[] = {
4453 {"tzinfo", (getter)datetimetz_tzinfo},
4454 {NULL}
4455};
4456
4457/*
4458 * Constructors.
4459 * These are like the datetime methods of the same names, but allow an
4460 * optional tzinfo argument.
4461 */
4462
Tim Peters12bf3392002-12-24 05:41:27 +00004463static char *datetimetz_kws[] = {
4464 "year", "month", "day", "hour", "minute", "second",
4465 "microsecond", "tzinfo", NULL
4466};
4467
Tim Peters2a799bf2002-12-16 20:18:38 +00004468static PyObject *
4469datetimetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4470{
4471 PyObject *self = NULL;
4472 int year;
4473 int month;
4474 int day;
4475 int hour = 0;
4476 int minute = 0;
4477 int second = 0;
4478 int usecond = 0;
4479 PyObject *tzinfo = Py_None;
4480
Tim Peters12bf3392002-12-24 05:41:27 +00004481 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO", datetimetz_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00004482 &year, &month, &day, &hour, &minute,
4483 &second, &usecond, &tzinfo)) {
4484 if (check_date_args(year, month, day) < 0)
4485 return NULL;
4486 if (check_time_args(hour, minute, second, usecond) < 0)
4487 return NULL;
4488 if (check_tzinfo_subclass(tzinfo) < 0)
4489 return NULL;
4490 self = new_datetimetz(year, month, day,
4491 hour, minute, second, usecond,
4492 tzinfo);
4493 }
4494 return self;
4495}
4496
4497/* Return best possible local time -- this isn't constrained by the
4498 * precision of a timestamp.
4499 */
4500static PyObject *
4501datetimetz_now(PyObject *cls, PyObject *args, PyObject *kw)
4502{
4503 PyObject *self = NULL;
4504 PyObject *tzinfo = Py_None;
4505 static char *keywords[] = {"tzinfo", NULL};
4506
4507 if (PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords,
4508 &tzinfo)) {
4509 if (check_tzinfo_subclass(tzinfo) < 0)
4510 return NULL;
4511 self = datetime_best_possible(cls, localtime);
4512 if (self != NULL)
4513 replace_tzinfo(self, tzinfo);
4514 }
4515 return self;
4516}
4517
4518/* Return new local datetime from timestamp (Python timestamp -- a double). */
4519static PyObject *
4520datetimetz_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
4521{
4522 PyObject *self = NULL;
4523 double timestamp;
4524 PyObject *tzinfo = Py_None;
4525 static char *keywords[] = {"timestamp", "tzinfo", NULL};
4526
4527 if (PyArg_ParseTupleAndKeywords(args, kw, "d|O:fromtimestamp",
4528 keywords, &timestamp, &tzinfo)) {
4529 if (check_tzinfo_subclass(tzinfo) < 0)
4530 return NULL;
4531 self = datetime_from_timestamp(cls, localtime, timestamp);
4532 if (self != NULL)
4533 replace_tzinfo(self, tzinfo);
4534 }
4535 return self;
4536}
4537
4538/* Note: utcnow() is inherited, and doesn't accept tzinfo.
4539 * Ditto utcfromtimestamp(). Ditto combine().
4540 */
4541
4542
4543/*
4544 * Destructor.
4545 */
4546
4547static void
4548datetimetz_dealloc(PyDateTime_DateTimeTZ *self)
4549{
4550 Py_XDECREF(self->tzinfo);
4551 self->ob_type->tp_free((PyObject *)self);
4552}
4553
4554/*
4555 * Indirect access to tzinfo methods.
4556 */
4557
Tim Peters2a799bf2002-12-16 20:18:38 +00004558/* These are all METH_NOARGS, so don't need to check the arglist. */
4559static PyObject *
4560datetimetz_utcoffset(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004561 return offset_as_timedelta(self->tzinfo, "utcoffset",
4562 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00004563}
4564
4565static PyObject *
4566datetimetz_dst(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004567 return offset_as_timedelta(self->tzinfo, "dst", (PyObject *)self);
Tim Peters855fe882002-12-22 03:43:39 +00004568}
4569
4570static PyObject *
4571datetimetz_tzname(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004572 return call_tzname(self->tzinfo, (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00004573}
4574
4575/*
4576 * datetimetz arithmetic.
4577 */
4578
4579/* If base is Py_NotImplemented or NULL, just return it.
4580 * Else base is a datetime, exactly one of {left, right} is a datetimetz,
4581 * and we want to create a datetimetz with the same date and time fields
4582 * as base, and with the tzinfo field from left or right. Do that,
4583 * return it, and decref base. This is used to transform the result of
4584 * a binary datetime operation (base) into a datetimetz result.
4585 */
4586static PyObject *
4587attach_tzinfo(PyObject *base, PyObject *left, PyObject *right)
4588{
4589 PyDateTime_DateTimeTZ *self;
4590 PyDateTime_DateTimeTZ *result;
4591
4592 if (base == NULL || base == Py_NotImplemented)
4593 return base;
4594
4595 assert(PyDateTime_CheckExact(base));
4596
4597 if (PyDateTimeTZ_Check(left)) {
4598 assert(! PyDateTimeTZ_Check(right));
4599 self = (PyDateTime_DateTimeTZ *)left;
4600 }
4601 else {
4602 assert(PyDateTimeTZ_Check(right));
4603 self = (PyDateTime_DateTimeTZ *)right;
4604 }
4605 result = PyObject_New(PyDateTime_DateTimeTZ,
4606 &PyDateTime_DateTimeTZType);
4607 if (result != NULL) {
4608 memcpy(result->data, ((PyDateTime_DateTime *)base)->data,
4609 _PyDateTime_DATETIME_DATASIZE);
4610 Py_INCREF(self->tzinfo);
4611 result->tzinfo = self->tzinfo;
4612 }
4613 Py_DECREF(base);
4614 return (PyObject *)result;
4615}
4616
4617static PyObject *
4618datetimetz_add(PyObject *left, PyObject *right)
4619{
4620 return attach_tzinfo(datetime_add(left, right), left, right);
4621}
4622
4623static PyObject *
4624datetimetz_subtract(PyObject *left, PyObject *right)
4625{
4626 PyObject *result = Py_NotImplemented;
4627
4628 if (PyDateTime_Check(left)) {
4629 /* datetime - ??? */
4630 if (PyDateTime_Check(right)) {
4631 /* datetime - datetime */
4632 naivety n1, n2;
4633 int offset1, offset2;
4634 PyDateTime_Delta *delta;
4635
Tim Peterse39a80c2002-12-30 21:28:52 +00004636 if (classify_two_utcoffsets(left, &offset1, &n1, left,
4637 right, &offset2, &n2,
4638 right) < 0)
Tim Peters00237032002-12-27 02:21:51 +00004639 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00004640 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00004641 if (n1 != n2) {
4642 PyErr_SetString(PyExc_TypeError,
4643 "can't subtract offset-naive and "
4644 "offset-aware datetimes");
4645 return NULL;
4646 }
4647 delta = (PyDateTime_Delta *)sub_datetime_datetime(
4648 (PyDateTime_DateTime *)left,
4649 (PyDateTime_DateTime *)right);
4650 if (delta == NULL || offset1 == offset2)
4651 return (PyObject *)delta;
4652 /* (left - offset1) - (right - offset2) =
4653 * (left - right) + (offset2 - offset1)
4654 */
4655 result = new_delta(delta->days,
4656 delta->seconds +
4657 (offset2 - offset1) * 60,
4658 delta->microseconds,
4659 1);
4660 Py_DECREF(delta);
4661 }
4662 else if (PyDelta_Check(right)) {
4663 /* datetimetz - delta */
4664 result = sub_datetime_timedelta(
4665 (PyDateTime_DateTime *)left,
4666 (PyDateTime_Delta *)right);
4667 result = attach_tzinfo(result, left, right);
4668 }
4669 }
4670
4671 if (result == Py_NotImplemented)
4672 Py_INCREF(result);
4673 return result;
4674}
4675
4676/* Various ways to turn a datetime into a string. */
4677
4678static PyObject *
4679datetimetz_repr(PyDateTime_DateTimeTZ *self)
4680{
4681 PyObject *baserepr = datetime_repr((PyDateTime_DateTime *)self);
4682
4683 if (baserepr == NULL)
4684 return NULL;
4685 return append_keyword_tzinfo(baserepr, self->tzinfo);
4686}
4687
4688/* Note: tp_str is inherited from datetime. */
4689
4690static PyObject *
4691datetimetz_isoformat(PyDateTime_DateTimeTZ *self,
4692 PyObject *args, PyObject *kw)
4693{
4694 char buf[100];
4695 PyObject *result = datetime_isoformat((PyDateTime_DateTime *)self,
4696 args, kw);
4697
4698 if (result == NULL || self->tzinfo == Py_None)
4699 return result;
4700
4701 /* We need to append the UTC offset. */
4702 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
4703 (PyObject *)self) < 0) {
4704 Py_DECREF(result);
4705 return NULL;
4706 }
4707 PyString_ConcatAndDel(&result, PyString_FromString(buf));
4708 return result;
4709}
4710
4711/* Miscellaneous methods. */
4712
4713/* Note: tp_richcompare and tp_hash are inherited from datetime. */
4714
4715static PyObject *
Tim Peters12bf3392002-12-24 05:41:27 +00004716datetimetz_replace(PyDateTime_DateTimeTZ *self, PyObject *args, PyObject *kw)
4717{
4718 PyObject *clone;
4719 PyObject *tuple;
4720 int y = GET_YEAR(self);
4721 int m = GET_MONTH(self);
4722 int d = GET_DAY(self);
4723 int hh = DATE_GET_HOUR(self);
4724 int mm = DATE_GET_MINUTE(self);
4725 int ss = DATE_GET_SECOND(self);
4726 int us = DATE_GET_MICROSECOND(self);
4727 PyObject *tzinfo = self->tzinfo;
4728
4729 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO:replace",
4730 datetimetz_kws,
4731 &y, &m, &d, &hh, &mm, &ss, &us,
4732 &tzinfo))
4733 return NULL;
4734 tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
4735 if (tuple == NULL)
4736 return NULL;
4737 clone = datetimetz_new(self->ob_type, tuple, NULL);
4738 Py_DECREF(tuple);
4739 return clone;
4740}
4741
4742static PyObject *
Tim Peters80475bb2002-12-25 07:40:55 +00004743datetimetz_astimezone(PyDateTime_DateTimeTZ *self, PyObject *args,
4744 PyObject *kw)
4745{
4746 int y = GET_YEAR(self);
4747 int m = GET_MONTH(self);
4748 int d = GET_DAY(self);
4749 int hh = DATE_GET_HOUR(self);
4750 int mm = DATE_GET_MINUTE(self);
4751 int ss = DATE_GET_SECOND(self);
4752 int us = DATE_GET_MICROSECOND(self);
4753
Tim Peters521fc152002-12-31 17:36:56 +00004754 PyObject *result;
4755 PyObject *temp;
Tim Petersf3615152003-01-01 21:51:37 +00004756 int selfoff, resoff, resdst, total_added_to_result;
Tim Peters521fc152002-12-31 17:36:56 +00004757 int none;
Tim Petersf3615152003-01-01 21:51:37 +00004758 int delta;
Tim Peters521fc152002-12-31 17:36:56 +00004759
Tim Peters80475bb2002-12-25 07:40:55 +00004760 PyObject *tzinfo;
4761 static char *keywords[] = {"tz", NULL};
4762
4763 if (! PyArg_ParseTupleAndKeywords(args, kw, "O:astimezone", keywords,
4764 &tzinfo))
4765 return NULL;
4766 if (check_tzinfo_subclass(tzinfo) < 0)
4767 return NULL;
4768
Tim Peters521fc152002-12-31 17:36:56 +00004769 /* Don't call utcoffset unless necessary. */
4770 result = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4771 if (result == NULL ||
4772 tzinfo == Py_None ||
4773 self->tzinfo == Py_None ||
4774 self->tzinfo == tzinfo)
4775 return result;
4776
4777 /* Get the offsets. If either object turns out to be naive, again
4778 * there's no conversion of date or time fields.
4779 */
Tim Petersb5a16f32003-01-01 04:48:01 +00004780 selfoff = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4781 if (selfoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004782 goto Fail;
4783 if (none)
4784 return result;
4785
Tim Petersb5a16f32003-01-01 04:48:01 +00004786 resoff = call_utcoffset(tzinfo, result, &none);
4787 if (resoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004788 goto Fail;
4789 if (none)
4790 return result;
4791
Tim Petersf3615152003-01-01 21:51:37 +00004792 /* See the long comment block at the end of this file for an
4793 * explanation of this algorithm. That it always works requires a
4794 * pretty intricate proof.
Tim Peters521fc152002-12-31 17:36:56 +00004795 */
Tim Petersf3615152003-01-01 21:51:37 +00004796 resdst = call_dst(tzinfo, result, &none);
4797 if (resdst == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004798 goto Fail;
Tim Petersf3615152003-01-01 21:51:37 +00004799 /* None and 0 dst() results are the same to us here. Debatable. */
4800 total_added_to_result = resoff - resdst - selfoff;
4801 if (total_added_to_result != 0) {
4802 mm += total_added_to_result;
Tim Petersb5a16f32003-01-01 04:48:01 +00004803 if ((mm < 0 || mm >= 60) &&
4804 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters521fc152002-12-31 17:36:56 +00004805 goto Fail;
4806 temp = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4807 if (temp == NULL)
4808 goto Fail;
4809 Py_DECREF(result);
4810 result = temp;
4811
Tim Petersb5a16f32003-01-01 04:48:01 +00004812 resoff = call_utcoffset(tzinfo, result, &none);
4813 if (resoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004814 goto Fail;
4815 if (none)
4816 goto Inconsistent;
Tim Petersf3615152003-01-01 21:51:37 +00004817 }
4818
4819 /* The distance now from self to result is
4820 * self - result == naive(self) - selfoff - (naive(result) - resoff) ==
4821 * naive(self) - selfoff -
4822 * ((naive(self) + total_added_to_result - resoff) ==
4823 * - selfoff - total_added_to_result + resoff.
Tim Peters521fc152002-12-31 17:36:56 +00004824 */
Tim Petersf3615152003-01-01 21:51:37 +00004825 delta = resoff - selfoff - total_added_to_result;
4826
4827 /* Now self and result are the same UTC time iff delta is 0.
4828 * If it is 0, we're done, although that takes some proving.
4829 */
4830 if (delta == 0)
4831 return result;
4832
4833 total_added_to_result += delta;
4834 mm += delta;
4835 if ((mm < 0 || mm >= 60) &&
4836 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters521fc152002-12-31 17:36:56 +00004837 goto Fail;
Tim Petersf3615152003-01-01 21:51:37 +00004838
Tim Peters521fc152002-12-31 17:36:56 +00004839 temp = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4840 if (temp == NULL)
4841 goto Fail;
Tim Petersf3615152003-01-01 21:51:37 +00004842 Py_DECREF(result);
4843 result = temp;
Tim Peters521fc152002-12-31 17:36:56 +00004844
Tim Petersf3615152003-01-01 21:51:37 +00004845 resoff = call_utcoffset(tzinfo, result, &none);
4846 if (resoff == -1 && PyErr_Occurred())
4847 goto Fail;
4848 if (none)
4849 goto Inconsistent;
4850
4851 if (resoff - selfoff == total_added_to_result)
4852 /* self and result are the same UTC time */
Tim Peters521fc152002-12-31 17:36:56 +00004853 return result;
Tim Petersb5a16f32003-01-01 04:48:01 +00004854
4855 /* Else there's no way to spell self in zone tzinfo. */
Tim Peters521fc152002-12-31 17:36:56 +00004856 PyErr_SetString(PyExc_ValueError, "astimezone(): the source "
4857 "datetimetz can't be expressed in the target "
4858 "timezone's local time");
4859 goto Fail;
4860
4861Inconsistent:
4862 PyErr_SetString(PyExc_ValueError, "astimezone(): tz.utcoffset() "
4863 "gave inconsistent results; cannot convert");
4864
4865 /* fall thru to failure */
4866Fail:
4867 Py_DECREF(result);
4868 return NULL;
Tim Peters80475bb2002-12-25 07:40:55 +00004869}
4870
4871static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00004872datetimetz_timetuple(PyDateTime_DateTimeTZ *self)
4873{
4874 int dstflag = -1;
4875
4876 if (self->tzinfo != Py_None) {
4877 int none;
4878
4879 dstflag = call_dst(self->tzinfo, (PyObject *)self, &none);
4880 if (dstflag == -1 && PyErr_Occurred())
4881 return NULL;
4882
4883 if (none)
4884 dstflag = -1;
4885 else if (dstflag != 0)
4886 dstflag = 1;
4887
4888 }
4889 return build_struct_time(GET_YEAR(self),
4890 GET_MONTH(self),
4891 GET_DAY(self),
4892 DATE_GET_HOUR(self),
4893 DATE_GET_MINUTE(self),
4894 DATE_GET_SECOND(self),
4895 dstflag);
4896}
4897
4898static PyObject *
4899datetimetz_utctimetuple(PyDateTime_DateTimeTZ *self)
4900{
4901 int y = GET_YEAR(self);
4902 int m = GET_MONTH(self);
4903 int d = GET_DAY(self);
4904 int hh = DATE_GET_HOUR(self);
4905 int mm = DATE_GET_MINUTE(self);
4906 int ss = DATE_GET_SECOND(self);
4907 int us = 0; /* microseconds are ignored in a timetuple */
4908 int offset = 0;
4909
4910 if (self->tzinfo != Py_None) {
4911 int none;
4912
4913 offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4914 if (offset == -1 && PyErr_Occurred())
4915 return NULL;
4916 }
4917 /* Even if offset is 0, don't call timetuple() -- tm_isdst should be
4918 * 0 in a UTC timetuple regardless of what dst() says.
4919 */
4920 if (offset) {
4921 /* Subtract offset minutes & normalize. */
4922 int stat;
4923
4924 mm -= offset;
4925 stat = normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us);
4926 if (stat < 0) {
4927 /* At the edges, it's possible we overflowed
4928 * beyond MINYEAR or MAXYEAR.
4929 */
4930 if (PyErr_ExceptionMatches(PyExc_OverflowError))
4931 PyErr_Clear();
4932 else
4933 return NULL;
4934 }
4935 }
4936 return build_struct_time(y, m, d, hh, mm, ss, 0);
4937}
4938
4939static PyObject *
4940datetimetz_gettimetz(PyDateTime_DateTimeTZ *self)
4941{
4942 return new_timetz(DATE_GET_HOUR(self),
4943 DATE_GET_MINUTE(self),
4944 DATE_GET_SECOND(self),
4945 DATE_GET_MICROSECOND(self),
4946 self->tzinfo);
4947}
4948
4949/*
4950 * Pickle support. Quite a maze!
4951 */
4952
4953/* Let basestate be the state string returned by datetime_getstate.
4954 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4955 * So it's a tuple in any (non-error) case.
4956 */
4957static PyObject *
4958datetimetz_getstate(PyDateTime_DateTimeTZ *self)
4959{
4960 PyObject *basestate;
4961 PyObject *result = NULL;
4962
4963 basestate = datetime_getstate((PyDateTime_DateTime *)self);
4964 if (basestate != NULL) {
4965 if (self->tzinfo == Py_None)
4966 result = Py_BuildValue("(O)", basestate);
4967 else
4968 result = Py_BuildValue("OO", basestate, self->tzinfo);
4969 Py_DECREF(basestate);
4970 }
4971 return result;
4972}
4973
4974static PyObject *
4975datetimetz_setstate(PyDateTime_DateTimeTZ *self, PyObject *state)
4976{
4977 PyObject *temp;
4978 PyObject *basestate;
4979 PyObject *tzinfo = Py_None;
4980
4981 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
4982 &PyString_Type, &basestate,
4983 &tzinfo))
4984 return NULL;
4985 temp = datetime_setstate((PyDateTime_DateTime *)self, basestate);
4986 if (temp == NULL)
4987 return NULL;
4988 Py_DECREF(temp);
4989
4990 Py_INCREF(tzinfo);
4991 Py_XDECREF(self->tzinfo);
4992 self->tzinfo = tzinfo;
4993
4994 Py_INCREF(Py_None);
4995 return Py_None;
4996}
4997
4998static PyObject *
4999datetimetz_pickler(PyObject *module, PyDateTime_DateTimeTZ *datetimetz)
5000{
5001 PyObject *state;
5002 PyObject *result = NULL;
5003
5004 if (! PyDateTimeTZ_CheckExact(datetimetz)) {
5005 PyErr_Format(PyExc_TypeError,
5006 "bad type passed to datetimetz pickler: %s",
5007 datetimetz->ob_type->tp_name);
5008 return NULL;
5009 }
5010 state = datetimetz_getstate(datetimetz);
5011 if (state) {
5012 result = Py_BuildValue("O(O)",
5013 datetimetz_unpickler_object,
5014 state);
5015 Py_DECREF(state);
5016 }
5017 return result;
5018}
5019
5020static PyObject *
5021datetimetz_unpickler(PyObject *module, PyObject *arg)
5022{
5023 PyDateTime_DateTimeTZ *self;
5024
5025 self = PyObject_New(PyDateTime_DateTimeTZ, &PyDateTime_DateTimeTZType);
5026 if (self != NULL) {
5027 PyObject *res;
5028
5029 self->tzinfo = NULL;
5030 res = datetimetz_setstate(self, arg);
5031 if (res == NULL) {
5032 Py_DECREF(self);
5033 return NULL;
5034 }
5035 Py_DECREF(res);
5036 }
5037 return (PyObject *)self;
5038}
5039
5040
5041static PyMethodDef datetimetz_methods[] = {
5042 /* Class methods: */
5043 /* Inherited: combine(), utcnow(), utcfromtimestamp() */
5044
5045 {"now", (PyCFunction)datetimetz_now,
5046 METH_KEYWORDS | METH_CLASS,
5047 PyDoc_STR("[tzinfo] -> new datetimetz with local day and time.")},
5048
5049 {"fromtimestamp", (PyCFunction)datetimetz_fromtimestamp,
5050 METH_KEYWORDS | METH_CLASS,
5051 PyDoc_STR("timestamp[, tzinfo] -> local time from POSIX timestamp.")},
5052
5053 /* Instance methods: */
5054 /* Inherited: date(), time(), ctime(). */
5055 {"timetuple", (PyCFunction)datetimetz_timetuple, METH_NOARGS,
5056 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
5057
5058 {"utctimetuple", (PyCFunction)datetimetz_utctimetuple, METH_NOARGS,
5059 PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")},
5060
5061 {"timetz", (PyCFunction)datetimetz_gettimetz, METH_NOARGS,
5062 PyDoc_STR("Return timetz object with same hour, minute, second, "
5063 "microsecond, and tzinfo.")},
5064
5065 {"isoformat", (PyCFunction)datetimetz_isoformat, METH_KEYWORDS,
5066 PyDoc_STR("[sep] -> string in ISO 8601 format, "
5067 "YYYY-MM-DDTHH:MM:SS[.mmmmmm][+HH:MM].\n\n"
5068 "sep is used to separate the year from the time, and "
5069 "defaults to 'T'.")},
5070
5071 {"utcoffset", (PyCFunction)datetimetz_utcoffset, METH_NOARGS,
5072 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
5073
5074 {"tzname", (PyCFunction)datetimetz_tzname, METH_NOARGS,
5075 PyDoc_STR("Return self.tzinfo.tzname(self).")},
5076
5077 {"dst", (PyCFunction)datetimetz_dst, METH_NOARGS,
5078 PyDoc_STR("Return self.tzinfo.dst(self).")},
5079
Tim Peters12bf3392002-12-24 05:41:27 +00005080 {"replace", (PyCFunction)datetimetz_replace, METH_KEYWORDS,
5081 PyDoc_STR("Return datetimetz with new specified fields.")},
5082
Tim Peters80475bb2002-12-25 07:40:55 +00005083 {"astimezone", (PyCFunction)datetimetz_astimezone, METH_KEYWORDS,
5084 PyDoc_STR("tz -> convert to local time in new timezone tz\n")},
5085
Tim Peters2a799bf2002-12-16 20:18:38 +00005086 {"__setstate__", (PyCFunction)datetimetz_setstate, METH_O,
5087 PyDoc_STR("__setstate__(state)")},
5088
5089 {"__getstate__", (PyCFunction)datetimetz_getstate, METH_NOARGS,
5090 PyDoc_STR("__getstate__() -> state")},
5091 {NULL, NULL}
5092};
5093
5094static char datetimetz_doc[] =
5095PyDoc_STR("date/time type.");
5096
5097static PyNumberMethods datetimetz_as_number = {
5098 datetimetz_add, /* nb_add */
5099 datetimetz_subtract, /* nb_subtract */
5100 0, /* nb_multiply */
5101 0, /* nb_divide */
5102 0, /* nb_remainder */
5103 0, /* nb_divmod */
5104 0, /* nb_power */
5105 0, /* nb_negative */
5106 0, /* nb_positive */
5107 0, /* nb_absolute */
5108 0, /* nb_nonzero */
5109};
5110
5111statichere PyTypeObject PyDateTime_DateTimeTZType = {
5112 PyObject_HEAD_INIT(NULL)
5113 0, /* ob_size */
5114 "datetime.datetimetz", /* tp_name */
5115 sizeof(PyDateTime_DateTimeTZ), /* tp_basicsize */
5116 0, /* tp_itemsize */
5117 (destructor)datetimetz_dealloc, /* tp_dealloc */
5118 0, /* tp_print */
5119 0, /* tp_getattr */
5120 0, /* tp_setattr */
5121 0, /* tp_compare */
5122 (reprfunc)datetimetz_repr, /* tp_repr */
5123 &datetimetz_as_number, /* tp_as_number */
5124 0, /* tp_as_sequence */
5125 0, /* tp_as_mapping */
5126 0, /* tp_hash */
5127 0, /* tp_call */
5128 0, /* tp_str */
5129 PyObject_GenericGetAttr, /* tp_getattro */
5130 0, /* tp_setattro */
5131 0, /* tp_as_buffer */
5132 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
5133 Py_TPFLAGS_BASETYPE, /* tp_flags */
5134 datetimetz_doc, /* tp_doc */
5135 0, /* tp_traverse */
5136 0, /* tp_clear */
5137 0, /* tp_richcompare */
5138 0, /* tp_weaklistoffset */
5139 0, /* tp_iter */
5140 0, /* tp_iternext */
5141 datetimetz_methods, /* tp_methods */
5142 0, /* tp_members */
5143 datetimetz_getset, /* tp_getset */
5144 &PyDateTime_DateTimeType, /* tp_base */
5145 0, /* tp_dict */
5146 0, /* tp_descr_get */
5147 0, /* tp_descr_set */
5148 0, /* tp_dictoffset */
5149 0, /* tp_init */
5150 0, /* tp_alloc */
5151 datetimetz_new, /* tp_new */
5152 _PyObject_Del, /* tp_free */
5153};
5154
5155/* ---------------------------------------------------------------------------
5156 * Module methods and initialization.
5157 */
5158
5159static PyMethodDef module_methods[] = {
5160 /* Private functions for pickling support, registered with the
5161 * copy_reg module by the module init function.
5162 */
5163 {"_date_pickler", (PyCFunction)date_pickler, METH_O, NULL},
5164 {"_date_unpickler", (PyCFunction)date_unpickler, METH_O, NULL},
5165 {"_datetime_pickler", (PyCFunction)datetime_pickler, METH_O, NULL},
5166 {"_datetime_unpickler", (PyCFunction)datetime_unpickler,METH_O, NULL},
5167 {"_datetimetz_pickler", (PyCFunction)datetimetz_pickler,METH_O, NULL},
5168 {"_datetimetz_unpickler",(PyCFunction)datetimetz_unpickler,METH_O, NULL},
5169 {"_time_pickler", (PyCFunction)time_pickler, METH_O, NULL},
5170 {"_time_unpickler", (PyCFunction)time_unpickler, METH_O, NULL},
5171 {"_timetz_pickler", (PyCFunction)timetz_pickler, METH_O, NULL},
5172 {"_timetz_unpickler", (PyCFunction)timetz_unpickler, METH_O, NULL},
5173 {"_tzinfo_pickler", (PyCFunction)tzinfo_pickler, METH_O, NULL},
5174 {"_tzinfo_unpickler", (PyCFunction)tzinfo_unpickler, METH_NOARGS,
5175 NULL},
5176 {NULL, NULL}
5177};
5178
5179PyMODINIT_FUNC
5180initdatetime(void)
5181{
5182 PyObject *m; /* a module object */
5183 PyObject *d; /* its dict */
5184 PyObject *x;
5185
5186 /* Types that use __reduce__ for pickling need to set the following
5187 * magical attr in the type dict, with a true value.
5188 */
5189 PyObject *safepickle = PyString_FromString("__safe_for_unpickling__");
5190 if (safepickle == NULL)
5191 return;
5192
5193 m = Py_InitModule3("datetime", module_methods,
5194 "Fast implementation of the datetime type.");
5195
5196 if (PyType_Ready(&PyDateTime_DateType) < 0)
5197 return;
5198 if (PyType_Ready(&PyDateTime_DateTimeType) < 0)
5199 return;
5200 if (PyType_Ready(&PyDateTime_DeltaType) < 0)
5201 return;
5202 if (PyType_Ready(&PyDateTime_TimeType) < 0)
5203 return;
5204 if (PyType_Ready(&PyDateTime_TZInfoType) < 0)
5205 return;
5206 if (PyType_Ready(&PyDateTime_TimeTZType) < 0)
5207 return;
5208 if (PyType_Ready(&PyDateTime_DateTimeTZType) < 0)
5209 return;
5210
5211 /* Pickling support, via registering functions with copy_reg. */
5212 {
5213 PyObject *pickler;
5214 PyObject *copyreg = PyImport_ImportModule("copy_reg");
5215
5216 if (copyreg == NULL) return;
5217
5218 pickler = PyObject_GetAttrString(m, "_date_pickler");
5219 if (pickler == NULL) return;
5220 date_unpickler_object = PyObject_GetAttrString(m,
5221 "_date_unpickler");
5222 if (date_unpickler_object == NULL) return;
5223 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5224 &PyDateTime_DateType,
5225 pickler,
5226 date_unpickler_object);
5227 if (x == NULL) return;
5228 Py_DECREF(x);
5229 Py_DECREF(pickler);
5230
5231 pickler = PyObject_GetAttrString(m, "_datetime_pickler");
5232 if (pickler == NULL) return;
5233 datetime_unpickler_object = PyObject_GetAttrString(m,
5234 "_datetime_unpickler");
5235 if (datetime_unpickler_object == NULL) return;
5236 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5237 &PyDateTime_DateTimeType,
5238 pickler,
5239 datetime_unpickler_object);
5240 if (x == NULL) return;
5241 Py_DECREF(x);
5242 Py_DECREF(pickler);
5243
5244 pickler = PyObject_GetAttrString(m, "_time_pickler");
5245 if (pickler == NULL) return;
5246 time_unpickler_object = PyObject_GetAttrString(m,
5247 "_time_unpickler");
5248 if (time_unpickler_object == NULL) return;
5249 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5250 &PyDateTime_TimeType,
5251 pickler,
5252 time_unpickler_object);
5253 if (x == NULL) return;
5254 Py_DECREF(x);
5255 Py_DECREF(pickler);
5256
5257 pickler = PyObject_GetAttrString(m, "_timetz_pickler");
5258 if (pickler == NULL) return;
5259 timetz_unpickler_object = PyObject_GetAttrString(m,
5260 "_timetz_unpickler");
5261 if (timetz_unpickler_object == NULL) return;
5262 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5263 &PyDateTime_TimeTZType,
5264 pickler,
5265 timetz_unpickler_object);
5266 if (x == NULL) return;
5267 Py_DECREF(x);
5268 Py_DECREF(pickler);
5269
5270 pickler = PyObject_GetAttrString(m, "_tzinfo_pickler");
5271 if (pickler == NULL) return;
5272 tzinfo_unpickler_object = PyObject_GetAttrString(m,
5273 "_tzinfo_unpickler");
5274 if (tzinfo_unpickler_object == NULL) return;
5275 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5276 &PyDateTime_TZInfoType,
5277 pickler,
5278 tzinfo_unpickler_object);
5279 if (x== NULL) return;
5280 Py_DECREF(x);
5281 Py_DECREF(pickler);
5282
5283 pickler = PyObject_GetAttrString(m, "_datetimetz_pickler");
5284 if (pickler == NULL) return;
5285 datetimetz_unpickler_object = PyObject_GetAttrString(m,
5286 "_datetimetz_unpickler");
5287 if (datetimetz_unpickler_object == NULL) return;
5288 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5289 &PyDateTime_DateTimeTZType,
5290 pickler,
5291 datetimetz_unpickler_object);
5292 if (x== NULL) return;
5293 Py_DECREF(x);
5294 Py_DECREF(pickler);
5295
5296 Py_DECREF(copyreg);
5297 }
5298
5299 /* timedelta values */
5300 d = PyDateTime_DeltaType.tp_dict;
5301
5302 if (PyDict_SetItem(d, safepickle, Py_True) < 0)
5303 return;
5304
5305 x = new_delta(0, 0, 1, 0);
5306 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5307 return;
5308 Py_DECREF(x);
5309
5310 x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0);
5311 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5312 return;
5313 Py_DECREF(x);
5314
5315 x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0);
5316 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5317 return;
5318 Py_DECREF(x);
5319
5320 /* date values */
5321 d = PyDateTime_DateType.tp_dict;
5322
5323 x = new_date(1, 1, 1);
5324 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5325 return;
5326 Py_DECREF(x);
5327
5328 x = new_date(MAXYEAR, 12, 31);
5329 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5330 return;
5331 Py_DECREF(x);
5332
5333 x = new_delta(1, 0, 0, 0);
5334 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5335 return;
5336 Py_DECREF(x);
5337
5338 /* datetime values */
5339 d = PyDateTime_DateTimeType.tp_dict;
5340
5341 x = new_datetime(1, 1, 1, 0, 0, 0, 0);
5342 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5343 return;
5344 Py_DECREF(x);
5345
5346 x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999);
5347 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5348 return;
5349 Py_DECREF(x);
5350
5351 x = new_delta(0, 0, 1, 0);
5352 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5353 return;
5354 Py_DECREF(x);
5355
5356 /* time values */
5357 d = PyDateTime_TimeType.tp_dict;
5358
5359 x = new_time(0, 0, 0, 0);
5360 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5361 return;
5362 Py_DECREF(x);
5363
5364 x = new_time(23, 59, 59, 999999);
5365 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5366 return;
5367 Py_DECREF(x);
5368
5369 x = new_delta(0, 0, 1, 0);
5370 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5371 return;
5372 Py_DECREF(x);
5373
5374 /* timetz values */
5375 d = PyDateTime_TimeTZType.tp_dict;
5376
5377 x = new_timetz(0, 0, 0, 0, Py_None);
5378 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5379 return;
5380 Py_DECREF(x);
5381
5382 x = new_timetz(23, 59, 59, 999999, Py_None);
5383 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5384 return;
5385 Py_DECREF(x);
5386
5387 x = new_delta(0, 0, 1, 0);
5388 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5389 return;
5390 Py_DECREF(x);
5391
5392 /* datetimetz values */
5393 d = PyDateTime_DateTimeTZType.tp_dict;
5394
5395 x = new_datetimetz(1, 1, 1, 0, 0, 0, 0, Py_None);
5396 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5397 return;
5398 Py_DECREF(x);
5399
5400 x = new_datetimetz(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None);
5401 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5402 return;
5403 Py_DECREF(x);
5404
5405 x = new_delta(0, 0, 1, 0);
5406 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5407 return;
5408 Py_DECREF(x);
5409
5410 Py_DECREF(safepickle);
5411
5412 /* module initialization */
5413 PyModule_AddIntConstant(m, "MINYEAR", MINYEAR);
5414 PyModule_AddIntConstant(m, "MAXYEAR", MAXYEAR);
5415
5416 Py_INCREF(&PyDateTime_DateType);
5417 PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType);
5418
5419 Py_INCREF(&PyDateTime_DateTimeType);
5420 PyModule_AddObject(m, "datetime",
5421 (PyObject *) &PyDateTime_DateTimeType);
5422
5423 Py_INCREF(&PyDateTime_DeltaType);
5424 PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType);
5425
5426 Py_INCREF(&PyDateTime_TimeType);
5427 PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType);
5428
5429 Py_INCREF(&PyDateTime_TZInfoType);
5430 PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
5431
5432 Py_INCREF(&PyDateTime_TimeTZType);
5433 PyModule_AddObject(m, "timetz", (PyObject *) &PyDateTime_TimeTZType);
5434
5435 Py_INCREF(&PyDateTime_DateTimeTZType);
5436 PyModule_AddObject(m, "datetimetz",
5437 (PyObject *)&PyDateTime_DateTimeTZType);
5438
5439 /* A 4-year cycle has an extra leap day over what we'd get from
5440 * pasting together 4 single years.
5441 */
5442 assert(DI4Y == 4 * 365 + 1);
5443 assert(DI4Y == days_before_year(4+1));
5444
5445 /* Similarly, a 400-year cycle has an extra leap day over what we'd
5446 * get from pasting together 4 100-year cycles.
5447 */
5448 assert(DI400Y == 4 * DI100Y + 1);
5449 assert(DI400Y == days_before_year(400+1));
5450
5451 /* OTOH, a 100-year cycle has one fewer leap day than we'd get from
5452 * pasting together 25 4-year cycles.
5453 */
5454 assert(DI100Y == 25 * DI4Y - 1);
5455 assert(DI100Y == days_before_year(100+1));
5456
5457 us_per_us = PyInt_FromLong(1);
5458 us_per_ms = PyInt_FromLong(1000);
5459 us_per_second = PyInt_FromLong(1000000);
5460 us_per_minute = PyInt_FromLong(60000000);
5461 seconds_per_day = PyInt_FromLong(24 * 3600);
5462 if (us_per_us == NULL || us_per_ms == NULL || us_per_second == NULL ||
5463 us_per_minute == NULL || seconds_per_day == NULL)
5464 return;
5465
5466 /* The rest are too big for 32-bit ints, but even
5467 * us_per_week fits in 40 bits, so doubles should be exact.
5468 */
5469 us_per_hour = PyLong_FromDouble(3600000000.0);
5470 us_per_day = PyLong_FromDouble(86400000000.0);
5471 us_per_week = PyLong_FromDouble(604800000000.0);
5472 if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL)
5473 return;
5474}
Tim Petersf3615152003-01-01 21:51:37 +00005475
5476/* ---------------------------------------------------------------------------
5477Some time zone algebra. For a datetimetz x, let
5478 x.n = x stripped of its timezone -- its naive time.
5479 x.o = x.utcoffset(), and assuming that doesn't raise an exception or
5480 return None
5481 x.d = x.dst(), and assuming that doesn't raise an exception or
5482 return None
5483 x.s = x's standard offset, x.o - x.d
5484
5485Now some derived rules, where k is a duration (timedelta).
5486
54871. x.o = x.s + x.d
5488 This follows from the definition of x.s.
5489
54902. If x and y have the same tzinfo member, x.s == y.s.
5491 This is actually a requirement, an assumption we need to make about
5492 sane tzinfo classes.
5493
54943. The naive UTC time corresponding to x is x.n - x.o.
5495 This is again a requirement for a sane tzinfo class.
5496
54974. (x+k).s = x.s
5498 This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
5499
55005. (y+k).n = y.n + k
5501 Again follows from how arithmetic is defined.
5502
5503Now we can explain x.astimezone(tz). Let's assume it's an interesting case
5504(meaning that the various tzinfo methods exist, and don't blow up or return
5505None when called).
5506
5507The function wants to return a datetimetz y with timezone tz, equivalent to x.
5508
5509By #3, we want
5510
5511 y.n - y.o = x.n - x.o [1]
5512
5513The algorithm starts by attaching tz to x.n, and calling that y. So
5514x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
5515becomes true; in effect, we want to solve [2] for k:
5516
5517 (y+k).n - (y+k).o = x.n - x.o [2]
5518
5519By #1, this is the same as
5520
5521 (y+k).n - ((y+k).s + (y+k).d) = x.n - x.o [3]
5522
5523By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
5524Substituting that into [3],
5525
5526 x.n + k - (y+k).s - (y+k).d = x.n - x.o; the x.n terms cancel, leaving
5527 k - (y+k).s - (y+k).d = - x.o; rearranging,
5528 k = (y+k).s - x.o - (y+k).d; by #4, (y+k).s == y.s, so
5529 k = y.s - x.o - (y+k).d; then by #1, y.s = y.o - y.d, so
5530 k = y.o - y.d - x.o - (y+k).d
5531
5532On the RHS, (y+k).d can't be computed directly, but all the rest can be, and
5533we approximate k by ignoring the (y+k).d term at first. Note that k can't
5534be very large, since all offset-returning methods return a duration of
5535magnitude less than 24 hours. For that reason, if y is firmly in std time,
5536(y+k).d must be 0, so ignoring it has no consequence then.
5537
5538In any case, the new value is
5539
Tim Petersc3bb26a2003-01-02 03:14:59 +00005540 z.n = y.n + y.o - y.d - x.o
Tim Petersf3615152003-01-01 21:51:37 +00005541
5542If
5543 z.n - z.o = x.n - x.o [4]
5544
5545then, we have an equivalent time, and are almost done. The insecurity here is
5546at the start of daylight time. Picture US Eastern for concreteness. The wall
5547time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
5548sense then. A sensible Eastern tzinfo class will consider such a time to be
5549EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST on the
5550day DST starts. We want to return the 1:MM EST spelling because that's
5551the only spelling that makes sense on the local wall clock.
5552
5553Claim: When [4] is true, we have "the right" spelling in this endcase. No
5554further adjustment is necessary.
5555
5556Proof: The right spelling has z.d = 0, and the wrong spelling has z.d != 0
5557(for US Eastern, the wrong spelling has z.d = 60 minutes, but we can't assume
5558that all time zones work this way -- we can assume a time zone is in daylight
5559time iff dst() doesn't return 0). By [4], and recalling that z.o = z.s + z.d,
5560
5561 z.n - z.s - z.d = x.n - x.o [5]
5562
5563Also
5564
5565 z.n = (y + y.o - y.d - x.o).n by the construction of z, which equals
5566 y.n + y.o - y.d - x.o by #5.
5567
5568Plugging that into [5],
5569
5570 y.n + y.o - y.d - x.o - z.s - z.d = x.n - x.o; cancelling the x.o terms,
5571 y.n + y.o - y.d - z.s - z.d = x.n; but x.n = y.n too, so they also cancel,
5572 y.o - y.d - z.s - z.d = 0; then y.o = y.s + y.d, so
5573 y.s + y.d - y.d - z.s - z.d = 0; then the y.d terms cancel,
5574 y.s - z.s - z.d = 0; but y and z are in the same timezone, so by #2
5575 y.s = z.s, and they also cancel, leaving
5576 - z.d = 0; or,
5577 z.d = 0
5578
5579Therefore z is the standard-time spelling, and there's nothing left to do in
5580this case.
5581
Tim Petersc3bb26a2003-01-02 03:14:59 +00005582QED
Tim Petersf3615152003-01-01 21:51:37 +00005583
Tim Petersc3bb26a2003-01-02 03:14:59 +00005584Note that we actually proved something stronger: [4] is true if and only if
5585z.dst() returns 0. The "only if" part was proved directly. The "if" part
5586is proved by starting with z.d = 0 and reading the proof bottom-up; all the
5587steps are "iff", so are reversible.
5588
5589Next: if [4] isn't true, we're not done. It's helpful to step back and look
5590at
5591
5592 z.n = y.n + y.o - y.d - x.o = y.n-x.o + y.o-y.d
5593
5594from a higher level. Since y.n = x.n, the y.n-x.o part gives x's UTC
5595equivalent hour. Then since y.s=y.o-y.d, the y.o-y.d part converts x's UTC
5596equivalent into tz's standard time. IOW, z is the correct spelling of x in
5597tz's standard time.
5598If
5599 z.n - z.o != x.n - x.o
5600despite that, then either (1) x is in the "unspellable hour" at the end
5601of tz's daylight period; or, (2) z.n needs to be shifted into tz's daylight
5602time.
5603
5604Assuming #2, that would be easy if we could ask the tzinfo object what the
5605daylight offset would be if DST were in effect. And we could compute z.d,
5606but we already have enough info to compute it from the quantities we know:
5607
5608Claim: The adjustment needed is adding (x.n-x.o)-(z.n-z.o) to z.n.
5609
5610Proof: By the comment following the last proof, z.d is not 0 now, and z.d
5611is what we need to add to z.n (it's the "missing part" of the conversion from
5612x's UTC equivalent to z's daylight time).
5613
5614 z.d = z.o - z.s by #1; z.s = y.s since they're in the same time zone, so
5615 z.d = z.o - y.s; then y.s = y.o - y.d by #1, so
5616 z.d = z.o - (y.o - y.d); then since z.n = y.n+y.o-y.d-x.o, y.o-y.d=
5617 z.n-y.n+x.o, so
5618 z.d = z.o - (z.n - y.n + x.o); then x.n = y.n, so
5619 z.d = z.o - (z.n - x.n + x.o)
5620and simple rearranging gives the desired
5621 z.d = (x.n - x.o) - (z.n - z.o)
5622
5623The code actually optimizes this some more, in a straightforward way. Letting
5624
5625 z'.n = z.n + (x.n - x.o) - (z.n - z.o)
5626
5627we can again ask whether
5628
5629 z'.n - z'.o = x.n - x.o
5630
5631If so, we're done. If not, the tzinfo class is insane, or we're trying to
5632convert to the hour that can't be spelled in tz.
Tim Petersf3615152003-01-01 21:51:37 +00005633--------------------------------------------------------------------------- */