blob: 2c75de8180d069e341982fc8b8585502901a8ef0 [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
Tim Peters5d644dd2003-01-02 16:32:54 +0000123/* Round a double to the nearest long. |x| must be small enough to fit
124 * in a C long; this is not checked.
125 */
126static long
127round_to_long(double x)
128{
129 if (x >= 0.0)
130 x = floor(x + 0.5);
131 else
132 x = ceil(x - 0.5);
133 return (long)x;
134}
135
Tim Peters2a799bf2002-12-16 20:18:38 +0000136/* ---------------------------------------------------------------------------
137 * General calendrical helper functions
138 */
139
140/* For each month ordinal in 1..12, the number of days in that month,
141 * and the number of days before that month in the same year. These
142 * are correct for non-leap years only.
143 */
144static int _days_in_month[] = {
145 0, /* unused; this vector uses 1-based indexing */
146 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
147};
148
149static int _days_before_month[] = {
150 0, /* unused; this vector uses 1-based indexing */
151 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
152};
153
154/* year -> 1 if leap year, else 0. */
155static int
156is_leap(int year)
157{
158 /* Cast year to unsigned. The result is the same either way, but
159 * C can generate faster code for unsigned mod than for signed
160 * mod (especially for % 4 -- a good compiler should just grab
161 * the last 2 bits when the LHS is unsigned).
162 */
163 const unsigned int ayear = (unsigned int)year;
164 return ayear % 4 == 0 && (ayear % 100 != 0 || ayear % 400 == 0);
165}
166
167/* year, month -> number of days in that month in that year */
168static int
169days_in_month(int year, int month)
170{
171 assert(month >= 1);
172 assert(month <= 12);
173 if (month == 2 && is_leap(year))
174 return 29;
175 else
176 return _days_in_month[month];
177}
178
179/* year, month -> number of days in year preceeding first day of month */
180static int
181days_before_month(int year, int month)
182{
183 int days;
184
185 assert(month >= 1);
186 assert(month <= 12);
187 days = _days_before_month[month];
188 if (month > 2 && is_leap(year))
189 ++days;
190 return days;
191}
192
193/* year -> number of days before January 1st of year. Remember that we
194 * start with year 1, so days_before_year(1) == 0.
195 */
196static int
197days_before_year(int year)
198{
199 int y = year - 1;
200 /* This is incorrect if year <= 0; we really want the floor
201 * here. But so long as MINYEAR is 1, the smallest year this
202 * can see is 0 (this can happen in some normalization endcases),
203 * so we'll just special-case that.
204 */
205 assert (year >= 0);
206 if (y >= 0)
207 return y*365 + y/4 - y/100 + y/400;
208 else {
209 assert(y == -1);
210 return -366;
211 }
212}
213
214/* Number of days in 4, 100, and 400 year cycles. That these have
215 * the correct values is asserted in the module init function.
216 */
217#define DI4Y 1461 /* days_before_year(5); days in 4 years */
218#define DI100Y 36524 /* days_before_year(101); days in 100 years */
219#define DI400Y 146097 /* days_before_year(401); days in 400 years */
220
221/* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */
222static void
223ord_to_ymd(int ordinal, int *year, int *month, int *day)
224{
225 int n, n1, n4, n100, n400, leapyear, preceding;
226
227 /* ordinal is a 1-based index, starting at 1-Jan-1. The pattern of
228 * leap years repeats exactly every 400 years. The basic strategy is
229 * to find the closest 400-year boundary at or before ordinal, then
230 * work with the offset from that boundary to ordinal. Life is much
231 * clearer if we subtract 1 from ordinal first -- then the values
232 * of ordinal at 400-year boundaries are exactly those divisible
233 * by DI400Y:
234 *
235 * D M Y n n-1
236 * -- --- ---- ---------- ----------------
237 * 31 Dec -400 -DI400Y -DI400Y -1
238 * 1 Jan -399 -DI400Y +1 -DI400Y 400-year boundary
239 * ...
240 * 30 Dec 000 -1 -2
241 * 31 Dec 000 0 -1
242 * 1 Jan 001 1 0 400-year boundary
243 * 2 Jan 001 2 1
244 * 3 Jan 001 3 2
245 * ...
246 * 31 Dec 400 DI400Y DI400Y -1
247 * 1 Jan 401 DI400Y +1 DI400Y 400-year boundary
248 */
249 assert(ordinal >= 1);
250 --ordinal;
251 n400 = ordinal / DI400Y;
252 n = ordinal % DI400Y;
253 *year = n400 * 400 + 1;
254
255 /* Now n is the (non-negative) offset, in days, from January 1 of
256 * year, to the desired date. Now compute how many 100-year cycles
257 * precede n.
258 * Note that it's possible for n100 to equal 4! In that case 4 full
259 * 100-year cycles precede the desired day, which implies the
260 * desired day is December 31 at the end of a 400-year cycle.
261 */
262 n100 = n / DI100Y;
263 n = n % DI100Y;
264
265 /* Now compute how many 4-year cycles precede it. */
266 n4 = n / DI4Y;
267 n = n % DI4Y;
268
269 /* And now how many single years. Again n1 can be 4, and again
270 * meaning that the desired day is December 31 at the end of the
271 * 4-year cycle.
272 */
273 n1 = n / 365;
274 n = n % 365;
275
276 *year += n100 * 100 + n4 * 4 + n1;
277 if (n1 == 4 || n100 == 4) {
278 assert(n == 0);
279 *year -= 1;
280 *month = 12;
281 *day = 31;
282 return;
283 }
284
285 /* Now the year is correct, and n is the offset from January 1. We
286 * find the month via an estimate that's either exact or one too
287 * large.
288 */
289 leapyear = n1 == 3 && (n4 != 24 || n100 == 3);
290 assert(leapyear == is_leap(*year));
291 *month = (n + 50) >> 5;
292 preceding = (_days_before_month[*month] + (*month > 2 && leapyear));
293 if (preceding > n) {
294 /* estimate is too large */
295 *month -= 1;
296 preceding -= days_in_month(*year, *month);
297 }
298 n -= preceding;
299 assert(0 <= n);
300 assert(n < days_in_month(*year, *month));
301
302 *day = n + 1;
303}
304
305/* year, month, day -> ordinal, considering 01-Jan-0001 as day 1. */
306static int
307ymd_to_ord(int year, int month, int day)
308{
309 return days_before_year(year) + days_before_month(year, month) + day;
310}
311
312/* Day of week, where Monday==0, ..., Sunday==6. 1/1/1 was a Monday. */
313static int
314weekday(int year, int month, int day)
315{
316 return (ymd_to_ord(year, month, day) + 6) % 7;
317}
318
319/* Ordinal of the Monday starting week 1 of the ISO year. Week 1 is the
320 * first calendar week containing a Thursday.
321 */
322static int
323iso_week1_monday(int year)
324{
325 int first_day = ymd_to_ord(year, 1, 1); /* ord of 1/1 */
326 /* 0 if 1/1 is a Monday, 1 if a Tue, etc. */
327 int first_weekday = (first_day + 6) % 7;
328 /* ordinal of closest Monday at or before 1/1 */
329 int week1_monday = first_day - first_weekday;
330
331 if (first_weekday > 3) /* if 1/1 was Fri, Sat, Sun */
332 week1_monday += 7;
333 return week1_monday;
334}
335
336/* ---------------------------------------------------------------------------
337 * Range checkers.
338 */
339
340/* Check that -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS. If so, return 0.
341 * If not, raise OverflowError and return -1.
342 */
343static int
344check_delta_day_range(int days)
345{
346 if (-MAX_DELTA_DAYS <= days && days <= MAX_DELTA_DAYS)
347 return 0;
348 PyErr_Format(PyExc_OverflowError,
349 "days=%d; must have magnitude <= %d",
Guido van Rossumbd43e912002-12-16 20:34:55 +0000350 days, MAX_DELTA_DAYS);
Tim Peters2a799bf2002-12-16 20:18:38 +0000351 return -1;
352}
353
354/* Check that date arguments are in range. Return 0 if they are. If they
355 * aren't, raise ValueError and return -1.
356 */
357static int
358check_date_args(int year, int month, int day)
359{
360
361 if (year < MINYEAR || year > MAXYEAR) {
362 PyErr_SetString(PyExc_ValueError,
363 "year is out of range");
364 return -1;
365 }
366 if (month < 1 || month > 12) {
367 PyErr_SetString(PyExc_ValueError,
368 "month must be in 1..12");
369 return -1;
370 }
371 if (day < 1 || day > days_in_month(year, month)) {
372 PyErr_SetString(PyExc_ValueError,
373 "day is out of range for month");
374 return -1;
375 }
376 return 0;
377}
378
379/* Check that time arguments are in range. Return 0 if they are. If they
380 * aren't, raise ValueError and return -1.
381 */
382static int
383check_time_args(int h, int m, int s, int us)
384{
385 if (h < 0 || h > 23) {
386 PyErr_SetString(PyExc_ValueError,
387 "hour must be in 0..23");
388 return -1;
389 }
390 if (m < 0 || m > 59) {
391 PyErr_SetString(PyExc_ValueError,
392 "minute must be in 0..59");
393 return -1;
394 }
395 if (s < 0 || s > 59) {
396 PyErr_SetString(PyExc_ValueError,
397 "second must be in 0..59");
398 return -1;
399 }
400 if (us < 0 || us > 999999) {
401 PyErr_SetString(PyExc_ValueError,
402 "microsecond must be in 0..999999");
403 return -1;
404 }
405 return 0;
406}
407
408/* ---------------------------------------------------------------------------
409 * Normalization utilities.
410 */
411
412/* One step of a mixed-radix conversion. A "hi" unit is equivalent to
413 * factor "lo" units. factor must be > 0. If *lo is less than 0, or
414 * at least factor, enough of *lo is converted into "hi" units so that
415 * 0 <= *lo < factor. The input values must be such that int overflow
416 * is impossible.
417 */
418static void
419normalize_pair(int *hi, int *lo, int factor)
420{
421 assert(factor > 0);
422 assert(lo != hi);
423 if (*lo < 0 || *lo >= factor) {
424 const int num_hi = divmod(*lo, factor, lo);
425 const int new_hi = *hi + num_hi;
426 assert(! SIGNED_ADD_OVERFLOWED(new_hi, *hi, num_hi));
427 *hi = new_hi;
428 }
429 assert(0 <= *lo && *lo < factor);
430}
431
432/* Fiddle days (d), seconds (s), and microseconds (us) so that
433 * 0 <= *s < 24*3600
434 * 0 <= *us < 1000000
435 * The input values must be such that the internals don't overflow.
436 * The way this routine is used, we don't get close.
437 */
438static void
439normalize_d_s_us(int *d, int *s, int *us)
440{
441 if (*us < 0 || *us >= 1000000) {
442 normalize_pair(s, us, 1000000);
443 /* |s| can't be bigger than about
444 * |original s| + |original us|/1000000 now.
445 */
446
447 }
448 if (*s < 0 || *s >= 24*3600) {
449 normalize_pair(d, s, 24*3600);
450 /* |d| can't be bigger than about
451 * |original d| +
452 * (|original s| + |original us|/1000000) / (24*3600) now.
453 */
454 }
455 assert(0 <= *s && *s < 24*3600);
456 assert(0 <= *us && *us < 1000000);
457}
458
459/* Fiddle years (y), months (m), and days (d) so that
460 * 1 <= *m <= 12
461 * 1 <= *d <= days_in_month(*y, *m)
462 * The input values must be such that the internals don't overflow.
463 * The way this routine is used, we don't get close.
464 */
465static void
466normalize_y_m_d(int *y, int *m, int *d)
467{
468 int dim; /* # of days in month */
469
470 /* This gets muddy: the proper range for day can't be determined
471 * without knowing the correct month and year, but if day is, e.g.,
472 * plus or minus a million, the current month and year values make
473 * no sense (and may also be out of bounds themselves).
474 * Saying 12 months == 1 year should be non-controversial.
475 */
476 if (*m < 1 || *m > 12) {
477 --*m;
478 normalize_pair(y, m, 12);
479 ++*m;
480 /* |y| can't be bigger than about
481 * |original y| + |original m|/12 now.
482 */
483 }
484 assert(1 <= *m && *m <= 12);
485
486 /* Now only day can be out of bounds (year may also be out of bounds
487 * for a datetime object, but we don't care about that here).
488 * If day is out of bounds, what to do is arguable, but at least the
489 * method here is principled and explainable.
490 */
491 dim = days_in_month(*y, *m);
492 if (*d < 1 || *d > dim) {
493 /* Move day-1 days from the first of the month. First try to
494 * get off cheap if we're only one day out of range
495 * (adjustments for timezone alone can't be worse than that).
496 */
497 if (*d == 0) {
498 --*m;
499 if (*m > 0)
500 *d = days_in_month(*y, *m);
501 else {
502 --*y;
503 *m = 12;
504 *d = 31;
505 }
506 }
507 else if (*d == dim + 1) {
508 /* move forward a day */
509 ++*m;
510 *d = 1;
511 if (*m > 12) {
512 *m = 1;
513 ++*y;
514 }
515 }
516 else {
517 int ordinal = ymd_to_ord(*y, *m, 1) +
518 *d - 1;
519 ord_to_ymd(ordinal, y, m, d);
520 }
521 }
522 assert(*m > 0);
523 assert(*d > 0);
524}
525
526/* Fiddle out-of-bounds months and days so that the result makes some kind
527 * of sense. The parameters are both inputs and outputs. Returns < 0 on
528 * failure, where failure means the adjusted year is out of bounds.
529 */
530static int
531normalize_date(int *year, int *month, int *day)
532{
533 int result;
534
535 normalize_y_m_d(year, month, day);
536 if (MINYEAR <= *year && *year <= MAXYEAR)
537 result = 0;
538 else {
539 PyErr_SetString(PyExc_OverflowError,
540 "date value out of range");
541 result = -1;
542 }
543 return result;
544}
545
546/* Force all the datetime fields into range. The parameters are both
547 * inputs and outputs. Returns < 0 on error.
548 */
549static int
550normalize_datetime(int *year, int *month, int *day,
551 int *hour, int *minute, int *second,
552 int *microsecond)
553{
554 normalize_pair(second, microsecond, 1000000);
555 normalize_pair(minute, second, 60);
556 normalize_pair(hour, minute, 60);
557 normalize_pair(day, hour, 24);
558 return normalize_date(year, month, day);
559}
560
561/* ---------------------------------------------------------------------------
562 * tzinfo helpers.
563 */
564
Tim Peters855fe882002-12-22 03:43:39 +0000565/* Ensure that p is None or of a tzinfo subclass. Return 0 if OK; if not
566 * raise TypeError and return -1.
567 */
568static int
569check_tzinfo_subclass(PyObject *p)
570{
571 if (p == Py_None || PyTZInfo_Check(p))
572 return 0;
573 PyErr_Format(PyExc_TypeError,
574 "tzinfo argument must be None or of a tzinfo subclass, "
575 "not type '%s'",
576 p->ob_type->tp_name);
577 return -1;
578}
579
Tim Petersbad8ff02002-12-30 20:52:32 +0000580/* Return tzinfo.methname(tzinfoarg), without any checking of results.
Tim Peters855fe882002-12-22 03:43:39 +0000581 * If tzinfo is None, returns None.
582 */
583static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000584call_tzinfo_method(PyObject *tzinfo, char *methname, PyObject *tzinfoarg)
Tim Peters855fe882002-12-22 03:43:39 +0000585{
586 PyObject *result;
587
Tim Petersbad8ff02002-12-30 20:52:32 +0000588 assert(tzinfo && methname && tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000589 assert(check_tzinfo_subclass(tzinfo) >= 0);
590 if (tzinfo == Py_None) {
591 result = Py_None;
592 Py_INCREF(result);
593 }
594 else
Tim Petersbad8ff02002-12-30 20:52:32 +0000595 result = PyObject_CallMethod(tzinfo, methname, "O", tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000596 return result;
597}
598
Tim Peters2a799bf2002-12-16 20:18:38 +0000599/* If self has a tzinfo member, return a BORROWED reference to it. Else
600 * return NULL, which is NOT AN ERROR. There are no error returns here,
601 * and the caller must not decref the result.
602 */
603static PyObject *
604get_tzinfo_member(PyObject *self)
605{
606 PyObject *tzinfo = NULL;
607
608 if (PyDateTimeTZ_Check(self))
609 tzinfo = ((PyDateTime_DateTimeTZ *)self)->tzinfo;
610 else if (PyTimeTZ_Check(self))
611 tzinfo = ((PyDateTime_TimeTZ *)self)->tzinfo;
612
613 return tzinfo;
614}
615
Tim Peters80475bb2002-12-25 07:40:55 +0000616/* self is a datetimetz. Replace its tzinfo member. */
617void
618replace_tzinfo(PyObject *self, PyObject *newtzinfo)
619{
620 assert(self != NULL);
621 assert(PyDateTimeTZ_Check(self));
622 assert(check_tzinfo_subclass(newtzinfo) >= 0);
623 Py_INCREF(newtzinfo);
624 Py_DECREF(((PyDateTime_DateTimeTZ *)self)->tzinfo);
625 ((PyDateTime_DateTimeTZ *)self)->tzinfo = newtzinfo;
626}
627
Tim Petersbad8ff02002-12-30 20:52:32 +0000628
629/* Call getattr(tzinfo, name)(tzinfoarg), and extract an int from the
Tim Peters2a799bf2002-12-16 20:18:38 +0000630 * result. tzinfo must be an instance of the tzinfo class. If the method
631 * returns None, this returns 0 and sets *none to 1. If the method doesn't
Tim Peters397301e2003-01-02 21:28:08 +0000632 * return None or timedelta, TypeError is raised and this returns -1. If it
633 * returnsa timedelta and the value is out of range or isn't a whole number
634 * of minutes, ValueError is raised and this returns -1.
Tim Peters2a799bf2002-12-16 20:18:38 +0000635 * Else *none is set to 0 and the integer method result is returned.
636 */
637static int
638call_utc_tzinfo_method(PyObject *tzinfo, char *name, PyObject *tzinfoarg,
639 int *none)
640{
641 PyObject *u;
Tim Peters397301e2003-01-02 21:28:08 +0000642 int result = -1;
Tim Peters2a799bf2002-12-16 20:18:38 +0000643
644 assert(tzinfo != NULL);
645 assert(PyTZInfo_Check(tzinfo));
646 assert(tzinfoarg != NULL);
647
648 *none = 0;
Tim Petersbad8ff02002-12-30 20:52:32 +0000649 u = call_tzinfo_method(tzinfo, name, tzinfoarg);
Tim Peters2a799bf2002-12-16 20:18:38 +0000650 if (u == NULL)
651 return -1;
652
Tim Peters27362852002-12-23 16:17:39 +0000653 else if (u == Py_None) {
Tim Peters2a799bf2002-12-16 20:18:38 +0000654 result = 0;
655 *none = 1;
Tim Peters2a799bf2002-12-16 20:18:38 +0000656 }
Tim Peters855fe882002-12-22 03:43:39 +0000657 else if (PyDelta_Check(u)) {
658 const int days = GET_TD_DAYS(u);
659 if (days < -1 || days > 0)
660 result = 24*60; /* trigger ValueError below */
661 else {
662 /* next line can't overflow because we know days
663 * is -1 or 0 now
664 */
665 int ss = days * 24 * 3600 + GET_TD_SECONDS(u);
666 result = divmod(ss, 60, &ss);
667 if (ss || GET_TD_MICROSECONDS(u)) {
668 PyErr_Format(PyExc_ValueError,
669 "tzinfo.%s() must return a "
670 "whole number of minutes",
671 name);
672 result = -1;
Tim Peters855fe882002-12-22 03:43:39 +0000673 }
674 }
675 }
Tim Peters2a799bf2002-12-16 20:18:38 +0000676 else {
677 PyErr_Format(PyExc_TypeError,
Tim Peters397301e2003-01-02 21:28:08 +0000678 "tzinfo.%s() must return None or "
Tim Peters855fe882002-12-22 03:43:39 +0000679 "timedelta, not '%s'",
680 name, u->ob_type->tp_name);
Tim Peters2a799bf2002-12-16 20:18:38 +0000681 }
682
Tim Peters2a799bf2002-12-16 20:18:38 +0000683 Py_DECREF(u);
684 if (result < -1439 || result > 1439) {
685 PyErr_Format(PyExc_ValueError,
686 "tzinfo.%s() returned %ld; must be in "
687 "-1439 .. 1439",
688 name, result);
689 result = -1;
690 }
Tim Peters397301e2003-01-02 21:28:08 +0000691 return result;
Tim Peters2a799bf2002-12-16 20:18:38 +0000692}
693
694/* Call tzinfo.utcoffset(tzinfoarg), and extract an integer from the
695 * result. tzinfo must be an instance of the tzinfo class. If utcoffset()
696 * returns None, call_utcoffset returns 0 and sets *none to 1. If uctoffset()
Tim Peters397301e2003-01-02 21:28:08 +0000697 * doesn't return None or timedelta, TypeError is raised and this returns -1.
698 * If utcoffset() returns an invalid timedelta (out of range, or not a whole
699 * # of minutes), ValueError is raised and this returns -1. Else *none is
700 * set to 0 and the offset is returned (as int # of minutes east of UTC).
Tim Peters2a799bf2002-12-16 20:18:38 +0000701 */
702static int
703call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
704{
705 return call_utc_tzinfo_method(tzinfo, "utcoffset", tzinfoarg, none);
706}
707
Tim Peters855fe882002-12-22 03:43:39 +0000708static PyObject *new_delta(int d, int sec, int usec, int normalize);
709
Tim Petersbad8ff02002-12-30 20:52:32 +0000710/* Call tzinfo.name(tzinfoarg), and return the offset as a timedelta or None.
711 */
Tim Peters855fe882002-12-22 03:43:39 +0000712static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000713offset_as_timedelta(PyObject *tzinfo, char *name, PyObject *tzinfoarg) {
Tim Peters855fe882002-12-22 03:43:39 +0000714 PyObject *result;
715
Tim Petersbad8ff02002-12-30 20:52:32 +0000716 assert(tzinfo && name && tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000717 if (tzinfo == Py_None) {
718 result = Py_None;
719 Py_INCREF(result);
720 }
721 else {
722 int none;
Tim Petersbad8ff02002-12-30 20:52:32 +0000723 int offset = call_utc_tzinfo_method(tzinfo, name, tzinfoarg,
724 &none);
Tim Peters855fe882002-12-22 03:43:39 +0000725 if (offset < 0 && PyErr_Occurred())
726 return NULL;
727 if (none) {
728 result = Py_None;
729 Py_INCREF(result);
730 }
731 else
732 result = new_delta(0, offset * 60, 0, 1);
733 }
734 return result;
735}
736
Tim Peters2a799bf2002-12-16 20:18:38 +0000737/* Call tzinfo.dst(tzinfoarg), and extract an integer from the
738 * result. tzinfo must be an instance of the tzinfo class. If dst()
739 * returns None, call_dst returns 0 and sets *none to 1. If dst()
Tim Peters397301e2003-01-02 21:28:08 +0000740 & doesn't return None or timedelta, TypeError is raised and this
741 * returns -1. If dst() returns an invalid timedelta for for a UTC offset,
742 * ValueError is raised and this returns -1. Else *none is set to 0 and
743 * the offset is returned (as an int # of minutes east of UTC).
Tim Peters2a799bf2002-12-16 20:18:38 +0000744 */
745static int
746call_dst(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
747{
748 return call_utc_tzinfo_method(tzinfo, "dst", tzinfoarg, none);
749}
750
Tim Petersbad8ff02002-12-30 20:52:32 +0000751/* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be
Tim Peters855fe882002-12-22 03:43:39 +0000752 * an instance of the tzinfo class or None. If tzinfo isn't None, and
Tim Petersbad8ff02002-12-30 20:52:32 +0000753 * tzname() doesn't return None or a string, TypeError is raised and this
Tim Peters855fe882002-12-22 03:43:39 +0000754 * returns NULL.
Tim Peters2a799bf2002-12-16 20:18:38 +0000755 */
756static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000757call_tzname(PyObject *tzinfo, PyObject *tzinfoarg)
Tim Peters2a799bf2002-12-16 20:18:38 +0000758{
759 PyObject *result;
760
761 assert(tzinfo != NULL);
Tim Peters855fe882002-12-22 03:43:39 +0000762 assert(check_tzinfo_subclass(tzinfo) >= 0);
Tim Petersbad8ff02002-12-30 20:52:32 +0000763 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +0000764
Tim Peters855fe882002-12-22 03:43:39 +0000765 if (tzinfo == Py_None) {
766 result = Py_None;
767 Py_INCREF(result);
768 }
769 else
Tim Petersbad8ff02002-12-30 20:52:32 +0000770 result = PyObject_CallMethod(tzinfo, "tzname", "O", tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000771
772 if (result != NULL && result != Py_None && ! PyString_Check(result)) {
773 PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must "
Tim Peters2a799bf2002-12-16 20:18:38 +0000774 "return None or a string, not '%s'",
775 result->ob_type->tp_name);
776 Py_DECREF(result);
777 result = NULL;
778 }
779 return result;
780}
781
782typedef enum {
783 /* an exception has been set; the caller should pass it on */
784 OFFSET_ERROR,
785
786 /* type isn't date, datetime, datetimetz subclass, time, or
787 * timetz subclass
788 */
789 OFFSET_UNKNOWN,
790
791 /* date,
792 * datetime,
793 * datetimetz with None tzinfo,
Tim Peters855fe882002-12-22 03:43:39 +0000794 * datetimetz where utcoffset() returns None
Tim Peters2a799bf2002-12-16 20:18:38 +0000795 * time,
796 * timetz with None tzinfo,
797 * timetz where utcoffset() returns None
798 */
799 OFFSET_NAIVE,
800
801 /* timetz where utcoffset() doesn't return None,
802 * datetimetz where utcoffset() doesn't return None
803 */
804 OFFSET_AWARE,
805} naivety;
806
Tim Peters14b69412002-12-22 18:10:22 +0000807/* Classify an object as to whether it's naive or offset-aware. See
Tim Peters2a799bf2002-12-16 20:18:38 +0000808 * the "naivety" typedef for details. If the type is aware, *offset is set
809 * to minutes east of UTC (as returned by the tzinfo.utcoffset() method).
Tim Peters14b69412002-12-22 18:10:22 +0000810 * If the type is offset-naive (or unknown, or error), *offset is set to 0.
Tim Peterse39a80c2002-12-30 21:28:52 +0000811 * tzinfoarg is the argument to pass to the tzinfo.utcoffset() method.
Tim Peters2a799bf2002-12-16 20:18:38 +0000812 */
813static naivety
Tim Peterse39a80c2002-12-30 21:28:52 +0000814classify_utcoffset(PyObject *op, PyObject *tzinfoarg, int *offset)
Tim Peters2a799bf2002-12-16 20:18:38 +0000815{
816 int none;
817 PyObject *tzinfo;
818
Tim Peterse39a80c2002-12-30 21:28:52 +0000819 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +0000820 *offset = 0;
Tim Peters14b69412002-12-22 18:10:22 +0000821 tzinfo = get_tzinfo_member(op); /* NULL means no tzinfo, not error */
Tim Peters2a799bf2002-12-16 20:18:38 +0000822 if (tzinfo == Py_None)
823 return OFFSET_NAIVE;
Tim Peters14b69412002-12-22 18:10:22 +0000824 if (tzinfo == NULL) {
825 /* note that a datetime passes the PyDate_Check test */
826 return (PyTime_Check(op) || PyDate_Check(op)) ?
827 OFFSET_NAIVE : OFFSET_UNKNOWN;
828 }
Tim Peterse39a80c2002-12-30 21:28:52 +0000829 *offset = call_utcoffset(tzinfo, tzinfoarg, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +0000830 if (*offset == -1 && PyErr_Occurred())
831 return OFFSET_ERROR;
832 return none ? OFFSET_NAIVE : OFFSET_AWARE;
833}
834
Tim Peters00237032002-12-27 02:21:51 +0000835/* Classify two objects as to whether they're naive or offset-aware.
836 * This isn't quite the same as calling classify_utcoffset() twice: for
837 * binary operations (comparison and subtraction), we generally want to
838 * ignore the tzinfo members if they're identical. This is by design,
839 * so that results match "naive" expectations when mixing objects from a
840 * single timezone. So in that case, this sets both offsets to 0 and
841 * both naiveties to OFFSET_NAIVE.
842 * The function returns 0 if everything's OK, and -1 on error.
843 */
844static int
845classify_two_utcoffsets(PyObject *o1, int *offset1, naivety *n1,
Tim Peterse39a80c2002-12-30 21:28:52 +0000846 PyObject *tzinfoarg1,
847 PyObject *o2, int *offset2, naivety *n2,
848 PyObject *tzinfoarg2)
Tim Peters00237032002-12-27 02:21:51 +0000849{
850 if (get_tzinfo_member(o1) == get_tzinfo_member(o2)) {
851 *offset1 = *offset2 = 0;
852 *n1 = *n2 = OFFSET_NAIVE;
853 }
854 else {
Tim Peterse39a80c2002-12-30 21:28:52 +0000855 *n1 = classify_utcoffset(o1, tzinfoarg1, offset1);
Tim Peters00237032002-12-27 02:21:51 +0000856 if (*n1 == OFFSET_ERROR)
857 return -1;
Tim Peterse39a80c2002-12-30 21:28:52 +0000858 *n2 = classify_utcoffset(o2, tzinfoarg2, offset2);
Tim Peters00237032002-12-27 02:21:51 +0000859 if (*n2 == OFFSET_ERROR)
860 return -1;
861 }
862 return 0;
863}
864
Tim Peters2a799bf2002-12-16 20:18:38 +0000865/* repr is like "someclass(arg1, arg2)". If tzinfo isn't None,
866 * stuff
867 * ", tzinfo=" + repr(tzinfo)
868 * before the closing ")".
869 */
870static PyObject *
871append_keyword_tzinfo(PyObject *repr, PyObject *tzinfo)
872{
873 PyObject *temp;
874
875 assert(PyString_Check(repr));
876 assert(tzinfo);
877 if (tzinfo == Py_None)
878 return repr;
879 /* Get rid of the trailing ')'. */
880 assert(PyString_AsString(repr)[PyString_Size(repr)-1] == ')');
881 temp = PyString_FromStringAndSize(PyString_AsString(repr),
882 PyString_Size(repr) - 1);
883 Py_DECREF(repr);
884 if (temp == NULL)
885 return NULL;
886 repr = temp;
887
888 /* Append ", tzinfo=". */
889 PyString_ConcatAndDel(&repr, PyString_FromString(", tzinfo="));
890
891 /* Append repr(tzinfo). */
892 PyString_ConcatAndDel(&repr, PyObject_Repr(tzinfo));
893
894 /* Add a closing paren. */
895 PyString_ConcatAndDel(&repr, PyString_FromString(")"));
896 return repr;
897}
898
899/* ---------------------------------------------------------------------------
900 * String format helpers.
901 */
902
903static PyObject *
904format_ctime(PyDateTime_Date *date,
905 int hours, int minutes, int seconds)
906{
907 static char *DayNames[] = {
908 "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
909 };
910 static char *MonthNames[] = {
911 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
912 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
913 };
914
915 char buffer[128];
916 int wday = weekday(GET_YEAR(date), GET_MONTH(date), GET_DAY(date));
917
918 PyOS_snprintf(buffer, sizeof(buffer), "%s %s %2d %02d:%02d:%02d %04d",
919 DayNames[wday], MonthNames[GET_MONTH(date) - 1],
920 GET_DAY(date), hours, minutes, seconds,
921 GET_YEAR(date));
922 return PyString_FromString(buffer);
923}
924
925/* Add an hours & minutes UTC offset string to buf. buf has no more than
926 * buflen bytes remaining. The UTC offset is gotten by calling
927 * tzinfo.uctoffset(tzinfoarg). If that returns None, \0 is stored into
928 * *buf, and that's all. Else the returned value is checked for sanity (an
929 * integer in range), and if that's OK it's converted to an hours & minutes
930 * string of the form
931 * sign HH sep MM
932 * Returns 0 if everything is OK. If the return value from utcoffset() is
933 * bogus, an appropriate exception is set and -1 is returned.
934 */
935static int
Tim Peters328fff72002-12-20 01:31:27 +0000936format_utcoffset(char *buf, size_t buflen, const char *sep,
Tim Peters2a799bf2002-12-16 20:18:38 +0000937 PyObject *tzinfo, PyObject *tzinfoarg)
938{
939 int offset;
940 int hours;
941 int minutes;
942 char sign;
943 int none;
944
945 offset = call_utcoffset(tzinfo, tzinfoarg, &none);
946 if (offset == -1 && PyErr_Occurred())
947 return -1;
948 if (none) {
949 *buf = '\0';
950 return 0;
951 }
952 sign = '+';
953 if (offset < 0) {
954 sign = '-';
955 offset = - offset;
956 }
957 hours = divmod(offset, 60, &minutes);
958 PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes);
959 return 0;
960}
961
962/* I sure don't want to reproduce the strftime code from the time module,
963 * so this imports the module and calls it. All the hair is due to
964 * giving special meanings to the %z and %Z format codes via a preprocessing
965 * step on the format string.
Tim Petersbad8ff02002-12-30 20:52:32 +0000966 * tzinfoarg is the argument to pass to the object's tzinfo method, if
967 * needed.
Tim Peters2a799bf2002-12-16 20:18:38 +0000968 */
969static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000970wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
971 PyObject *tzinfoarg)
Tim Peters2a799bf2002-12-16 20:18:38 +0000972{
973 PyObject *result = NULL; /* guilty until proved innocent */
974
975 PyObject *zreplacement = NULL; /* py string, replacement for %z */
976 PyObject *Zreplacement = NULL; /* py string, replacement for %Z */
977
978 char *pin; /* pointer to next char in input format */
979 char ch; /* next char in input format */
980
981 PyObject *newfmt = NULL; /* py string, the output format */
982 char *pnew; /* pointer to available byte in output format */
983 char totalnew; /* number bytes total in output format buffer,
984 exclusive of trailing \0 */
985 char usednew; /* number bytes used so far in output format buffer */
986
987 char *ptoappend; /* pointer to string to append to output buffer */
988 int ntoappend; /* # of bytes to append to output buffer */
989
Tim Peters2a799bf2002-12-16 20:18:38 +0000990 assert(object && format && timetuple);
991 assert(PyString_Check(format));
992
Tim Petersd6844152002-12-22 20:58:42 +0000993 /* Give up if the year is before 1900.
994 * Python strftime() plays games with the year, and different
995 * games depending on whether envar PYTHON2K is set. This makes
996 * years before 1900 a nightmare, even if the platform strftime
997 * supports them (and not all do).
998 * We could get a lot farther here by avoiding Python's strftime
999 * wrapper and calling the C strftime() directly, but that isn't
1000 * an option in the Python implementation of this module.
1001 */
1002 {
1003 long year;
1004 PyObject *pyyear = PySequence_GetItem(timetuple, 0);
1005 if (pyyear == NULL) return NULL;
1006 assert(PyInt_Check(pyyear));
1007 year = PyInt_AsLong(pyyear);
1008 Py_DECREF(pyyear);
1009 if (year < 1900) {
1010 PyErr_Format(PyExc_ValueError, "year=%ld is before "
1011 "1900; the datetime strftime() "
1012 "methods require year >= 1900",
1013 year);
1014 return NULL;
1015 }
1016 }
1017
Tim Peters2a799bf2002-12-16 20:18:38 +00001018 /* Scan the input format, looking for %z and %Z escapes, building
Tim Peters328fff72002-12-20 01:31:27 +00001019 * a new format. Since computing the replacements for those codes
1020 * is expensive, don't unless they're actually used.
Tim Peters2a799bf2002-12-16 20:18:38 +00001021 */
1022 totalnew = PyString_Size(format); /* realistic if no %z/%Z */
1023 newfmt = PyString_FromStringAndSize(NULL, totalnew);
1024 if (newfmt == NULL) goto Done;
1025 pnew = PyString_AsString(newfmt);
1026 usednew = 0;
1027
1028 pin = PyString_AsString(format);
1029 while ((ch = *pin++) != '\0') {
1030 if (ch != '%') {
Tim Peters328fff72002-12-20 01:31:27 +00001031 ptoappend = pin - 1;
Tim Peters2a799bf2002-12-16 20:18:38 +00001032 ntoappend = 1;
1033 }
1034 else if ((ch = *pin++) == '\0') {
1035 /* There's a lone trailing %; doesn't make sense. */
1036 PyErr_SetString(PyExc_ValueError, "strftime format "
1037 "ends with raw %");
1038 goto Done;
1039 }
1040 /* A % has been seen and ch is the character after it. */
1041 else if (ch == 'z') {
1042 if (zreplacement == NULL) {
1043 /* format utcoffset */
Tim Peters328fff72002-12-20 01:31:27 +00001044 char buf[100];
Tim Peters2a799bf2002-12-16 20:18:38 +00001045 PyObject *tzinfo = get_tzinfo_member(object);
1046 zreplacement = PyString_FromString("");
1047 if (zreplacement == NULL) goto Done;
1048 if (tzinfo != Py_None && tzinfo != NULL) {
Tim Petersbad8ff02002-12-30 20:52:32 +00001049 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +00001050 if (format_utcoffset(buf,
Tim Peters328fff72002-12-20 01:31:27 +00001051 sizeof(buf),
Tim Peters2a799bf2002-12-16 20:18:38 +00001052 "",
1053 tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00001054 tzinfoarg) < 0)
Tim Peters2a799bf2002-12-16 20:18:38 +00001055 goto Done;
1056 Py_DECREF(zreplacement);
1057 zreplacement = PyString_FromString(buf);
1058 if (zreplacement == NULL) goto Done;
1059 }
1060 }
1061 assert(zreplacement != NULL);
1062 ptoappend = PyString_AsString(zreplacement);
1063 ntoappend = PyString_Size(zreplacement);
1064 }
1065 else if (ch == 'Z') {
1066 /* format tzname */
1067 if (Zreplacement == NULL) {
1068 PyObject *tzinfo = get_tzinfo_member(object);
1069 Zreplacement = PyString_FromString("");
1070 if (Zreplacement == NULL) goto Done;
1071 if (tzinfo != Py_None && tzinfo != NULL) {
Tim Petersbad8ff02002-12-30 20:52:32 +00001072 PyObject *temp;
1073 assert(tzinfoarg != NULL);
1074 temp = call_tzname(tzinfo, tzinfoarg);
Tim Peters2a799bf2002-12-16 20:18:38 +00001075 if (temp == NULL) goto Done;
1076 if (temp != Py_None) {
1077 assert(PyString_Check(temp));
1078 /* Since the tzname is getting
1079 * stuffed into the format, we
1080 * have to double any % signs
1081 * so that strftime doesn't
1082 * treat them as format codes.
1083 */
1084 Py_DECREF(Zreplacement);
1085 Zreplacement = PyObject_CallMethod(
1086 temp, "replace",
1087 "ss", "%", "%%");
1088 Py_DECREF(temp);
1089 if (Zreplacement == NULL)
1090 goto Done;
1091 }
1092 else
1093 Py_DECREF(temp);
1094 }
1095 }
1096 assert(Zreplacement != NULL);
1097 ptoappend = PyString_AsString(Zreplacement);
1098 ntoappend = PyString_Size(Zreplacement);
1099 }
1100 else {
Tim Peters328fff72002-12-20 01:31:27 +00001101 /* percent followed by neither z nor Z */
1102 ptoappend = pin - 2;
Tim Peters2a799bf2002-12-16 20:18:38 +00001103 ntoappend = 2;
1104 }
1105
1106 /* Append the ntoappend chars starting at ptoappend to
1107 * the new format.
1108 */
1109 assert(ntoappend >= 0);
1110 if (ntoappend == 0)
1111 continue;
1112 while (usednew + ntoappend > totalnew) {
1113 int bigger = totalnew << 1;
1114 if ((bigger >> 1) != totalnew) { /* overflow */
1115 PyErr_NoMemory();
1116 goto Done;
1117 }
1118 if (_PyString_Resize(&newfmt, bigger) < 0)
1119 goto Done;
1120 totalnew = bigger;
1121 pnew = PyString_AsString(newfmt) + usednew;
1122 }
1123 memcpy(pnew, ptoappend, ntoappend);
1124 pnew += ntoappend;
1125 usednew += ntoappend;
1126 assert(usednew <= totalnew);
1127 } /* end while() */
1128
1129 if (_PyString_Resize(&newfmt, usednew) < 0)
1130 goto Done;
1131 {
1132 PyObject *time = PyImport_ImportModule("time");
1133 if (time == NULL)
1134 goto Done;
1135 result = PyObject_CallMethod(time, "strftime", "OO",
1136 newfmt, timetuple);
1137 Py_DECREF(time);
1138 }
1139 Done:
1140 Py_XDECREF(zreplacement);
1141 Py_XDECREF(Zreplacement);
1142 Py_XDECREF(newfmt);
1143 return result;
1144}
1145
1146static char *
1147isoformat_date(PyDateTime_Date *dt, char buffer[], int bufflen)
1148{
1149 int x;
1150 x = PyOS_snprintf(buffer, bufflen,
1151 "%04d-%02d-%02d",
1152 GET_YEAR(dt), GET_MONTH(dt), GET_DAY(dt));
1153 return buffer + x;
1154}
1155
1156static void
1157isoformat_time(PyDateTime_DateTime *dt, char buffer[], int bufflen)
1158{
1159 int us = DATE_GET_MICROSECOND(dt);
1160
1161 PyOS_snprintf(buffer, bufflen,
1162 "%02d:%02d:%02d", /* 8 characters */
1163 DATE_GET_HOUR(dt),
1164 DATE_GET_MINUTE(dt),
1165 DATE_GET_SECOND(dt));
1166 if (us)
1167 PyOS_snprintf(buffer + 8, bufflen - 8, ".%06d", us);
1168}
1169
1170/* ---------------------------------------------------------------------------
1171 * Wrap functions from the time module. These aren't directly available
1172 * from C. Perhaps they should be.
1173 */
1174
1175/* Call time.time() and return its result (a Python float). */
1176static PyObject *
Guido van Rossumbd43e912002-12-16 20:34:55 +00001177time_time(void)
Tim Peters2a799bf2002-12-16 20:18:38 +00001178{
1179 PyObject *result = NULL;
1180 PyObject *time = PyImport_ImportModule("time");
1181
1182 if (time != NULL) {
1183 result = PyObject_CallMethod(time, "time", "()");
1184 Py_DECREF(time);
1185 }
1186 return result;
1187}
1188
1189/* Build a time.struct_time. The weekday and day number are automatically
1190 * computed from the y,m,d args.
1191 */
1192static PyObject *
1193build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
1194{
1195 PyObject *time;
1196 PyObject *result = NULL;
1197
1198 time = PyImport_ImportModule("time");
1199 if (time != NULL) {
1200 result = PyObject_CallMethod(time, "struct_time",
1201 "((iiiiiiiii))",
1202 y, m, d,
1203 hh, mm, ss,
1204 weekday(y, m, d),
1205 days_before_month(y, m) + d,
1206 dstflag);
1207 Py_DECREF(time);
1208 }
1209 return result;
1210}
1211
1212/* ---------------------------------------------------------------------------
1213 * Miscellaneous helpers.
1214 */
1215
1216/* For obscure reasons, we need to use tp_richcompare instead of tp_compare.
1217 * The comparisons here all most naturally compute a cmp()-like result.
1218 * This little helper turns that into a bool result for rich comparisons.
1219 */
1220static PyObject *
1221diff_to_bool(int diff, int op)
1222{
1223 PyObject *result;
1224 int istrue;
1225
1226 switch (op) {
1227 case Py_EQ: istrue = diff == 0; break;
1228 case Py_NE: istrue = diff != 0; break;
1229 case Py_LE: istrue = diff <= 0; break;
1230 case Py_GE: istrue = diff >= 0; break;
1231 case Py_LT: istrue = diff < 0; break;
1232 case Py_GT: istrue = diff > 0; break;
1233 default:
1234 assert(! "op unknown");
1235 istrue = 0; /* To shut up compiler */
1236 }
1237 result = istrue ? Py_True : Py_False;
1238 Py_INCREF(result);
1239 return result;
1240}
1241
1242/* ---------------------------------------------------------------------------
1243 * Helpers for setting object fields. These work on pointers to the
1244 * appropriate base class.
1245 */
1246
1247/* For date, datetime and datetimetz. */
1248static void
1249set_date_fields(PyDateTime_Date *self, int y, int m, int d)
1250{
1251 self->hashcode = -1;
1252 SET_YEAR(self, y);
1253 SET_MONTH(self, m);
1254 SET_DAY(self, d);
1255}
1256
1257/* For datetime and datetimetz. */
1258static void
1259set_datetime_time_fields(PyDateTime_Date *self, int h, int m, int s, int us)
1260{
1261 DATE_SET_HOUR(self, h);
1262 DATE_SET_MINUTE(self, m);
1263 DATE_SET_SECOND(self, s);
1264 DATE_SET_MICROSECOND(self, us);
1265}
1266
1267/* For time and timetz. */
1268static void
1269set_time_fields(PyDateTime_Time *self, int h, int m, int s, int us)
1270{
1271 self->hashcode = -1;
1272 TIME_SET_HOUR(self, h);
1273 TIME_SET_MINUTE(self, m);
1274 TIME_SET_SECOND(self, s);
1275 TIME_SET_MICROSECOND(self, us);
1276}
1277
1278/* ---------------------------------------------------------------------------
1279 * Create various objects, mostly without range checking.
1280 */
1281
1282/* Create a date instance with no range checking. */
1283static PyObject *
1284new_date(int year, int month, int day)
1285{
1286 PyDateTime_Date *self;
1287
1288 self = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
1289 if (self != NULL)
1290 set_date_fields(self, year, month, day);
1291 return (PyObject *) self;
1292}
1293
1294/* Create a datetime instance with no range checking. */
1295static PyObject *
1296new_datetime(int year, int month, int day, int hour, int minute,
1297 int second, int usecond)
1298{
1299 PyDateTime_DateTime *self;
1300
1301 self = PyObject_New(PyDateTime_DateTime, &PyDateTime_DateTimeType);
1302 if (self != NULL) {
1303 set_date_fields((PyDateTime_Date *)self, year, month, day);
1304 set_datetime_time_fields((PyDateTime_Date *)self,
1305 hour, minute, second, usecond);
1306 }
1307 return (PyObject *) self;
1308}
1309
1310/* Create a datetimetz instance with no range checking. */
1311static PyObject *
1312new_datetimetz(int year, int month, int day, int hour, int minute,
1313 int second, int usecond, PyObject *tzinfo)
1314{
1315 PyDateTime_DateTimeTZ *self;
1316
1317 self = PyObject_New(PyDateTime_DateTimeTZ, &PyDateTime_DateTimeTZType);
1318 if (self != NULL) {
1319 set_date_fields((PyDateTime_Date *)self, year, month, day);
1320 set_datetime_time_fields((PyDateTime_Date *)self,
1321 hour, minute, second, usecond);
1322 Py_INCREF(tzinfo);
1323 self->tzinfo = tzinfo;
1324 }
1325 return (PyObject *) self;
1326}
1327
1328/* Create a time instance with no range checking. */
1329static PyObject *
1330new_time(int hour, int minute, int second, int usecond)
1331{
1332 PyDateTime_Time *self;
1333
1334 self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
1335 if (self != NULL)
1336 set_time_fields(self, hour, minute, second, usecond);
1337 return (PyObject *) self;
1338}
1339
1340/* Create a timetz instance with no range checking. */
1341static PyObject *
1342new_timetz(int hour, int minute, int second, int usecond, PyObject *tzinfo)
1343{
1344 PyDateTime_TimeTZ *self;
1345
1346 self = PyObject_New(PyDateTime_TimeTZ, &PyDateTime_TimeTZType);
1347 if (self != NULL) {
1348 set_time_fields((PyDateTime_Time *)self,
1349 hour, minute, second, usecond);
1350 Py_INCREF(tzinfo);
1351 self->tzinfo = tzinfo;
1352 }
1353 return (PyObject *) self;
1354}
1355
1356/* Create a timedelta instance. Normalize the members iff normalize is
1357 * true. Passing false is a speed optimization, if you know for sure
1358 * that seconds and microseconds are already in their proper ranges. In any
1359 * case, raises OverflowError and returns NULL if the normalized days is out
1360 * of range).
1361 */
1362static PyObject *
1363new_delta(int days, int seconds, int microseconds, int normalize)
1364{
1365 PyDateTime_Delta *self;
1366
1367 if (normalize)
1368 normalize_d_s_us(&days, &seconds, &microseconds);
1369 assert(0 <= seconds && seconds < 24*3600);
1370 assert(0 <= microseconds && microseconds < 1000000);
1371
1372 if (check_delta_day_range(days) < 0)
1373 return NULL;
1374
1375 self = PyObject_New(PyDateTime_Delta, &PyDateTime_DeltaType);
1376 if (self != NULL) {
1377 self->hashcode = -1;
1378 SET_TD_DAYS(self, days);
1379 SET_TD_SECONDS(self, seconds);
1380 SET_TD_MICROSECONDS(self, microseconds);
1381 }
1382 return (PyObject *) self;
1383}
1384
1385
1386/* ---------------------------------------------------------------------------
1387 * Cached Python objects; these are set by the module init function.
1388 */
1389
1390/* Conversion factors. */
1391static PyObject *us_per_us = NULL; /* 1 */
1392static PyObject *us_per_ms = NULL; /* 1000 */
1393static PyObject *us_per_second = NULL; /* 1000000 */
1394static PyObject *us_per_minute = NULL; /* 1e6 * 60 as Python int */
1395static PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python long */
1396static PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python long */
1397static PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python long */
1398static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */
1399
1400/* Callables to support unpickling. */
1401static PyObject *date_unpickler_object = NULL;
1402static PyObject *datetime_unpickler_object = NULL;
1403static PyObject *datetimetz_unpickler_object = NULL;
1404static PyObject *tzinfo_unpickler_object = NULL;
1405static PyObject *time_unpickler_object = NULL;
1406static PyObject *timetz_unpickler_object = NULL;
1407
1408/* ---------------------------------------------------------------------------
1409 * Class implementations.
1410 */
1411
1412/*
1413 * PyDateTime_Delta implementation.
1414 */
1415
1416/* Convert a timedelta to a number of us,
1417 * (24*3600*self.days + self.seconds)*1000000 + self.microseconds
1418 * as a Python int or long.
1419 * Doing mixed-radix arithmetic by hand instead is excruciating in C,
1420 * due to ubiquitous overflow possibilities.
1421 */
1422static PyObject *
1423delta_to_microseconds(PyDateTime_Delta *self)
1424{
1425 PyObject *x1 = NULL;
1426 PyObject *x2 = NULL;
1427 PyObject *x3 = NULL;
1428 PyObject *result = NULL;
1429
1430 x1 = PyInt_FromLong(GET_TD_DAYS(self));
1431 if (x1 == NULL)
1432 goto Done;
1433 x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */
1434 if (x2 == NULL)
1435 goto Done;
1436 Py_DECREF(x1);
1437 x1 = NULL;
1438
1439 /* x2 has days in seconds */
1440 x1 = PyInt_FromLong(GET_TD_SECONDS(self)); /* seconds */
1441 if (x1 == NULL)
1442 goto Done;
1443 x3 = PyNumber_Add(x1, x2); /* days and seconds in seconds */
1444 if (x3 == NULL)
1445 goto Done;
1446 Py_DECREF(x1);
1447 Py_DECREF(x2);
1448 x1 = x2 = NULL;
1449
1450 /* x3 has days+seconds in seconds */
1451 x1 = PyNumber_Multiply(x3, us_per_second); /* us */
1452 if (x1 == NULL)
1453 goto Done;
1454 Py_DECREF(x3);
1455 x3 = NULL;
1456
1457 /* x1 has days+seconds in us */
1458 x2 = PyInt_FromLong(GET_TD_MICROSECONDS(self));
1459 if (x2 == NULL)
1460 goto Done;
1461 result = PyNumber_Add(x1, x2);
1462
1463Done:
1464 Py_XDECREF(x1);
1465 Py_XDECREF(x2);
1466 Py_XDECREF(x3);
1467 return result;
1468}
1469
1470/* Convert a number of us (as a Python int or long) to a timedelta.
1471 */
1472static PyObject *
1473microseconds_to_delta(PyObject *pyus)
1474{
1475 int us;
1476 int s;
1477 int d;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001478 long temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001479
1480 PyObject *tuple = NULL;
1481 PyObject *num = NULL;
1482 PyObject *result = NULL;
1483
1484 tuple = PyNumber_Divmod(pyus, us_per_second);
1485 if (tuple == NULL)
1486 goto Done;
1487
1488 num = PyTuple_GetItem(tuple, 1); /* us */
1489 if (num == NULL)
1490 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001491 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001492 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001493 if (temp == -1 && PyErr_Occurred())
1494 goto Done;
1495 assert(0 <= temp && temp < 1000000);
1496 us = (int)temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001497 if (us < 0) {
1498 /* The divisor was positive, so this must be an error. */
1499 assert(PyErr_Occurred());
1500 goto Done;
1501 }
1502
1503 num = PyTuple_GetItem(tuple, 0); /* leftover seconds */
1504 if (num == NULL)
1505 goto Done;
1506 Py_INCREF(num);
1507 Py_DECREF(tuple);
1508
1509 tuple = PyNumber_Divmod(num, seconds_per_day);
1510 if (tuple == NULL)
1511 goto Done;
1512 Py_DECREF(num);
1513
1514 num = PyTuple_GetItem(tuple, 1); /* seconds */
1515 if (num == NULL)
1516 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001517 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001518 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001519 if (temp == -1 && PyErr_Occurred())
1520 goto Done;
1521 assert(0 <= temp && temp < 24*3600);
1522 s = (int)temp;
1523
Tim Peters2a799bf2002-12-16 20:18:38 +00001524 if (s < 0) {
1525 /* The divisor was positive, so this must be an error. */
1526 assert(PyErr_Occurred());
1527 goto Done;
1528 }
1529
1530 num = PyTuple_GetItem(tuple, 0); /* leftover days */
1531 if (num == NULL)
1532 goto Done;
1533 Py_INCREF(num);
Tim Peters0b0f41c2002-12-19 01:44:38 +00001534 temp = PyLong_AsLong(num);
1535 if (temp == -1 && PyErr_Occurred())
Tim Peters2a799bf2002-12-16 20:18:38 +00001536 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001537 d = (int)temp;
1538 if ((long)d != temp) {
1539 PyErr_SetString(PyExc_OverflowError, "normalized days too "
1540 "large to fit in a C int");
1541 goto Done;
1542 }
Tim Peters2a799bf2002-12-16 20:18:38 +00001543 result = new_delta(d, s, us, 0);
1544
1545Done:
1546 Py_XDECREF(tuple);
1547 Py_XDECREF(num);
1548 return result;
1549}
1550
1551static PyObject *
1552multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
1553{
1554 PyObject *pyus_in;
1555 PyObject *pyus_out;
1556 PyObject *result;
1557
1558 pyus_in = delta_to_microseconds(delta);
1559 if (pyus_in == NULL)
1560 return NULL;
1561
1562 pyus_out = PyNumber_Multiply(pyus_in, intobj);
1563 Py_DECREF(pyus_in);
1564 if (pyus_out == NULL)
1565 return NULL;
1566
1567 result = microseconds_to_delta(pyus_out);
1568 Py_DECREF(pyus_out);
1569 return result;
1570}
1571
1572static PyObject *
1573divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj)
1574{
1575 PyObject *pyus_in;
1576 PyObject *pyus_out;
1577 PyObject *result;
1578
1579 pyus_in = delta_to_microseconds(delta);
1580 if (pyus_in == NULL)
1581 return NULL;
1582
1583 pyus_out = PyNumber_FloorDivide(pyus_in, intobj);
1584 Py_DECREF(pyus_in);
1585 if (pyus_out == NULL)
1586 return NULL;
1587
1588 result = microseconds_to_delta(pyus_out);
1589 Py_DECREF(pyus_out);
1590 return result;
1591}
1592
1593static PyObject *
1594delta_add(PyObject *left, PyObject *right)
1595{
1596 PyObject *result = Py_NotImplemented;
1597
1598 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1599 /* delta + delta */
1600 /* The C-level additions can't overflow because of the
1601 * invariant bounds.
1602 */
1603 int days = GET_TD_DAYS(left) + GET_TD_DAYS(right);
1604 int seconds = GET_TD_SECONDS(left) + GET_TD_SECONDS(right);
1605 int microseconds = GET_TD_MICROSECONDS(left) +
1606 GET_TD_MICROSECONDS(right);
1607 result = new_delta(days, seconds, microseconds, 1);
1608 }
1609
1610 if (result == Py_NotImplemented)
1611 Py_INCREF(result);
1612 return result;
1613}
1614
1615static PyObject *
1616delta_negative(PyDateTime_Delta *self)
1617{
1618 return new_delta(-GET_TD_DAYS(self),
1619 -GET_TD_SECONDS(self),
1620 -GET_TD_MICROSECONDS(self),
1621 1);
1622}
1623
1624static PyObject *
1625delta_positive(PyDateTime_Delta *self)
1626{
1627 /* Could optimize this (by returning self) if this isn't a
1628 * subclass -- but who uses unary + ? Approximately nobody.
1629 */
1630 return new_delta(GET_TD_DAYS(self),
1631 GET_TD_SECONDS(self),
1632 GET_TD_MICROSECONDS(self),
1633 0);
1634}
1635
1636static PyObject *
1637delta_abs(PyDateTime_Delta *self)
1638{
1639 PyObject *result;
1640
1641 assert(GET_TD_MICROSECONDS(self) >= 0);
1642 assert(GET_TD_SECONDS(self) >= 0);
1643
1644 if (GET_TD_DAYS(self) < 0)
1645 result = delta_negative(self);
1646 else
1647 result = delta_positive(self);
1648
1649 return result;
1650}
1651
1652static PyObject *
1653delta_subtract(PyObject *left, PyObject *right)
1654{
1655 PyObject *result = Py_NotImplemented;
1656
1657 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1658 /* delta - delta */
1659 PyObject *minus_right = PyNumber_Negative(right);
1660 if (minus_right) {
1661 result = delta_add(left, minus_right);
1662 Py_DECREF(minus_right);
1663 }
1664 else
1665 result = NULL;
1666 }
1667
1668 if (result == Py_NotImplemented)
1669 Py_INCREF(result);
1670 return result;
1671}
1672
1673/* This is more natural as a tp_compare, but doesn't work then: for whatever
1674 * reason, Python's try_3way_compare ignores tp_compare unless
1675 * PyInstance_Check returns true, but these aren't old-style classes.
1676 */
1677static PyObject *
1678delta_richcompare(PyDateTime_Delta *self, PyObject *other, int op)
1679{
1680 int diff;
1681
1682 if (! PyDelta_CheckExact(other)) {
1683 PyErr_Format(PyExc_TypeError,
1684 "can't compare %s to %s instance",
1685 self->ob_type->tp_name, other->ob_type->tp_name);
1686 return NULL;
1687 }
1688 diff = GET_TD_DAYS(self) - GET_TD_DAYS(other);
1689 if (diff == 0) {
1690 diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other);
1691 if (diff == 0)
1692 diff = GET_TD_MICROSECONDS(self) -
1693 GET_TD_MICROSECONDS(other);
1694 }
1695 return diff_to_bool(diff, op);
1696}
1697
1698static PyObject *delta_getstate(PyDateTime_Delta *self);
1699
1700static long
1701delta_hash(PyDateTime_Delta *self)
1702{
1703 if (self->hashcode == -1) {
1704 PyObject *temp = delta_getstate(self);
1705 if (temp != NULL) {
1706 self->hashcode = PyObject_Hash(temp);
1707 Py_DECREF(temp);
1708 }
1709 }
1710 return self->hashcode;
1711}
1712
1713static PyObject *
1714delta_multiply(PyObject *left, PyObject *right)
1715{
1716 PyObject *result = Py_NotImplemented;
1717
1718 if (PyDelta_Check(left)) {
1719 /* delta * ??? */
1720 if (PyInt_Check(right) || PyLong_Check(right))
1721 result = multiply_int_timedelta(right,
1722 (PyDateTime_Delta *) left);
1723 }
1724 else if (PyInt_Check(left) || PyLong_Check(left))
1725 result = multiply_int_timedelta(left,
1726 (PyDateTime_Delta *) right);
1727
1728 if (result == Py_NotImplemented)
1729 Py_INCREF(result);
1730 return result;
1731}
1732
1733static PyObject *
1734delta_divide(PyObject *left, PyObject *right)
1735{
1736 PyObject *result = Py_NotImplemented;
1737
1738 if (PyDelta_Check(left)) {
1739 /* delta * ??? */
1740 if (PyInt_Check(right) || PyLong_Check(right))
1741 result = divide_timedelta_int(
1742 (PyDateTime_Delta *)left,
1743 right);
1744 }
1745
1746 if (result == Py_NotImplemented)
1747 Py_INCREF(result);
1748 return result;
1749}
1750
1751/* Fold in the value of the tag ("seconds", "weeks", etc) component of a
1752 * timedelta constructor. sofar is the # of microseconds accounted for
1753 * so far, and there are factor microseconds per current unit, the number
1754 * of which is given by num. num * factor is added to sofar in a
1755 * numerically careful way, and that's the result. Any fractional
1756 * microseconds left over (this can happen if num is a float type) are
1757 * added into *leftover.
1758 * Note that there are many ways this can give an error (NULL) return.
1759 */
1760static PyObject *
1761accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
1762 double *leftover)
1763{
1764 PyObject *prod;
1765 PyObject *sum;
1766
1767 assert(num != NULL);
1768
1769 if (PyInt_Check(num) || PyLong_Check(num)) {
1770 prod = PyNumber_Multiply(num, factor);
1771 if (prod == NULL)
1772 return NULL;
1773 sum = PyNumber_Add(sofar, prod);
1774 Py_DECREF(prod);
1775 return sum;
1776 }
1777
1778 if (PyFloat_Check(num)) {
1779 double dnum;
1780 double fracpart;
1781 double intpart;
1782 PyObject *x;
1783 PyObject *y;
1784
1785 /* The Plan: decompose num into an integer part and a
1786 * fractional part, num = intpart + fracpart.
1787 * Then num * factor ==
1788 * intpart * factor + fracpart * factor
1789 * and the LHS can be computed exactly in long arithmetic.
1790 * The RHS is again broken into an int part and frac part.
1791 * and the frac part is added into *leftover.
1792 */
1793 dnum = PyFloat_AsDouble(num);
1794 if (dnum == -1.0 && PyErr_Occurred())
1795 return NULL;
1796 fracpart = modf(dnum, &intpart);
1797 x = PyLong_FromDouble(intpart);
1798 if (x == NULL)
1799 return NULL;
1800
1801 prod = PyNumber_Multiply(x, factor);
1802 Py_DECREF(x);
1803 if (prod == NULL)
1804 return NULL;
1805
1806 sum = PyNumber_Add(sofar, prod);
1807 Py_DECREF(prod);
1808 if (sum == NULL)
1809 return NULL;
1810
1811 if (fracpart == 0.0)
1812 return sum;
1813 /* So far we've lost no information. Dealing with the
1814 * fractional part requires float arithmetic, and may
1815 * lose a little info.
1816 */
1817 assert(PyInt_Check(factor) || PyLong_Check(factor));
1818 if (PyInt_Check(factor))
1819 dnum = (double)PyInt_AsLong(factor);
1820 else
1821 dnum = PyLong_AsDouble(factor);
1822
1823 dnum *= fracpart;
1824 fracpart = modf(dnum, &intpart);
1825 x = PyLong_FromDouble(intpart);
1826 if (x == NULL) {
1827 Py_DECREF(sum);
1828 return NULL;
1829 }
1830
1831 y = PyNumber_Add(sum, x);
1832 Py_DECREF(sum);
1833 Py_DECREF(x);
1834 *leftover += fracpart;
1835 return y;
1836 }
1837
1838 PyErr_Format(PyExc_TypeError,
1839 "unsupported type for timedelta %s component: %s",
1840 tag, num->ob_type->tp_name);
1841 return NULL;
1842}
1843
1844static PyObject *
1845delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1846{
1847 PyObject *self = NULL;
1848
1849 /* Argument objects. */
1850 PyObject *day = NULL;
1851 PyObject *second = NULL;
1852 PyObject *us = NULL;
1853 PyObject *ms = NULL;
1854 PyObject *minute = NULL;
1855 PyObject *hour = NULL;
1856 PyObject *week = NULL;
1857
1858 PyObject *x = NULL; /* running sum of microseconds */
1859 PyObject *y = NULL; /* temp sum of microseconds */
1860 double leftover_us = 0.0;
1861
1862 static char *keywords[] = {
1863 "days", "seconds", "microseconds", "milliseconds",
1864 "minutes", "hours", "weeks", NULL
1865 };
1866
1867 if (PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOO:__new__",
1868 keywords,
1869 &day, &second, &us,
1870 &ms, &minute, &hour, &week) == 0)
1871 goto Done;
1872
1873 x = PyInt_FromLong(0);
1874 if (x == NULL)
1875 goto Done;
1876
1877#define CLEANUP \
1878 Py_DECREF(x); \
1879 x = y; \
1880 if (x == NULL) \
1881 goto Done
1882
1883 if (us) {
1884 y = accum("microseconds", x, us, us_per_us, &leftover_us);
1885 CLEANUP;
1886 }
1887 if (ms) {
1888 y = accum("milliseconds", x, ms, us_per_ms, &leftover_us);
1889 CLEANUP;
1890 }
1891 if (second) {
1892 y = accum("seconds", x, second, us_per_second, &leftover_us);
1893 CLEANUP;
1894 }
1895 if (minute) {
1896 y = accum("minutes", x, minute, us_per_minute, &leftover_us);
1897 CLEANUP;
1898 }
1899 if (hour) {
1900 y = accum("hours", x, hour, us_per_hour, &leftover_us);
1901 CLEANUP;
1902 }
1903 if (day) {
1904 y = accum("days", x, day, us_per_day, &leftover_us);
1905 CLEANUP;
1906 }
1907 if (week) {
1908 y = accum("weeks", x, week, us_per_week, &leftover_us);
1909 CLEANUP;
1910 }
1911 if (leftover_us) {
1912 /* Round to nearest whole # of us, and add into x. */
Tim Peters5d644dd2003-01-02 16:32:54 +00001913 PyObject *temp = PyLong_FromLong(round_to_long(leftover_us));
Tim Peters2a799bf2002-12-16 20:18:38 +00001914 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;
Tim Peters5d644dd2003-01-02 16:32:54 +00002861 double fraction = timestamp - (double)timet;
2862 int us = (int)round_to_long(fraction * 1e6);
Tim Peters2a799bf2002-12-16 20:18:38 +00002863
2864 return datetime_from_timet_and_us(cls, f, timet, us);
2865}
2866
2867/* Internal helper.
2868 * Build most accurate possible datetime for current time. Pass localtime or
2869 * gmtime for f as appropriate.
2870 */
2871static PyObject *
2872datetime_best_possible(PyObject *cls, TM_FUNC f)
2873{
2874#ifdef HAVE_GETTIMEOFDAY
2875 struct timeval t;
2876
2877#ifdef GETTIMEOFDAY_NO_TZ
2878 gettimeofday(&t);
2879#else
2880 gettimeofday(&t, (struct timezone *)NULL);
2881#endif
2882 return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec);
2883
2884#else /* ! HAVE_GETTIMEOFDAY */
2885 /* No flavor of gettimeofday exists on this platform. Python's
2886 * time.time() does a lot of other platform tricks to get the
2887 * best time it can on the platform, and we're not going to do
2888 * better than that (if we could, the better code would belong
2889 * in time.time()!) We're limited by the precision of a double,
2890 * though.
2891 */
2892 PyObject *time;
2893 double dtime;
2894
2895 time = time_time();
2896 if (time == NULL)
2897 return NULL;
2898 dtime = PyFloat_AsDouble(time);
2899 Py_DECREF(time);
2900 if (dtime == -1.0 && PyErr_Occurred())
2901 return NULL;
2902 return datetime_from_timestamp(cls, f, dtime);
2903#endif /* ! HAVE_GETTIMEOFDAY */
2904}
2905
2906/* Return new local datetime from timestamp (Python timestamp -- a double). */
2907static PyObject *
2908datetime_fromtimestamp(PyObject *cls, PyObject *args)
2909{
2910 double timestamp;
2911 PyObject *result = NULL;
2912
2913 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2914 result = datetime_from_timestamp(cls, localtime, timestamp);
2915 return result;
2916}
2917
2918/* Return new UTC datetime from timestamp (Python timestamp -- a double). */
2919static PyObject *
2920datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
2921{
2922 double timestamp;
2923 PyObject *result = NULL;
2924
2925 if (PyArg_ParseTuple(args, "d:utcfromtimestamp", &timestamp))
2926 result = datetime_from_timestamp(cls, gmtime, timestamp);
2927 return result;
2928}
2929
2930/* Return best possible local time -- this isn't constrained by the
2931 * precision of a timestamp.
2932 */
2933static PyObject *
2934datetime_now(PyObject *cls, PyObject *dummy)
2935{
2936 return datetime_best_possible(cls, localtime);
2937}
2938
2939/* Return best possible UTC time -- this isn't constrained by the
2940 * precision of a timestamp.
2941 */
2942static PyObject *
2943datetime_utcnow(PyObject *cls, PyObject *dummy)
2944{
2945 return datetime_best_possible(cls, gmtime);
2946}
2947
2948/* Return new datetime or datetimetz from date/datetime/datetimetz and
2949 * time/timetz arguments.
2950 */
2951static PyObject *
2952datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
2953{
2954 static char *keywords[] = {"date", "time", NULL};
2955 PyObject *date;
2956 PyObject *time;
2957 PyObject *result = NULL;
2958
2959 if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!:combine", keywords,
2960 &PyDateTime_DateType, &date,
2961 &PyDateTime_TimeType, &time))
2962 result = PyObject_CallFunction(cls, "iiiiiii",
2963 GET_YEAR(date),
2964 GET_MONTH(date),
2965 GET_DAY(date),
2966 TIME_GET_HOUR(time),
2967 TIME_GET_MINUTE(time),
2968 TIME_GET_SECOND(time),
2969 TIME_GET_MICROSECOND(time));
2970 if (result && PyTimeTZ_Check(time) && PyDateTimeTZ_Check(result)) {
2971 /* Copy the tzinfo field. */
Tim Peters80475bb2002-12-25 07:40:55 +00002972 replace_tzinfo(result, ((PyDateTime_TimeTZ *)time)->tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00002973 }
2974 return result;
2975}
2976
2977/* datetime arithmetic. */
2978
2979static PyObject *
2980add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
2981{
2982 /* Note that the C-level additions can't overflow, because of
2983 * invariant bounds on the member values.
2984 */
2985 int year = GET_YEAR(date);
2986 int month = GET_MONTH(date);
2987 int day = GET_DAY(date) + GET_TD_DAYS(delta);
2988 int hour = DATE_GET_HOUR(date);
2989 int minute = DATE_GET_MINUTE(date);
2990 int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta);
2991 int microsecond = DATE_GET_MICROSECOND(date) +
2992 GET_TD_MICROSECONDS(delta);
2993
2994 if (normalize_datetime(&year, &month, &day,
2995 &hour, &minute, &second, &microsecond) < 0)
2996 return NULL;
2997 else
2998 return new_datetime(year, month, day,
2999 hour, minute, second, microsecond);
3000}
3001
3002static PyObject *
3003sub_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
3004{
3005 /* Note that the C-level subtractions can't overflow, because of
3006 * invariant bounds on the member values.
3007 */
3008 int year = GET_YEAR(date);
3009 int month = GET_MONTH(date);
3010 int day = GET_DAY(date) - GET_TD_DAYS(delta);
3011 int hour = DATE_GET_HOUR(date);
3012 int minute = DATE_GET_MINUTE(date);
3013 int second = DATE_GET_SECOND(date) - GET_TD_SECONDS(delta);
3014 int microsecond = DATE_GET_MICROSECOND(date) -
3015 GET_TD_MICROSECONDS(delta);
3016
3017 if (normalize_datetime(&year, &month, &day,
3018 &hour, &minute, &second, &microsecond) < 0)
3019 return NULL;
3020 else
3021 return new_datetime(year, month, day,
3022 hour, minute, second, microsecond);
3023}
3024
3025static PyObject *
3026sub_datetime_datetime(PyDateTime_DateTime *left, PyDateTime_DateTime *right)
3027{
3028 int days1 = ymd_to_ord(GET_YEAR(left), GET_MONTH(left), GET_DAY(left));
3029 int days2 = ymd_to_ord(GET_YEAR(right),
3030 GET_MONTH(right),
3031 GET_DAY(right));
3032 /* These can't overflow, since the values are normalized. At most
3033 * this gives the number of seconds in one day.
3034 */
3035 int delta_s = (DATE_GET_HOUR(left) - DATE_GET_HOUR(right)) * 3600 +
3036 (DATE_GET_MINUTE(left) - DATE_GET_MINUTE(right)) * 60 +
3037 DATE_GET_SECOND(left) - DATE_GET_SECOND(right);
3038 int delta_us = DATE_GET_MICROSECOND(left) -
3039 DATE_GET_MICROSECOND(right);
3040
3041 return new_delta(days1 - days2, delta_s, delta_us, 1);
3042}
3043
3044static PyObject *
3045datetime_add(PyObject *left, PyObject *right)
3046{
3047 if (PyDateTime_Check(left)) {
3048 /* datetime + ??? */
3049 if (PyDelta_Check(right))
3050 /* datetime + delta */
3051 return add_datetime_timedelta(
3052 (PyDateTime_DateTime *)left,
3053 (PyDateTime_Delta *)right);
3054 }
3055 else if (PyDelta_Check(left)) {
3056 /* delta + datetime */
3057 return add_datetime_timedelta((PyDateTime_DateTime *) right,
3058 (PyDateTime_Delta *) left);
3059 }
3060 Py_INCREF(Py_NotImplemented);
3061 return Py_NotImplemented;
3062}
3063
3064static PyObject *
3065datetime_subtract(PyObject *left, PyObject *right)
3066{
3067 PyObject *result = Py_NotImplemented;
3068
3069 if (PyDateTime_Check(left)) {
3070 /* datetime - ??? */
3071 if (PyDateTime_Check(right)) {
3072 /* datetime - datetime */
3073 result = sub_datetime_datetime(
3074 (PyDateTime_DateTime *)left,
3075 (PyDateTime_DateTime *)right);
3076 }
3077 else if (PyDelta_Check(right)) {
3078 /* datetime - delta */
3079 result = sub_datetime_timedelta(
3080 (PyDateTime_DateTime *)left,
3081 (PyDateTime_Delta *)right);
3082 }
3083 }
3084
3085 if (result == Py_NotImplemented)
3086 Py_INCREF(result);
3087 return result;
3088}
3089
3090/* Various ways to turn a datetime into a string. */
3091
3092static PyObject *
3093datetime_repr(PyDateTime_DateTime *self)
3094{
3095 char buffer[1000];
3096 char *typename = self->ob_type->tp_name;
3097
3098 if (DATE_GET_MICROSECOND(self)) {
3099 PyOS_snprintf(buffer, sizeof(buffer),
3100 "%s(%d, %d, %d, %d, %d, %d, %d)",
3101 typename,
3102 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3103 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3104 DATE_GET_SECOND(self),
3105 DATE_GET_MICROSECOND(self));
3106 }
3107 else if (DATE_GET_SECOND(self)) {
3108 PyOS_snprintf(buffer, sizeof(buffer),
3109 "%s(%d, %d, %d, %d, %d, %d)",
3110 typename,
3111 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3112 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3113 DATE_GET_SECOND(self));
3114 }
3115 else {
3116 PyOS_snprintf(buffer, sizeof(buffer),
3117 "%s(%d, %d, %d, %d, %d)",
3118 typename,
3119 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3120 DATE_GET_HOUR(self), DATE_GET_MINUTE(self));
3121 }
3122 return PyString_FromString(buffer);
3123}
3124
3125static PyObject *
3126datetime_str(PyDateTime_DateTime *self)
3127{
3128 return PyObject_CallMethod((PyObject *)self, "isoformat", "(s)", " ");
3129}
3130
3131static PyObject *
3132datetime_isoformat(PyDateTime_DateTime *self,
3133 PyObject *args, PyObject *kw)
3134{
3135 char sep = 'T';
3136 static char *keywords[] = {"sep", NULL};
3137 char buffer[100];
3138 char *cp;
3139
3140 if (!PyArg_ParseTupleAndKeywords(args, kw, "|c:isoformat", keywords,
3141 &sep))
3142 return NULL;
3143 cp = isoformat_date((PyDateTime_Date *)self, buffer, sizeof(buffer));
3144 assert(cp != NULL);
3145 *cp++ = sep;
3146 isoformat_time(self, cp, sizeof(buffer) - (cp - buffer));
3147 return PyString_FromString(buffer);
3148}
3149
3150static PyObject *
3151datetime_ctime(PyDateTime_DateTime *self)
3152{
3153 return format_ctime((PyDateTime_Date *)self,
3154 DATE_GET_HOUR(self),
3155 DATE_GET_MINUTE(self),
3156 DATE_GET_SECOND(self));
3157}
3158
3159/* Miscellaneous methods. */
3160
3161/* This is more natural as a tp_compare, but doesn't work then: for whatever
3162 * reason, Python's try_3way_compare ignores tp_compare unless
3163 * PyInstance_Check returns true, but these aren't old-style classes.
3164 * Note that this routine handles all comparisons for datetime and datetimetz.
3165 */
3166static PyObject *
3167datetime_richcompare(PyDateTime_DateTime *self, PyObject *other, int op)
3168{
3169 int diff;
3170 naivety n1, n2;
3171 int offset1, offset2;
3172
3173 if (! PyDateTime_Check(other)) {
3174 /* Stop this from falling back to address comparison. */
3175 PyErr_Format(PyExc_TypeError,
3176 "can't compare '%s' to '%s'",
3177 self->ob_type->tp_name,
3178 other->ob_type->tp_name);
3179 return NULL;
3180 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003181
Tim Peters00237032002-12-27 02:21:51 +00003182 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1,
Tim Peterse39a80c2002-12-30 21:28:52 +00003183 (PyObject *)self,
3184 other, &offset2, &n2,
3185 other) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003186 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003187 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters60c76e42002-12-27 00:41:11 +00003188 /* If they're both naive, or both aware and have the same offsets,
Tim Peters2a799bf2002-12-16 20:18:38 +00003189 * we get off cheap. Note that if they're both naive, offset1 ==
3190 * offset2 == 0 at this point.
3191 */
3192 if (n1 == n2 && offset1 == offset2) {
3193 diff = memcmp(self->data, ((PyDateTime_DateTime *)other)->data,
3194 _PyDateTime_DATETIME_DATASIZE);
3195 return diff_to_bool(diff, op);
3196 }
3197
3198 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3199 /* We want the sign of
3200 * (self - offset1 minutes) - (other - offset2 minutes) =
3201 * (self - other) + (offset2 - offset1) minutes.
3202 */
3203 PyDateTime_Delta *delta;
3204 int days, seconds, us;
3205
3206 assert(offset1 != offset2); /* else last "if" handled it */
3207 delta = (PyDateTime_Delta *)sub_datetime_datetime(self,
3208 (PyDateTime_DateTime *)other);
3209 if (delta == NULL)
3210 return NULL;
3211 days = delta->days;
3212 seconds = delta->seconds + (offset2 - offset1) * 60;
3213 us = delta->microseconds;
3214 Py_DECREF(delta);
3215 normalize_d_s_us(&days, &seconds, &us);
3216 diff = days;
3217 if (diff == 0)
3218 diff = seconds | us;
3219 return diff_to_bool(diff, op);
3220 }
3221
3222 assert(n1 != n2);
3223 PyErr_SetString(PyExc_TypeError,
3224 "can't compare offset-naive and "
3225 "offset-aware datetimes");
3226 return NULL;
3227}
3228
3229static PyObject *datetime_getstate(PyDateTime_DateTime *self);
3230
3231static long
3232datetime_hash(PyDateTime_DateTime *self)
3233{
3234 if (self->hashcode == -1) {
3235 naivety n;
3236 int offset;
3237 PyObject *temp;
3238
Tim Peterse39a80c2002-12-30 21:28:52 +00003239 n = classify_utcoffset((PyObject *)self, (PyObject *)self,
3240 &offset);
Tim Peters2a799bf2002-12-16 20:18:38 +00003241 assert(n != OFFSET_UNKNOWN);
3242 if (n == OFFSET_ERROR)
3243 return -1;
3244
3245 /* Reduce this to a hash of another object. */
3246 if (n == OFFSET_NAIVE)
3247 temp = datetime_getstate(self);
3248 else {
3249 int days;
3250 int seconds;
3251
3252 assert(n == OFFSET_AWARE);
3253 assert(PyDateTimeTZ_Check(self));
3254 days = ymd_to_ord(GET_YEAR(self),
3255 GET_MONTH(self),
3256 GET_DAY(self));
3257 seconds = DATE_GET_HOUR(self) * 3600 +
3258 (DATE_GET_MINUTE(self) - offset) * 60 +
3259 DATE_GET_SECOND(self);
3260 temp = new_delta(days,
3261 seconds,
3262 DATE_GET_MICROSECOND(self),
3263 1);
3264 }
3265 if (temp != NULL) {
3266 self->hashcode = PyObject_Hash(temp);
3267 Py_DECREF(temp);
3268 }
3269 }
3270 return self->hashcode;
3271}
3272
3273static PyObject *
Tim Peters12bf3392002-12-24 05:41:27 +00003274datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
3275{
3276 PyObject *clone;
3277 PyObject *tuple;
3278 int y = GET_YEAR(self);
3279 int m = GET_MONTH(self);
3280 int d = GET_DAY(self);
3281 int hh = DATE_GET_HOUR(self);
3282 int mm = DATE_GET_MINUTE(self);
3283 int ss = DATE_GET_SECOND(self);
3284 int us = DATE_GET_MICROSECOND(self);
3285
3286 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiii:replace",
3287 datetime_kws,
3288 &y, &m, &d, &hh, &mm, &ss, &us))
3289 return NULL;
3290 tuple = Py_BuildValue("iiiiiii", y, m, d, hh, mm, ss, us);
3291 if (tuple == NULL)
3292 return NULL;
3293 clone = datetime_new(self->ob_type, tuple, NULL);
3294 Py_DECREF(tuple);
3295 return clone;
3296}
3297
3298static PyObject *
Tim Peters80475bb2002-12-25 07:40:55 +00003299datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
3300{
3301 PyObject *tzinfo;
3302 static char *keywords[] = {"tz", NULL};
3303
3304 if (! PyArg_ParseTupleAndKeywords(args, kw, "O:astimezone", keywords,
3305 &tzinfo))
3306 return NULL;
3307 if (check_tzinfo_subclass(tzinfo) < 0)
3308 return NULL;
3309 return new_datetimetz(GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3310 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3311 DATE_GET_SECOND(self),
3312 DATE_GET_MICROSECOND(self),
3313 tzinfo);
3314}
3315
3316static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00003317datetime_timetuple(PyDateTime_DateTime *self)
3318{
3319 return build_struct_time(GET_YEAR(self),
3320 GET_MONTH(self),
3321 GET_DAY(self),
3322 DATE_GET_HOUR(self),
3323 DATE_GET_MINUTE(self),
3324 DATE_GET_SECOND(self),
3325 -1);
3326}
3327
3328static PyObject *
3329datetime_getdate(PyDateTime_DateTime *self)
3330{
3331 return new_date(GET_YEAR(self),
3332 GET_MONTH(self),
3333 GET_DAY(self));
3334}
3335
3336static PyObject *
3337datetime_gettime(PyDateTime_DateTime *self)
3338{
3339 return new_time(DATE_GET_HOUR(self),
3340 DATE_GET_MINUTE(self),
3341 DATE_GET_SECOND(self),
3342 DATE_GET_MICROSECOND(self));
3343}
3344
3345/* Pickle support. Quite a maze! */
3346
3347static PyObject *
3348datetime_getstate(PyDateTime_DateTime *self)
3349{
3350 return PyString_FromStringAndSize(self->data,
3351 _PyDateTime_DATETIME_DATASIZE);
3352}
3353
3354static PyObject *
3355datetime_setstate(PyDateTime_DateTime *self, PyObject *state)
3356{
3357 const int len = PyString_Size(state);
3358 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
3359
3360 if (! PyString_Check(state) ||
3361 len != _PyDateTime_DATETIME_DATASIZE) {
3362 PyErr_SetString(PyExc_TypeError,
3363 "bad argument to datetime.__setstate__");
3364 return NULL;
3365 }
3366 memcpy(self->data, pdata, _PyDateTime_DATETIME_DATASIZE);
3367 self->hashcode = -1;
3368
3369 Py_INCREF(Py_None);
3370 return Py_None;
3371}
3372
3373/* XXX This seems a ridiculously inefficient way to pickle a short string. */
3374static PyObject *
3375datetime_pickler(PyObject *module, PyDateTime_DateTime *datetime)
3376{
3377 PyObject *state;
3378 PyObject *result = NULL;
3379
3380 if (! PyDateTime_CheckExact(datetime)) {
3381 PyErr_Format(PyExc_TypeError,
3382 "bad type passed to datetime pickler: %s",
3383 datetime->ob_type->tp_name);
3384 return NULL;
3385 }
3386 state = datetime_getstate(datetime);
3387 if (state) {
3388 result = Py_BuildValue("O(O)",
3389 datetime_unpickler_object,
3390 state);
3391 Py_DECREF(state);
3392 }
3393 return result;
3394}
3395
3396static PyObject *
3397datetime_unpickler(PyObject *module, PyObject *arg)
3398{
3399 PyDateTime_DateTime *self;
3400
3401 if (! PyString_CheckExact(arg)) {
3402 PyErr_Format(PyExc_TypeError,
3403 "bad type passed to datetime unpickler: %s",
3404 arg->ob_type->tp_name);
3405 return NULL;
3406 }
3407 self = PyObject_New(PyDateTime_DateTime, &PyDateTime_DateTimeType);
3408 if (self != NULL) {
3409 PyObject *res = datetime_setstate(self, arg);
3410 if (res == NULL) {
3411 Py_DECREF(self);
3412 return NULL;
3413 }
3414 Py_DECREF(res);
3415 }
3416 return (PyObject *)self;
3417}
3418
3419static PyMethodDef datetime_methods[] = {
3420 /* Class methods: */
3421 {"now", (PyCFunction)datetime_now,
3422 METH_NOARGS | METH_CLASS,
3423 PyDoc_STR("Return a new datetime representing local day and time.")},
3424
3425 {"utcnow", (PyCFunction)datetime_utcnow,
3426 METH_NOARGS | METH_CLASS,
3427 PyDoc_STR("Return a new datetime representing UTC day and time.")},
3428
3429 {"fromtimestamp", (PyCFunction)datetime_fromtimestamp,
3430 METH_VARARGS | METH_CLASS,
3431 PyDoc_STR("timestamp -> local datetime from a POSIX timestamp "
3432 "(like time.time()).")},
3433
3434 {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
3435 METH_VARARGS | METH_CLASS,
3436 PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp "
3437 "(like time.time()).")},
3438
3439 {"combine", (PyCFunction)datetime_combine,
3440 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
3441 PyDoc_STR("date, time -> datetime with same date and time fields")},
3442
3443 /* Instance methods: */
3444 {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS,
3445 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
3446
3447 {"date", (PyCFunction)datetime_getdate, METH_NOARGS,
3448 PyDoc_STR("Return date object with same year, month and day.")},
3449
3450 {"time", (PyCFunction)datetime_gettime, METH_NOARGS,
3451 PyDoc_STR("Return time object with same hour, minute, second and "
3452 "microsecond.")},
3453
3454 {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
3455 PyDoc_STR("Return ctime() style string.")},
3456
3457 {"isoformat", (PyCFunction)datetime_isoformat, METH_KEYWORDS,
3458 PyDoc_STR("[sep] -> string in ISO 8601 format, "
3459 "YYYY-MM-DDTHH:MM:SS[.mmmmmm].\n\n"
3460 "sep is used to separate the year from the time, and "
3461 "defaults\n"
3462 "to 'T'.")},
3463
Tim Peters12bf3392002-12-24 05:41:27 +00003464 {"replace", (PyCFunction)datetime_replace, METH_KEYWORDS,
3465 PyDoc_STR("Return datetime with new specified fields.")},
3466
Tim Peters80475bb2002-12-25 07:40:55 +00003467 {"astimezone", (PyCFunction)datetime_astimezone, METH_KEYWORDS,
3468 PyDoc_STR("tz -> datetimetz with same date & time, and tzinfo=tz\n")},
3469
Tim Peters2a799bf2002-12-16 20:18:38 +00003470 {"__setstate__", (PyCFunction)datetime_setstate, METH_O,
3471 PyDoc_STR("__setstate__(state)")},
3472
3473 {"__getstate__", (PyCFunction)datetime_getstate, METH_NOARGS,
3474 PyDoc_STR("__getstate__() -> state")},
3475 {NULL, NULL}
3476};
3477
3478static char datetime_doc[] =
3479PyDoc_STR("Basic date/time type.");
3480
3481static PyNumberMethods datetime_as_number = {
3482 datetime_add, /* nb_add */
3483 datetime_subtract, /* nb_subtract */
3484 0, /* nb_multiply */
3485 0, /* nb_divide */
3486 0, /* nb_remainder */
3487 0, /* nb_divmod */
3488 0, /* nb_power */
3489 0, /* nb_negative */
3490 0, /* nb_positive */
3491 0, /* nb_absolute */
3492 0, /* nb_nonzero */
3493};
3494
3495statichere PyTypeObject PyDateTime_DateTimeType = {
3496 PyObject_HEAD_INIT(NULL)
3497 0, /* ob_size */
3498 "datetime.datetime", /* tp_name */
3499 sizeof(PyDateTime_DateTime), /* tp_basicsize */
3500 0, /* tp_itemsize */
3501 (destructor)PyObject_Del, /* tp_dealloc */
3502 0, /* tp_print */
3503 0, /* tp_getattr */
3504 0, /* tp_setattr */
3505 0, /* tp_compare */
3506 (reprfunc)datetime_repr, /* tp_repr */
3507 &datetime_as_number, /* tp_as_number */
3508 0, /* tp_as_sequence */
3509 0, /* tp_as_mapping */
3510 (hashfunc)datetime_hash, /* tp_hash */
3511 0, /* tp_call */
3512 (reprfunc)datetime_str, /* tp_str */
3513 PyObject_GenericGetAttr, /* tp_getattro */
3514 0, /* tp_setattro */
3515 0, /* tp_as_buffer */
3516 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3517 Py_TPFLAGS_BASETYPE, /* tp_flags */
3518 datetime_doc, /* tp_doc */
3519 0, /* tp_traverse */
3520 0, /* tp_clear */
3521 (richcmpfunc)datetime_richcompare, /* tp_richcompare */
3522 0, /* tp_weaklistoffset */
3523 0, /* tp_iter */
3524 0, /* tp_iternext */
3525 datetime_methods, /* tp_methods */
3526 0, /* tp_members */
3527 datetime_getset, /* tp_getset */
3528 &PyDateTime_DateType, /* tp_base */
3529 0, /* tp_dict */
3530 0, /* tp_descr_get */
3531 0, /* tp_descr_set */
3532 0, /* tp_dictoffset */
3533 0, /* tp_init */
3534 0, /* tp_alloc */
3535 datetime_new, /* tp_new */
3536 _PyObject_Del, /* tp_free */
3537};
3538
3539/*
3540 * PyDateTime_Time implementation.
3541 */
3542
3543/* Accessor properties. */
3544
3545static PyObject *
3546time_hour(PyDateTime_Time *self, void *unused)
3547{
3548 return PyInt_FromLong(TIME_GET_HOUR(self));
3549}
3550
3551static PyObject *
3552time_minute(PyDateTime_Time *self, void *unused)
3553{
3554 return PyInt_FromLong(TIME_GET_MINUTE(self));
3555}
3556
3557static PyObject *
Jack Jansen51cd8a22002-12-17 20:57:24 +00003558py_time_second(PyDateTime_Time *self, void *unused)
Tim Peters2a799bf2002-12-16 20:18:38 +00003559{
3560 return PyInt_FromLong(TIME_GET_SECOND(self));
3561}
3562
3563static PyObject *
3564time_microsecond(PyDateTime_Time *self, void *unused)
3565{
3566 return PyInt_FromLong(TIME_GET_MICROSECOND(self));
3567}
3568
3569static PyGetSetDef time_getset[] = {
3570 {"hour", (getter)time_hour},
3571 {"minute", (getter)time_minute},
Jack Jansen51cd8a22002-12-17 20:57:24 +00003572 {"second", (getter)py_time_second},
Tim Peters2a799bf2002-12-16 20:18:38 +00003573 {"microsecond", (getter)time_microsecond},
3574 {NULL}
3575};
3576
3577/* Constructors. */
3578
Tim Peters12bf3392002-12-24 05:41:27 +00003579static char *time_kws[] = {"hour", "minute", "second", "microsecond", NULL};
3580
Tim Peters2a799bf2002-12-16 20:18:38 +00003581static PyObject *
3582time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
3583{
3584 PyObject *self = NULL;
3585 int hour = 0;
3586 int minute = 0;
3587 int second = 0;
3588 int usecond = 0;
3589
Tim Peters2a799bf2002-12-16 20:18:38 +00003590
Tim Peters12bf3392002-12-24 05:41:27 +00003591 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiii", time_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00003592 &hour, &minute, &second, &usecond)) {
3593 if (check_time_args(hour, minute, second, usecond) < 0)
3594 return NULL;
3595 self = new_time(hour, minute, second, usecond);
3596 }
3597 return self;
3598}
3599
3600/* Various ways to turn a time into a string. */
3601
3602static PyObject *
3603time_repr(PyDateTime_Time *self)
3604{
3605 char buffer[100];
3606 char *typename = self->ob_type->tp_name;
3607 int h = TIME_GET_HOUR(self);
3608 int m = TIME_GET_MINUTE(self);
3609 int s = TIME_GET_SECOND(self);
3610 int us = TIME_GET_MICROSECOND(self);
3611
3612 if (us)
3613 PyOS_snprintf(buffer, sizeof(buffer),
3614 "%s(%d, %d, %d, %d)", typename, h, m, s, us);
3615 else if (s)
3616 PyOS_snprintf(buffer, sizeof(buffer),
3617 "%s(%d, %d, %d)", typename, h, m, s);
3618 else
3619 PyOS_snprintf(buffer, sizeof(buffer),
3620 "%s(%d, %d)", typename, h, m);
3621 return PyString_FromString(buffer);
3622}
3623
3624static PyObject *
3625time_str(PyDateTime_Time *self)
3626{
3627 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
3628}
3629
3630static PyObject *
3631time_isoformat(PyDateTime_Time *self)
3632{
3633 char buffer[100];
3634 /* Reuse the time format code from the datetime type. */
3635 PyDateTime_DateTime datetime;
3636 PyDateTime_DateTime *pdatetime = &datetime;
3637
3638 /* Copy over just the time bytes. */
3639 memcpy(pdatetime->data + _PyDateTime_DATE_DATASIZE,
3640 self->data,
3641 _PyDateTime_TIME_DATASIZE);
3642
3643 isoformat_time(pdatetime, buffer, sizeof(buffer));
3644 return PyString_FromString(buffer);
3645}
3646
3647static PyObject *
3648time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3649{
3650 PyObject *result;
3651 PyObject *format;
3652 PyObject *tuple;
3653 static char *keywords[] = {"format", NULL};
3654
3655 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
3656 &PyString_Type, &format))
3657 return NULL;
3658
Tim Peters83b85f12002-12-22 20:34:46 +00003659 /* Python's strftime does insane things with the year part of the
3660 * timetuple. The year is forced to (the otherwise nonsensical)
3661 * 1900 to worm around that.
3662 */
Tim Peters2a799bf2002-12-16 20:18:38 +00003663 tuple = Py_BuildValue("iiiiiiiii",
Tim Peters83b85f12002-12-22 20:34:46 +00003664 1900, 0, 0, /* year, month, day */
Tim Peters2a799bf2002-12-16 20:18:38 +00003665 TIME_GET_HOUR(self),
3666 TIME_GET_MINUTE(self),
3667 TIME_GET_SECOND(self),
3668 0, 0, -1); /* weekday, daynum, dst */
3669 if (tuple == NULL)
3670 return NULL;
3671 assert(PyTuple_Size(tuple) == 9);
Tim Petersbad8ff02002-12-30 20:52:32 +00003672 result = wrap_strftime((PyObject *)self, format, tuple, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003673 Py_DECREF(tuple);
3674 return result;
3675}
3676
3677/* Miscellaneous methods. */
3678
3679/* This is more natural as a tp_compare, but doesn't work then: for whatever
3680 * reason, Python's try_3way_compare ignores tp_compare unless
3681 * PyInstance_Check returns true, but these aren't old-style classes.
3682 * Note that this routine handles all comparisons for time and timetz.
3683 */
3684static PyObject *
3685time_richcompare(PyDateTime_Time *self, PyObject *other, int op)
3686{
3687 int diff;
3688 naivety n1, n2;
3689 int offset1, offset2;
3690
3691 if (! PyTime_Check(other)) {
3692 /* Stop this from falling back to address comparison. */
3693 PyErr_Format(PyExc_TypeError,
3694 "can't compare '%s' to '%s'",
3695 self->ob_type->tp_name,
3696 other->ob_type->tp_name);
3697 return NULL;
3698 }
Tim Peterse39a80c2002-12-30 21:28:52 +00003699 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1, Py_None,
3700 other, &offset2, &n2, Py_None) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003701 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003702 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00003703 /* If they're both naive, or both aware and have the same offsets,
3704 * we get off cheap. Note that if they're both naive, offset1 ==
3705 * offset2 == 0 at this point.
3706 */
3707 if (n1 == n2 && offset1 == offset2) {
3708 diff = memcmp(self->data, ((PyDateTime_Time *)other)->data,
3709 _PyDateTime_TIME_DATASIZE);
3710 return diff_to_bool(diff, op);
3711 }
3712
3713 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3714 assert(offset1 != offset2); /* else last "if" handled it */
3715 /* Convert everything except microseconds to seconds. These
3716 * can't overflow (no more than the # of seconds in 2 days).
3717 */
3718 offset1 = TIME_GET_HOUR(self) * 3600 +
3719 (TIME_GET_MINUTE(self) - offset1) * 60 +
3720 TIME_GET_SECOND(self);
3721 offset2 = TIME_GET_HOUR(other) * 3600 +
3722 (TIME_GET_MINUTE(other) - offset2) * 60 +
3723 TIME_GET_SECOND(other);
3724 diff = offset1 - offset2;
3725 if (diff == 0)
3726 diff = TIME_GET_MICROSECOND(self) -
3727 TIME_GET_MICROSECOND(other);
3728 return diff_to_bool(diff, op);
3729 }
3730
3731 assert(n1 != n2);
3732 PyErr_SetString(PyExc_TypeError,
3733 "can't compare offset-naive and "
3734 "offset-aware times");
3735 return NULL;
3736}
3737
3738static PyObject *time_getstate(PyDateTime_Time *self);
3739
3740static long
3741time_hash(PyDateTime_Time *self)
3742{
3743 if (self->hashcode == -1) {
3744 naivety n;
3745 int offset;
3746 PyObject *temp;
3747
Tim Peterse39a80c2002-12-30 21:28:52 +00003748 n = classify_utcoffset((PyObject *)self, Py_None, &offset);
Tim Peters2a799bf2002-12-16 20:18:38 +00003749 assert(n != OFFSET_UNKNOWN);
3750 if (n == OFFSET_ERROR)
3751 return -1;
3752
3753 /* Reduce this to a hash of another object. */
3754 if (offset == 0)
3755 temp = time_getstate(self);
3756 else {
3757 int hour;
3758 int minute;
3759
3760 assert(n == OFFSET_AWARE);
3761 assert(PyTimeTZ_Check(self));
3762 hour = divmod(TIME_GET_HOUR(self) * 60 +
3763 TIME_GET_MINUTE(self) - offset,
3764 60,
3765 &minute);
3766 if (0 <= hour && hour < 24)
3767 temp = new_time(hour, minute,
3768 TIME_GET_SECOND(self),
3769 TIME_GET_MICROSECOND(self));
3770 else
3771 temp = Py_BuildValue("iiii",
3772 hour, minute,
3773 TIME_GET_SECOND(self),
3774 TIME_GET_MICROSECOND(self));
3775 }
3776 if (temp != NULL) {
3777 self->hashcode = PyObject_Hash(temp);
3778 Py_DECREF(temp);
3779 }
3780 }
3781 return self->hashcode;
3782}
3783
Tim Peters12bf3392002-12-24 05:41:27 +00003784static PyObject *
3785time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3786{
3787 PyObject *clone;
3788 PyObject *tuple;
3789 int hh = TIME_GET_HOUR(self);
3790 int mm = TIME_GET_MINUTE(self);
3791 int ss = TIME_GET_SECOND(self);
3792 int us = TIME_GET_MICROSECOND(self);
3793
3794 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiii:replace",
3795 time_kws,
3796 &hh, &mm, &ss, &us))
3797 return NULL;
3798 tuple = Py_BuildValue("iiii", hh, mm, ss, us);
3799 if (tuple == NULL)
3800 return NULL;
3801 clone = time_new(self->ob_type, tuple, NULL);
3802 Py_DECREF(tuple);
3803 return clone;
3804}
3805
Tim Peters2a799bf2002-12-16 20:18:38 +00003806static int
3807time_nonzero(PyDateTime_Time *self)
3808{
3809 return TIME_GET_HOUR(self) ||
3810 TIME_GET_MINUTE(self) ||
3811 TIME_GET_SECOND(self) ||
3812 TIME_GET_MICROSECOND(self);
3813}
3814
3815/* Pickle support. Quite a maze! */
3816
3817static PyObject *
3818time_getstate(PyDateTime_Time *self)
3819{
3820 return PyString_FromStringAndSize(self->data,
3821 _PyDateTime_TIME_DATASIZE);
3822}
3823
3824static PyObject *
3825time_setstate(PyDateTime_Time *self, PyObject *state)
3826{
3827 const int len = PyString_Size(state);
3828 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
3829
3830 if (! PyString_Check(state) ||
3831 len != _PyDateTime_TIME_DATASIZE) {
3832 PyErr_SetString(PyExc_TypeError,
3833 "bad argument to time.__setstate__");
3834 return NULL;
3835 }
3836 memcpy(self->data, pdata, _PyDateTime_TIME_DATASIZE);
3837 self->hashcode = -1;
3838
3839 Py_INCREF(Py_None);
3840 return Py_None;
3841}
3842
3843/* XXX This seems a ridiculously inefficient way to pickle a short string. */
3844static PyObject *
3845time_pickler(PyObject *module, PyDateTime_Time *time)
3846{
3847 PyObject *state;
3848 PyObject *result = NULL;
3849
3850 if (! PyTime_CheckExact(time)) {
3851 PyErr_Format(PyExc_TypeError,
3852 "bad type passed to time pickler: %s",
3853 time->ob_type->tp_name);
3854 return NULL;
3855 }
3856 state = time_getstate(time);
3857 if (state) {
3858 result = Py_BuildValue("O(O)",
3859 time_unpickler_object,
3860 state);
3861 Py_DECREF(state);
3862 }
3863 return result;
3864}
3865
3866static PyObject *
3867time_unpickler(PyObject *module, PyObject *arg)
3868{
3869 PyDateTime_Time *self;
3870
3871 if (! PyString_CheckExact(arg)) {
3872 PyErr_Format(PyExc_TypeError,
3873 "bad type passed to time unpickler: %s",
3874 arg->ob_type->tp_name);
3875 return NULL;
3876 }
3877 self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
3878 if (self != NULL) {
3879 PyObject *res = time_setstate(self, arg);
3880 if (res == NULL) {
3881 Py_DECREF(self);
3882 return NULL;
3883 }
3884 Py_DECREF(res);
3885 }
3886 return (PyObject *)self;
3887}
3888
3889static PyMethodDef time_methods[] = {
3890 {"isoformat", (PyCFunction)time_isoformat, METH_KEYWORDS,
3891 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm].")},
3892
3893 {"strftime", (PyCFunction)time_strftime, METH_KEYWORDS,
3894 PyDoc_STR("format -> strftime() style string.")},
3895
Tim Peters12bf3392002-12-24 05:41:27 +00003896 {"replace", (PyCFunction)time_replace, METH_KEYWORDS,
3897 PyDoc_STR("Return datetime with new specified fields.")},
3898
Tim Peters2a799bf2002-12-16 20:18:38 +00003899 {"__setstate__", (PyCFunction)time_setstate, METH_O,
3900 PyDoc_STR("__setstate__(state)")},
3901
3902 {"__getstate__", (PyCFunction)time_getstate, METH_NOARGS,
3903 PyDoc_STR("__getstate__() -> state")},
3904 {NULL, NULL}
3905};
3906
3907static char time_doc[] =
3908PyDoc_STR("Basic time type.");
3909
3910static PyNumberMethods time_as_number = {
3911 0, /* nb_add */
3912 0, /* nb_subtract */
3913 0, /* nb_multiply */
3914 0, /* nb_divide */
3915 0, /* nb_remainder */
3916 0, /* nb_divmod */
3917 0, /* nb_power */
3918 0, /* nb_negative */
3919 0, /* nb_positive */
3920 0, /* nb_absolute */
3921 (inquiry)time_nonzero, /* nb_nonzero */
3922};
3923
3924statichere PyTypeObject PyDateTime_TimeType = {
3925 PyObject_HEAD_INIT(NULL)
3926 0, /* ob_size */
3927 "datetime.time", /* tp_name */
3928 sizeof(PyDateTime_Time), /* tp_basicsize */
3929 0, /* tp_itemsize */
3930 (destructor)PyObject_Del, /* tp_dealloc */
3931 0, /* tp_print */
3932 0, /* tp_getattr */
3933 0, /* tp_setattr */
3934 0, /* tp_compare */
3935 (reprfunc)time_repr, /* tp_repr */
3936 &time_as_number, /* tp_as_number */
3937 0, /* tp_as_sequence */
3938 0, /* tp_as_mapping */
3939 (hashfunc)time_hash, /* tp_hash */
3940 0, /* tp_call */
3941 (reprfunc)time_str, /* tp_str */
3942 PyObject_GenericGetAttr, /* tp_getattro */
3943 0, /* tp_setattro */
3944 0, /* tp_as_buffer */
3945 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3946 Py_TPFLAGS_BASETYPE, /* tp_flags */
3947 time_doc, /* tp_doc */
3948 0, /* tp_traverse */
3949 0, /* tp_clear */
3950 (richcmpfunc)time_richcompare, /* tp_richcompare */
3951 0, /* tp_weaklistoffset */
3952 0, /* tp_iter */
3953 0, /* tp_iternext */
3954 time_methods, /* tp_methods */
3955 0, /* tp_members */
3956 time_getset, /* tp_getset */
3957 0, /* tp_base */
3958 0, /* tp_dict */
3959 0, /* tp_descr_get */
3960 0, /* tp_descr_set */
3961 0, /* tp_dictoffset */
3962 0, /* tp_init */
3963 0, /* tp_alloc */
3964 time_new, /* tp_new */
3965 _PyObject_Del, /* tp_free */
3966};
3967
3968/*
3969 * PyDateTime_TZInfo implementation.
3970 */
3971
3972/* This is a pure abstract base class, so doesn't do anything beyond
3973 * raising NotImplemented exceptions. Real tzinfo classes need
3974 * to derive from this. This is mostly for clarity, and for efficiency in
3975 * datetimetz and timetz constructors (their tzinfo arguments need to
3976 * be subclasses of this tzinfo class, which is easy and quick to check).
3977 *
3978 * Note: For reasons having to do with pickling of subclasses, we have
3979 * to allow tzinfo objects to be instantiated. This wasn't an issue
3980 * in the Python implementation (__init__() could raise NotImplementedError
3981 * there without ill effect), but doing so in the C implementation hit a
3982 * brick wall.
3983 */
3984
3985static PyObject *
3986tzinfo_nogo(const char* methodname)
3987{
3988 PyErr_Format(PyExc_NotImplementedError,
3989 "a tzinfo subclass must implement %s()",
3990 methodname);
3991 return NULL;
3992}
3993
3994/* Methods. A subclass must implement these. */
3995
3996static PyObject*
3997tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt)
3998{
3999 return tzinfo_nogo("tzname");
4000}
4001
4002static PyObject*
4003tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt)
4004{
4005 return tzinfo_nogo("utcoffset");
4006}
4007
4008static PyObject*
4009tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
4010{
4011 return tzinfo_nogo("dst");
4012}
4013
4014/*
4015 * Pickle support. This is solely so that tzinfo subclasses can use
4016 * pickling -- tzinfo itself is supposed to be uninstantiable. The
4017 * pickler and unpickler functions are given module-level private
4018 * names, and registered with copy_reg, by the module init function.
4019 */
4020
4021static PyObject*
4022tzinfo_pickler(PyDateTime_TZInfo *self) {
4023 return Py_BuildValue("O()", tzinfo_unpickler_object);
4024}
4025
4026static PyObject*
4027tzinfo_unpickler(PyObject * unused) {
4028 return PyType_GenericNew(&PyDateTime_TZInfoType, NULL, NULL);
4029}
4030
4031
4032static PyMethodDef tzinfo_methods[] = {
4033 {"tzname", (PyCFunction)tzinfo_tzname, METH_O,
4034 PyDoc_STR("datetime -> string name of time zone.")},
4035
4036 {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
4037 PyDoc_STR("datetime -> minutes east of UTC (negative for "
4038 "west of UTC).")},
4039
4040 {"dst", (PyCFunction)tzinfo_dst, METH_O,
4041 PyDoc_STR("datetime -> DST offset in minutes east of UTC.")},
4042
4043 {NULL, NULL}
4044};
4045
4046static char tzinfo_doc[] =
4047PyDoc_STR("Abstract base class for time zone info objects.");
4048
4049 statichere PyTypeObject PyDateTime_TZInfoType = {
4050 PyObject_HEAD_INIT(NULL)
4051 0, /* ob_size */
4052 "datetime.tzinfo", /* tp_name */
4053 sizeof(PyDateTime_TZInfo), /* tp_basicsize */
4054 0, /* tp_itemsize */
4055 0, /* tp_dealloc */
4056 0, /* tp_print */
4057 0, /* tp_getattr */
4058 0, /* tp_setattr */
4059 0, /* tp_compare */
4060 0, /* tp_repr */
4061 0, /* tp_as_number */
4062 0, /* tp_as_sequence */
4063 0, /* tp_as_mapping */
4064 0, /* tp_hash */
4065 0, /* tp_call */
4066 0, /* tp_str */
4067 PyObject_GenericGetAttr, /* tp_getattro */
4068 0, /* tp_setattro */
4069 0, /* tp_as_buffer */
4070 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4071 Py_TPFLAGS_BASETYPE, /* tp_flags */
4072 tzinfo_doc, /* tp_doc */
4073 0, /* tp_traverse */
4074 0, /* tp_clear */
4075 0, /* tp_richcompare */
4076 0, /* tp_weaklistoffset */
4077 0, /* tp_iter */
4078 0, /* tp_iternext */
4079 tzinfo_methods, /* tp_methods */
4080 0, /* tp_members */
4081 0, /* tp_getset */
4082 0, /* tp_base */
4083 0, /* tp_dict */
4084 0, /* tp_descr_get */
4085 0, /* tp_descr_set */
4086 0, /* tp_dictoffset */
4087 0, /* tp_init */
4088 0, /* tp_alloc */
4089 PyType_GenericNew, /* tp_new */
4090 0, /* tp_free */
4091};
4092
4093/*
4094 * PyDateTime_TimeTZ implementation.
4095 */
4096
4097/* Accessor properties. Properties for hour, minute, second and microsecond
4098 * are inherited from time.
4099 */
4100
4101static PyObject *
4102timetz_tzinfo(PyDateTime_TimeTZ *self, void *unused)
4103{
4104 Py_INCREF(self->tzinfo);
4105 return self->tzinfo;
4106}
4107
4108static PyGetSetDef timetz_getset[] = {
4109 {"tzinfo", (getter)timetz_tzinfo},
4110 {NULL}
4111};
4112
4113/*
4114 * Constructors.
4115 */
4116
Tim Peters12bf3392002-12-24 05:41:27 +00004117static char *timetz_kws[] = {"hour", "minute", "second", "microsecond",
4118 "tzinfo", NULL};
4119
Tim Peters2a799bf2002-12-16 20:18:38 +00004120static PyObject *
4121timetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4122{
4123 PyObject *self = NULL;
4124 int hour = 0;
4125 int minute = 0;
4126 int second = 0;
4127 int usecond = 0;
4128 PyObject *tzinfo = Py_None;
4129
Tim Peters12bf3392002-12-24 05:41:27 +00004130 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", timetz_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00004131 &hour, &minute, &second, &usecond,
4132 &tzinfo)) {
4133 if (check_time_args(hour, minute, second, usecond) < 0)
4134 return NULL;
4135 if (check_tzinfo_subclass(tzinfo) < 0)
4136 return NULL;
4137 self = new_timetz(hour, minute, second, usecond, tzinfo);
4138 }
4139 return self;
4140}
4141
4142/*
4143 * Destructor.
4144 */
4145
4146static void
4147timetz_dealloc(PyDateTime_TimeTZ *self)
4148{
4149 Py_XDECREF(self->tzinfo);
4150 self->ob_type->tp_free((PyObject *)self);
4151}
4152
4153/*
Tim Peters855fe882002-12-22 03:43:39 +00004154 * Indirect access to tzinfo methods.
Tim Peters2a799bf2002-12-16 20:18:38 +00004155 */
4156
Tim Peters2a799bf2002-12-16 20:18:38 +00004157/* These are all METH_NOARGS, so don't need to check the arglist. */
4158static PyObject *
4159timetz_utcoffset(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004160 return offset_as_timedelta(self->tzinfo, "utcoffset", Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004161}
4162
4163static PyObject *
4164timetz_dst(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004165 return offset_as_timedelta(self->tzinfo, "dst", Py_None);
Tim Peters855fe882002-12-22 03:43:39 +00004166}
4167
4168static PyObject *
4169timetz_tzname(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004170 return call_tzname(self->tzinfo, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004171}
4172
4173/*
4174 * Various ways to turn a timetz into a string.
4175 */
4176
4177static PyObject *
4178timetz_repr(PyDateTime_TimeTZ *self)
4179{
4180 PyObject *baserepr = time_repr((PyDateTime_Time *)self);
4181
4182 if (baserepr == NULL)
4183 return NULL;
4184 return append_keyword_tzinfo(baserepr, self->tzinfo);
4185}
4186
4187/* Note: tp_str is inherited from time. */
4188
4189static PyObject *
4190timetz_isoformat(PyDateTime_TimeTZ *self)
4191{
4192 char buf[100];
4193 PyObject *result = time_isoformat((PyDateTime_Time *)self);
4194
4195 if (result == NULL || self->tzinfo == Py_None)
4196 return result;
4197
4198 /* We need to append the UTC offset. */
4199 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00004200 Py_None) < 0) {
Tim Peters2a799bf2002-12-16 20:18:38 +00004201 Py_DECREF(result);
4202 return NULL;
4203 }
4204 PyString_ConcatAndDel(&result, PyString_FromString(buf));
4205 return result;
4206}
4207
4208/* Note: strftime() is inherited from time. */
4209
4210/*
4211 * Miscellaneous methods.
4212 */
4213
4214/* Note: tp_richcompare and tp_hash are inherited from time. */
4215
Tim Peters12bf3392002-12-24 05:41:27 +00004216static PyObject *
4217timetz_replace(PyDateTime_TimeTZ *self, PyObject *args, PyObject *kw)
4218{
4219 PyObject *clone;
4220 PyObject *tuple;
4221 int hh = TIME_GET_HOUR(self);
4222 int mm = TIME_GET_MINUTE(self);
4223 int ss = TIME_GET_SECOND(self);
4224 int us = TIME_GET_MICROSECOND(self);
4225 PyObject *tzinfo = self->tzinfo;
4226
4227 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
4228 timetz_kws,
4229 &hh, &mm, &ss, &us, &tzinfo))
4230 return NULL;
4231 tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
4232 if (tuple == NULL)
4233 return NULL;
4234 clone = timetz_new(self->ob_type, tuple, NULL);
4235 Py_DECREF(tuple);
4236 return clone;
4237}
4238
Tim Peters2a799bf2002-12-16 20:18:38 +00004239static int
4240timetz_nonzero(PyDateTime_TimeTZ *self)
4241{
4242 int offset;
4243 int none;
4244
4245 if (TIME_GET_SECOND(self) || TIME_GET_MICROSECOND(self)) {
4246 /* Since utcoffset is in whole minutes, nothing can
4247 * alter the conclusion that this is nonzero.
4248 */
4249 return 1;
4250 }
4251 offset = 0;
4252 if (self->tzinfo != Py_None) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004253 offset = call_utcoffset(self->tzinfo, Py_None, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +00004254 if (offset == -1 && PyErr_Occurred())
4255 return -1;
4256 }
4257 return (TIME_GET_MINUTE(self) - offset + TIME_GET_HOUR(self)*60) != 0;
4258}
4259
4260/*
4261 * Pickle support. Quite a maze!
4262 */
4263
4264/* Let basestate be the state string returned by time_getstate.
4265 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4266 * So it's a tuple in any (non-error) case.
4267 */
4268static PyObject *
4269timetz_getstate(PyDateTime_TimeTZ *self)
4270{
4271 PyObject *basestate;
4272 PyObject *result = NULL;
4273
4274 basestate = time_getstate((PyDateTime_Time *)self);
4275 if (basestate != NULL) {
4276 if (self->tzinfo == Py_None)
4277 result = Py_BuildValue("(O)", basestate);
4278 else
4279 result = Py_BuildValue("OO", basestate, self->tzinfo);
4280 Py_DECREF(basestate);
4281 }
4282 return result;
4283}
4284
4285static PyObject *
4286timetz_setstate(PyDateTime_TimeTZ *self, PyObject *state)
4287{
4288 PyObject *temp;
4289 PyObject *basestate;
4290 PyObject *tzinfo = Py_None;
4291
4292 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
4293 &PyString_Type, &basestate,
4294 &tzinfo))
4295 return NULL;
4296 temp = time_setstate((PyDateTime_Time *)self, basestate);
4297 if (temp == NULL)
4298 return NULL;
4299 Py_DECREF(temp);
4300
4301 Py_INCREF(tzinfo);
4302 Py_XDECREF(self->tzinfo);
4303 self->tzinfo = tzinfo;
4304
4305 Py_INCREF(Py_None);
4306 return Py_None;
4307}
4308
4309static PyObject *
4310timetz_pickler(PyObject *module, PyDateTime_TimeTZ *timetz)
4311{
4312 PyObject *state;
4313 PyObject *result = NULL;
4314
4315 if (! PyTimeTZ_CheckExact(timetz)) {
4316 PyErr_Format(PyExc_TypeError,
4317 "bad type passed to timetz pickler: %s",
4318 timetz->ob_type->tp_name);
4319 return NULL;
4320 }
4321 state = timetz_getstate(timetz);
4322 if (state) {
4323 result = Py_BuildValue("O(O)",
4324 timetz_unpickler_object,
4325 state);
4326 Py_DECREF(state);
4327 }
4328 return result;
4329}
4330
4331static PyObject *
4332timetz_unpickler(PyObject *module, PyObject *arg)
4333{
4334 PyDateTime_TimeTZ *self;
4335
4336 self = PyObject_New(PyDateTime_TimeTZ, &PyDateTime_TimeTZType);
4337 if (self != NULL) {
4338 PyObject *res;
4339
4340 self->tzinfo = NULL;
4341 res = timetz_setstate(self, arg);
4342 if (res == NULL) {
4343 Py_DECREF(self);
4344 return NULL;
4345 }
4346 Py_DECREF(res);
4347 }
4348 return (PyObject *)self;
4349}
4350
4351static PyMethodDef timetz_methods[] = {
4352 {"isoformat", (PyCFunction)timetz_isoformat, METH_KEYWORDS,
4353 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]"
4354 "[+HH:MM].")},
4355
4356 {"utcoffset", (PyCFunction)timetz_utcoffset, METH_NOARGS,
4357 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
4358
4359 {"tzname", (PyCFunction)timetz_tzname, METH_NOARGS,
4360 PyDoc_STR("Return self.tzinfo.tzname(self).")},
4361
4362 {"dst", (PyCFunction)timetz_dst, METH_NOARGS,
4363 PyDoc_STR("Return self.tzinfo.dst(self).")},
4364
Tim Peters12bf3392002-12-24 05:41:27 +00004365 {"replace", (PyCFunction)timetz_replace, METH_KEYWORDS,
4366 PyDoc_STR("Return timetz with new specified fields.")},
4367
Tim Peters2a799bf2002-12-16 20:18:38 +00004368 {"__setstate__", (PyCFunction)timetz_setstate, METH_O,
4369 PyDoc_STR("__setstate__(state)")},
4370
4371 {"__getstate__", (PyCFunction)timetz_getstate, METH_NOARGS,
4372 PyDoc_STR("__getstate__() -> state")},
4373 {NULL, NULL}
4374
4375};
4376
4377static char timetz_doc[] =
4378PyDoc_STR("Time type.");
4379
4380static PyNumberMethods timetz_as_number = {
4381 0, /* nb_add */
4382 0, /* nb_subtract */
4383 0, /* nb_multiply */
4384 0, /* nb_divide */
4385 0, /* nb_remainder */
4386 0, /* nb_divmod */
4387 0, /* nb_power */
4388 0, /* nb_negative */
4389 0, /* nb_positive */
4390 0, /* nb_absolute */
4391 (inquiry)timetz_nonzero, /* nb_nonzero */
4392};
4393
4394statichere PyTypeObject PyDateTime_TimeTZType = {
4395 PyObject_HEAD_INIT(NULL)
4396 0, /* ob_size */
4397 "datetime.timetz", /* tp_name */
4398 sizeof(PyDateTime_TimeTZ), /* tp_basicsize */
4399 0, /* tp_itemsize */
4400 (destructor)timetz_dealloc, /* tp_dealloc */
4401 0, /* tp_print */
4402 0, /* tp_getattr */
4403 0, /* tp_setattr */
4404 0, /* tp_compare */
4405 (reprfunc)timetz_repr, /* tp_repr */
4406 &timetz_as_number, /* tp_as_number */
4407 0, /* tp_as_sequence */
4408 0, /* tp_as_mapping */
4409 0, /* tp_hash */
4410 0, /* tp_call */
4411 0, /* tp_str */
4412 PyObject_GenericGetAttr, /* tp_getattro */
4413 0, /* tp_setattro */
4414 0, /* tp_as_buffer */
4415 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4416 Py_TPFLAGS_BASETYPE, /* tp_flags */
Guido van Rossumbd43e912002-12-16 20:34:55 +00004417 timetz_doc, /* tp_doc */
Tim Peters2a799bf2002-12-16 20:18:38 +00004418 0, /* tp_traverse */
4419 0, /* tp_clear */
4420 0, /* tp_richcompare */
4421 0, /* tp_weaklistoffset */
4422 0, /* tp_iter */
4423 0, /* tp_iternext */
4424 timetz_methods, /* tp_methods */
4425 0, /* tp_members */
4426 timetz_getset, /* tp_getset */
4427 &PyDateTime_TimeType, /* tp_base */
4428 0, /* tp_dict */
4429 0, /* tp_descr_get */
4430 0, /* tp_descr_set */
4431 0, /* tp_dictoffset */
4432 0, /* tp_init */
4433 0, /* tp_alloc */
4434 timetz_new, /* tp_new */
4435 _PyObject_Del, /* tp_free */
4436};
4437
4438/*
4439 * PyDateTime_DateTimeTZ implementation.
4440 */
4441
4442/* Accessor properties. Properties for day, month, year, hour, minute,
4443 * second and microsecond are inherited from datetime.
4444 */
4445
4446static PyObject *
4447datetimetz_tzinfo(PyDateTime_DateTimeTZ *self, void *unused)
4448{
4449 Py_INCREF(self->tzinfo);
4450 return self->tzinfo;
4451}
4452
4453static PyGetSetDef datetimetz_getset[] = {
4454 {"tzinfo", (getter)datetimetz_tzinfo},
4455 {NULL}
4456};
4457
4458/*
4459 * Constructors.
4460 * These are like the datetime methods of the same names, but allow an
4461 * optional tzinfo argument.
4462 */
4463
Tim Peters12bf3392002-12-24 05:41:27 +00004464static char *datetimetz_kws[] = {
4465 "year", "month", "day", "hour", "minute", "second",
4466 "microsecond", "tzinfo", NULL
4467};
4468
Tim Peters2a799bf2002-12-16 20:18:38 +00004469static PyObject *
4470datetimetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4471{
4472 PyObject *self = NULL;
4473 int year;
4474 int month;
4475 int day;
4476 int hour = 0;
4477 int minute = 0;
4478 int second = 0;
4479 int usecond = 0;
4480 PyObject *tzinfo = Py_None;
4481
Tim Peters12bf3392002-12-24 05:41:27 +00004482 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO", datetimetz_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00004483 &year, &month, &day, &hour, &minute,
4484 &second, &usecond, &tzinfo)) {
4485 if (check_date_args(year, month, day) < 0)
4486 return NULL;
4487 if (check_time_args(hour, minute, second, usecond) < 0)
4488 return NULL;
4489 if (check_tzinfo_subclass(tzinfo) < 0)
4490 return NULL;
4491 self = new_datetimetz(year, month, day,
4492 hour, minute, second, usecond,
4493 tzinfo);
4494 }
4495 return self;
4496}
4497
4498/* Return best possible local time -- this isn't constrained by the
4499 * precision of a timestamp.
4500 */
4501static PyObject *
4502datetimetz_now(PyObject *cls, PyObject *args, PyObject *kw)
4503{
4504 PyObject *self = NULL;
4505 PyObject *tzinfo = Py_None;
4506 static char *keywords[] = {"tzinfo", NULL};
4507
4508 if (PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords,
4509 &tzinfo)) {
4510 if (check_tzinfo_subclass(tzinfo) < 0)
4511 return NULL;
4512 self = datetime_best_possible(cls, localtime);
4513 if (self != NULL)
4514 replace_tzinfo(self, tzinfo);
4515 }
4516 return self;
4517}
4518
4519/* Return new local datetime from timestamp (Python timestamp -- a double). */
4520static PyObject *
4521datetimetz_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
4522{
4523 PyObject *self = NULL;
4524 double timestamp;
4525 PyObject *tzinfo = Py_None;
4526 static char *keywords[] = {"timestamp", "tzinfo", NULL};
4527
4528 if (PyArg_ParseTupleAndKeywords(args, kw, "d|O:fromtimestamp",
4529 keywords, &timestamp, &tzinfo)) {
4530 if (check_tzinfo_subclass(tzinfo) < 0)
4531 return NULL;
4532 self = datetime_from_timestamp(cls, localtime, timestamp);
4533 if (self != NULL)
4534 replace_tzinfo(self, tzinfo);
4535 }
4536 return self;
4537}
4538
4539/* Note: utcnow() is inherited, and doesn't accept tzinfo.
4540 * Ditto utcfromtimestamp(). Ditto combine().
4541 */
4542
4543
4544/*
4545 * Destructor.
4546 */
4547
4548static void
4549datetimetz_dealloc(PyDateTime_DateTimeTZ *self)
4550{
4551 Py_XDECREF(self->tzinfo);
4552 self->ob_type->tp_free((PyObject *)self);
4553}
4554
4555/*
4556 * Indirect access to tzinfo methods.
4557 */
4558
Tim Peters2a799bf2002-12-16 20:18:38 +00004559/* These are all METH_NOARGS, so don't need to check the arglist. */
4560static PyObject *
4561datetimetz_utcoffset(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004562 return offset_as_timedelta(self->tzinfo, "utcoffset",
4563 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00004564}
4565
4566static PyObject *
4567datetimetz_dst(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004568 return offset_as_timedelta(self->tzinfo, "dst", (PyObject *)self);
Tim Peters855fe882002-12-22 03:43:39 +00004569}
4570
4571static PyObject *
4572datetimetz_tzname(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004573 return call_tzname(self->tzinfo, (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00004574}
4575
4576/*
4577 * datetimetz arithmetic.
4578 */
4579
4580/* If base is Py_NotImplemented or NULL, just return it.
4581 * Else base is a datetime, exactly one of {left, right} is a datetimetz,
4582 * and we want to create a datetimetz with the same date and time fields
4583 * as base, and with the tzinfo field from left or right. Do that,
4584 * return it, and decref base. This is used to transform the result of
4585 * a binary datetime operation (base) into a datetimetz result.
4586 */
4587static PyObject *
4588attach_tzinfo(PyObject *base, PyObject *left, PyObject *right)
4589{
4590 PyDateTime_DateTimeTZ *self;
4591 PyDateTime_DateTimeTZ *result;
4592
4593 if (base == NULL || base == Py_NotImplemented)
4594 return base;
4595
4596 assert(PyDateTime_CheckExact(base));
4597
4598 if (PyDateTimeTZ_Check(left)) {
4599 assert(! PyDateTimeTZ_Check(right));
4600 self = (PyDateTime_DateTimeTZ *)left;
4601 }
4602 else {
4603 assert(PyDateTimeTZ_Check(right));
4604 self = (PyDateTime_DateTimeTZ *)right;
4605 }
4606 result = PyObject_New(PyDateTime_DateTimeTZ,
4607 &PyDateTime_DateTimeTZType);
4608 if (result != NULL) {
4609 memcpy(result->data, ((PyDateTime_DateTime *)base)->data,
4610 _PyDateTime_DATETIME_DATASIZE);
4611 Py_INCREF(self->tzinfo);
4612 result->tzinfo = self->tzinfo;
4613 }
4614 Py_DECREF(base);
4615 return (PyObject *)result;
4616}
4617
4618static PyObject *
4619datetimetz_add(PyObject *left, PyObject *right)
4620{
4621 return attach_tzinfo(datetime_add(left, right), left, right);
4622}
4623
4624static PyObject *
4625datetimetz_subtract(PyObject *left, PyObject *right)
4626{
4627 PyObject *result = Py_NotImplemented;
4628
4629 if (PyDateTime_Check(left)) {
4630 /* datetime - ??? */
4631 if (PyDateTime_Check(right)) {
4632 /* datetime - datetime */
4633 naivety n1, n2;
4634 int offset1, offset2;
4635 PyDateTime_Delta *delta;
4636
Tim Peterse39a80c2002-12-30 21:28:52 +00004637 if (classify_two_utcoffsets(left, &offset1, &n1, left,
4638 right, &offset2, &n2,
4639 right) < 0)
Tim Peters00237032002-12-27 02:21:51 +00004640 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00004641 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00004642 if (n1 != n2) {
4643 PyErr_SetString(PyExc_TypeError,
4644 "can't subtract offset-naive and "
4645 "offset-aware datetimes");
4646 return NULL;
4647 }
4648 delta = (PyDateTime_Delta *)sub_datetime_datetime(
4649 (PyDateTime_DateTime *)left,
4650 (PyDateTime_DateTime *)right);
4651 if (delta == NULL || offset1 == offset2)
4652 return (PyObject *)delta;
4653 /* (left - offset1) - (right - offset2) =
4654 * (left - right) + (offset2 - offset1)
4655 */
4656 result = new_delta(delta->days,
4657 delta->seconds +
4658 (offset2 - offset1) * 60,
4659 delta->microseconds,
4660 1);
4661 Py_DECREF(delta);
4662 }
4663 else if (PyDelta_Check(right)) {
4664 /* datetimetz - delta */
4665 result = sub_datetime_timedelta(
4666 (PyDateTime_DateTime *)left,
4667 (PyDateTime_Delta *)right);
4668 result = attach_tzinfo(result, left, right);
4669 }
4670 }
4671
4672 if (result == Py_NotImplemented)
4673 Py_INCREF(result);
4674 return result;
4675}
4676
4677/* Various ways to turn a datetime into a string. */
4678
4679static PyObject *
4680datetimetz_repr(PyDateTime_DateTimeTZ *self)
4681{
4682 PyObject *baserepr = datetime_repr((PyDateTime_DateTime *)self);
4683
4684 if (baserepr == NULL)
4685 return NULL;
4686 return append_keyword_tzinfo(baserepr, self->tzinfo);
4687}
4688
4689/* Note: tp_str is inherited from datetime. */
4690
4691static PyObject *
4692datetimetz_isoformat(PyDateTime_DateTimeTZ *self,
4693 PyObject *args, PyObject *kw)
4694{
4695 char buf[100];
4696 PyObject *result = datetime_isoformat((PyDateTime_DateTime *)self,
4697 args, kw);
4698
4699 if (result == NULL || self->tzinfo == Py_None)
4700 return result;
4701
4702 /* We need to append the UTC offset. */
4703 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
4704 (PyObject *)self) < 0) {
4705 Py_DECREF(result);
4706 return NULL;
4707 }
4708 PyString_ConcatAndDel(&result, PyString_FromString(buf));
4709 return result;
4710}
4711
4712/* Miscellaneous methods. */
4713
4714/* Note: tp_richcompare and tp_hash are inherited from datetime. */
4715
4716static PyObject *
Tim Peters12bf3392002-12-24 05:41:27 +00004717datetimetz_replace(PyDateTime_DateTimeTZ *self, PyObject *args, PyObject *kw)
4718{
4719 PyObject *clone;
4720 PyObject *tuple;
4721 int y = GET_YEAR(self);
4722 int m = GET_MONTH(self);
4723 int d = GET_DAY(self);
4724 int hh = DATE_GET_HOUR(self);
4725 int mm = DATE_GET_MINUTE(self);
4726 int ss = DATE_GET_SECOND(self);
4727 int us = DATE_GET_MICROSECOND(self);
4728 PyObject *tzinfo = self->tzinfo;
4729
4730 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO:replace",
4731 datetimetz_kws,
4732 &y, &m, &d, &hh, &mm, &ss, &us,
4733 &tzinfo))
4734 return NULL;
4735 tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
4736 if (tuple == NULL)
4737 return NULL;
4738 clone = datetimetz_new(self->ob_type, tuple, NULL);
4739 Py_DECREF(tuple);
4740 return clone;
4741}
4742
4743static PyObject *
Tim Peters80475bb2002-12-25 07:40:55 +00004744datetimetz_astimezone(PyDateTime_DateTimeTZ *self, PyObject *args,
4745 PyObject *kw)
4746{
4747 int y = GET_YEAR(self);
4748 int m = GET_MONTH(self);
4749 int d = GET_DAY(self);
4750 int hh = DATE_GET_HOUR(self);
4751 int mm = DATE_GET_MINUTE(self);
4752 int ss = DATE_GET_SECOND(self);
4753 int us = DATE_GET_MICROSECOND(self);
4754
Tim Peters521fc152002-12-31 17:36:56 +00004755 PyObject *result;
4756 PyObject *temp;
Tim Petersf3615152003-01-01 21:51:37 +00004757 int selfoff, resoff, resdst, total_added_to_result;
Tim Peters521fc152002-12-31 17:36:56 +00004758 int none;
Tim Petersf3615152003-01-01 21:51:37 +00004759 int delta;
Tim Peters521fc152002-12-31 17:36:56 +00004760
Tim Peters80475bb2002-12-25 07:40:55 +00004761 PyObject *tzinfo;
4762 static char *keywords[] = {"tz", NULL};
4763
4764 if (! PyArg_ParseTupleAndKeywords(args, kw, "O:astimezone", keywords,
4765 &tzinfo))
4766 return NULL;
4767 if (check_tzinfo_subclass(tzinfo) < 0)
4768 return NULL;
4769
Tim Peters521fc152002-12-31 17:36:56 +00004770 /* Don't call utcoffset unless necessary. */
4771 result = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4772 if (result == NULL ||
4773 tzinfo == Py_None ||
4774 self->tzinfo == Py_None ||
4775 self->tzinfo == tzinfo)
4776 return result;
4777
4778 /* Get the offsets. If either object turns out to be naive, again
4779 * there's no conversion of date or time fields.
4780 */
Tim Petersb5a16f32003-01-01 04:48:01 +00004781 selfoff = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4782 if (selfoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004783 goto Fail;
4784 if (none)
4785 return result;
4786
Tim Petersb5a16f32003-01-01 04:48:01 +00004787 resoff = call_utcoffset(tzinfo, result, &none);
4788 if (resoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004789 goto Fail;
4790 if (none)
4791 return result;
4792
Tim Petersf3615152003-01-01 21:51:37 +00004793 /* See the long comment block at the end of this file for an
4794 * explanation of this algorithm. That it always works requires a
4795 * pretty intricate proof.
Tim Peters521fc152002-12-31 17:36:56 +00004796 */
Tim Petersf3615152003-01-01 21:51:37 +00004797 resdst = call_dst(tzinfo, result, &none);
4798 if (resdst == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004799 goto Fail;
Tim Peters710fb152003-01-02 19:35:54 +00004800 if (none) {
4801 PyErr_SetString(PyExc_ValueError, "astimezone(): utcoffset() "
4802 "returned a duration but dst() returned None");
4803 goto Fail;
4804 }
Tim Petersf3615152003-01-01 21:51:37 +00004805 total_added_to_result = resoff - resdst - selfoff;
4806 if (total_added_to_result != 0) {
4807 mm += total_added_to_result;
Tim Petersb5a16f32003-01-01 04:48:01 +00004808 if ((mm < 0 || mm >= 60) &&
4809 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters521fc152002-12-31 17:36:56 +00004810 goto Fail;
4811 temp = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4812 if (temp == NULL)
4813 goto Fail;
4814 Py_DECREF(result);
4815 result = temp;
4816
Tim Petersb5a16f32003-01-01 04:48:01 +00004817 resoff = call_utcoffset(tzinfo, result, &none);
4818 if (resoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004819 goto Fail;
4820 if (none)
4821 goto Inconsistent;
Tim Petersf3615152003-01-01 21:51:37 +00004822 }
4823
4824 /* The distance now from self to result is
4825 * self - result == naive(self) - selfoff - (naive(result) - resoff) ==
4826 * naive(self) - selfoff -
4827 * ((naive(self) + total_added_to_result - resoff) ==
4828 * - selfoff - total_added_to_result + resoff.
Tim Peters521fc152002-12-31 17:36:56 +00004829 */
Tim Petersf3615152003-01-01 21:51:37 +00004830 delta = resoff - selfoff - total_added_to_result;
4831
4832 /* Now self and result are the same UTC time iff delta is 0.
4833 * If it is 0, we're done, although that takes some proving.
4834 */
4835 if (delta == 0)
4836 return result;
4837
4838 total_added_to_result += delta;
4839 mm += delta;
4840 if ((mm < 0 || mm >= 60) &&
4841 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters521fc152002-12-31 17:36:56 +00004842 goto Fail;
Tim Petersf3615152003-01-01 21:51:37 +00004843
Tim Peters521fc152002-12-31 17:36:56 +00004844 temp = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4845 if (temp == NULL)
4846 goto Fail;
Tim Petersf3615152003-01-01 21:51:37 +00004847 Py_DECREF(result);
4848 result = temp;
Tim Peters521fc152002-12-31 17:36:56 +00004849
Tim Petersf3615152003-01-01 21:51:37 +00004850 resoff = call_utcoffset(tzinfo, result, &none);
4851 if (resoff == -1 && PyErr_Occurred())
4852 goto Fail;
4853 if (none)
4854 goto Inconsistent;
4855
4856 if (resoff - selfoff == total_added_to_result)
4857 /* self and result are the same UTC time */
Tim Peters521fc152002-12-31 17:36:56 +00004858 return result;
Tim Petersb5a16f32003-01-01 04:48:01 +00004859
4860 /* Else there's no way to spell self in zone tzinfo. */
Tim Peters521fc152002-12-31 17:36:56 +00004861 PyErr_SetString(PyExc_ValueError, "astimezone(): the source "
4862 "datetimetz can't be expressed in the target "
4863 "timezone's local time");
4864 goto Fail;
4865
4866Inconsistent:
4867 PyErr_SetString(PyExc_ValueError, "astimezone(): tz.utcoffset() "
4868 "gave inconsistent results; cannot convert");
4869
4870 /* fall thru to failure */
4871Fail:
4872 Py_DECREF(result);
4873 return NULL;
Tim Peters80475bb2002-12-25 07:40:55 +00004874}
4875
4876static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00004877datetimetz_timetuple(PyDateTime_DateTimeTZ *self)
4878{
4879 int dstflag = -1;
4880
4881 if (self->tzinfo != Py_None) {
4882 int none;
4883
4884 dstflag = call_dst(self->tzinfo, (PyObject *)self, &none);
4885 if (dstflag == -1 && PyErr_Occurred())
4886 return NULL;
4887
4888 if (none)
4889 dstflag = -1;
4890 else if (dstflag != 0)
4891 dstflag = 1;
4892
4893 }
4894 return build_struct_time(GET_YEAR(self),
4895 GET_MONTH(self),
4896 GET_DAY(self),
4897 DATE_GET_HOUR(self),
4898 DATE_GET_MINUTE(self),
4899 DATE_GET_SECOND(self),
4900 dstflag);
4901}
4902
4903static PyObject *
4904datetimetz_utctimetuple(PyDateTime_DateTimeTZ *self)
4905{
4906 int y = GET_YEAR(self);
4907 int m = GET_MONTH(self);
4908 int d = GET_DAY(self);
4909 int hh = DATE_GET_HOUR(self);
4910 int mm = DATE_GET_MINUTE(self);
4911 int ss = DATE_GET_SECOND(self);
4912 int us = 0; /* microseconds are ignored in a timetuple */
4913 int offset = 0;
4914
4915 if (self->tzinfo != Py_None) {
4916 int none;
4917
4918 offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4919 if (offset == -1 && PyErr_Occurred())
4920 return NULL;
4921 }
4922 /* Even if offset is 0, don't call timetuple() -- tm_isdst should be
4923 * 0 in a UTC timetuple regardless of what dst() says.
4924 */
4925 if (offset) {
4926 /* Subtract offset minutes & normalize. */
4927 int stat;
4928
4929 mm -= offset;
4930 stat = normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us);
4931 if (stat < 0) {
4932 /* At the edges, it's possible we overflowed
4933 * beyond MINYEAR or MAXYEAR.
4934 */
4935 if (PyErr_ExceptionMatches(PyExc_OverflowError))
4936 PyErr_Clear();
4937 else
4938 return NULL;
4939 }
4940 }
4941 return build_struct_time(y, m, d, hh, mm, ss, 0);
4942}
4943
4944static PyObject *
4945datetimetz_gettimetz(PyDateTime_DateTimeTZ *self)
4946{
4947 return new_timetz(DATE_GET_HOUR(self),
4948 DATE_GET_MINUTE(self),
4949 DATE_GET_SECOND(self),
4950 DATE_GET_MICROSECOND(self),
4951 self->tzinfo);
4952}
4953
4954/*
4955 * Pickle support. Quite a maze!
4956 */
4957
4958/* Let basestate be the state string returned by datetime_getstate.
4959 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4960 * So it's a tuple in any (non-error) case.
4961 */
4962static PyObject *
4963datetimetz_getstate(PyDateTime_DateTimeTZ *self)
4964{
4965 PyObject *basestate;
4966 PyObject *result = NULL;
4967
4968 basestate = datetime_getstate((PyDateTime_DateTime *)self);
4969 if (basestate != NULL) {
4970 if (self->tzinfo == Py_None)
4971 result = Py_BuildValue("(O)", basestate);
4972 else
4973 result = Py_BuildValue("OO", basestate, self->tzinfo);
4974 Py_DECREF(basestate);
4975 }
4976 return result;
4977}
4978
4979static PyObject *
4980datetimetz_setstate(PyDateTime_DateTimeTZ *self, PyObject *state)
4981{
4982 PyObject *temp;
4983 PyObject *basestate;
4984 PyObject *tzinfo = Py_None;
4985
4986 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
4987 &PyString_Type, &basestate,
4988 &tzinfo))
4989 return NULL;
4990 temp = datetime_setstate((PyDateTime_DateTime *)self, basestate);
4991 if (temp == NULL)
4992 return NULL;
4993 Py_DECREF(temp);
4994
4995 Py_INCREF(tzinfo);
4996 Py_XDECREF(self->tzinfo);
4997 self->tzinfo = tzinfo;
4998
4999 Py_INCREF(Py_None);
5000 return Py_None;
5001}
5002
5003static PyObject *
5004datetimetz_pickler(PyObject *module, PyDateTime_DateTimeTZ *datetimetz)
5005{
5006 PyObject *state;
5007 PyObject *result = NULL;
5008
5009 if (! PyDateTimeTZ_CheckExact(datetimetz)) {
5010 PyErr_Format(PyExc_TypeError,
5011 "bad type passed to datetimetz pickler: %s",
5012 datetimetz->ob_type->tp_name);
5013 return NULL;
5014 }
5015 state = datetimetz_getstate(datetimetz);
5016 if (state) {
5017 result = Py_BuildValue("O(O)",
5018 datetimetz_unpickler_object,
5019 state);
5020 Py_DECREF(state);
5021 }
5022 return result;
5023}
5024
5025static PyObject *
5026datetimetz_unpickler(PyObject *module, PyObject *arg)
5027{
5028 PyDateTime_DateTimeTZ *self;
5029
5030 self = PyObject_New(PyDateTime_DateTimeTZ, &PyDateTime_DateTimeTZType);
5031 if (self != NULL) {
5032 PyObject *res;
5033
5034 self->tzinfo = NULL;
5035 res = datetimetz_setstate(self, arg);
5036 if (res == NULL) {
5037 Py_DECREF(self);
5038 return NULL;
5039 }
5040 Py_DECREF(res);
5041 }
5042 return (PyObject *)self;
5043}
5044
5045
5046static PyMethodDef datetimetz_methods[] = {
5047 /* Class methods: */
5048 /* Inherited: combine(), utcnow(), utcfromtimestamp() */
5049
5050 {"now", (PyCFunction)datetimetz_now,
5051 METH_KEYWORDS | METH_CLASS,
5052 PyDoc_STR("[tzinfo] -> new datetimetz with local day and time.")},
5053
5054 {"fromtimestamp", (PyCFunction)datetimetz_fromtimestamp,
5055 METH_KEYWORDS | METH_CLASS,
5056 PyDoc_STR("timestamp[, tzinfo] -> local time from POSIX timestamp.")},
5057
5058 /* Instance methods: */
5059 /* Inherited: date(), time(), ctime(). */
5060 {"timetuple", (PyCFunction)datetimetz_timetuple, METH_NOARGS,
5061 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
5062
5063 {"utctimetuple", (PyCFunction)datetimetz_utctimetuple, METH_NOARGS,
5064 PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")},
5065
5066 {"timetz", (PyCFunction)datetimetz_gettimetz, METH_NOARGS,
5067 PyDoc_STR("Return timetz object with same hour, minute, second, "
5068 "microsecond, and tzinfo.")},
5069
5070 {"isoformat", (PyCFunction)datetimetz_isoformat, METH_KEYWORDS,
5071 PyDoc_STR("[sep] -> string in ISO 8601 format, "
5072 "YYYY-MM-DDTHH:MM:SS[.mmmmmm][+HH:MM].\n\n"
5073 "sep is used to separate the year from the time, and "
5074 "defaults to 'T'.")},
5075
5076 {"utcoffset", (PyCFunction)datetimetz_utcoffset, METH_NOARGS,
5077 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
5078
5079 {"tzname", (PyCFunction)datetimetz_tzname, METH_NOARGS,
5080 PyDoc_STR("Return self.tzinfo.tzname(self).")},
5081
5082 {"dst", (PyCFunction)datetimetz_dst, METH_NOARGS,
5083 PyDoc_STR("Return self.tzinfo.dst(self).")},
5084
Tim Peters12bf3392002-12-24 05:41:27 +00005085 {"replace", (PyCFunction)datetimetz_replace, METH_KEYWORDS,
5086 PyDoc_STR("Return datetimetz with new specified fields.")},
5087
Tim Peters80475bb2002-12-25 07:40:55 +00005088 {"astimezone", (PyCFunction)datetimetz_astimezone, METH_KEYWORDS,
5089 PyDoc_STR("tz -> convert to local time in new timezone tz\n")},
5090
Tim Peters2a799bf2002-12-16 20:18:38 +00005091 {"__setstate__", (PyCFunction)datetimetz_setstate, METH_O,
5092 PyDoc_STR("__setstate__(state)")},
5093
5094 {"__getstate__", (PyCFunction)datetimetz_getstate, METH_NOARGS,
5095 PyDoc_STR("__getstate__() -> state")},
5096 {NULL, NULL}
5097};
5098
5099static char datetimetz_doc[] =
5100PyDoc_STR("date/time type.");
5101
5102static PyNumberMethods datetimetz_as_number = {
5103 datetimetz_add, /* nb_add */
5104 datetimetz_subtract, /* nb_subtract */
5105 0, /* nb_multiply */
5106 0, /* nb_divide */
5107 0, /* nb_remainder */
5108 0, /* nb_divmod */
5109 0, /* nb_power */
5110 0, /* nb_negative */
5111 0, /* nb_positive */
5112 0, /* nb_absolute */
5113 0, /* nb_nonzero */
5114};
5115
5116statichere PyTypeObject PyDateTime_DateTimeTZType = {
5117 PyObject_HEAD_INIT(NULL)
5118 0, /* ob_size */
5119 "datetime.datetimetz", /* tp_name */
5120 sizeof(PyDateTime_DateTimeTZ), /* tp_basicsize */
5121 0, /* tp_itemsize */
5122 (destructor)datetimetz_dealloc, /* tp_dealloc */
5123 0, /* tp_print */
5124 0, /* tp_getattr */
5125 0, /* tp_setattr */
5126 0, /* tp_compare */
5127 (reprfunc)datetimetz_repr, /* tp_repr */
5128 &datetimetz_as_number, /* tp_as_number */
5129 0, /* tp_as_sequence */
5130 0, /* tp_as_mapping */
5131 0, /* tp_hash */
5132 0, /* tp_call */
5133 0, /* tp_str */
5134 PyObject_GenericGetAttr, /* tp_getattro */
5135 0, /* tp_setattro */
5136 0, /* tp_as_buffer */
5137 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
5138 Py_TPFLAGS_BASETYPE, /* tp_flags */
5139 datetimetz_doc, /* tp_doc */
5140 0, /* tp_traverse */
5141 0, /* tp_clear */
5142 0, /* tp_richcompare */
5143 0, /* tp_weaklistoffset */
5144 0, /* tp_iter */
5145 0, /* tp_iternext */
5146 datetimetz_methods, /* tp_methods */
5147 0, /* tp_members */
5148 datetimetz_getset, /* tp_getset */
5149 &PyDateTime_DateTimeType, /* tp_base */
5150 0, /* tp_dict */
5151 0, /* tp_descr_get */
5152 0, /* tp_descr_set */
5153 0, /* tp_dictoffset */
5154 0, /* tp_init */
5155 0, /* tp_alloc */
5156 datetimetz_new, /* tp_new */
5157 _PyObject_Del, /* tp_free */
5158};
5159
5160/* ---------------------------------------------------------------------------
5161 * Module methods and initialization.
5162 */
5163
5164static PyMethodDef module_methods[] = {
5165 /* Private functions for pickling support, registered with the
5166 * copy_reg module by the module init function.
5167 */
5168 {"_date_pickler", (PyCFunction)date_pickler, METH_O, NULL},
5169 {"_date_unpickler", (PyCFunction)date_unpickler, METH_O, NULL},
5170 {"_datetime_pickler", (PyCFunction)datetime_pickler, METH_O, NULL},
5171 {"_datetime_unpickler", (PyCFunction)datetime_unpickler,METH_O, NULL},
5172 {"_datetimetz_pickler", (PyCFunction)datetimetz_pickler,METH_O, NULL},
5173 {"_datetimetz_unpickler",(PyCFunction)datetimetz_unpickler,METH_O, NULL},
5174 {"_time_pickler", (PyCFunction)time_pickler, METH_O, NULL},
5175 {"_time_unpickler", (PyCFunction)time_unpickler, METH_O, NULL},
5176 {"_timetz_pickler", (PyCFunction)timetz_pickler, METH_O, NULL},
5177 {"_timetz_unpickler", (PyCFunction)timetz_unpickler, METH_O, NULL},
5178 {"_tzinfo_pickler", (PyCFunction)tzinfo_pickler, METH_O, NULL},
5179 {"_tzinfo_unpickler", (PyCFunction)tzinfo_unpickler, METH_NOARGS,
5180 NULL},
5181 {NULL, NULL}
5182};
5183
5184PyMODINIT_FUNC
5185initdatetime(void)
5186{
5187 PyObject *m; /* a module object */
5188 PyObject *d; /* its dict */
5189 PyObject *x;
5190
5191 /* Types that use __reduce__ for pickling need to set the following
5192 * magical attr in the type dict, with a true value.
5193 */
5194 PyObject *safepickle = PyString_FromString("__safe_for_unpickling__");
5195 if (safepickle == NULL)
5196 return;
5197
5198 m = Py_InitModule3("datetime", module_methods,
5199 "Fast implementation of the datetime type.");
5200
5201 if (PyType_Ready(&PyDateTime_DateType) < 0)
5202 return;
5203 if (PyType_Ready(&PyDateTime_DateTimeType) < 0)
5204 return;
5205 if (PyType_Ready(&PyDateTime_DeltaType) < 0)
5206 return;
5207 if (PyType_Ready(&PyDateTime_TimeType) < 0)
5208 return;
5209 if (PyType_Ready(&PyDateTime_TZInfoType) < 0)
5210 return;
5211 if (PyType_Ready(&PyDateTime_TimeTZType) < 0)
5212 return;
5213 if (PyType_Ready(&PyDateTime_DateTimeTZType) < 0)
5214 return;
5215
5216 /* Pickling support, via registering functions with copy_reg. */
5217 {
5218 PyObject *pickler;
5219 PyObject *copyreg = PyImport_ImportModule("copy_reg");
5220
5221 if (copyreg == NULL) return;
5222
5223 pickler = PyObject_GetAttrString(m, "_date_pickler");
5224 if (pickler == NULL) return;
5225 date_unpickler_object = PyObject_GetAttrString(m,
5226 "_date_unpickler");
5227 if (date_unpickler_object == NULL) return;
5228 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5229 &PyDateTime_DateType,
5230 pickler,
5231 date_unpickler_object);
5232 if (x == NULL) return;
5233 Py_DECREF(x);
5234 Py_DECREF(pickler);
5235
5236 pickler = PyObject_GetAttrString(m, "_datetime_pickler");
5237 if (pickler == NULL) return;
5238 datetime_unpickler_object = PyObject_GetAttrString(m,
5239 "_datetime_unpickler");
5240 if (datetime_unpickler_object == NULL) return;
5241 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5242 &PyDateTime_DateTimeType,
5243 pickler,
5244 datetime_unpickler_object);
5245 if (x == NULL) return;
5246 Py_DECREF(x);
5247 Py_DECREF(pickler);
5248
5249 pickler = PyObject_GetAttrString(m, "_time_pickler");
5250 if (pickler == NULL) return;
5251 time_unpickler_object = PyObject_GetAttrString(m,
5252 "_time_unpickler");
5253 if (time_unpickler_object == NULL) return;
5254 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5255 &PyDateTime_TimeType,
5256 pickler,
5257 time_unpickler_object);
5258 if (x == NULL) return;
5259 Py_DECREF(x);
5260 Py_DECREF(pickler);
5261
5262 pickler = PyObject_GetAttrString(m, "_timetz_pickler");
5263 if (pickler == NULL) return;
5264 timetz_unpickler_object = PyObject_GetAttrString(m,
5265 "_timetz_unpickler");
5266 if (timetz_unpickler_object == NULL) return;
5267 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5268 &PyDateTime_TimeTZType,
5269 pickler,
5270 timetz_unpickler_object);
5271 if (x == NULL) return;
5272 Py_DECREF(x);
5273 Py_DECREF(pickler);
5274
5275 pickler = PyObject_GetAttrString(m, "_tzinfo_pickler");
5276 if (pickler == NULL) return;
5277 tzinfo_unpickler_object = PyObject_GetAttrString(m,
5278 "_tzinfo_unpickler");
5279 if (tzinfo_unpickler_object == NULL) return;
5280 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5281 &PyDateTime_TZInfoType,
5282 pickler,
5283 tzinfo_unpickler_object);
5284 if (x== NULL) return;
5285 Py_DECREF(x);
5286 Py_DECREF(pickler);
5287
5288 pickler = PyObject_GetAttrString(m, "_datetimetz_pickler");
5289 if (pickler == NULL) return;
5290 datetimetz_unpickler_object = PyObject_GetAttrString(m,
5291 "_datetimetz_unpickler");
5292 if (datetimetz_unpickler_object == NULL) return;
5293 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5294 &PyDateTime_DateTimeTZType,
5295 pickler,
5296 datetimetz_unpickler_object);
5297 if (x== NULL) return;
5298 Py_DECREF(x);
5299 Py_DECREF(pickler);
5300
5301 Py_DECREF(copyreg);
5302 }
5303
5304 /* timedelta values */
5305 d = PyDateTime_DeltaType.tp_dict;
5306
5307 if (PyDict_SetItem(d, safepickle, Py_True) < 0)
5308 return;
5309
5310 x = new_delta(0, 0, 1, 0);
5311 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5312 return;
5313 Py_DECREF(x);
5314
5315 x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0);
5316 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5317 return;
5318 Py_DECREF(x);
5319
5320 x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0);
5321 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5322 return;
5323 Py_DECREF(x);
5324
5325 /* date values */
5326 d = PyDateTime_DateType.tp_dict;
5327
5328 x = new_date(1, 1, 1);
5329 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5330 return;
5331 Py_DECREF(x);
5332
5333 x = new_date(MAXYEAR, 12, 31);
5334 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5335 return;
5336 Py_DECREF(x);
5337
5338 x = new_delta(1, 0, 0, 0);
5339 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5340 return;
5341 Py_DECREF(x);
5342
5343 /* datetime values */
5344 d = PyDateTime_DateTimeType.tp_dict;
5345
5346 x = new_datetime(1, 1, 1, 0, 0, 0, 0);
5347 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5348 return;
5349 Py_DECREF(x);
5350
5351 x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999);
5352 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5353 return;
5354 Py_DECREF(x);
5355
5356 x = new_delta(0, 0, 1, 0);
5357 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5358 return;
5359 Py_DECREF(x);
5360
5361 /* time values */
5362 d = PyDateTime_TimeType.tp_dict;
5363
5364 x = new_time(0, 0, 0, 0);
5365 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5366 return;
5367 Py_DECREF(x);
5368
5369 x = new_time(23, 59, 59, 999999);
5370 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5371 return;
5372 Py_DECREF(x);
5373
5374 x = new_delta(0, 0, 1, 0);
5375 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5376 return;
5377 Py_DECREF(x);
5378
5379 /* timetz values */
5380 d = PyDateTime_TimeTZType.tp_dict;
5381
5382 x = new_timetz(0, 0, 0, 0, Py_None);
5383 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5384 return;
5385 Py_DECREF(x);
5386
5387 x = new_timetz(23, 59, 59, 999999, Py_None);
5388 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5389 return;
5390 Py_DECREF(x);
5391
5392 x = new_delta(0, 0, 1, 0);
5393 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5394 return;
5395 Py_DECREF(x);
5396
5397 /* datetimetz values */
5398 d = PyDateTime_DateTimeTZType.tp_dict;
5399
5400 x = new_datetimetz(1, 1, 1, 0, 0, 0, 0, Py_None);
5401 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5402 return;
5403 Py_DECREF(x);
5404
5405 x = new_datetimetz(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None);
5406 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5407 return;
5408 Py_DECREF(x);
5409
5410 x = new_delta(0, 0, 1, 0);
5411 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5412 return;
5413 Py_DECREF(x);
5414
5415 Py_DECREF(safepickle);
5416
5417 /* module initialization */
5418 PyModule_AddIntConstant(m, "MINYEAR", MINYEAR);
5419 PyModule_AddIntConstant(m, "MAXYEAR", MAXYEAR);
5420
5421 Py_INCREF(&PyDateTime_DateType);
5422 PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType);
5423
5424 Py_INCREF(&PyDateTime_DateTimeType);
5425 PyModule_AddObject(m, "datetime",
5426 (PyObject *) &PyDateTime_DateTimeType);
5427
5428 Py_INCREF(&PyDateTime_DeltaType);
5429 PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType);
5430
5431 Py_INCREF(&PyDateTime_TimeType);
5432 PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType);
5433
5434 Py_INCREF(&PyDateTime_TZInfoType);
5435 PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
5436
5437 Py_INCREF(&PyDateTime_TimeTZType);
5438 PyModule_AddObject(m, "timetz", (PyObject *) &PyDateTime_TimeTZType);
5439
5440 Py_INCREF(&PyDateTime_DateTimeTZType);
5441 PyModule_AddObject(m, "datetimetz",
5442 (PyObject *)&PyDateTime_DateTimeTZType);
5443
5444 /* A 4-year cycle has an extra leap day over what we'd get from
5445 * pasting together 4 single years.
5446 */
5447 assert(DI4Y == 4 * 365 + 1);
5448 assert(DI4Y == days_before_year(4+1));
5449
5450 /* Similarly, a 400-year cycle has an extra leap day over what we'd
5451 * get from pasting together 4 100-year cycles.
5452 */
5453 assert(DI400Y == 4 * DI100Y + 1);
5454 assert(DI400Y == days_before_year(400+1));
5455
5456 /* OTOH, a 100-year cycle has one fewer leap day than we'd get from
5457 * pasting together 25 4-year cycles.
5458 */
5459 assert(DI100Y == 25 * DI4Y - 1);
5460 assert(DI100Y == days_before_year(100+1));
5461
5462 us_per_us = PyInt_FromLong(1);
5463 us_per_ms = PyInt_FromLong(1000);
5464 us_per_second = PyInt_FromLong(1000000);
5465 us_per_minute = PyInt_FromLong(60000000);
5466 seconds_per_day = PyInt_FromLong(24 * 3600);
5467 if (us_per_us == NULL || us_per_ms == NULL || us_per_second == NULL ||
5468 us_per_minute == NULL || seconds_per_day == NULL)
5469 return;
5470
5471 /* The rest are too big for 32-bit ints, but even
5472 * us_per_week fits in 40 bits, so doubles should be exact.
5473 */
5474 us_per_hour = PyLong_FromDouble(3600000000.0);
5475 us_per_day = PyLong_FromDouble(86400000000.0);
5476 us_per_week = PyLong_FromDouble(604800000000.0);
5477 if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL)
5478 return;
5479}
Tim Petersf3615152003-01-01 21:51:37 +00005480
5481/* ---------------------------------------------------------------------------
5482Some time zone algebra. For a datetimetz x, let
5483 x.n = x stripped of its timezone -- its naive time.
5484 x.o = x.utcoffset(), and assuming that doesn't raise an exception or
5485 return None
5486 x.d = x.dst(), and assuming that doesn't raise an exception or
5487 return None
5488 x.s = x's standard offset, x.o - x.d
5489
5490Now some derived rules, where k is a duration (timedelta).
5491
54921. x.o = x.s + x.d
5493 This follows from the definition of x.s.
5494
Tim Petersc5dc4da2003-01-02 17:55:03 +000054952. If x and y have the same tzinfo member, x.s = y.s.
Tim Petersf3615152003-01-01 21:51:37 +00005496 This is actually a requirement, an assumption we need to make about
5497 sane tzinfo classes.
5498
54993. The naive UTC time corresponding to x is x.n - x.o.
5500 This is again a requirement for a sane tzinfo class.
5501
55024. (x+k).s = x.s
5503 This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
5504
Tim Petersc5dc4da2003-01-02 17:55:03 +000055055. (x+k).n = x.n + k
Tim Petersf3615152003-01-01 21:51:37 +00005506 Again follows from how arithmetic is defined.
5507
5508Now we can explain x.astimezone(tz). Let's assume it's an interesting case
5509(meaning that the various tzinfo methods exist, and don't blow up or return
5510None when called).
5511
5512The function wants to return a datetimetz y with timezone tz, equivalent to x.
5513
5514By #3, we want
5515
5516 y.n - y.o = x.n - x.o [1]
5517
5518The algorithm starts by attaching tz to x.n, and calling that y. So
5519x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
5520becomes true; in effect, we want to solve [2] for k:
5521
5522 (y+k).n - (y+k).o = x.n - x.o [2]
5523
5524By #1, this is the same as
5525
5526 (y+k).n - ((y+k).s + (y+k).d) = x.n - x.o [3]
5527
5528By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
5529Substituting that into [3],
5530
5531 x.n + k - (y+k).s - (y+k).d = x.n - x.o; the x.n terms cancel, leaving
5532 k - (y+k).s - (y+k).d = - x.o; rearranging,
5533 k = (y+k).s - x.o - (y+k).d; by #4, (y+k).s == y.s, so
5534 k = y.s - x.o - (y+k).d; then by #1, y.s = y.o - y.d, so
5535 k = y.o - y.d - x.o - (y+k).d
5536
5537On the RHS, (y+k).d can't be computed directly, but all the rest can be, and
5538we approximate k by ignoring the (y+k).d term at first. Note that k can't
5539be very large, since all offset-returning methods return a duration of
5540magnitude less than 24 hours. For that reason, if y is firmly in std time,
5541(y+k).d must be 0, so ignoring it has no consequence then.
5542
5543In any case, the new value is
5544
Tim Petersc5dc4da2003-01-02 17:55:03 +00005545 z = y + y.o - y.d - x.o [4]
Tim Petersf3615152003-01-01 21:51:37 +00005546
Tim Petersc5dc4da2003-01-02 17:55:03 +00005547It's helpful to step back at look at [4] from a higher level: rewrite it as
Tim Petersf3615152003-01-01 21:51:37 +00005548
Tim Petersc5dc4da2003-01-02 17:55:03 +00005549 z = (y - x.o) + (y.o - y.d)
5550
5551(y - x.o).n = [by #5] y.n - x.o = [since y.n=x.n] x.n - x.o = [by #3] x's
5552UTC equivalent time. So the y-x.o part essentially converts x to UTC. Then
5553the y.o-y.d part essentially converts x's UTC equivalent into tz's standard
5554time (y.o-y.d=y.s by #1).
5555
5556At this point, if
5557
5558 z.n - z.o = x.n - x.o [5]
5559
5560we have an equivalent time, and are almost done. The insecurity here is
Tim Petersf3615152003-01-01 21:51:37 +00005561at the start of daylight time. Picture US Eastern for concreteness. The wall
5562time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
5563sense then. A sensible Eastern tzinfo class will consider such a time to be
5564EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST on the
5565day DST starts. We want to return the 1:MM EST spelling because that's
5566the only spelling that makes sense on the local wall clock.
5567
Tim Petersc5dc4da2003-01-02 17:55:03 +00005568In fact, if [5] holds at this point, we do have the standard-time spelling,
5569but that takes a bit of proof. We first prove a stronger result. What's the
5570difference between the LHS and RHS of [5]? Let
Tim Petersf3615152003-01-01 21:51:37 +00005571
Tim Petersc5dc4da2003-01-02 17:55:03 +00005572 diff = (x.n - x.o) - (z.n - z.o) [6]
Tim Petersf3615152003-01-01 21:51:37 +00005573
Tim Petersc5dc4da2003-01-02 17:55:03 +00005574Now
5575 z.n = by [4]
5576 (y + y.o - y.d - x.o).n = by #5
5577 y.n + y.o - y.d - x.o = since y.n = x.n
5578 x.n + y.o - y.d - x.o = since y.o = y.s + y.d by #1
5579 x.n + (y.s + y.d) - y.d - x.o = cancelling the y.d terms
5580 x.n + y.s - x.o = since z and y are have the same tzinfo member,
5581 y.s = z.s by #2
5582 x.n + z.s - x.o
Tim Petersf3615152003-01-01 21:51:37 +00005583
Tim Petersc5dc4da2003-01-02 17:55:03 +00005584Plugging that back into [6] gives
Tim Petersf3615152003-01-01 21:51:37 +00005585
Tim Petersc5dc4da2003-01-02 17:55:03 +00005586 diff =
5587 (x.n - x.o) - ((x.n + z.s - x.o) - z.o) = expanding
5588 x.n - x.o - x.n - z.s + x.o + z.o = cancelling
5589 - z.s + z.o = by #2
5590 z.d
Tim Petersf3615152003-01-01 21:51:37 +00005591
Tim Petersc5dc4da2003-01-02 17:55:03 +00005592So diff = z.d.
Tim Petersf3615152003-01-01 21:51:37 +00005593
Tim Petersc5dc4da2003-01-02 17:55:03 +00005594If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
5595spelling we wanted in the endcase described above. We're done.
Tim Petersf3615152003-01-01 21:51:37 +00005596
Tim Petersc5dc4da2003-01-02 17:55:03 +00005597If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
5598add to z (in effect, z is in tz's standard time, and we need to shift the
5599offset into tz's daylight time).
Tim Petersf3615152003-01-01 21:51:37 +00005600
Tim Petersc5dc4da2003-01-02 17:55:03 +00005601Let
Tim Petersf3615152003-01-01 21:51:37 +00005602
Tim Peters4fede1a2003-01-04 00:26:59 +00005603 z' = z + z.d = z + diff [7]
Tim Petersc3bb26a2003-01-02 03:14:59 +00005604
Tim Peters4fede1a2003-01-04 00:26:59 +00005605and we can again ask whether
Tim Petersc3bb26a2003-01-02 03:14:59 +00005606
Tim Peters4fede1a2003-01-04 00:26:59 +00005607 z'.n - z'.o = x.n - x.o [8]
Tim Petersc3bb26a2003-01-02 03:14:59 +00005608
5609If so, we're done. If not, the tzinfo class is insane, or we're trying to
Tim Peters4fede1a2003-01-04 00:26:59 +00005610convert to the hour that can't be spelled in tz. This also requires a
5611bit of proof. As before, let's compute the difference between the LHS and
5612RHS of [8] (and skipping some of the justifications for the kinds of
5613substitutions we've done several times already):
5614
5615 diff' = (x.n - x.o) - (z'.n - z'.o) = replacing z'.n via [7]
5616 (x.n - x.o) - (z.n + diff - z'.o) = replacing diff via [6]
5617 (x.n - x.o) - (z.n + (x.n - x.o) - (z.n - z.o) - z'.o) =
5618 x.n - x.o - z.n - x.n + x.o + z.n - z.o + z'.o = cancel x.n
5619 - x.o - z.n + x.o + z.n - z.o + z'.o = cancel x.o
5620 - z.n + z.n - z.o + z'.o = cancel z.n
5621 - z.o + z'.o = #1 twice
5622 -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
5623 z'.d - z.d
5624
5625So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
5626we've found the UTC-equivalent so are done.
5627
5628How could they differ? z' = z + z.d [7], so merely moving z' by a dst()
5629offset, and starting *from* a time already in DST (we know z.d != 0), would
5630have to change the result dst() returns: we start in DST, and moving a
5631little further into it takes us out of DST.
5632
5633There's (only) one sane case where this can happen: at the end of DST,
5634there's an hour in UTC with no spelling in a hybrid tzinfo class. In US
5635Eastern, that's 6:MM UTC = 1:MM EST = 2:MM EDT. During that hour, on an
5636Eastern clock 1:MM is taken as being in daylight time (5:MM UTC), but 2:MM is
5637taken as being in standard time (7:MM UTC). There is no local time mapping to
56386:MM UTC. The local clock jumps from 1:59 back to 1:00 again, and repeats the
56391:MM hour in standard time. Since that's what the local clock *does*, we want
5640to map both UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
5641in local time, but so it goes -- it's the way the local clock works.
5642
5643When x = 6:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
5644so z=1:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
5645z' = z + z.d = 2:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
5646(correctly) concludes that z' is not UTC-equivalent to x.
5647
5648Because we know z.d said z was in daylight time (else [5] would have held and
5649we would have stopped then), and we know z.d != z'.d (else [8] would have held
5650and we we have stopped then), and there are only 2 possible values dst() can
5651return in Eastern, it follows that z'.d must be 0 (which it is in the example,
5652but the reasoning doesn't depend on the example -- it depends on there being
5653two possible dst() outcomes, one zero and the other non-zero). Therefore
5654z' must be in standard time, and is not the spelling we want in this case.
5655z is in daylight time, and is the spelling we want. Note again that z is
5656not UTC-equivalent as far as the hybrid tzinfo class is concerned (because
5657it takes z as being in standard time rather than the daylight time we intend
5658here), but returning it gives the real-life "local clock repeats an hour"
5659behavior when mapping the "unspellable" UTC hour into tz.
Tim Petersf3615152003-01-01 21:51:37 +00005660--------------------------------------------------------------------------- */