blob: 642c11f9ed8b56e035fd9bc9be9bf02831e92f83 [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);
Tim Peters33e0f382003-01-10 02:05:14 +0000624 Py_XDECREF(((PyDateTime_DateTimeTZ *)self)->tzinfo);
Tim Peters80475bb2002-12-25 07:40:55 +0000625 ((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,
Neal Norwitz506a2242003-01-04 01:02:25 +0000686 "tzinfo.%s() returned %d; must be in "
Tim Peters2a799bf2002-12-16 20:18:38 +0000687 "-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;
Tim Peters2a799bf2002-12-16 20:18:38 +00001402static PyObject *datetimetz_unpickler_object = NULL;
1403static PyObject *tzinfo_unpickler_object = NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00001404static PyObject *timetz_unpickler_object = NULL;
1405
1406/* ---------------------------------------------------------------------------
1407 * Class implementations.
1408 */
1409
1410/*
1411 * PyDateTime_Delta implementation.
1412 */
1413
1414/* Convert a timedelta to a number of us,
1415 * (24*3600*self.days + self.seconds)*1000000 + self.microseconds
1416 * as a Python int or long.
1417 * Doing mixed-radix arithmetic by hand instead is excruciating in C,
1418 * due to ubiquitous overflow possibilities.
1419 */
1420static PyObject *
1421delta_to_microseconds(PyDateTime_Delta *self)
1422{
1423 PyObject *x1 = NULL;
1424 PyObject *x2 = NULL;
1425 PyObject *x3 = NULL;
1426 PyObject *result = NULL;
1427
1428 x1 = PyInt_FromLong(GET_TD_DAYS(self));
1429 if (x1 == NULL)
1430 goto Done;
1431 x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */
1432 if (x2 == NULL)
1433 goto Done;
1434 Py_DECREF(x1);
1435 x1 = NULL;
1436
1437 /* x2 has days in seconds */
1438 x1 = PyInt_FromLong(GET_TD_SECONDS(self)); /* seconds */
1439 if (x1 == NULL)
1440 goto Done;
1441 x3 = PyNumber_Add(x1, x2); /* days and seconds in seconds */
1442 if (x3 == NULL)
1443 goto Done;
1444 Py_DECREF(x1);
1445 Py_DECREF(x2);
1446 x1 = x2 = NULL;
1447
1448 /* x3 has days+seconds in seconds */
1449 x1 = PyNumber_Multiply(x3, us_per_second); /* us */
1450 if (x1 == NULL)
1451 goto Done;
1452 Py_DECREF(x3);
1453 x3 = NULL;
1454
1455 /* x1 has days+seconds in us */
1456 x2 = PyInt_FromLong(GET_TD_MICROSECONDS(self));
1457 if (x2 == NULL)
1458 goto Done;
1459 result = PyNumber_Add(x1, x2);
1460
1461Done:
1462 Py_XDECREF(x1);
1463 Py_XDECREF(x2);
1464 Py_XDECREF(x3);
1465 return result;
1466}
1467
1468/* Convert a number of us (as a Python int or long) to a timedelta.
1469 */
1470static PyObject *
1471microseconds_to_delta(PyObject *pyus)
1472{
1473 int us;
1474 int s;
1475 int d;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001476 long temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001477
1478 PyObject *tuple = NULL;
1479 PyObject *num = NULL;
1480 PyObject *result = NULL;
1481
1482 tuple = PyNumber_Divmod(pyus, us_per_second);
1483 if (tuple == NULL)
1484 goto Done;
1485
1486 num = PyTuple_GetItem(tuple, 1); /* us */
1487 if (num == NULL)
1488 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001489 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001490 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001491 if (temp == -1 && PyErr_Occurred())
1492 goto Done;
1493 assert(0 <= temp && temp < 1000000);
1494 us = (int)temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001495 if (us < 0) {
1496 /* The divisor was positive, so this must be an error. */
1497 assert(PyErr_Occurred());
1498 goto Done;
1499 }
1500
1501 num = PyTuple_GetItem(tuple, 0); /* leftover seconds */
1502 if (num == NULL)
1503 goto Done;
1504 Py_INCREF(num);
1505 Py_DECREF(tuple);
1506
1507 tuple = PyNumber_Divmod(num, seconds_per_day);
1508 if (tuple == NULL)
1509 goto Done;
1510 Py_DECREF(num);
1511
1512 num = PyTuple_GetItem(tuple, 1); /* seconds */
1513 if (num == NULL)
1514 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001515 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001516 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001517 if (temp == -1 && PyErr_Occurred())
1518 goto Done;
1519 assert(0 <= temp && temp < 24*3600);
1520 s = (int)temp;
1521
Tim Peters2a799bf2002-12-16 20:18:38 +00001522 if (s < 0) {
1523 /* The divisor was positive, so this must be an error. */
1524 assert(PyErr_Occurred());
1525 goto Done;
1526 }
1527
1528 num = PyTuple_GetItem(tuple, 0); /* leftover days */
1529 if (num == NULL)
1530 goto Done;
1531 Py_INCREF(num);
Tim Peters0b0f41c2002-12-19 01:44:38 +00001532 temp = PyLong_AsLong(num);
1533 if (temp == -1 && PyErr_Occurred())
Tim Peters2a799bf2002-12-16 20:18:38 +00001534 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001535 d = (int)temp;
1536 if ((long)d != temp) {
1537 PyErr_SetString(PyExc_OverflowError, "normalized days too "
1538 "large to fit in a C int");
1539 goto Done;
1540 }
Tim Peters2a799bf2002-12-16 20:18:38 +00001541 result = new_delta(d, s, us, 0);
1542
1543Done:
1544 Py_XDECREF(tuple);
1545 Py_XDECREF(num);
1546 return result;
1547}
1548
1549static PyObject *
1550multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
1551{
1552 PyObject *pyus_in;
1553 PyObject *pyus_out;
1554 PyObject *result;
1555
1556 pyus_in = delta_to_microseconds(delta);
1557 if (pyus_in == NULL)
1558 return NULL;
1559
1560 pyus_out = PyNumber_Multiply(pyus_in, intobj);
1561 Py_DECREF(pyus_in);
1562 if (pyus_out == NULL)
1563 return NULL;
1564
1565 result = microseconds_to_delta(pyus_out);
1566 Py_DECREF(pyus_out);
1567 return result;
1568}
1569
1570static PyObject *
1571divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj)
1572{
1573 PyObject *pyus_in;
1574 PyObject *pyus_out;
1575 PyObject *result;
1576
1577 pyus_in = delta_to_microseconds(delta);
1578 if (pyus_in == NULL)
1579 return NULL;
1580
1581 pyus_out = PyNumber_FloorDivide(pyus_in, intobj);
1582 Py_DECREF(pyus_in);
1583 if (pyus_out == NULL)
1584 return NULL;
1585
1586 result = microseconds_to_delta(pyus_out);
1587 Py_DECREF(pyus_out);
1588 return result;
1589}
1590
1591static PyObject *
1592delta_add(PyObject *left, PyObject *right)
1593{
1594 PyObject *result = Py_NotImplemented;
1595
1596 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1597 /* delta + delta */
1598 /* The C-level additions can't overflow because of the
1599 * invariant bounds.
1600 */
1601 int days = GET_TD_DAYS(left) + GET_TD_DAYS(right);
1602 int seconds = GET_TD_SECONDS(left) + GET_TD_SECONDS(right);
1603 int microseconds = GET_TD_MICROSECONDS(left) +
1604 GET_TD_MICROSECONDS(right);
1605 result = new_delta(days, seconds, microseconds, 1);
1606 }
1607
1608 if (result == Py_NotImplemented)
1609 Py_INCREF(result);
1610 return result;
1611}
1612
1613static PyObject *
1614delta_negative(PyDateTime_Delta *self)
1615{
1616 return new_delta(-GET_TD_DAYS(self),
1617 -GET_TD_SECONDS(self),
1618 -GET_TD_MICROSECONDS(self),
1619 1);
1620}
1621
1622static PyObject *
1623delta_positive(PyDateTime_Delta *self)
1624{
1625 /* Could optimize this (by returning self) if this isn't a
1626 * subclass -- but who uses unary + ? Approximately nobody.
1627 */
1628 return new_delta(GET_TD_DAYS(self),
1629 GET_TD_SECONDS(self),
1630 GET_TD_MICROSECONDS(self),
1631 0);
1632}
1633
1634static PyObject *
1635delta_abs(PyDateTime_Delta *self)
1636{
1637 PyObject *result;
1638
1639 assert(GET_TD_MICROSECONDS(self) >= 0);
1640 assert(GET_TD_SECONDS(self) >= 0);
1641
1642 if (GET_TD_DAYS(self) < 0)
1643 result = delta_negative(self);
1644 else
1645 result = delta_positive(self);
1646
1647 return result;
1648}
1649
1650static PyObject *
1651delta_subtract(PyObject *left, PyObject *right)
1652{
1653 PyObject *result = Py_NotImplemented;
1654
1655 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1656 /* delta - delta */
1657 PyObject *minus_right = PyNumber_Negative(right);
1658 if (minus_right) {
1659 result = delta_add(left, minus_right);
1660 Py_DECREF(minus_right);
1661 }
1662 else
1663 result = NULL;
1664 }
1665
1666 if (result == Py_NotImplemented)
1667 Py_INCREF(result);
1668 return result;
1669}
1670
1671/* This is more natural as a tp_compare, but doesn't work then: for whatever
1672 * reason, Python's try_3way_compare ignores tp_compare unless
1673 * PyInstance_Check returns true, but these aren't old-style classes.
1674 */
1675static PyObject *
1676delta_richcompare(PyDateTime_Delta *self, PyObject *other, int op)
1677{
1678 int diff;
1679
1680 if (! PyDelta_CheckExact(other)) {
1681 PyErr_Format(PyExc_TypeError,
1682 "can't compare %s to %s instance",
1683 self->ob_type->tp_name, other->ob_type->tp_name);
1684 return NULL;
1685 }
1686 diff = GET_TD_DAYS(self) - GET_TD_DAYS(other);
1687 if (diff == 0) {
1688 diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other);
1689 if (diff == 0)
1690 diff = GET_TD_MICROSECONDS(self) -
1691 GET_TD_MICROSECONDS(other);
1692 }
1693 return diff_to_bool(diff, op);
1694}
1695
1696static PyObject *delta_getstate(PyDateTime_Delta *self);
1697
1698static long
1699delta_hash(PyDateTime_Delta *self)
1700{
1701 if (self->hashcode == -1) {
1702 PyObject *temp = delta_getstate(self);
1703 if (temp != NULL) {
1704 self->hashcode = PyObject_Hash(temp);
1705 Py_DECREF(temp);
1706 }
1707 }
1708 return self->hashcode;
1709}
1710
1711static PyObject *
1712delta_multiply(PyObject *left, PyObject *right)
1713{
1714 PyObject *result = Py_NotImplemented;
1715
1716 if (PyDelta_Check(left)) {
1717 /* delta * ??? */
1718 if (PyInt_Check(right) || PyLong_Check(right))
1719 result = multiply_int_timedelta(right,
1720 (PyDateTime_Delta *) left);
1721 }
1722 else if (PyInt_Check(left) || PyLong_Check(left))
1723 result = multiply_int_timedelta(left,
1724 (PyDateTime_Delta *) right);
1725
1726 if (result == Py_NotImplemented)
1727 Py_INCREF(result);
1728 return result;
1729}
1730
1731static PyObject *
1732delta_divide(PyObject *left, PyObject *right)
1733{
1734 PyObject *result = Py_NotImplemented;
1735
1736 if (PyDelta_Check(left)) {
1737 /* delta * ??? */
1738 if (PyInt_Check(right) || PyLong_Check(right))
1739 result = divide_timedelta_int(
1740 (PyDateTime_Delta *)left,
1741 right);
1742 }
1743
1744 if (result == Py_NotImplemented)
1745 Py_INCREF(result);
1746 return result;
1747}
1748
1749/* Fold in the value of the tag ("seconds", "weeks", etc) component of a
1750 * timedelta constructor. sofar is the # of microseconds accounted for
1751 * so far, and there are factor microseconds per current unit, the number
1752 * of which is given by num. num * factor is added to sofar in a
1753 * numerically careful way, and that's the result. Any fractional
1754 * microseconds left over (this can happen if num is a float type) are
1755 * added into *leftover.
1756 * Note that there are many ways this can give an error (NULL) return.
1757 */
1758static PyObject *
1759accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
1760 double *leftover)
1761{
1762 PyObject *prod;
1763 PyObject *sum;
1764
1765 assert(num != NULL);
1766
1767 if (PyInt_Check(num) || PyLong_Check(num)) {
1768 prod = PyNumber_Multiply(num, factor);
1769 if (prod == NULL)
1770 return NULL;
1771 sum = PyNumber_Add(sofar, prod);
1772 Py_DECREF(prod);
1773 return sum;
1774 }
1775
1776 if (PyFloat_Check(num)) {
1777 double dnum;
1778 double fracpart;
1779 double intpart;
1780 PyObject *x;
1781 PyObject *y;
1782
1783 /* The Plan: decompose num into an integer part and a
1784 * fractional part, num = intpart + fracpart.
1785 * Then num * factor ==
1786 * intpart * factor + fracpart * factor
1787 * and the LHS can be computed exactly in long arithmetic.
1788 * The RHS is again broken into an int part and frac part.
1789 * and the frac part is added into *leftover.
1790 */
1791 dnum = PyFloat_AsDouble(num);
1792 if (dnum == -1.0 && PyErr_Occurred())
1793 return NULL;
1794 fracpart = modf(dnum, &intpart);
1795 x = PyLong_FromDouble(intpart);
1796 if (x == NULL)
1797 return NULL;
1798
1799 prod = PyNumber_Multiply(x, factor);
1800 Py_DECREF(x);
1801 if (prod == NULL)
1802 return NULL;
1803
1804 sum = PyNumber_Add(sofar, prod);
1805 Py_DECREF(prod);
1806 if (sum == NULL)
1807 return NULL;
1808
1809 if (fracpart == 0.0)
1810 return sum;
1811 /* So far we've lost no information. Dealing with the
1812 * fractional part requires float arithmetic, and may
1813 * lose a little info.
1814 */
1815 assert(PyInt_Check(factor) || PyLong_Check(factor));
1816 if (PyInt_Check(factor))
1817 dnum = (double)PyInt_AsLong(factor);
1818 else
1819 dnum = PyLong_AsDouble(factor);
1820
1821 dnum *= fracpart;
1822 fracpart = modf(dnum, &intpart);
1823 x = PyLong_FromDouble(intpart);
1824 if (x == NULL) {
1825 Py_DECREF(sum);
1826 return NULL;
1827 }
1828
1829 y = PyNumber_Add(sum, x);
1830 Py_DECREF(sum);
1831 Py_DECREF(x);
1832 *leftover += fracpart;
1833 return y;
1834 }
1835
1836 PyErr_Format(PyExc_TypeError,
1837 "unsupported type for timedelta %s component: %s",
1838 tag, num->ob_type->tp_name);
1839 return NULL;
1840}
1841
1842static PyObject *
1843delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1844{
1845 PyObject *self = NULL;
1846
1847 /* Argument objects. */
1848 PyObject *day = NULL;
1849 PyObject *second = NULL;
1850 PyObject *us = NULL;
1851 PyObject *ms = NULL;
1852 PyObject *minute = NULL;
1853 PyObject *hour = NULL;
1854 PyObject *week = NULL;
1855
1856 PyObject *x = NULL; /* running sum of microseconds */
1857 PyObject *y = NULL; /* temp sum of microseconds */
1858 double leftover_us = 0.0;
1859
1860 static char *keywords[] = {
1861 "days", "seconds", "microseconds", "milliseconds",
1862 "minutes", "hours", "weeks", NULL
1863 };
1864
1865 if (PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOO:__new__",
1866 keywords,
1867 &day, &second, &us,
1868 &ms, &minute, &hour, &week) == 0)
1869 goto Done;
1870
1871 x = PyInt_FromLong(0);
1872 if (x == NULL)
1873 goto Done;
1874
1875#define CLEANUP \
1876 Py_DECREF(x); \
1877 x = y; \
1878 if (x == NULL) \
1879 goto Done
1880
1881 if (us) {
1882 y = accum("microseconds", x, us, us_per_us, &leftover_us);
1883 CLEANUP;
1884 }
1885 if (ms) {
1886 y = accum("milliseconds", x, ms, us_per_ms, &leftover_us);
1887 CLEANUP;
1888 }
1889 if (second) {
1890 y = accum("seconds", x, second, us_per_second, &leftover_us);
1891 CLEANUP;
1892 }
1893 if (minute) {
1894 y = accum("minutes", x, minute, us_per_minute, &leftover_us);
1895 CLEANUP;
1896 }
1897 if (hour) {
1898 y = accum("hours", x, hour, us_per_hour, &leftover_us);
1899 CLEANUP;
1900 }
1901 if (day) {
1902 y = accum("days", x, day, us_per_day, &leftover_us);
1903 CLEANUP;
1904 }
1905 if (week) {
1906 y = accum("weeks", x, week, us_per_week, &leftover_us);
1907 CLEANUP;
1908 }
1909 if (leftover_us) {
1910 /* Round to nearest whole # of us, and add into x. */
Tim Peters5d644dd2003-01-02 16:32:54 +00001911 PyObject *temp = PyLong_FromLong(round_to_long(leftover_us));
Tim Peters2a799bf2002-12-16 20:18:38 +00001912 if (temp == NULL) {
1913 Py_DECREF(x);
1914 goto Done;
1915 }
1916 y = PyNumber_Add(x, temp);
1917 Py_DECREF(temp);
1918 CLEANUP;
1919 }
1920
1921 self = microseconds_to_delta(x);
1922 Py_DECREF(x);
1923Done:
1924 return self;
1925
1926#undef CLEANUP
1927}
1928
1929static int
1930delta_nonzero(PyDateTime_Delta *self)
1931{
1932 return (GET_TD_DAYS(self) != 0
1933 || GET_TD_SECONDS(self) != 0
1934 || GET_TD_MICROSECONDS(self) != 0);
1935}
1936
1937static PyObject *
1938delta_repr(PyDateTime_Delta *self)
1939{
1940 if (GET_TD_MICROSECONDS(self) != 0)
1941 return PyString_FromFormat("%s(%d, %d, %d)",
1942 self->ob_type->tp_name,
1943 GET_TD_DAYS(self),
1944 GET_TD_SECONDS(self),
1945 GET_TD_MICROSECONDS(self));
1946 if (GET_TD_SECONDS(self) != 0)
1947 return PyString_FromFormat("%s(%d, %d)",
1948 self->ob_type->tp_name,
1949 GET_TD_DAYS(self),
1950 GET_TD_SECONDS(self));
1951
1952 return PyString_FromFormat("%s(%d)",
1953 self->ob_type->tp_name,
1954 GET_TD_DAYS(self));
1955}
1956
1957static PyObject *
1958delta_str(PyDateTime_Delta *self)
1959{
1960 int days = GET_TD_DAYS(self);
1961 int seconds = GET_TD_SECONDS(self);
1962 int us = GET_TD_MICROSECONDS(self);
1963 int hours;
1964 int minutes;
Tim Petersba873472002-12-18 20:19:21 +00001965 char buf[100];
1966 char *pbuf = buf;
1967 size_t buflen = sizeof(buf);
1968 int n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001969
1970 minutes = divmod(seconds, 60, &seconds);
1971 hours = divmod(minutes, 60, &minutes);
1972
1973 if (days) {
Tim Petersba873472002-12-18 20:19:21 +00001974 n = PyOS_snprintf(pbuf, buflen, "%d day%s, ", days,
1975 (days == 1 || days == -1) ? "" : "s");
1976 if (n < 0 || (size_t)n >= buflen)
1977 goto Fail;
1978 pbuf += n;
1979 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001980 }
1981
Tim Petersba873472002-12-18 20:19:21 +00001982 n = PyOS_snprintf(pbuf, buflen, "%d:%02d:%02d",
1983 hours, minutes, seconds);
1984 if (n < 0 || (size_t)n >= buflen)
1985 goto Fail;
1986 pbuf += n;
1987 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001988
1989 if (us) {
Tim Petersba873472002-12-18 20:19:21 +00001990 n = PyOS_snprintf(pbuf, buflen, ".%06d", us);
1991 if (n < 0 || (size_t)n >= buflen)
1992 goto Fail;
1993 pbuf += n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001994 }
1995
Tim Petersba873472002-12-18 20:19:21 +00001996 return PyString_FromStringAndSize(buf, pbuf - buf);
1997
1998 Fail:
1999 PyErr_SetString(PyExc_SystemError, "goofy result from PyOS_snprintf");
2000 return NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00002001}
2002
2003/* Pickle support. Quite a maze! While __getstate__/__setstate__ sufficed
2004 * in the Python implementation, the C implementation also requires
2005 * __reduce__, and a __safe_for_unpickling__ attr in the type object.
2006 */
2007static PyObject *
2008delta_getstate(PyDateTime_Delta *self)
2009{
2010 return Py_BuildValue("iii", GET_TD_DAYS(self),
2011 GET_TD_SECONDS(self),
2012 GET_TD_MICROSECONDS(self));
2013}
2014
2015static PyObject *
2016delta_setstate(PyDateTime_Delta *self, PyObject *state)
2017{
2018 int day;
2019 int second;
2020 int us;
2021
2022 if (!PyArg_ParseTuple(state, "iii:__setstate__", &day, &second, &us))
2023 return NULL;
2024
2025 self->hashcode = -1;
2026 SET_TD_DAYS(self, day);
2027 SET_TD_SECONDS(self, second);
2028 SET_TD_MICROSECONDS(self, us);
2029
2030 Py_INCREF(Py_None);
2031 return Py_None;
2032}
2033
2034static PyObject *
2035delta_reduce(PyDateTime_Delta* self)
2036{
2037 PyObject* result = NULL;
2038 PyObject* state = delta_getstate(self);
2039
2040 if (state != NULL) {
2041 /* The funky "()" in the format string creates an empty
2042 * tuple as the 2nd component of the result 3-tuple.
2043 */
2044 result = Py_BuildValue("O()O", self->ob_type, state);
2045 Py_DECREF(state);
2046 }
2047 return result;
2048}
2049
2050#define OFFSET(field) offsetof(PyDateTime_Delta, field)
2051
2052static PyMemberDef delta_members[] = {
Neal Norwitzdfb80862002-12-19 02:30:56 +00002053 {"days", T_INT, OFFSET(days), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002054 PyDoc_STR("Number of days.")},
2055
Neal Norwitzdfb80862002-12-19 02:30:56 +00002056 {"seconds", T_INT, OFFSET(seconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002057 PyDoc_STR("Number of seconds (>= 0 and less than 1 day).")},
2058
Neal Norwitzdfb80862002-12-19 02:30:56 +00002059 {"microseconds", T_INT, OFFSET(microseconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002060 PyDoc_STR("Number of microseconds (>= 0 and less than 1 second).")},
2061 {NULL}
2062};
2063
2064static PyMethodDef delta_methods[] = {
2065 {"__setstate__", (PyCFunction)delta_setstate, METH_O,
2066 PyDoc_STR("__setstate__(state)")},
2067
2068 {"__reduce__", (PyCFunction)delta_reduce, METH_NOARGS,
2069 PyDoc_STR("__setstate__(state)")},
2070
2071 {"__getstate__", (PyCFunction)delta_getstate, METH_NOARGS,
2072 PyDoc_STR("__getstate__() -> state")},
2073 {NULL, NULL},
2074};
2075
2076static char delta_doc[] =
2077PyDoc_STR("Difference between two datetime values.");
2078
2079static PyNumberMethods delta_as_number = {
2080 delta_add, /* nb_add */
2081 delta_subtract, /* nb_subtract */
2082 delta_multiply, /* nb_multiply */
2083 delta_divide, /* nb_divide */
2084 0, /* nb_remainder */
2085 0, /* nb_divmod */
2086 0, /* nb_power */
2087 (unaryfunc)delta_negative, /* nb_negative */
2088 (unaryfunc)delta_positive, /* nb_positive */
2089 (unaryfunc)delta_abs, /* nb_absolute */
2090 (inquiry)delta_nonzero, /* nb_nonzero */
2091 0, /*nb_invert*/
2092 0, /*nb_lshift*/
2093 0, /*nb_rshift*/
2094 0, /*nb_and*/
2095 0, /*nb_xor*/
2096 0, /*nb_or*/
2097 0, /*nb_coerce*/
2098 0, /*nb_int*/
2099 0, /*nb_long*/
2100 0, /*nb_float*/
2101 0, /*nb_oct*/
2102 0, /*nb_hex*/
2103 0, /*nb_inplace_add*/
2104 0, /*nb_inplace_subtract*/
2105 0, /*nb_inplace_multiply*/
2106 0, /*nb_inplace_divide*/
2107 0, /*nb_inplace_remainder*/
2108 0, /*nb_inplace_power*/
2109 0, /*nb_inplace_lshift*/
2110 0, /*nb_inplace_rshift*/
2111 0, /*nb_inplace_and*/
2112 0, /*nb_inplace_xor*/
2113 0, /*nb_inplace_or*/
2114 delta_divide, /* nb_floor_divide */
2115 0, /* nb_true_divide */
2116 0, /* nb_inplace_floor_divide */
2117 0, /* nb_inplace_true_divide */
2118};
2119
2120static PyTypeObject PyDateTime_DeltaType = {
2121 PyObject_HEAD_INIT(NULL)
2122 0, /* ob_size */
2123 "datetime.timedelta", /* tp_name */
2124 sizeof(PyDateTime_Delta), /* tp_basicsize */
2125 0, /* tp_itemsize */
2126 0, /* tp_dealloc */
2127 0, /* tp_print */
2128 0, /* tp_getattr */
2129 0, /* tp_setattr */
2130 0, /* tp_compare */
2131 (reprfunc)delta_repr, /* tp_repr */
2132 &delta_as_number, /* tp_as_number */
2133 0, /* tp_as_sequence */
2134 0, /* tp_as_mapping */
2135 (hashfunc)delta_hash, /* tp_hash */
2136 0, /* tp_call */
2137 (reprfunc)delta_str, /* tp_str */
2138 PyObject_GenericGetAttr, /* tp_getattro */
2139 0, /* tp_setattro */
2140 0, /* tp_as_buffer */
2141 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
2142 delta_doc, /* tp_doc */
2143 0, /* tp_traverse */
2144 0, /* tp_clear */
2145 (richcmpfunc)delta_richcompare, /* tp_richcompare */
2146 0, /* tp_weaklistoffset */
2147 0, /* tp_iter */
2148 0, /* tp_iternext */
2149 delta_methods, /* tp_methods */
2150 delta_members, /* tp_members */
2151 0, /* tp_getset */
2152 0, /* tp_base */
2153 0, /* tp_dict */
2154 0, /* tp_descr_get */
2155 0, /* tp_descr_set */
2156 0, /* tp_dictoffset */
2157 0, /* tp_init */
2158 0, /* tp_alloc */
2159 delta_new, /* tp_new */
2160 _PyObject_Del, /* tp_free */
2161};
2162
2163/*
2164 * PyDateTime_Date implementation.
2165 */
2166
2167/* Accessor properties. */
2168
2169static PyObject *
2170date_year(PyDateTime_Date *self, void *unused)
2171{
2172 return PyInt_FromLong(GET_YEAR(self));
2173}
2174
2175static PyObject *
2176date_month(PyDateTime_Date *self, void *unused)
2177{
2178 return PyInt_FromLong(GET_MONTH(self));
2179}
2180
2181static PyObject *
2182date_day(PyDateTime_Date *self, void *unused)
2183{
2184 return PyInt_FromLong(GET_DAY(self));
2185}
2186
2187static PyGetSetDef date_getset[] = {
2188 {"year", (getter)date_year},
2189 {"month", (getter)date_month},
2190 {"day", (getter)date_day},
2191 {NULL}
2192};
2193
2194/* Constructors. */
2195
Tim Peters12bf3392002-12-24 05:41:27 +00002196static char *date_kws[] = {"year", "month", "day", NULL};
2197
Tim Peters2a799bf2002-12-16 20:18:38 +00002198static PyObject *
2199date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2200{
2201 PyObject *self = NULL;
2202 int year;
2203 int month;
2204 int day;
2205
Tim Peters12bf3392002-12-24 05:41:27 +00002206 if (PyArg_ParseTupleAndKeywords(args, kw, "iii", date_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002207 &year, &month, &day)) {
2208 if (check_date_args(year, month, day) < 0)
2209 return NULL;
2210 self = new_date(year, month, day);
2211 }
2212 return self;
2213}
2214
2215/* Return new date from localtime(t). */
2216static PyObject *
2217date_local_from_time_t(PyObject *cls, time_t t)
2218{
2219 struct tm *tm;
2220 PyObject *result = NULL;
2221
2222 tm = localtime(&t);
2223 if (tm)
2224 result = PyObject_CallFunction(cls, "iii",
2225 tm->tm_year + 1900,
2226 tm->tm_mon + 1,
2227 tm->tm_mday);
2228 else
2229 PyErr_SetString(PyExc_ValueError,
2230 "timestamp out of range for "
2231 "platform localtime() function");
2232 return result;
2233}
2234
2235/* Return new date from current time.
2236 * We say this is equivalent to fromtimestamp(time.time()), and the
2237 * only way to be sure of that is to *call* time.time(). That's not
2238 * generally the same as calling C's time.
2239 */
2240static PyObject *
2241date_today(PyObject *cls, PyObject *dummy)
2242{
2243 PyObject *time;
2244 PyObject *result;
2245
2246 time = time_time();
2247 if (time == NULL)
2248 return NULL;
2249
2250 /* Note well: today() is a class method, so this may not call
2251 * date.fromtimestamp. For example, it may call
2252 * datetime.fromtimestamp. That's why we need all the accuracy
2253 * time.time() delivers; if someone were gonzo about optimization,
2254 * date.today() could get away with plain C time().
2255 */
2256 result = PyObject_CallMethod(cls, "fromtimestamp", "O", time);
2257 Py_DECREF(time);
2258 return result;
2259}
2260
2261/* Return new date from given timestamp (Python timestamp -- a double). */
2262static PyObject *
2263date_fromtimestamp(PyObject *cls, PyObject *args)
2264{
2265 double timestamp;
2266 PyObject *result = NULL;
2267
2268 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2269 result = date_local_from_time_t(cls, (time_t)timestamp);
2270 return result;
2271}
2272
2273/* Return new date from proleptic Gregorian ordinal. Raises ValueError if
2274 * the ordinal is out of range.
2275 */
2276static PyObject *
2277date_fromordinal(PyObject *cls, PyObject *args)
2278{
2279 PyObject *result = NULL;
2280 int ordinal;
2281
2282 if (PyArg_ParseTuple(args, "i:fromordinal", &ordinal)) {
2283 int year;
2284 int month;
2285 int day;
2286
2287 if (ordinal < 1)
2288 PyErr_SetString(PyExc_ValueError, "ordinal must be "
2289 ">= 1");
2290 else {
2291 ord_to_ymd(ordinal, &year, &month, &day);
2292 result = PyObject_CallFunction(cls, "iii",
2293 year, month, day);
2294 }
2295 }
2296 return result;
2297}
2298
2299/*
2300 * Date arithmetic.
2301 */
2302
2303/* date + timedelta -> date. If arg negate is true, subtract the timedelta
2304 * instead.
2305 */
2306static PyObject *
2307add_date_timedelta(PyDateTime_Date *date, PyDateTime_Delta *delta, int negate)
2308{
2309 PyObject *result = NULL;
2310 int year = GET_YEAR(date);
2311 int month = GET_MONTH(date);
2312 int deltadays = GET_TD_DAYS(delta);
2313 /* C-level overflow is impossible because |deltadays| < 1e9. */
2314 int day = GET_DAY(date) + (negate ? -deltadays : deltadays);
2315
2316 if (normalize_date(&year, &month, &day) >= 0)
2317 result = new_date(year, month, day);
2318 return result;
2319}
2320
2321static PyObject *
2322date_add(PyObject *left, PyObject *right)
2323{
2324 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2325 Py_INCREF(Py_NotImplemented);
2326 return Py_NotImplemented;
2327 }
2328 if (PyDate_CheckExact(left)) {
2329 /* date + ??? */
2330 if (PyDelta_Check(right))
2331 /* date + delta */
2332 return add_date_timedelta((PyDateTime_Date *) left,
2333 (PyDateTime_Delta *) right,
2334 0);
2335 }
2336 else {
2337 /* ??? + date
2338 * 'right' must be one of us, or we wouldn't have been called
2339 */
2340 if (PyDelta_Check(left))
2341 /* delta + date */
2342 return add_date_timedelta((PyDateTime_Date *) right,
2343 (PyDateTime_Delta *) left,
2344 0);
2345 }
2346 Py_INCREF(Py_NotImplemented);
2347 return Py_NotImplemented;
2348}
2349
2350static PyObject *
2351date_subtract(PyObject *left, PyObject *right)
2352{
2353 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2354 Py_INCREF(Py_NotImplemented);
2355 return Py_NotImplemented;
2356 }
2357 if (PyDate_CheckExact(left)) {
2358 if (PyDate_CheckExact(right)) {
2359 /* date - date */
2360 int left_ord = ymd_to_ord(GET_YEAR(left),
2361 GET_MONTH(left),
2362 GET_DAY(left));
2363 int right_ord = ymd_to_ord(GET_YEAR(right),
2364 GET_MONTH(right),
2365 GET_DAY(right));
2366 return new_delta(left_ord - right_ord, 0, 0, 0);
2367 }
2368 if (PyDelta_Check(right)) {
2369 /* date - delta */
2370 return add_date_timedelta((PyDateTime_Date *) left,
2371 (PyDateTime_Delta *) right,
2372 1);
2373 }
2374 }
2375 Py_INCREF(Py_NotImplemented);
2376 return Py_NotImplemented;
2377}
2378
2379
2380/* Various ways to turn a date into a string. */
2381
2382static PyObject *
2383date_repr(PyDateTime_Date *self)
2384{
2385 char buffer[1028];
2386 char *typename;
2387
2388 typename = self->ob_type->tp_name;
2389 PyOS_snprintf(buffer, sizeof(buffer), "%s(%d, %d, %d)",
2390 typename,
2391 GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2392
2393 return PyString_FromString(buffer);
2394}
2395
2396static PyObject *
2397date_isoformat(PyDateTime_Date *self)
2398{
2399 char buffer[128];
2400
2401 isoformat_date(self, buffer, sizeof(buffer));
2402 return PyString_FromString(buffer);
2403}
2404
2405/* str() calls the appropriate isofomat() method. */
2406static PyObject *
2407date_str(PyDateTime_Date *self)
2408{
2409 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
2410}
2411
2412
2413static PyObject *
2414date_ctime(PyDateTime_Date *self)
2415{
2416 return format_ctime(self, 0, 0, 0);
2417}
2418
2419static PyObject *
2420date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2421{
2422 /* This method can be inherited, and needs to call the
2423 * timetuple() method appropriate to self's class.
2424 */
2425 PyObject *result;
2426 PyObject *format;
2427 PyObject *tuple;
2428 static char *keywords[] = {"format", NULL};
2429
2430 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
2431 &PyString_Type, &format))
2432 return NULL;
2433
2434 tuple = PyObject_CallMethod((PyObject *)self, "timetuple", "()");
2435 if (tuple == NULL)
2436 return NULL;
Tim Petersbad8ff02002-12-30 20:52:32 +00002437 result = wrap_strftime((PyObject *)self, format, tuple,
2438 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00002439 Py_DECREF(tuple);
2440 return result;
2441}
2442
2443/* ISO methods. */
2444
2445static PyObject *
2446date_isoweekday(PyDateTime_Date *self)
2447{
2448 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2449
2450 return PyInt_FromLong(dow + 1);
2451}
2452
2453static PyObject *
2454date_isocalendar(PyDateTime_Date *self)
2455{
2456 int year = GET_YEAR(self);
2457 int week1_monday = iso_week1_monday(year);
2458 int today = ymd_to_ord(year, GET_MONTH(self), GET_DAY(self));
2459 int week;
2460 int day;
2461
2462 week = divmod(today - week1_monday, 7, &day);
2463 if (week < 0) {
2464 --year;
2465 week1_monday = iso_week1_monday(year);
2466 week = divmod(today - week1_monday, 7, &day);
2467 }
2468 else if (week >= 52 && today >= iso_week1_monday(year + 1)) {
2469 ++year;
2470 week = 0;
2471 }
2472 return Py_BuildValue("iii", year, week + 1, day + 1);
2473}
2474
2475/* Miscellaneous methods. */
2476
2477/* This is more natural as a tp_compare, but doesn't work then: for whatever
2478 * reason, Python's try_3way_compare ignores tp_compare unless
2479 * PyInstance_Check returns true, but these aren't old-style classes.
2480 */
2481static PyObject *
2482date_richcompare(PyDateTime_Date *self, PyObject *other, int op)
2483{
2484 int diff;
2485
2486 if (! PyDate_Check(other)) {
2487 PyErr_Format(PyExc_TypeError,
2488 "can't compare date to %s instance",
2489 other->ob_type->tp_name);
2490 return NULL;
2491 }
2492 diff = memcmp(self->data, ((PyDateTime_Date *)other)->data,
2493 _PyDateTime_DATE_DATASIZE);
2494 return diff_to_bool(diff, op);
2495}
2496
2497static PyObject *
2498date_timetuple(PyDateTime_Date *self)
2499{
2500 return build_struct_time(GET_YEAR(self),
2501 GET_MONTH(self),
2502 GET_DAY(self),
2503 0, 0, 0, -1);
2504}
2505
Tim Peters12bf3392002-12-24 05:41:27 +00002506static PyObject *
2507date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2508{
2509 PyObject *clone;
2510 PyObject *tuple;
2511 int year = GET_YEAR(self);
2512 int month = GET_MONTH(self);
2513 int day = GET_DAY(self);
2514
2515 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iii:replace", date_kws,
2516 &year, &month, &day))
2517 return NULL;
2518 tuple = Py_BuildValue("iii", year, month, day);
2519 if (tuple == NULL)
2520 return NULL;
2521 clone = date_new(self->ob_type, tuple, NULL);
2522 Py_DECREF(tuple);
2523 return clone;
2524}
2525
Tim Peters2a799bf2002-12-16 20:18:38 +00002526static PyObject *date_getstate(PyDateTime_Date *self);
2527
2528static long
2529date_hash(PyDateTime_Date *self)
2530{
2531 if (self->hashcode == -1) {
2532 PyObject *temp = date_getstate(self);
2533 if (temp != NULL) {
2534 self->hashcode = PyObject_Hash(temp);
2535 Py_DECREF(temp);
2536 }
2537 }
2538 return self->hashcode;
2539}
2540
2541static PyObject *
2542date_toordinal(PyDateTime_Date *self)
2543{
2544 return PyInt_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self),
2545 GET_DAY(self)));
2546}
2547
2548static PyObject *
2549date_weekday(PyDateTime_Date *self)
2550{
2551 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2552
2553 return PyInt_FromLong(dow);
2554}
2555
2556/* Pickle support. Quite a maze! */
2557
2558static PyObject *
2559date_getstate(PyDateTime_Date *self)
2560{
Jack Jansenb8941f22003-01-08 16:28:45 +00002561 return PyString_FromStringAndSize((char *)self->data,
Tim Peters2a799bf2002-12-16 20:18:38 +00002562 _PyDateTime_DATE_DATASIZE);
2563}
2564
2565static PyObject *
2566date_setstate(PyDateTime_Date *self, PyObject *state)
2567{
2568 const int len = PyString_Size(state);
2569 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
2570
2571 if (! PyString_Check(state) ||
2572 len != _PyDateTime_DATE_DATASIZE) {
2573 PyErr_SetString(PyExc_TypeError,
2574 "bad argument to date.__setstate__");
2575 return NULL;
2576 }
2577 memcpy(self->data, pdata, _PyDateTime_DATE_DATASIZE);
2578 self->hashcode = -1;
2579
2580 Py_INCREF(Py_None);
2581 return Py_None;
2582}
2583
2584/* XXX This seems a ridiculously inefficient way to pickle a short string. */
2585static PyObject *
2586date_pickler(PyObject *module, PyDateTime_Date *date)
2587{
2588 PyObject *state;
2589 PyObject *result = NULL;
2590
2591 if (! PyDate_CheckExact(date)) {
2592 PyErr_Format(PyExc_TypeError,
2593 "bad type passed to date pickler: %s",
2594 date->ob_type->tp_name);
2595 return NULL;
2596 }
2597 state = date_getstate(date);
2598 if (state) {
2599 result = Py_BuildValue("O(O)", date_unpickler_object, state);
2600 Py_DECREF(state);
2601 }
2602 return result;
2603}
2604
2605static PyObject *
2606date_unpickler(PyObject *module, PyObject *arg)
2607{
2608 PyDateTime_Date *self;
2609
2610 if (! PyString_CheckExact(arg)) {
2611 PyErr_Format(PyExc_TypeError,
2612 "bad type passed to date unpickler: %s",
2613 arg->ob_type->tp_name);
2614 return NULL;
2615 }
2616 self = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
2617 if (self != NULL) {
2618 PyObject *res = date_setstate(self, arg);
2619 if (res == NULL) {
2620 Py_DECREF(self);
2621 return NULL;
2622 }
2623 Py_DECREF(res);
2624 }
2625 return (PyObject *)self;
2626}
2627
2628static PyMethodDef date_methods[] = {
2629 /* Class methods: */
2630 {"fromtimestamp", (PyCFunction)date_fromtimestamp, METH_VARARGS |
2631 METH_CLASS,
2632 PyDoc_STR("timestamp -> local date from a POSIX timestamp (like "
2633 "time.time()).")},
2634
2635 {"fromordinal", (PyCFunction)date_fromordinal, METH_VARARGS |
2636 METH_CLASS,
2637 PyDoc_STR("int -> date corresponding to a proleptic Gregorian "
2638 "ordinal.")},
2639
2640 {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS,
2641 PyDoc_STR("Current date or datetime: same as "
2642 "self.__class__.fromtimestamp(time.time()).")},
2643
2644 /* Instance methods: */
2645
2646 {"ctime", (PyCFunction)date_ctime, METH_NOARGS,
2647 PyDoc_STR("Return ctime() style string.")},
2648
2649 {"strftime", (PyCFunction)date_strftime, METH_KEYWORDS,
2650 PyDoc_STR("format -> strftime() style string.")},
2651
2652 {"timetuple", (PyCFunction)date_timetuple, METH_NOARGS,
2653 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
2654
2655 {"isocalendar", (PyCFunction)date_isocalendar, METH_NOARGS,
2656 PyDoc_STR("Return a 3-tuple containing ISO year, week number, and "
2657 "weekday.")},
2658
2659 {"isoformat", (PyCFunction)date_isoformat, METH_NOARGS,
2660 PyDoc_STR("Return string in ISO 8601 format, YYYY-MM-DD.")},
2661
2662 {"isoweekday", (PyCFunction)date_isoweekday, METH_NOARGS,
2663 PyDoc_STR("Return the day of the week represented by the date.\n"
2664 "Monday == 1 ... Sunday == 7")},
2665
2666 {"toordinal", (PyCFunction)date_toordinal, METH_NOARGS,
2667 PyDoc_STR("Return proleptic Gregorian ordinal. January 1 of year "
2668 "1 is day 1.")},
2669
2670 {"weekday", (PyCFunction)date_weekday, METH_NOARGS,
2671 PyDoc_STR("Return the day of the week represented by the date.\n"
2672 "Monday == 0 ... Sunday == 6")},
2673
Tim Peters12bf3392002-12-24 05:41:27 +00002674 {"replace", (PyCFunction)date_replace, METH_KEYWORDS,
2675 PyDoc_STR("Return date with new specified fields.")},
2676
Tim Peters2a799bf2002-12-16 20:18:38 +00002677 {"__setstate__", (PyCFunction)date_setstate, METH_O,
2678 PyDoc_STR("__setstate__(state)")},
2679
2680 {"__getstate__", (PyCFunction)date_getstate, METH_NOARGS,
2681 PyDoc_STR("__getstate__() -> state")},
2682
2683 {NULL, NULL}
2684};
2685
2686static char date_doc[] =
2687PyDoc_STR("Basic date type.");
2688
2689static PyNumberMethods date_as_number = {
2690 date_add, /* nb_add */
2691 date_subtract, /* nb_subtract */
2692 0, /* nb_multiply */
2693 0, /* nb_divide */
2694 0, /* nb_remainder */
2695 0, /* nb_divmod */
2696 0, /* nb_power */
2697 0, /* nb_negative */
2698 0, /* nb_positive */
2699 0, /* nb_absolute */
2700 0, /* nb_nonzero */
2701};
2702
2703static PyTypeObject PyDateTime_DateType = {
2704 PyObject_HEAD_INIT(NULL)
2705 0, /* ob_size */
2706 "datetime.date", /* tp_name */
2707 sizeof(PyDateTime_Date), /* tp_basicsize */
2708 0, /* tp_itemsize */
2709 (destructor)PyObject_Del, /* tp_dealloc */
2710 0, /* tp_print */
2711 0, /* tp_getattr */
2712 0, /* tp_setattr */
2713 0, /* tp_compare */
2714 (reprfunc)date_repr, /* tp_repr */
2715 &date_as_number, /* tp_as_number */
2716 0, /* tp_as_sequence */
2717 0, /* tp_as_mapping */
2718 (hashfunc)date_hash, /* tp_hash */
2719 0, /* tp_call */
2720 (reprfunc)date_str, /* tp_str */
2721 PyObject_GenericGetAttr, /* tp_getattro */
2722 0, /* tp_setattro */
2723 0, /* tp_as_buffer */
2724 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
2725 Py_TPFLAGS_BASETYPE, /* tp_flags */
2726 date_doc, /* tp_doc */
2727 0, /* tp_traverse */
2728 0, /* tp_clear */
2729 (richcmpfunc)date_richcompare, /* tp_richcompare */
2730 0, /* tp_weaklistoffset */
2731 0, /* tp_iter */
2732 0, /* tp_iternext */
2733 date_methods, /* tp_methods */
2734 0, /* tp_members */
2735 date_getset, /* tp_getset */
2736 0, /* tp_base */
2737 0, /* tp_dict */
2738 0, /* tp_descr_get */
2739 0, /* tp_descr_set */
2740 0, /* tp_dictoffset */
2741 0, /* tp_init */
2742 0, /* tp_alloc */
2743 date_new, /* tp_new */
2744 _PyObject_Del, /* tp_free */
2745};
2746
2747/*
2748 * PyDateTime_DateTime implementation.
2749 */
2750
2751/* Accessor properties. */
2752
2753static PyObject *
2754datetime_hour(PyDateTime_DateTime *self, void *unused)
2755{
2756 return PyInt_FromLong(DATE_GET_HOUR(self));
2757}
2758
2759static PyObject *
2760datetime_minute(PyDateTime_DateTime *self, void *unused)
2761{
2762 return PyInt_FromLong(DATE_GET_MINUTE(self));
2763}
2764
2765static PyObject *
2766datetime_second(PyDateTime_DateTime *self, void *unused)
2767{
2768 return PyInt_FromLong(DATE_GET_SECOND(self));
2769}
2770
2771static PyObject *
2772datetime_microsecond(PyDateTime_DateTime *self, void *unused)
2773{
2774 return PyInt_FromLong(DATE_GET_MICROSECOND(self));
2775}
2776
2777static PyGetSetDef datetime_getset[] = {
2778 {"hour", (getter)datetime_hour},
2779 {"minute", (getter)datetime_minute},
2780 {"second", (getter)datetime_second},
2781 {"microsecond", (getter)datetime_microsecond},
2782 {NULL}
2783};
2784
2785/* Constructors. */
2786
Tim Peters12bf3392002-12-24 05:41:27 +00002787
2788static char *datetime_kws[] = {"year", "month", "day",
2789 "hour", "minute", "second", "microsecond",
2790 NULL};
2791
Tim Peters2a799bf2002-12-16 20:18:38 +00002792static PyObject *
2793datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2794{
2795 PyObject *self = NULL;
2796 int year;
2797 int month;
2798 int day;
2799 int hour = 0;
2800 int minute = 0;
2801 int second = 0;
2802 int usecond = 0;
2803
Tim Peters12bf3392002-12-24 05:41:27 +00002804 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiii", datetime_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002805 &year, &month, &day, &hour, &minute,
2806 &second, &usecond)) {
2807 if (check_date_args(year, month, day) < 0)
2808 return NULL;
2809 if (check_time_args(hour, minute, second, usecond) < 0)
2810 return NULL;
2811 self = new_datetime(year, month, day,
2812 hour, minute, second, usecond);
2813 }
2814 return self;
2815}
2816
2817
2818/* TM_FUNC is the shared type of localtime() and gmtime(). */
2819typedef struct tm *(*TM_FUNC)(const time_t *timer);
2820
2821/* Internal helper.
2822 * Build datetime from a time_t and a distinct count of microseconds.
2823 * Pass localtime or gmtime for f, to control the interpretation of timet.
2824 */
2825static PyObject *
2826datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us)
2827{
2828 struct tm *tm;
2829 PyObject *result = NULL;
2830
2831 tm = f(&timet);
Tim Peters75a6e3b2003-01-04 18:17:36 +00002832 if (tm) {
2833 /* The platform localtime/gmtime may insert leap seconds,
2834 * indicated by tm->tm_sec > 59. We don't care about them,
2835 * except to the extent that passing them on to the datetime
2836 * constructor would raise ValueError for a reason that
2837 * made no sense to the user.
2838 */
2839 if (tm->tm_sec > 59)
2840 tm->tm_sec = 59;
Tim Peters2a799bf2002-12-16 20:18:38 +00002841 result = PyObject_CallFunction(cls, "iiiiiii",
2842 tm->tm_year + 1900,
2843 tm->tm_mon + 1,
2844 tm->tm_mday,
2845 tm->tm_hour,
2846 tm->tm_min,
2847 tm->tm_sec,
2848 us);
Tim Peters75a6e3b2003-01-04 18:17:36 +00002849 }
Tim Peters2a799bf2002-12-16 20:18:38 +00002850 else
2851 PyErr_SetString(PyExc_ValueError,
2852 "timestamp out of range for "
2853 "platform localtime()/gmtime() function");
2854 return result;
2855}
2856
2857/* Internal helper.
2858 * Build datetime from a Python timestamp. Pass localtime or gmtime for f,
2859 * to control the interpretation of the timestamp. Since a double doesn't
2860 * have enough bits to cover a datetime's full range of precision, it's
2861 * better to call datetime_from_timet_and_us provided you have a way
2862 * to get that much precision (e.g., C time() isn't good enough).
2863 */
2864static PyObject *
2865datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp)
2866{
2867 time_t timet = (time_t)timestamp;
Tim Peters5d644dd2003-01-02 16:32:54 +00002868 double fraction = timestamp - (double)timet;
2869 int us = (int)round_to_long(fraction * 1e6);
Tim Peters2a799bf2002-12-16 20:18:38 +00002870
2871 return datetime_from_timet_and_us(cls, f, timet, us);
2872}
2873
2874/* Internal helper.
2875 * Build most accurate possible datetime for current time. Pass localtime or
2876 * gmtime for f as appropriate.
2877 */
2878static PyObject *
2879datetime_best_possible(PyObject *cls, TM_FUNC f)
2880{
2881#ifdef HAVE_GETTIMEOFDAY
2882 struct timeval t;
2883
2884#ifdef GETTIMEOFDAY_NO_TZ
2885 gettimeofday(&t);
2886#else
2887 gettimeofday(&t, (struct timezone *)NULL);
2888#endif
2889 return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec);
2890
2891#else /* ! HAVE_GETTIMEOFDAY */
2892 /* No flavor of gettimeofday exists on this platform. Python's
2893 * time.time() does a lot of other platform tricks to get the
2894 * best time it can on the platform, and we're not going to do
2895 * better than that (if we could, the better code would belong
2896 * in time.time()!) We're limited by the precision of a double,
2897 * though.
2898 */
2899 PyObject *time;
2900 double dtime;
2901
2902 time = time_time();
2903 if (time == NULL)
2904 return NULL;
2905 dtime = PyFloat_AsDouble(time);
2906 Py_DECREF(time);
2907 if (dtime == -1.0 && PyErr_Occurred())
2908 return NULL;
2909 return datetime_from_timestamp(cls, f, dtime);
2910#endif /* ! HAVE_GETTIMEOFDAY */
2911}
2912
2913/* Return new local datetime from timestamp (Python timestamp -- a double). */
2914static PyObject *
2915datetime_fromtimestamp(PyObject *cls, PyObject *args)
2916{
2917 double timestamp;
2918 PyObject *result = NULL;
2919
2920 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2921 result = datetime_from_timestamp(cls, localtime, timestamp);
2922 return result;
2923}
2924
2925/* Return new UTC datetime from timestamp (Python timestamp -- a double). */
2926static PyObject *
2927datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
2928{
2929 double timestamp;
2930 PyObject *result = NULL;
2931
2932 if (PyArg_ParseTuple(args, "d:utcfromtimestamp", &timestamp))
2933 result = datetime_from_timestamp(cls, gmtime, timestamp);
2934 return result;
2935}
2936
2937/* Return best possible local time -- this isn't constrained by the
2938 * precision of a timestamp.
2939 */
2940static PyObject *
2941datetime_now(PyObject *cls, PyObject *dummy)
2942{
2943 return datetime_best_possible(cls, localtime);
2944}
2945
2946/* Return best possible UTC time -- this isn't constrained by the
2947 * precision of a timestamp.
2948 */
2949static PyObject *
2950datetime_utcnow(PyObject *cls, PyObject *dummy)
2951{
2952 return datetime_best_possible(cls, gmtime);
2953}
2954
2955/* Return new datetime or datetimetz from date/datetime/datetimetz and
2956 * time/timetz arguments.
2957 */
2958static PyObject *
2959datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
2960{
2961 static char *keywords[] = {"date", "time", NULL};
2962 PyObject *date;
2963 PyObject *time;
2964 PyObject *result = NULL;
2965
2966 if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!:combine", keywords,
2967 &PyDateTime_DateType, &date,
2968 &PyDateTime_TimeType, &time))
2969 result = PyObject_CallFunction(cls, "iiiiiii",
2970 GET_YEAR(date),
2971 GET_MONTH(date),
2972 GET_DAY(date),
2973 TIME_GET_HOUR(time),
2974 TIME_GET_MINUTE(time),
2975 TIME_GET_SECOND(time),
2976 TIME_GET_MICROSECOND(time));
2977 if (result && PyTimeTZ_Check(time) && PyDateTimeTZ_Check(result)) {
2978 /* Copy the tzinfo field. */
Tim Peters80475bb2002-12-25 07:40:55 +00002979 replace_tzinfo(result, ((PyDateTime_TimeTZ *)time)->tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00002980 }
2981 return result;
2982}
2983
2984/* datetime arithmetic. */
2985
2986static PyObject *
2987add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
2988{
2989 /* Note that the C-level additions can't overflow, because of
2990 * invariant bounds on the member values.
2991 */
2992 int year = GET_YEAR(date);
2993 int month = GET_MONTH(date);
2994 int day = GET_DAY(date) + GET_TD_DAYS(delta);
2995 int hour = DATE_GET_HOUR(date);
2996 int minute = DATE_GET_MINUTE(date);
2997 int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta);
2998 int microsecond = DATE_GET_MICROSECOND(date) +
2999 GET_TD_MICROSECONDS(delta);
3000
3001 if (normalize_datetime(&year, &month, &day,
3002 &hour, &minute, &second, &microsecond) < 0)
3003 return NULL;
3004 else
3005 return new_datetime(year, month, day,
3006 hour, minute, second, microsecond);
3007}
3008
3009static PyObject *
3010sub_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
3011{
3012 /* Note that the C-level subtractions can't overflow, because of
3013 * invariant bounds on the member values.
3014 */
3015 int year = GET_YEAR(date);
3016 int month = GET_MONTH(date);
3017 int day = GET_DAY(date) - GET_TD_DAYS(delta);
3018 int hour = DATE_GET_HOUR(date);
3019 int minute = DATE_GET_MINUTE(date);
3020 int second = DATE_GET_SECOND(date) - GET_TD_SECONDS(delta);
3021 int microsecond = DATE_GET_MICROSECOND(date) -
3022 GET_TD_MICROSECONDS(delta);
3023
3024 if (normalize_datetime(&year, &month, &day,
3025 &hour, &minute, &second, &microsecond) < 0)
3026 return NULL;
3027 else
3028 return new_datetime(year, month, day,
3029 hour, minute, second, microsecond);
3030}
3031
3032static PyObject *
3033sub_datetime_datetime(PyDateTime_DateTime *left, PyDateTime_DateTime *right)
3034{
3035 int days1 = ymd_to_ord(GET_YEAR(left), GET_MONTH(left), GET_DAY(left));
3036 int days2 = ymd_to_ord(GET_YEAR(right),
3037 GET_MONTH(right),
3038 GET_DAY(right));
3039 /* These can't overflow, since the values are normalized. At most
3040 * this gives the number of seconds in one day.
3041 */
3042 int delta_s = (DATE_GET_HOUR(left) - DATE_GET_HOUR(right)) * 3600 +
3043 (DATE_GET_MINUTE(left) - DATE_GET_MINUTE(right)) * 60 +
3044 DATE_GET_SECOND(left) - DATE_GET_SECOND(right);
3045 int delta_us = DATE_GET_MICROSECOND(left) -
3046 DATE_GET_MICROSECOND(right);
3047
3048 return new_delta(days1 - days2, delta_s, delta_us, 1);
3049}
3050
3051static PyObject *
3052datetime_add(PyObject *left, PyObject *right)
3053{
3054 if (PyDateTime_Check(left)) {
3055 /* datetime + ??? */
3056 if (PyDelta_Check(right))
3057 /* datetime + delta */
3058 return add_datetime_timedelta(
3059 (PyDateTime_DateTime *)left,
3060 (PyDateTime_Delta *)right);
3061 }
3062 else if (PyDelta_Check(left)) {
3063 /* delta + datetime */
3064 return add_datetime_timedelta((PyDateTime_DateTime *) right,
3065 (PyDateTime_Delta *) left);
3066 }
3067 Py_INCREF(Py_NotImplemented);
3068 return Py_NotImplemented;
3069}
3070
3071static PyObject *
3072datetime_subtract(PyObject *left, PyObject *right)
3073{
3074 PyObject *result = Py_NotImplemented;
3075
3076 if (PyDateTime_Check(left)) {
3077 /* datetime - ??? */
3078 if (PyDateTime_Check(right)) {
3079 /* datetime - datetime */
3080 result = sub_datetime_datetime(
3081 (PyDateTime_DateTime *)left,
3082 (PyDateTime_DateTime *)right);
3083 }
3084 else if (PyDelta_Check(right)) {
3085 /* datetime - delta */
3086 result = sub_datetime_timedelta(
3087 (PyDateTime_DateTime *)left,
3088 (PyDateTime_Delta *)right);
3089 }
3090 }
3091
3092 if (result == Py_NotImplemented)
3093 Py_INCREF(result);
3094 return result;
3095}
3096
3097/* Various ways to turn a datetime into a string. */
3098
3099static PyObject *
3100datetime_repr(PyDateTime_DateTime *self)
3101{
3102 char buffer[1000];
3103 char *typename = self->ob_type->tp_name;
3104
3105 if (DATE_GET_MICROSECOND(self)) {
3106 PyOS_snprintf(buffer, sizeof(buffer),
3107 "%s(%d, %d, %d, %d, %d, %d, %d)",
3108 typename,
3109 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3110 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3111 DATE_GET_SECOND(self),
3112 DATE_GET_MICROSECOND(self));
3113 }
3114 else if (DATE_GET_SECOND(self)) {
3115 PyOS_snprintf(buffer, sizeof(buffer),
3116 "%s(%d, %d, %d, %d, %d, %d)",
3117 typename,
3118 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3119 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3120 DATE_GET_SECOND(self));
3121 }
3122 else {
3123 PyOS_snprintf(buffer, sizeof(buffer),
3124 "%s(%d, %d, %d, %d, %d)",
3125 typename,
3126 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3127 DATE_GET_HOUR(self), DATE_GET_MINUTE(self));
3128 }
3129 return PyString_FromString(buffer);
3130}
3131
3132static PyObject *
3133datetime_str(PyDateTime_DateTime *self)
3134{
3135 return PyObject_CallMethod((PyObject *)self, "isoformat", "(s)", " ");
3136}
3137
3138static PyObject *
3139datetime_isoformat(PyDateTime_DateTime *self,
3140 PyObject *args, PyObject *kw)
3141{
3142 char sep = 'T';
3143 static char *keywords[] = {"sep", NULL};
3144 char buffer[100];
3145 char *cp;
3146
3147 if (!PyArg_ParseTupleAndKeywords(args, kw, "|c:isoformat", keywords,
3148 &sep))
3149 return NULL;
3150 cp = isoformat_date((PyDateTime_Date *)self, buffer, sizeof(buffer));
3151 assert(cp != NULL);
3152 *cp++ = sep;
3153 isoformat_time(self, cp, sizeof(buffer) - (cp - buffer));
3154 return PyString_FromString(buffer);
3155}
3156
3157static PyObject *
3158datetime_ctime(PyDateTime_DateTime *self)
3159{
3160 return format_ctime((PyDateTime_Date *)self,
3161 DATE_GET_HOUR(self),
3162 DATE_GET_MINUTE(self),
3163 DATE_GET_SECOND(self));
3164}
3165
3166/* Miscellaneous methods. */
3167
3168/* This is more natural as a tp_compare, but doesn't work then: for whatever
3169 * reason, Python's try_3way_compare ignores tp_compare unless
3170 * PyInstance_Check returns true, but these aren't old-style classes.
3171 * Note that this routine handles all comparisons for datetime and datetimetz.
3172 */
3173static PyObject *
3174datetime_richcompare(PyDateTime_DateTime *self, PyObject *other, int op)
3175{
3176 int diff;
3177 naivety n1, n2;
3178 int offset1, offset2;
3179
3180 if (! PyDateTime_Check(other)) {
3181 /* Stop this from falling back to address comparison. */
3182 PyErr_Format(PyExc_TypeError,
3183 "can't compare '%s' to '%s'",
3184 self->ob_type->tp_name,
3185 other->ob_type->tp_name);
3186 return NULL;
3187 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003188
Tim Peters00237032002-12-27 02:21:51 +00003189 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1,
Tim Peterse39a80c2002-12-30 21:28:52 +00003190 (PyObject *)self,
3191 other, &offset2, &n2,
3192 other) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003193 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003194 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters60c76e42002-12-27 00:41:11 +00003195 /* If they're both naive, or both aware and have the same offsets,
Tim Peters2a799bf2002-12-16 20:18:38 +00003196 * we get off cheap. Note that if they're both naive, offset1 ==
3197 * offset2 == 0 at this point.
3198 */
3199 if (n1 == n2 && offset1 == offset2) {
3200 diff = memcmp(self->data, ((PyDateTime_DateTime *)other)->data,
3201 _PyDateTime_DATETIME_DATASIZE);
3202 return diff_to_bool(diff, op);
3203 }
3204
3205 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3206 /* We want the sign of
3207 * (self - offset1 minutes) - (other - offset2 minutes) =
3208 * (self - other) + (offset2 - offset1) minutes.
3209 */
3210 PyDateTime_Delta *delta;
3211 int days, seconds, us;
3212
3213 assert(offset1 != offset2); /* else last "if" handled it */
3214 delta = (PyDateTime_Delta *)sub_datetime_datetime(self,
3215 (PyDateTime_DateTime *)other);
3216 if (delta == NULL)
3217 return NULL;
3218 days = delta->days;
3219 seconds = delta->seconds + (offset2 - offset1) * 60;
3220 us = delta->microseconds;
3221 Py_DECREF(delta);
3222 normalize_d_s_us(&days, &seconds, &us);
3223 diff = days;
3224 if (diff == 0)
3225 diff = seconds | us;
3226 return diff_to_bool(diff, op);
3227 }
3228
3229 assert(n1 != n2);
3230 PyErr_SetString(PyExc_TypeError,
3231 "can't compare offset-naive and "
3232 "offset-aware datetimes");
3233 return NULL;
3234}
3235
Tim Peters2a799bf2002-12-16 20:18:38 +00003236static long
3237datetime_hash(PyDateTime_DateTime *self)
3238{
3239 if (self->hashcode == -1) {
3240 naivety n;
3241 int offset;
3242 PyObject *temp;
3243
Tim Peterse39a80c2002-12-30 21:28:52 +00003244 n = classify_utcoffset((PyObject *)self, (PyObject *)self,
3245 &offset);
Tim Peters2a799bf2002-12-16 20:18:38 +00003246 assert(n != OFFSET_UNKNOWN);
3247 if (n == OFFSET_ERROR)
3248 return -1;
3249
3250 /* Reduce this to a hash of another object. */
3251 if (n == OFFSET_NAIVE)
Tim Peters33e0f382003-01-10 02:05:14 +00003252 temp = PyString_FromStringAndSize(
3253 (char *)self->data,
3254 _PyDateTime_DATETIME_DATASIZE);
Tim Peters2a799bf2002-12-16 20:18:38 +00003255 else {
3256 int days;
3257 int seconds;
3258
3259 assert(n == OFFSET_AWARE);
3260 assert(PyDateTimeTZ_Check(self));
3261 days = ymd_to_ord(GET_YEAR(self),
3262 GET_MONTH(self),
3263 GET_DAY(self));
3264 seconds = DATE_GET_HOUR(self) * 3600 +
3265 (DATE_GET_MINUTE(self) - offset) * 60 +
3266 DATE_GET_SECOND(self);
3267 temp = new_delta(days,
3268 seconds,
3269 DATE_GET_MICROSECOND(self),
3270 1);
3271 }
3272 if (temp != NULL) {
3273 self->hashcode = PyObject_Hash(temp);
3274 Py_DECREF(temp);
3275 }
3276 }
3277 return self->hashcode;
3278}
3279
3280static PyObject *
Tim Peters12bf3392002-12-24 05:41:27 +00003281datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
3282{
3283 PyObject *clone;
3284 PyObject *tuple;
3285 int y = GET_YEAR(self);
3286 int m = GET_MONTH(self);
3287 int d = GET_DAY(self);
3288 int hh = DATE_GET_HOUR(self);
3289 int mm = DATE_GET_MINUTE(self);
3290 int ss = DATE_GET_SECOND(self);
3291 int us = DATE_GET_MICROSECOND(self);
3292
3293 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiii:replace",
3294 datetime_kws,
3295 &y, &m, &d, &hh, &mm, &ss, &us))
3296 return NULL;
3297 tuple = Py_BuildValue("iiiiiii", y, m, d, hh, mm, ss, us);
3298 if (tuple == NULL)
3299 return NULL;
3300 clone = datetime_new(self->ob_type, tuple, NULL);
3301 Py_DECREF(tuple);
3302 return clone;
3303}
3304
3305static PyObject *
Tim Peters80475bb2002-12-25 07:40:55 +00003306datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
3307{
3308 PyObject *tzinfo;
3309 static char *keywords[] = {"tz", NULL};
3310
3311 if (! PyArg_ParseTupleAndKeywords(args, kw, "O:astimezone", keywords,
3312 &tzinfo))
3313 return NULL;
3314 if (check_tzinfo_subclass(tzinfo) < 0)
3315 return NULL;
3316 return new_datetimetz(GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3317 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3318 DATE_GET_SECOND(self),
3319 DATE_GET_MICROSECOND(self),
3320 tzinfo);
3321}
3322
3323static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00003324datetime_timetuple(PyDateTime_DateTime *self)
3325{
3326 return build_struct_time(GET_YEAR(self),
3327 GET_MONTH(self),
3328 GET_DAY(self),
3329 DATE_GET_HOUR(self),
3330 DATE_GET_MINUTE(self),
3331 DATE_GET_SECOND(self),
3332 -1);
3333}
3334
3335static PyObject *
3336datetime_getdate(PyDateTime_DateTime *self)
3337{
3338 return new_date(GET_YEAR(self),
3339 GET_MONTH(self),
3340 GET_DAY(self));
3341}
3342
3343static PyObject *
3344datetime_gettime(PyDateTime_DateTime *self)
3345{
Tim Peters0bf60bd2003-01-08 20:40:01 +00003346 return new_timetz(DATE_GET_HOUR(self),
3347 DATE_GET_MINUTE(self),
3348 DATE_GET_SECOND(self),
3349 DATE_GET_MICROSECOND(self),
3350 Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003351}
3352
Tim Peters2a799bf2002-12-16 20:18:38 +00003353static PyMethodDef datetime_methods[] = {
3354 /* Class methods: */
3355 {"now", (PyCFunction)datetime_now,
3356 METH_NOARGS | METH_CLASS,
3357 PyDoc_STR("Return a new datetime representing local day and time.")},
3358
3359 {"utcnow", (PyCFunction)datetime_utcnow,
3360 METH_NOARGS | METH_CLASS,
3361 PyDoc_STR("Return a new datetime representing UTC day and time.")},
3362
3363 {"fromtimestamp", (PyCFunction)datetime_fromtimestamp,
3364 METH_VARARGS | METH_CLASS,
3365 PyDoc_STR("timestamp -> local datetime from a POSIX timestamp "
3366 "(like time.time()).")},
3367
3368 {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
3369 METH_VARARGS | METH_CLASS,
3370 PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp "
3371 "(like time.time()).")},
3372
3373 {"combine", (PyCFunction)datetime_combine,
3374 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
3375 PyDoc_STR("date, time -> datetime with same date and time fields")},
3376
3377 /* Instance methods: */
3378 {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS,
3379 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
3380
3381 {"date", (PyCFunction)datetime_getdate, METH_NOARGS,
3382 PyDoc_STR("Return date object with same year, month and day.")},
3383
3384 {"time", (PyCFunction)datetime_gettime, METH_NOARGS,
Tim Peters0bf60bd2003-01-08 20:40:01 +00003385 PyDoc_STR("Return time object with same time but with tzinfo=None.")},
Tim Peters2a799bf2002-12-16 20:18:38 +00003386
3387 {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
3388 PyDoc_STR("Return ctime() style string.")},
3389
3390 {"isoformat", (PyCFunction)datetime_isoformat, METH_KEYWORDS,
3391 PyDoc_STR("[sep] -> string in ISO 8601 format, "
3392 "YYYY-MM-DDTHH:MM:SS[.mmmmmm].\n\n"
3393 "sep is used to separate the year from the time, and "
3394 "defaults\n"
3395 "to 'T'.")},
3396
Tim Peters12bf3392002-12-24 05:41:27 +00003397 {"replace", (PyCFunction)datetime_replace, METH_KEYWORDS,
3398 PyDoc_STR("Return datetime with new specified fields.")},
3399
Tim Peters80475bb2002-12-25 07:40:55 +00003400 {"astimezone", (PyCFunction)datetime_astimezone, METH_KEYWORDS,
3401 PyDoc_STR("tz -> datetimetz with same date & time, and tzinfo=tz\n")},
3402
Tim Peters2a799bf2002-12-16 20:18:38 +00003403 {NULL, NULL}
3404};
3405
3406static char datetime_doc[] =
3407PyDoc_STR("Basic date/time type.");
3408
3409static PyNumberMethods datetime_as_number = {
3410 datetime_add, /* nb_add */
3411 datetime_subtract, /* nb_subtract */
3412 0, /* nb_multiply */
3413 0, /* nb_divide */
3414 0, /* nb_remainder */
3415 0, /* nb_divmod */
3416 0, /* nb_power */
3417 0, /* nb_negative */
3418 0, /* nb_positive */
3419 0, /* nb_absolute */
3420 0, /* nb_nonzero */
3421};
3422
3423statichere PyTypeObject PyDateTime_DateTimeType = {
3424 PyObject_HEAD_INIT(NULL)
3425 0, /* ob_size */
3426 "datetime.datetime", /* tp_name */
3427 sizeof(PyDateTime_DateTime), /* tp_basicsize */
3428 0, /* tp_itemsize */
3429 (destructor)PyObject_Del, /* tp_dealloc */
3430 0, /* tp_print */
3431 0, /* tp_getattr */
3432 0, /* tp_setattr */
3433 0, /* tp_compare */
3434 (reprfunc)datetime_repr, /* tp_repr */
3435 &datetime_as_number, /* tp_as_number */
3436 0, /* tp_as_sequence */
3437 0, /* tp_as_mapping */
3438 (hashfunc)datetime_hash, /* tp_hash */
3439 0, /* tp_call */
3440 (reprfunc)datetime_str, /* tp_str */
3441 PyObject_GenericGetAttr, /* tp_getattro */
3442 0, /* tp_setattro */
3443 0, /* tp_as_buffer */
3444 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3445 Py_TPFLAGS_BASETYPE, /* tp_flags */
3446 datetime_doc, /* tp_doc */
3447 0, /* tp_traverse */
3448 0, /* tp_clear */
3449 (richcmpfunc)datetime_richcompare, /* tp_richcompare */
3450 0, /* tp_weaklistoffset */
3451 0, /* tp_iter */
3452 0, /* tp_iternext */
3453 datetime_methods, /* tp_methods */
3454 0, /* tp_members */
3455 datetime_getset, /* tp_getset */
3456 &PyDateTime_DateType, /* tp_base */
3457 0, /* tp_dict */
3458 0, /* tp_descr_get */
3459 0, /* tp_descr_set */
3460 0, /* tp_dictoffset */
3461 0, /* tp_init */
3462 0, /* tp_alloc */
3463 datetime_new, /* tp_new */
3464 _PyObject_Del, /* tp_free */
3465};
3466
3467/*
3468 * PyDateTime_Time implementation.
3469 */
3470
3471/* Accessor properties. */
3472
3473static PyObject *
3474time_hour(PyDateTime_Time *self, void *unused)
3475{
3476 return PyInt_FromLong(TIME_GET_HOUR(self));
3477}
3478
3479static PyObject *
3480time_minute(PyDateTime_Time *self, void *unused)
3481{
3482 return PyInt_FromLong(TIME_GET_MINUTE(self));
3483}
3484
3485static PyObject *
Jack Jansen51cd8a22002-12-17 20:57:24 +00003486py_time_second(PyDateTime_Time *self, void *unused)
Tim Peters2a799bf2002-12-16 20:18:38 +00003487{
3488 return PyInt_FromLong(TIME_GET_SECOND(self));
3489}
3490
3491static PyObject *
3492time_microsecond(PyDateTime_Time *self, void *unused)
3493{
3494 return PyInt_FromLong(TIME_GET_MICROSECOND(self));
3495}
3496
3497static PyGetSetDef time_getset[] = {
3498 {"hour", (getter)time_hour},
3499 {"minute", (getter)time_minute},
Jack Jansen51cd8a22002-12-17 20:57:24 +00003500 {"second", (getter)py_time_second},
Tim Peters2a799bf2002-12-16 20:18:38 +00003501 {"microsecond", (getter)time_microsecond},
3502 {NULL}
3503};
3504
3505/* Constructors. */
3506
Tim Peters12bf3392002-12-24 05:41:27 +00003507static char *time_kws[] = {"hour", "minute", "second", "microsecond", NULL};
3508
Tim Peters2a799bf2002-12-16 20:18:38 +00003509static PyObject *
3510time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
3511{
3512 PyObject *self = NULL;
3513 int hour = 0;
3514 int minute = 0;
3515 int second = 0;
3516 int usecond = 0;
3517
Tim Peters2a799bf2002-12-16 20:18:38 +00003518
Tim Peters12bf3392002-12-24 05:41:27 +00003519 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiii", time_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00003520 &hour, &minute, &second, &usecond)) {
3521 if (check_time_args(hour, minute, second, usecond) < 0)
3522 return NULL;
3523 self = new_time(hour, minute, second, usecond);
3524 }
3525 return self;
3526}
3527
3528/* Various ways to turn a time into a string. */
3529
3530static PyObject *
3531time_repr(PyDateTime_Time *self)
3532{
3533 char buffer[100];
3534 char *typename = self->ob_type->tp_name;
3535 int h = TIME_GET_HOUR(self);
3536 int m = TIME_GET_MINUTE(self);
3537 int s = TIME_GET_SECOND(self);
3538 int us = TIME_GET_MICROSECOND(self);
3539
3540 if (us)
3541 PyOS_snprintf(buffer, sizeof(buffer),
3542 "%s(%d, %d, %d, %d)", typename, h, m, s, us);
3543 else if (s)
3544 PyOS_snprintf(buffer, sizeof(buffer),
3545 "%s(%d, %d, %d)", typename, h, m, s);
3546 else
3547 PyOS_snprintf(buffer, sizeof(buffer),
3548 "%s(%d, %d)", typename, h, m);
3549 return PyString_FromString(buffer);
3550}
3551
3552static PyObject *
3553time_str(PyDateTime_Time *self)
3554{
3555 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
3556}
3557
3558static PyObject *
3559time_isoformat(PyDateTime_Time *self)
3560{
3561 char buffer[100];
3562 /* Reuse the time format code from the datetime type. */
3563 PyDateTime_DateTime datetime;
3564 PyDateTime_DateTime *pdatetime = &datetime;
3565
3566 /* Copy over just the time bytes. */
3567 memcpy(pdatetime->data + _PyDateTime_DATE_DATASIZE,
3568 self->data,
3569 _PyDateTime_TIME_DATASIZE);
3570
3571 isoformat_time(pdatetime, buffer, sizeof(buffer));
3572 return PyString_FromString(buffer);
3573}
3574
3575static PyObject *
3576time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3577{
3578 PyObject *result;
3579 PyObject *format;
3580 PyObject *tuple;
3581 static char *keywords[] = {"format", NULL};
3582
3583 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
3584 &PyString_Type, &format))
3585 return NULL;
3586
Tim Peters83b85f12002-12-22 20:34:46 +00003587 /* Python's strftime does insane things with the year part of the
3588 * timetuple. The year is forced to (the otherwise nonsensical)
3589 * 1900 to worm around that.
3590 */
Tim Peters2a799bf2002-12-16 20:18:38 +00003591 tuple = Py_BuildValue("iiiiiiiii",
Tim Peters83b85f12002-12-22 20:34:46 +00003592 1900, 0, 0, /* year, month, day */
Tim Peters2a799bf2002-12-16 20:18:38 +00003593 TIME_GET_HOUR(self),
3594 TIME_GET_MINUTE(self),
3595 TIME_GET_SECOND(self),
3596 0, 0, -1); /* weekday, daynum, dst */
3597 if (tuple == NULL)
3598 return NULL;
3599 assert(PyTuple_Size(tuple) == 9);
Tim Petersbad8ff02002-12-30 20:52:32 +00003600 result = wrap_strftime((PyObject *)self, format, tuple, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003601 Py_DECREF(tuple);
3602 return result;
3603}
3604
3605/* Miscellaneous methods. */
3606
3607/* This is more natural as a tp_compare, but doesn't work then: for whatever
3608 * reason, Python's try_3way_compare ignores tp_compare unless
3609 * PyInstance_Check returns true, but these aren't old-style classes.
3610 * Note that this routine handles all comparisons for time and timetz.
3611 */
3612static PyObject *
3613time_richcompare(PyDateTime_Time *self, PyObject *other, int op)
3614{
3615 int diff;
3616 naivety n1, n2;
3617 int offset1, offset2;
3618
3619 if (! PyTime_Check(other)) {
3620 /* Stop this from falling back to address comparison. */
3621 PyErr_Format(PyExc_TypeError,
3622 "can't compare '%s' to '%s'",
3623 self->ob_type->tp_name,
3624 other->ob_type->tp_name);
3625 return NULL;
3626 }
Tim Peterse39a80c2002-12-30 21:28:52 +00003627 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1, Py_None,
3628 other, &offset2, &n2, Py_None) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003629 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003630 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00003631 /* If they're both naive, or both aware and have the same offsets,
3632 * we get off cheap. Note that if they're both naive, offset1 ==
3633 * offset2 == 0 at this point.
3634 */
3635 if (n1 == n2 && offset1 == offset2) {
3636 diff = memcmp(self->data, ((PyDateTime_Time *)other)->data,
3637 _PyDateTime_TIME_DATASIZE);
3638 return diff_to_bool(diff, op);
3639 }
3640
3641 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3642 assert(offset1 != offset2); /* else last "if" handled it */
3643 /* Convert everything except microseconds to seconds. These
3644 * can't overflow (no more than the # of seconds in 2 days).
3645 */
3646 offset1 = TIME_GET_HOUR(self) * 3600 +
3647 (TIME_GET_MINUTE(self) - offset1) * 60 +
3648 TIME_GET_SECOND(self);
3649 offset2 = TIME_GET_HOUR(other) * 3600 +
3650 (TIME_GET_MINUTE(other) - offset2) * 60 +
3651 TIME_GET_SECOND(other);
3652 diff = offset1 - offset2;
3653 if (diff == 0)
3654 diff = TIME_GET_MICROSECOND(self) -
3655 TIME_GET_MICROSECOND(other);
3656 return diff_to_bool(diff, op);
3657 }
3658
3659 assert(n1 != n2);
3660 PyErr_SetString(PyExc_TypeError,
3661 "can't compare offset-naive and "
3662 "offset-aware times");
3663 return NULL;
3664}
3665
Tim Peters2a799bf2002-12-16 20:18:38 +00003666static long
3667time_hash(PyDateTime_Time *self)
3668{
3669 if (self->hashcode == -1) {
3670 naivety n;
3671 int offset;
3672 PyObject *temp;
3673
Tim Peterse39a80c2002-12-30 21:28:52 +00003674 n = classify_utcoffset((PyObject *)self, Py_None, &offset);
Tim Peters2a799bf2002-12-16 20:18:38 +00003675 assert(n != OFFSET_UNKNOWN);
3676 if (n == OFFSET_ERROR)
3677 return -1;
3678
3679 /* Reduce this to a hash of another object. */
3680 if (offset == 0)
Tim Peters33e0f382003-01-10 02:05:14 +00003681 temp = PyString_FromStringAndSize((char *)self->data,
3682 _PyDateTime_TIME_DATASIZE);
Tim Peters2a799bf2002-12-16 20:18:38 +00003683 else {
3684 int hour;
3685 int minute;
3686
3687 assert(n == OFFSET_AWARE);
3688 assert(PyTimeTZ_Check(self));
3689 hour = divmod(TIME_GET_HOUR(self) * 60 +
3690 TIME_GET_MINUTE(self) - offset,
3691 60,
3692 &minute);
3693 if (0 <= hour && hour < 24)
3694 temp = new_time(hour, minute,
3695 TIME_GET_SECOND(self),
3696 TIME_GET_MICROSECOND(self));
3697 else
3698 temp = Py_BuildValue("iiii",
3699 hour, minute,
3700 TIME_GET_SECOND(self),
3701 TIME_GET_MICROSECOND(self));
3702 }
3703 if (temp != NULL) {
3704 self->hashcode = PyObject_Hash(temp);
3705 Py_DECREF(temp);
3706 }
3707 }
3708 return self->hashcode;
3709}
3710
Tim Peters12bf3392002-12-24 05:41:27 +00003711static PyObject *
3712time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3713{
3714 PyObject *clone;
3715 PyObject *tuple;
3716 int hh = TIME_GET_HOUR(self);
3717 int mm = TIME_GET_MINUTE(self);
3718 int ss = TIME_GET_SECOND(self);
3719 int us = TIME_GET_MICROSECOND(self);
3720
3721 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiii:replace",
3722 time_kws,
3723 &hh, &mm, &ss, &us))
3724 return NULL;
3725 tuple = Py_BuildValue("iiii", hh, mm, ss, us);
3726 if (tuple == NULL)
3727 return NULL;
3728 clone = time_new(self->ob_type, tuple, NULL);
3729 Py_DECREF(tuple);
3730 return clone;
3731}
3732
Tim Peters2a799bf2002-12-16 20:18:38 +00003733static int
3734time_nonzero(PyDateTime_Time *self)
3735{
3736 return TIME_GET_HOUR(self) ||
3737 TIME_GET_MINUTE(self) ||
3738 TIME_GET_SECOND(self) ||
3739 TIME_GET_MICROSECOND(self);
3740}
3741
Tim Peters2a799bf2002-12-16 20:18:38 +00003742static PyMethodDef time_methods[] = {
3743 {"isoformat", (PyCFunction)time_isoformat, METH_KEYWORDS,
3744 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm].")},
3745
3746 {"strftime", (PyCFunction)time_strftime, METH_KEYWORDS,
3747 PyDoc_STR("format -> strftime() style string.")},
3748
Tim Peters12bf3392002-12-24 05:41:27 +00003749 {"replace", (PyCFunction)time_replace, METH_KEYWORDS,
3750 PyDoc_STR("Return datetime with new specified fields.")},
Tim Peters2a799bf2002-12-16 20:18:38 +00003751 {NULL, NULL}
3752};
3753
3754static char time_doc[] =
3755PyDoc_STR("Basic time type.");
3756
3757static PyNumberMethods time_as_number = {
3758 0, /* nb_add */
3759 0, /* nb_subtract */
3760 0, /* nb_multiply */
3761 0, /* nb_divide */
3762 0, /* nb_remainder */
3763 0, /* nb_divmod */
3764 0, /* nb_power */
3765 0, /* nb_negative */
3766 0, /* nb_positive */
3767 0, /* nb_absolute */
3768 (inquiry)time_nonzero, /* nb_nonzero */
3769};
3770
3771statichere PyTypeObject PyDateTime_TimeType = {
3772 PyObject_HEAD_INIT(NULL)
3773 0, /* ob_size */
3774 "datetime.time", /* tp_name */
3775 sizeof(PyDateTime_Time), /* tp_basicsize */
3776 0, /* tp_itemsize */
3777 (destructor)PyObject_Del, /* tp_dealloc */
3778 0, /* tp_print */
3779 0, /* tp_getattr */
3780 0, /* tp_setattr */
3781 0, /* tp_compare */
3782 (reprfunc)time_repr, /* tp_repr */
3783 &time_as_number, /* tp_as_number */
3784 0, /* tp_as_sequence */
3785 0, /* tp_as_mapping */
3786 (hashfunc)time_hash, /* tp_hash */
3787 0, /* tp_call */
3788 (reprfunc)time_str, /* tp_str */
3789 PyObject_GenericGetAttr, /* tp_getattro */
3790 0, /* tp_setattro */
3791 0, /* tp_as_buffer */
3792 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3793 Py_TPFLAGS_BASETYPE, /* tp_flags */
3794 time_doc, /* tp_doc */
3795 0, /* tp_traverse */
3796 0, /* tp_clear */
3797 (richcmpfunc)time_richcompare, /* tp_richcompare */
3798 0, /* tp_weaklistoffset */
3799 0, /* tp_iter */
3800 0, /* tp_iternext */
3801 time_methods, /* tp_methods */
3802 0, /* tp_members */
3803 time_getset, /* tp_getset */
3804 0, /* tp_base */
3805 0, /* tp_dict */
3806 0, /* tp_descr_get */
3807 0, /* tp_descr_set */
3808 0, /* tp_dictoffset */
3809 0, /* tp_init */
3810 0, /* tp_alloc */
3811 time_new, /* tp_new */
3812 _PyObject_Del, /* tp_free */
3813};
3814
3815/*
3816 * PyDateTime_TZInfo implementation.
3817 */
3818
3819/* This is a pure abstract base class, so doesn't do anything beyond
3820 * raising NotImplemented exceptions. Real tzinfo classes need
3821 * to derive from this. This is mostly for clarity, and for efficiency in
3822 * datetimetz and timetz constructors (their tzinfo arguments need to
3823 * be subclasses of this tzinfo class, which is easy and quick to check).
3824 *
3825 * Note: For reasons having to do with pickling of subclasses, we have
3826 * to allow tzinfo objects to be instantiated. This wasn't an issue
3827 * in the Python implementation (__init__() could raise NotImplementedError
3828 * there without ill effect), but doing so in the C implementation hit a
3829 * brick wall.
3830 */
3831
3832static PyObject *
3833tzinfo_nogo(const char* methodname)
3834{
3835 PyErr_Format(PyExc_NotImplementedError,
3836 "a tzinfo subclass must implement %s()",
3837 methodname);
3838 return NULL;
3839}
3840
3841/* Methods. A subclass must implement these. */
3842
3843static PyObject*
3844tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt)
3845{
3846 return tzinfo_nogo("tzname");
3847}
3848
3849static PyObject*
3850tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt)
3851{
3852 return tzinfo_nogo("utcoffset");
3853}
3854
3855static PyObject*
3856tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
3857{
3858 return tzinfo_nogo("dst");
3859}
3860
3861/*
3862 * Pickle support. This is solely so that tzinfo subclasses can use
3863 * pickling -- tzinfo itself is supposed to be uninstantiable. The
3864 * pickler and unpickler functions are given module-level private
3865 * names, and registered with copy_reg, by the module init function.
3866 */
3867
3868static PyObject*
3869tzinfo_pickler(PyDateTime_TZInfo *self) {
3870 return Py_BuildValue("O()", tzinfo_unpickler_object);
3871}
3872
3873static PyObject*
3874tzinfo_unpickler(PyObject * unused) {
3875 return PyType_GenericNew(&PyDateTime_TZInfoType, NULL, NULL);
3876}
3877
3878
3879static PyMethodDef tzinfo_methods[] = {
3880 {"tzname", (PyCFunction)tzinfo_tzname, METH_O,
3881 PyDoc_STR("datetime -> string name of time zone.")},
3882
3883 {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
3884 PyDoc_STR("datetime -> minutes east of UTC (negative for "
3885 "west of UTC).")},
3886
3887 {"dst", (PyCFunction)tzinfo_dst, METH_O,
3888 PyDoc_STR("datetime -> DST offset in minutes east of UTC.")},
3889
3890 {NULL, NULL}
3891};
3892
3893static char tzinfo_doc[] =
3894PyDoc_STR("Abstract base class for time zone info objects.");
3895
3896 statichere PyTypeObject PyDateTime_TZInfoType = {
3897 PyObject_HEAD_INIT(NULL)
3898 0, /* ob_size */
3899 "datetime.tzinfo", /* tp_name */
3900 sizeof(PyDateTime_TZInfo), /* tp_basicsize */
3901 0, /* tp_itemsize */
3902 0, /* tp_dealloc */
3903 0, /* tp_print */
3904 0, /* tp_getattr */
3905 0, /* tp_setattr */
3906 0, /* tp_compare */
3907 0, /* tp_repr */
3908 0, /* tp_as_number */
3909 0, /* tp_as_sequence */
3910 0, /* tp_as_mapping */
3911 0, /* tp_hash */
3912 0, /* tp_call */
3913 0, /* tp_str */
3914 PyObject_GenericGetAttr, /* tp_getattro */
3915 0, /* tp_setattro */
3916 0, /* tp_as_buffer */
3917 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3918 Py_TPFLAGS_BASETYPE, /* tp_flags */
3919 tzinfo_doc, /* tp_doc */
3920 0, /* tp_traverse */
3921 0, /* tp_clear */
3922 0, /* tp_richcompare */
3923 0, /* tp_weaklistoffset */
3924 0, /* tp_iter */
3925 0, /* tp_iternext */
3926 tzinfo_methods, /* tp_methods */
3927 0, /* tp_members */
3928 0, /* tp_getset */
3929 0, /* tp_base */
3930 0, /* tp_dict */
3931 0, /* tp_descr_get */
3932 0, /* tp_descr_set */
3933 0, /* tp_dictoffset */
3934 0, /* tp_init */
3935 0, /* tp_alloc */
3936 PyType_GenericNew, /* tp_new */
3937 0, /* tp_free */
3938};
3939
3940/*
3941 * PyDateTime_TimeTZ implementation.
3942 */
3943
3944/* Accessor properties. Properties for hour, minute, second and microsecond
3945 * are inherited from time.
3946 */
3947
3948static PyObject *
3949timetz_tzinfo(PyDateTime_TimeTZ *self, void *unused)
3950{
3951 Py_INCREF(self->tzinfo);
3952 return self->tzinfo;
3953}
3954
3955static PyGetSetDef timetz_getset[] = {
3956 {"tzinfo", (getter)timetz_tzinfo},
3957 {NULL}
3958};
3959
3960/*
3961 * Constructors.
3962 */
3963
Tim Peters12bf3392002-12-24 05:41:27 +00003964static char *timetz_kws[] = {"hour", "minute", "second", "microsecond",
3965 "tzinfo", NULL};
3966
Tim Peters2a799bf2002-12-16 20:18:38 +00003967static PyObject *
3968timetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
3969{
3970 PyObject *self = NULL;
3971 int hour = 0;
3972 int minute = 0;
3973 int second = 0;
3974 int usecond = 0;
3975 PyObject *tzinfo = Py_None;
3976
Tim Peters12bf3392002-12-24 05:41:27 +00003977 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", timetz_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00003978 &hour, &minute, &second, &usecond,
3979 &tzinfo)) {
3980 if (check_time_args(hour, minute, second, usecond) < 0)
3981 return NULL;
3982 if (check_tzinfo_subclass(tzinfo) < 0)
3983 return NULL;
3984 self = new_timetz(hour, minute, second, usecond, tzinfo);
3985 }
3986 return self;
3987}
3988
3989/*
3990 * Destructor.
3991 */
3992
3993static void
3994timetz_dealloc(PyDateTime_TimeTZ *self)
3995{
3996 Py_XDECREF(self->tzinfo);
3997 self->ob_type->tp_free((PyObject *)self);
3998}
3999
4000/*
Tim Peters855fe882002-12-22 03:43:39 +00004001 * Indirect access to tzinfo methods.
Tim Peters2a799bf2002-12-16 20:18:38 +00004002 */
4003
Tim Peters2a799bf2002-12-16 20:18:38 +00004004/* These are all METH_NOARGS, so don't need to check the arglist. */
4005static PyObject *
4006timetz_utcoffset(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004007 return offset_as_timedelta(self->tzinfo, "utcoffset", Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004008}
4009
4010static PyObject *
4011timetz_dst(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004012 return offset_as_timedelta(self->tzinfo, "dst", Py_None);
Tim Peters855fe882002-12-22 03:43:39 +00004013}
4014
4015static PyObject *
4016timetz_tzname(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004017 return call_tzname(self->tzinfo, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004018}
4019
4020/*
4021 * Various ways to turn a timetz into a string.
4022 */
4023
4024static PyObject *
4025timetz_repr(PyDateTime_TimeTZ *self)
4026{
4027 PyObject *baserepr = time_repr((PyDateTime_Time *)self);
4028
4029 if (baserepr == NULL)
4030 return NULL;
4031 return append_keyword_tzinfo(baserepr, self->tzinfo);
4032}
4033
4034/* Note: tp_str is inherited from time. */
4035
4036static PyObject *
4037timetz_isoformat(PyDateTime_TimeTZ *self)
4038{
4039 char buf[100];
4040 PyObject *result = time_isoformat((PyDateTime_Time *)self);
4041
4042 if (result == NULL || self->tzinfo == Py_None)
4043 return result;
4044
4045 /* We need to append the UTC offset. */
4046 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00004047 Py_None) < 0) {
Tim Peters2a799bf2002-12-16 20:18:38 +00004048 Py_DECREF(result);
4049 return NULL;
4050 }
4051 PyString_ConcatAndDel(&result, PyString_FromString(buf));
4052 return result;
4053}
4054
4055/* Note: strftime() is inherited from time. */
4056
4057/*
4058 * Miscellaneous methods.
4059 */
4060
4061/* Note: tp_richcompare and tp_hash are inherited from time. */
4062
Tim Peters12bf3392002-12-24 05:41:27 +00004063static PyObject *
4064timetz_replace(PyDateTime_TimeTZ *self, PyObject *args, PyObject *kw)
4065{
4066 PyObject *clone;
4067 PyObject *tuple;
4068 int hh = TIME_GET_HOUR(self);
4069 int mm = TIME_GET_MINUTE(self);
4070 int ss = TIME_GET_SECOND(self);
4071 int us = TIME_GET_MICROSECOND(self);
4072 PyObject *tzinfo = self->tzinfo;
4073
4074 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
4075 timetz_kws,
4076 &hh, &mm, &ss, &us, &tzinfo))
4077 return NULL;
4078 tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
4079 if (tuple == NULL)
4080 return NULL;
4081 clone = timetz_new(self->ob_type, tuple, NULL);
4082 Py_DECREF(tuple);
4083 return clone;
4084}
4085
Tim Peters2a799bf2002-12-16 20:18:38 +00004086static int
4087timetz_nonzero(PyDateTime_TimeTZ *self)
4088{
4089 int offset;
4090 int none;
4091
4092 if (TIME_GET_SECOND(self) || TIME_GET_MICROSECOND(self)) {
4093 /* Since utcoffset is in whole minutes, nothing can
4094 * alter the conclusion that this is nonzero.
4095 */
4096 return 1;
4097 }
4098 offset = 0;
4099 if (self->tzinfo != Py_None) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004100 offset = call_utcoffset(self->tzinfo, Py_None, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +00004101 if (offset == -1 && PyErr_Occurred())
4102 return -1;
4103 }
4104 return (TIME_GET_MINUTE(self) - offset + TIME_GET_HOUR(self)*60) != 0;
4105}
4106
4107/*
4108 * Pickle support. Quite a maze!
4109 */
4110
Tim Peters33e0f382003-01-10 02:05:14 +00004111/* Let basestate be the non-tzinfo data string.
Tim Peters2a799bf2002-12-16 20:18:38 +00004112 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4113 * So it's a tuple in any (non-error) case.
4114 */
4115static PyObject *
4116timetz_getstate(PyDateTime_TimeTZ *self)
4117{
4118 PyObject *basestate;
4119 PyObject *result = NULL;
4120
Tim Peters33e0f382003-01-10 02:05:14 +00004121 basestate = PyString_FromStringAndSize((char *)self->data,
4122 _PyDateTime_TIME_DATASIZE);
Tim Peters2a799bf2002-12-16 20:18:38 +00004123 if (basestate != NULL) {
4124 if (self->tzinfo == Py_None)
4125 result = Py_BuildValue("(O)", basestate);
4126 else
4127 result = Py_BuildValue("OO", basestate, self->tzinfo);
4128 Py_DECREF(basestate);
4129 }
4130 return result;
4131}
4132
4133static PyObject *
4134timetz_setstate(PyDateTime_TimeTZ *self, PyObject *state)
4135{
Tim Peters2a799bf2002-12-16 20:18:38 +00004136 PyObject *basestate;
4137 PyObject *tzinfo = Py_None;
4138
4139 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
4140 &PyString_Type, &basestate,
4141 &tzinfo))
4142 return NULL;
Tim Peters33e0f382003-01-10 02:05:14 +00004143 if (PyString_Size(basestate) != _PyDateTime_TIME_DATASIZE ||
4144 check_tzinfo_subclass(tzinfo) < 0) {
4145 PyErr_SetString(PyExc_TypeError,
4146 "bad argument to time.__setstate__");
Tim Peters2a799bf2002-12-16 20:18:38 +00004147 return NULL;
Tim Peters33e0f382003-01-10 02:05:14 +00004148 }
4149 memcpy((char *)self->data,
4150 PyString_AsString(basestate),
4151 _PyDateTime_TIME_DATASIZE);
4152 self->hashcode = -1;
Tim Peters2a799bf2002-12-16 20:18:38 +00004153 Py_INCREF(tzinfo);
4154 Py_XDECREF(self->tzinfo);
4155 self->tzinfo = tzinfo;
Tim Peters2a799bf2002-12-16 20:18:38 +00004156 Py_INCREF(Py_None);
4157 return Py_None;
4158}
4159
4160static PyObject *
4161timetz_pickler(PyObject *module, PyDateTime_TimeTZ *timetz)
4162{
4163 PyObject *state;
4164 PyObject *result = NULL;
4165
4166 if (! PyTimeTZ_CheckExact(timetz)) {
4167 PyErr_Format(PyExc_TypeError,
4168 "bad type passed to timetz pickler: %s",
4169 timetz->ob_type->tp_name);
4170 return NULL;
4171 }
4172 state = timetz_getstate(timetz);
4173 if (state) {
4174 result = Py_BuildValue("O(O)",
4175 timetz_unpickler_object,
4176 state);
4177 Py_DECREF(state);
4178 }
4179 return result;
4180}
4181
4182static PyObject *
4183timetz_unpickler(PyObject *module, PyObject *arg)
4184{
4185 PyDateTime_TimeTZ *self;
4186
4187 self = PyObject_New(PyDateTime_TimeTZ, &PyDateTime_TimeTZType);
4188 if (self != NULL) {
4189 PyObject *res;
4190
4191 self->tzinfo = NULL;
4192 res = timetz_setstate(self, arg);
4193 if (res == NULL) {
4194 Py_DECREF(self);
4195 return NULL;
4196 }
4197 Py_DECREF(res);
4198 }
4199 return (PyObject *)self;
4200}
4201
4202static PyMethodDef timetz_methods[] = {
4203 {"isoformat", (PyCFunction)timetz_isoformat, METH_KEYWORDS,
4204 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]"
4205 "[+HH:MM].")},
4206
4207 {"utcoffset", (PyCFunction)timetz_utcoffset, METH_NOARGS,
4208 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
4209
4210 {"tzname", (PyCFunction)timetz_tzname, METH_NOARGS,
4211 PyDoc_STR("Return self.tzinfo.tzname(self).")},
4212
4213 {"dst", (PyCFunction)timetz_dst, METH_NOARGS,
4214 PyDoc_STR("Return self.tzinfo.dst(self).")},
4215
Tim Peters12bf3392002-12-24 05:41:27 +00004216 {"replace", (PyCFunction)timetz_replace, METH_KEYWORDS,
4217 PyDoc_STR("Return timetz with new specified fields.")},
4218
Tim Peters2a799bf2002-12-16 20:18:38 +00004219 {"__setstate__", (PyCFunction)timetz_setstate, METH_O,
4220 PyDoc_STR("__setstate__(state)")},
4221
4222 {"__getstate__", (PyCFunction)timetz_getstate, METH_NOARGS,
4223 PyDoc_STR("__getstate__() -> state")},
4224 {NULL, NULL}
4225
4226};
4227
4228static char timetz_doc[] =
4229PyDoc_STR("Time type.");
4230
4231static PyNumberMethods timetz_as_number = {
4232 0, /* nb_add */
4233 0, /* nb_subtract */
4234 0, /* nb_multiply */
4235 0, /* nb_divide */
4236 0, /* nb_remainder */
4237 0, /* nb_divmod */
4238 0, /* nb_power */
4239 0, /* nb_negative */
4240 0, /* nb_positive */
4241 0, /* nb_absolute */
4242 (inquiry)timetz_nonzero, /* nb_nonzero */
4243};
4244
4245statichere PyTypeObject PyDateTime_TimeTZType = {
4246 PyObject_HEAD_INIT(NULL)
4247 0, /* ob_size */
Tim Peters0bf60bd2003-01-08 20:40:01 +00004248 "datetime.time", /* tp_name */
Tim Peters2a799bf2002-12-16 20:18:38 +00004249 sizeof(PyDateTime_TimeTZ), /* tp_basicsize */
4250 0, /* tp_itemsize */
4251 (destructor)timetz_dealloc, /* tp_dealloc */
4252 0, /* tp_print */
4253 0, /* tp_getattr */
4254 0, /* tp_setattr */
4255 0, /* tp_compare */
4256 (reprfunc)timetz_repr, /* tp_repr */
4257 &timetz_as_number, /* tp_as_number */
4258 0, /* tp_as_sequence */
4259 0, /* tp_as_mapping */
4260 0, /* tp_hash */
4261 0, /* tp_call */
4262 0, /* tp_str */
4263 PyObject_GenericGetAttr, /* tp_getattro */
4264 0, /* tp_setattro */
4265 0, /* tp_as_buffer */
4266 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4267 Py_TPFLAGS_BASETYPE, /* tp_flags */
Guido van Rossumbd43e912002-12-16 20:34:55 +00004268 timetz_doc, /* tp_doc */
Tim Peters2a799bf2002-12-16 20:18:38 +00004269 0, /* tp_traverse */
4270 0, /* tp_clear */
4271 0, /* tp_richcompare */
4272 0, /* tp_weaklistoffset */
4273 0, /* tp_iter */
4274 0, /* tp_iternext */
4275 timetz_methods, /* tp_methods */
4276 0, /* tp_members */
4277 timetz_getset, /* tp_getset */
4278 &PyDateTime_TimeType, /* tp_base */
4279 0, /* tp_dict */
4280 0, /* tp_descr_get */
4281 0, /* tp_descr_set */
4282 0, /* tp_dictoffset */
4283 0, /* tp_init */
4284 0, /* tp_alloc */
4285 timetz_new, /* tp_new */
4286 _PyObject_Del, /* tp_free */
4287};
4288
4289/*
4290 * PyDateTime_DateTimeTZ implementation.
4291 */
4292
4293/* Accessor properties. Properties for day, month, year, hour, minute,
4294 * second and microsecond are inherited from datetime.
4295 */
4296
4297static PyObject *
4298datetimetz_tzinfo(PyDateTime_DateTimeTZ *self, void *unused)
4299{
4300 Py_INCREF(self->tzinfo);
4301 return self->tzinfo;
4302}
4303
4304static PyGetSetDef datetimetz_getset[] = {
4305 {"tzinfo", (getter)datetimetz_tzinfo},
4306 {NULL}
4307};
4308
4309/*
4310 * Constructors.
4311 * These are like the datetime methods of the same names, but allow an
4312 * optional tzinfo argument.
4313 */
4314
Tim Peters12bf3392002-12-24 05:41:27 +00004315static char *datetimetz_kws[] = {
4316 "year", "month", "day", "hour", "minute", "second",
4317 "microsecond", "tzinfo", NULL
4318};
4319
Tim Peters2a799bf2002-12-16 20:18:38 +00004320static PyObject *
4321datetimetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4322{
4323 PyObject *self = NULL;
4324 int year;
4325 int month;
4326 int day;
4327 int hour = 0;
4328 int minute = 0;
4329 int second = 0;
4330 int usecond = 0;
4331 PyObject *tzinfo = Py_None;
4332
Tim Peters12bf3392002-12-24 05:41:27 +00004333 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO", datetimetz_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00004334 &year, &month, &day, &hour, &minute,
4335 &second, &usecond, &tzinfo)) {
4336 if (check_date_args(year, month, day) < 0)
4337 return NULL;
4338 if (check_time_args(hour, minute, second, usecond) < 0)
4339 return NULL;
4340 if (check_tzinfo_subclass(tzinfo) < 0)
4341 return NULL;
4342 self = new_datetimetz(year, month, day,
4343 hour, minute, second, usecond,
4344 tzinfo);
4345 }
4346 return self;
4347}
4348
4349/* Return best possible local time -- this isn't constrained by the
4350 * precision of a timestamp.
4351 */
4352static PyObject *
4353datetimetz_now(PyObject *cls, PyObject *args, PyObject *kw)
4354{
4355 PyObject *self = NULL;
4356 PyObject *tzinfo = Py_None;
4357 static char *keywords[] = {"tzinfo", NULL};
4358
4359 if (PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords,
4360 &tzinfo)) {
4361 if (check_tzinfo_subclass(tzinfo) < 0)
4362 return NULL;
4363 self = datetime_best_possible(cls, localtime);
4364 if (self != NULL)
4365 replace_tzinfo(self, tzinfo);
4366 }
4367 return self;
4368}
4369
4370/* Return new local datetime from timestamp (Python timestamp -- a double). */
4371static PyObject *
4372datetimetz_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
4373{
4374 PyObject *self = NULL;
4375 double timestamp;
4376 PyObject *tzinfo = Py_None;
4377 static char *keywords[] = {"timestamp", "tzinfo", NULL};
4378
4379 if (PyArg_ParseTupleAndKeywords(args, kw, "d|O:fromtimestamp",
4380 keywords, &timestamp, &tzinfo)) {
4381 if (check_tzinfo_subclass(tzinfo) < 0)
4382 return NULL;
4383 self = datetime_from_timestamp(cls, localtime, timestamp);
4384 if (self != NULL)
4385 replace_tzinfo(self, tzinfo);
4386 }
4387 return self;
4388}
4389
4390/* Note: utcnow() is inherited, and doesn't accept tzinfo.
4391 * Ditto utcfromtimestamp(). Ditto combine().
4392 */
4393
4394
4395/*
4396 * Destructor.
4397 */
4398
4399static void
4400datetimetz_dealloc(PyDateTime_DateTimeTZ *self)
4401{
4402 Py_XDECREF(self->tzinfo);
4403 self->ob_type->tp_free((PyObject *)self);
4404}
4405
4406/*
4407 * Indirect access to tzinfo methods.
4408 */
4409
Tim Peters2a799bf2002-12-16 20:18:38 +00004410/* These are all METH_NOARGS, so don't need to check the arglist. */
4411static PyObject *
4412datetimetz_utcoffset(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004413 return offset_as_timedelta(self->tzinfo, "utcoffset",
4414 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00004415}
4416
4417static PyObject *
4418datetimetz_dst(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004419 return offset_as_timedelta(self->tzinfo, "dst", (PyObject *)self);
Tim Peters855fe882002-12-22 03:43:39 +00004420}
4421
4422static PyObject *
4423datetimetz_tzname(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004424 return call_tzname(self->tzinfo, (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00004425}
4426
4427/*
4428 * datetimetz arithmetic.
4429 */
4430
4431/* If base is Py_NotImplemented or NULL, just return it.
4432 * Else base is a datetime, exactly one of {left, right} is a datetimetz,
4433 * and we want to create a datetimetz with the same date and time fields
4434 * as base, and with the tzinfo field from left or right. Do that,
4435 * return it, and decref base. This is used to transform the result of
4436 * a binary datetime operation (base) into a datetimetz result.
4437 */
4438static PyObject *
4439attach_tzinfo(PyObject *base, PyObject *left, PyObject *right)
4440{
4441 PyDateTime_DateTimeTZ *self;
4442 PyDateTime_DateTimeTZ *result;
4443
4444 if (base == NULL || base == Py_NotImplemented)
4445 return base;
4446
4447 assert(PyDateTime_CheckExact(base));
4448
4449 if (PyDateTimeTZ_Check(left)) {
4450 assert(! PyDateTimeTZ_Check(right));
4451 self = (PyDateTime_DateTimeTZ *)left;
4452 }
4453 else {
4454 assert(PyDateTimeTZ_Check(right));
4455 self = (PyDateTime_DateTimeTZ *)right;
4456 }
4457 result = PyObject_New(PyDateTime_DateTimeTZ,
4458 &PyDateTime_DateTimeTZType);
4459 if (result != NULL) {
4460 memcpy(result->data, ((PyDateTime_DateTime *)base)->data,
4461 _PyDateTime_DATETIME_DATASIZE);
4462 Py_INCREF(self->tzinfo);
4463 result->tzinfo = self->tzinfo;
4464 }
4465 Py_DECREF(base);
4466 return (PyObject *)result;
4467}
4468
4469static PyObject *
4470datetimetz_add(PyObject *left, PyObject *right)
4471{
4472 return attach_tzinfo(datetime_add(left, right), left, right);
4473}
4474
4475static PyObject *
4476datetimetz_subtract(PyObject *left, PyObject *right)
4477{
4478 PyObject *result = Py_NotImplemented;
4479
4480 if (PyDateTime_Check(left)) {
4481 /* datetime - ??? */
4482 if (PyDateTime_Check(right)) {
4483 /* datetime - datetime */
4484 naivety n1, n2;
4485 int offset1, offset2;
4486 PyDateTime_Delta *delta;
4487
Tim Peterse39a80c2002-12-30 21:28:52 +00004488 if (classify_two_utcoffsets(left, &offset1, &n1, left,
4489 right, &offset2, &n2,
4490 right) < 0)
Tim Peters00237032002-12-27 02:21:51 +00004491 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00004492 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00004493 if (n1 != n2) {
4494 PyErr_SetString(PyExc_TypeError,
4495 "can't subtract offset-naive and "
4496 "offset-aware datetimes");
4497 return NULL;
4498 }
4499 delta = (PyDateTime_Delta *)sub_datetime_datetime(
4500 (PyDateTime_DateTime *)left,
4501 (PyDateTime_DateTime *)right);
4502 if (delta == NULL || offset1 == offset2)
4503 return (PyObject *)delta;
4504 /* (left - offset1) - (right - offset2) =
4505 * (left - right) + (offset2 - offset1)
4506 */
4507 result = new_delta(delta->days,
4508 delta->seconds +
4509 (offset2 - offset1) * 60,
4510 delta->microseconds,
4511 1);
4512 Py_DECREF(delta);
4513 }
4514 else if (PyDelta_Check(right)) {
4515 /* datetimetz - delta */
4516 result = sub_datetime_timedelta(
4517 (PyDateTime_DateTime *)left,
4518 (PyDateTime_Delta *)right);
4519 result = attach_tzinfo(result, left, right);
4520 }
4521 }
4522
4523 if (result == Py_NotImplemented)
4524 Py_INCREF(result);
4525 return result;
4526}
4527
4528/* Various ways to turn a datetime into a string. */
4529
4530static PyObject *
4531datetimetz_repr(PyDateTime_DateTimeTZ *self)
4532{
4533 PyObject *baserepr = datetime_repr((PyDateTime_DateTime *)self);
4534
4535 if (baserepr == NULL)
4536 return NULL;
4537 return append_keyword_tzinfo(baserepr, self->tzinfo);
4538}
4539
4540/* Note: tp_str is inherited from datetime. */
4541
4542static PyObject *
4543datetimetz_isoformat(PyDateTime_DateTimeTZ *self,
4544 PyObject *args, PyObject *kw)
4545{
4546 char buf[100];
4547 PyObject *result = datetime_isoformat((PyDateTime_DateTime *)self,
4548 args, kw);
4549
4550 if (result == NULL || self->tzinfo == Py_None)
4551 return result;
4552
4553 /* We need to append the UTC offset. */
4554 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
4555 (PyObject *)self) < 0) {
4556 Py_DECREF(result);
4557 return NULL;
4558 }
4559 PyString_ConcatAndDel(&result, PyString_FromString(buf));
4560 return result;
4561}
4562
4563/* Miscellaneous methods. */
4564
4565/* Note: tp_richcompare and tp_hash are inherited from datetime. */
4566
4567static PyObject *
Tim Peters12bf3392002-12-24 05:41:27 +00004568datetimetz_replace(PyDateTime_DateTimeTZ *self, PyObject *args, PyObject *kw)
4569{
4570 PyObject *clone;
4571 PyObject *tuple;
4572 int y = GET_YEAR(self);
4573 int m = GET_MONTH(self);
4574 int d = GET_DAY(self);
4575 int hh = DATE_GET_HOUR(self);
4576 int mm = DATE_GET_MINUTE(self);
4577 int ss = DATE_GET_SECOND(self);
4578 int us = DATE_GET_MICROSECOND(self);
4579 PyObject *tzinfo = self->tzinfo;
4580
4581 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO:replace",
4582 datetimetz_kws,
4583 &y, &m, &d, &hh, &mm, &ss, &us,
4584 &tzinfo))
4585 return NULL;
4586 tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
4587 if (tuple == NULL)
4588 return NULL;
4589 clone = datetimetz_new(self->ob_type, tuple, NULL);
4590 Py_DECREF(tuple);
4591 return clone;
4592}
4593
4594static PyObject *
Tim Peters80475bb2002-12-25 07:40:55 +00004595datetimetz_astimezone(PyDateTime_DateTimeTZ *self, PyObject *args,
4596 PyObject *kw)
4597{
4598 int y = GET_YEAR(self);
4599 int m = GET_MONTH(self);
4600 int d = GET_DAY(self);
4601 int hh = DATE_GET_HOUR(self);
4602 int mm = DATE_GET_MINUTE(self);
4603 int ss = DATE_GET_SECOND(self);
4604 int us = DATE_GET_MICROSECOND(self);
4605
Tim Peters521fc152002-12-31 17:36:56 +00004606 PyObject *result;
4607 PyObject *temp;
Tim Petersadf64202003-01-04 06:03:15 +00004608 int selfoff, resoff, dst1, dst2;
Tim Peters521fc152002-12-31 17:36:56 +00004609 int none;
Tim Petersf3615152003-01-01 21:51:37 +00004610 int delta;
Tim Peters521fc152002-12-31 17:36:56 +00004611
Tim Peters80475bb2002-12-25 07:40:55 +00004612 PyObject *tzinfo;
4613 static char *keywords[] = {"tz", NULL};
4614
4615 if (! PyArg_ParseTupleAndKeywords(args, kw, "O:astimezone", keywords,
4616 &tzinfo))
4617 return NULL;
4618 if (check_tzinfo_subclass(tzinfo) < 0)
4619 return NULL;
4620
Tim Peters521fc152002-12-31 17:36:56 +00004621 /* Don't call utcoffset unless necessary. */
4622 result = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4623 if (result == NULL ||
4624 tzinfo == Py_None ||
4625 self->tzinfo == Py_None ||
4626 self->tzinfo == tzinfo)
4627 return result;
4628
4629 /* Get the offsets. If either object turns out to be naive, again
4630 * there's no conversion of date or time fields.
4631 */
Tim Petersb5a16f32003-01-01 04:48:01 +00004632 selfoff = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4633 if (selfoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004634 goto Fail;
4635 if (none)
4636 return result;
4637
Tim Petersb5a16f32003-01-01 04:48:01 +00004638 resoff = call_utcoffset(tzinfo, result, &none);
4639 if (resoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004640 goto Fail;
4641 if (none)
4642 return result;
4643
Tim Petersf3615152003-01-01 21:51:37 +00004644 /* See the long comment block at the end of this file for an
4645 * explanation of this algorithm. That it always works requires a
Tim Petersadf64202003-01-04 06:03:15 +00004646 * pretty intricate proof. There are many equivalent ways to code
4647 * up the proof as an algorithm. This way favors calling dst() over
4648 * calling utcoffset(), because "the usual" utcoffset() calls dst()
4649 * itself, and calling the latter instead saves a Python-level
4650 * function call. This way of coding it also follows the proof
4651 * closely, w/ x=self, y=result, z=result, and z'=temp.
Tim Peters521fc152002-12-31 17:36:56 +00004652 */
Tim Petersadf64202003-01-04 06:03:15 +00004653 dst1 = call_dst(tzinfo, result, &none);
4654 if (dst1 == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004655 goto Fail;
Tim Peters710fb152003-01-02 19:35:54 +00004656 if (none) {
4657 PyErr_SetString(PyExc_ValueError, "astimezone(): utcoffset() "
4658 "returned a duration but dst() returned None");
4659 goto Fail;
4660 }
Tim Petersadf64202003-01-04 06:03:15 +00004661 delta = resoff - dst1 - selfoff;
4662 if (delta) {
4663 mm += delta;
Tim Petersb5a16f32003-01-01 04:48:01 +00004664 if ((mm < 0 || mm >= 60) &&
4665 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters521fc152002-12-31 17:36:56 +00004666 goto Fail;
4667 temp = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4668 if (temp == NULL)
4669 goto Fail;
4670 Py_DECREF(result);
4671 result = temp;
4672
Tim Petersadf64202003-01-04 06:03:15 +00004673 dst1 = call_dst(tzinfo, result, &none);
4674 if (dst1 == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004675 goto Fail;
4676 if (none)
4677 goto Inconsistent;
Tim Petersf3615152003-01-01 21:51:37 +00004678 }
Tim Petersadf64202003-01-04 06:03:15 +00004679 if (dst1 == 0)
Tim Petersf3615152003-01-01 21:51:37 +00004680 return result;
4681
Tim Petersadf64202003-01-04 06:03:15 +00004682 mm += dst1;
Tim Petersf3615152003-01-01 21:51:37 +00004683 if ((mm < 0 || mm >= 60) &&
4684 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters521fc152002-12-31 17:36:56 +00004685 goto Fail;
4686 temp = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4687 if (temp == NULL)
4688 goto Fail;
Tim Peters521fc152002-12-31 17:36:56 +00004689
Tim Petersadf64202003-01-04 06:03:15 +00004690 dst2 = call_dst(tzinfo, temp, &none);
4691 if (dst2 == -1 && PyErr_Occurred()) {
4692 Py_DECREF(temp);
Tim Petersf3615152003-01-01 21:51:37 +00004693 goto Fail;
Tim Petersadf64202003-01-04 06:03:15 +00004694 }
4695 if (none) {
4696 Py_DECREF(temp);
Tim Petersf3615152003-01-01 21:51:37 +00004697 goto Inconsistent;
Tim Petersadf64202003-01-04 06:03:15 +00004698 }
Tim Petersf3615152003-01-01 21:51:37 +00004699
Tim Petersadf64202003-01-04 06:03:15 +00004700 if (dst1 == dst2) {
4701 /* The normal case: we want temp, not result. */
4702 Py_DECREF(result);
4703 result = temp;
4704 }
4705 else {
4706 /* The "unspellable hour" at the end of DST. */
4707 Py_DECREF(temp);
4708 }
4709 return result;
Tim Peters521fc152002-12-31 17:36:56 +00004710
4711Inconsistent:
Tim Petersadf64202003-01-04 06:03:15 +00004712 PyErr_SetString(PyExc_ValueError, "astimezone(): tz.dst() gave"
4713 "inconsistent results; cannot convert");
Tim Peters521fc152002-12-31 17:36:56 +00004714
4715 /* fall thru to failure */
4716Fail:
4717 Py_DECREF(result);
4718 return NULL;
Tim Peters80475bb2002-12-25 07:40:55 +00004719}
4720
4721static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00004722datetimetz_timetuple(PyDateTime_DateTimeTZ *self)
4723{
4724 int dstflag = -1;
4725
4726 if (self->tzinfo != Py_None) {
4727 int none;
4728
4729 dstflag = call_dst(self->tzinfo, (PyObject *)self, &none);
4730 if (dstflag == -1 && PyErr_Occurred())
4731 return NULL;
4732
4733 if (none)
4734 dstflag = -1;
4735 else if (dstflag != 0)
4736 dstflag = 1;
4737
4738 }
4739 return build_struct_time(GET_YEAR(self),
4740 GET_MONTH(self),
4741 GET_DAY(self),
4742 DATE_GET_HOUR(self),
4743 DATE_GET_MINUTE(self),
4744 DATE_GET_SECOND(self),
4745 dstflag);
4746}
4747
4748static PyObject *
4749datetimetz_utctimetuple(PyDateTime_DateTimeTZ *self)
4750{
4751 int y = GET_YEAR(self);
4752 int m = GET_MONTH(self);
4753 int d = GET_DAY(self);
4754 int hh = DATE_GET_HOUR(self);
4755 int mm = DATE_GET_MINUTE(self);
4756 int ss = DATE_GET_SECOND(self);
4757 int us = 0; /* microseconds are ignored in a timetuple */
4758 int offset = 0;
4759
4760 if (self->tzinfo != Py_None) {
4761 int none;
4762
4763 offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4764 if (offset == -1 && PyErr_Occurred())
4765 return NULL;
4766 }
4767 /* Even if offset is 0, don't call timetuple() -- tm_isdst should be
4768 * 0 in a UTC timetuple regardless of what dst() says.
4769 */
4770 if (offset) {
4771 /* Subtract offset minutes & normalize. */
4772 int stat;
4773
4774 mm -= offset;
4775 stat = normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us);
4776 if (stat < 0) {
4777 /* At the edges, it's possible we overflowed
4778 * beyond MINYEAR or MAXYEAR.
4779 */
4780 if (PyErr_ExceptionMatches(PyExc_OverflowError))
4781 PyErr_Clear();
4782 else
4783 return NULL;
4784 }
4785 }
4786 return build_struct_time(y, m, d, hh, mm, ss, 0);
4787}
4788
4789static PyObject *
4790datetimetz_gettimetz(PyDateTime_DateTimeTZ *self)
4791{
4792 return new_timetz(DATE_GET_HOUR(self),
4793 DATE_GET_MINUTE(self),
4794 DATE_GET_SECOND(self),
4795 DATE_GET_MICROSECOND(self),
4796 self->tzinfo);
4797}
4798
4799/*
4800 * Pickle support. Quite a maze!
4801 */
4802
Tim Peters33e0f382003-01-10 02:05:14 +00004803
4804/* Pickle support. Quite a maze! */
4805
4806/* Let basestate be the state string returned by the date & time fields.
Tim Peters2a799bf2002-12-16 20:18:38 +00004807 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4808 * So it's a tuple in any (non-error) case.
4809 */
4810static PyObject *
4811datetimetz_getstate(PyDateTime_DateTimeTZ *self)
4812{
4813 PyObject *basestate;
4814 PyObject *result = NULL;
4815
Tim Peters33e0f382003-01-10 02:05:14 +00004816 basestate = PyString_FromStringAndSize((char *)self->data,
4817 _PyDateTime_DATETIME_DATASIZE);
Tim Peters2a799bf2002-12-16 20:18:38 +00004818 if (basestate != NULL) {
4819 if (self->tzinfo == Py_None)
4820 result = Py_BuildValue("(O)", basestate);
4821 else
4822 result = Py_BuildValue("OO", basestate, self->tzinfo);
4823 Py_DECREF(basestate);
4824 }
4825 return result;
4826}
4827
4828static PyObject *
4829datetimetz_setstate(PyDateTime_DateTimeTZ *self, PyObject *state)
4830{
Tim Peters2a799bf2002-12-16 20:18:38 +00004831 PyObject *basestate;
4832 PyObject *tzinfo = Py_None;
4833
4834 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
4835 &PyString_Type, &basestate,
4836 &tzinfo))
4837 return NULL;
Tim Peters33e0f382003-01-10 02:05:14 +00004838 if (PyString_Size(basestate) != _PyDateTime_DATETIME_DATASIZE ||
4839 check_tzinfo_subclass(tzinfo) < 0) {
4840 PyErr_SetString(PyExc_TypeError,
4841 "bad argument to datetime.__setstate__");
Tim Peters2a799bf2002-12-16 20:18:38 +00004842 return NULL;
Tim Peters33e0f382003-01-10 02:05:14 +00004843 }
4844 memcpy((char *)self->data,
4845 PyString_AsString(basestate),
4846 _PyDateTime_DATETIME_DATASIZE);
4847 self->hashcode = -1;
4848 replace_tzinfo((PyObject *)self, tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00004849 Py_INCREF(Py_None);
4850 return Py_None;
4851}
4852
4853static PyObject *
4854datetimetz_pickler(PyObject *module, PyDateTime_DateTimeTZ *datetimetz)
4855{
4856 PyObject *state;
4857 PyObject *result = NULL;
4858
4859 if (! PyDateTimeTZ_CheckExact(datetimetz)) {
4860 PyErr_Format(PyExc_TypeError,
4861 "bad type passed to datetimetz pickler: %s",
4862 datetimetz->ob_type->tp_name);
4863 return NULL;
4864 }
4865 state = datetimetz_getstate(datetimetz);
4866 if (state) {
4867 result = Py_BuildValue("O(O)",
4868 datetimetz_unpickler_object,
4869 state);
4870 Py_DECREF(state);
4871 }
4872 return result;
4873}
4874
4875static PyObject *
4876datetimetz_unpickler(PyObject *module, PyObject *arg)
4877{
4878 PyDateTime_DateTimeTZ *self;
4879
4880 self = PyObject_New(PyDateTime_DateTimeTZ, &PyDateTime_DateTimeTZType);
4881 if (self != NULL) {
4882 PyObject *res;
4883
4884 self->tzinfo = NULL;
4885 res = datetimetz_setstate(self, arg);
4886 if (res == NULL) {
4887 Py_DECREF(self);
4888 return NULL;
4889 }
4890 Py_DECREF(res);
4891 }
4892 return (PyObject *)self;
4893}
4894
4895
4896static PyMethodDef datetimetz_methods[] = {
4897 /* Class methods: */
4898 /* Inherited: combine(), utcnow(), utcfromtimestamp() */
4899
4900 {"now", (PyCFunction)datetimetz_now,
4901 METH_KEYWORDS | METH_CLASS,
4902 PyDoc_STR("[tzinfo] -> new datetimetz with local day and time.")},
4903
4904 {"fromtimestamp", (PyCFunction)datetimetz_fromtimestamp,
4905 METH_KEYWORDS | METH_CLASS,
4906 PyDoc_STR("timestamp[, tzinfo] -> local time from POSIX timestamp.")},
4907
4908 /* Instance methods: */
4909 /* Inherited: date(), time(), ctime(). */
4910 {"timetuple", (PyCFunction)datetimetz_timetuple, METH_NOARGS,
4911 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
4912
4913 {"utctimetuple", (PyCFunction)datetimetz_utctimetuple, METH_NOARGS,
4914 PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")},
4915
4916 {"timetz", (PyCFunction)datetimetz_gettimetz, METH_NOARGS,
4917 PyDoc_STR("Return timetz object with same hour, minute, second, "
4918 "microsecond, and tzinfo.")},
4919
4920 {"isoformat", (PyCFunction)datetimetz_isoformat, METH_KEYWORDS,
4921 PyDoc_STR("[sep] -> string in ISO 8601 format, "
4922 "YYYY-MM-DDTHH:MM:SS[.mmmmmm][+HH:MM].\n\n"
4923 "sep is used to separate the year from the time, and "
4924 "defaults to 'T'.")},
4925
4926 {"utcoffset", (PyCFunction)datetimetz_utcoffset, METH_NOARGS,
4927 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
4928
4929 {"tzname", (PyCFunction)datetimetz_tzname, METH_NOARGS,
4930 PyDoc_STR("Return self.tzinfo.tzname(self).")},
4931
4932 {"dst", (PyCFunction)datetimetz_dst, METH_NOARGS,
4933 PyDoc_STR("Return self.tzinfo.dst(self).")},
4934
Tim Peters12bf3392002-12-24 05:41:27 +00004935 {"replace", (PyCFunction)datetimetz_replace, METH_KEYWORDS,
4936 PyDoc_STR("Return datetimetz with new specified fields.")},
4937
Tim Peters80475bb2002-12-25 07:40:55 +00004938 {"astimezone", (PyCFunction)datetimetz_astimezone, METH_KEYWORDS,
4939 PyDoc_STR("tz -> convert to local time in new timezone tz\n")},
4940
Tim Peters2a799bf2002-12-16 20:18:38 +00004941 {"__setstate__", (PyCFunction)datetimetz_setstate, METH_O,
4942 PyDoc_STR("__setstate__(state)")},
4943
4944 {"__getstate__", (PyCFunction)datetimetz_getstate, METH_NOARGS,
4945 PyDoc_STR("__getstate__() -> state")},
4946 {NULL, NULL}
4947};
4948
4949static char datetimetz_doc[] =
4950PyDoc_STR("date/time type.");
4951
4952static PyNumberMethods datetimetz_as_number = {
4953 datetimetz_add, /* nb_add */
4954 datetimetz_subtract, /* nb_subtract */
4955 0, /* nb_multiply */
4956 0, /* nb_divide */
4957 0, /* nb_remainder */
4958 0, /* nb_divmod */
4959 0, /* nb_power */
4960 0, /* nb_negative */
4961 0, /* nb_positive */
4962 0, /* nb_absolute */
4963 0, /* nb_nonzero */
4964};
4965
4966statichere PyTypeObject PyDateTime_DateTimeTZType = {
4967 PyObject_HEAD_INIT(NULL)
4968 0, /* ob_size */
Tim Peters0bf60bd2003-01-08 20:40:01 +00004969 "datetime.datetime", /* tp_name */
Tim Peters2a799bf2002-12-16 20:18:38 +00004970 sizeof(PyDateTime_DateTimeTZ), /* tp_basicsize */
4971 0, /* tp_itemsize */
4972 (destructor)datetimetz_dealloc, /* tp_dealloc */
4973 0, /* tp_print */
4974 0, /* tp_getattr */
4975 0, /* tp_setattr */
4976 0, /* tp_compare */
4977 (reprfunc)datetimetz_repr, /* tp_repr */
4978 &datetimetz_as_number, /* tp_as_number */
4979 0, /* tp_as_sequence */
4980 0, /* tp_as_mapping */
4981 0, /* tp_hash */
4982 0, /* tp_call */
4983 0, /* tp_str */
4984 PyObject_GenericGetAttr, /* tp_getattro */
4985 0, /* tp_setattro */
4986 0, /* tp_as_buffer */
4987 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4988 Py_TPFLAGS_BASETYPE, /* tp_flags */
4989 datetimetz_doc, /* tp_doc */
4990 0, /* tp_traverse */
4991 0, /* tp_clear */
4992 0, /* tp_richcompare */
4993 0, /* tp_weaklistoffset */
4994 0, /* tp_iter */
4995 0, /* tp_iternext */
4996 datetimetz_methods, /* tp_methods */
4997 0, /* tp_members */
4998 datetimetz_getset, /* tp_getset */
4999 &PyDateTime_DateTimeType, /* tp_base */
5000 0, /* tp_dict */
5001 0, /* tp_descr_get */
5002 0, /* tp_descr_set */
5003 0, /* tp_dictoffset */
5004 0, /* tp_init */
5005 0, /* tp_alloc */
5006 datetimetz_new, /* tp_new */
5007 _PyObject_Del, /* tp_free */
5008};
5009
5010/* ---------------------------------------------------------------------------
5011 * Module methods and initialization.
5012 */
5013
5014static PyMethodDef module_methods[] = {
5015 /* Private functions for pickling support, registered with the
5016 * copy_reg module by the module init function.
5017 */
5018 {"_date_pickler", (PyCFunction)date_pickler, METH_O, NULL},
5019 {"_date_unpickler", (PyCFunction)date_unpickler, METH_O, NULL},
Tim Peters2a799bf2002-12-16 20:18:38 +00005020 {"_datetimetz_pickler", (PyCFunction)datetimetz_pickler,METH_O, NULL},
5021 {"_datetimetz_unpickler",(PyCFunction)datetimetz_unpickler,METH_O, NULL},
Tim Peters2a799bf2002-12-16 20:18:38 +00005022 {"_timetz_pickler", (PyCFunction)timetz_pickler, METH_O, NULL},
5023 {"_timetz_unpickler", (PyCFunction)timetz_unpickler, METH_O, NULL},
5024 {"_tzinfo_pickler", (PyCFunction)tzinfo_pickler, METH_O, NULL},
5025 {"_tzinfo_unpickler", (PyCFunction)tzinfo_unpickler, METH_NOARGS,
5026 NULL},
5027 {NULL, NULL}
5028};
5029
5030PyMODINIT_FUNC
5031initdatetime(void)
5032{
5033 PyObject *m; /* a module object */
5034 PyObject *d; /* its dict */
5035 PyObject *x;
5036
5037 /* Types that use __reduce__ for pickling need to set the following
5038 * magical attr in the type dict, with a true value.
5039 */
5040 PyObject *safepickle = PyString_FromString("__safe_for_unpickling__");
5041 if (safepickle == NULL)
5042 return;
5043
5044 m = Py_InitModule3("datetime", module_methods,
5045 "Fast implementation of the datetime type.");
5046
5047 if (PyType_Ready(&PyDateTime_DateType) < 0)
5048 return;
5049 if (PyType_Ready(&PyDateTime_DateTimeType) < 0)
5050 return;
5051 if (PyType_Ready(&PyDateTime_DeltaType) < 0)
5052 return;
5053 if (PyType_Ready(&PyDateTime_TimeType) < 0)
5054 return;
5055 if (PyType_Ready(&PyDateTime_TZInfoType) < 0)
5056 return;
5057 if (PyType_Ready(&PyDateTime_TimeTZType) < 0)
5058 return;
5059 if (PyType_Ready(&PyDateTime_DateTimeTZType) < 0)
5060 return;
5061
5062 /* Pickling support, via registering functions with copy_reg. */
5063 {
5064 PyObject *pickler;
5065 PyObject *copyreg = PyImport_ImportModule("copy_reg");
5066
5067 if (copyreg == NULL) return;
5068
5069 pickler = PyObject_GetAttrString(m, "_date_pickler");
5070 if (pickler == NULL) return;
5071 date_unpickler_object = PyObject_GetAttrString(m,
5072 "_date_unpickler");
5073 if (date_unpickler_object == NULL) return;
5074 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5075 &PyDateTime_DateType,
5076 pickler,
5077 date_unpickler_object);
5078 if (x == NULL) return;
5079 Py_DECREF(x);
5080 Py_DECREF(pickler);
5081
Tim Peters2a799bf2002-12-16 20:18:38 +00005082 pickler = PyObject_GetAttrString(m, "_timetz_pickler");
5083 if (pickler == NULL) return;
5084 timetz_unpickler_object = PyObject_GetAttrString(m,
5085 "_timetz_unpickler");
5086 if (timetz_unpickler_object == NULL) return;
5087 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5088 &PyDateTime_TimeTZType,
5089 pickler,
5090 timetz_unpickler_object);
5091 if (x == NULL) return;
5092 Py_DECREF(x);
5093 Py_DECREF(pickler);
5094
5095 pickler = PyObject_GetAttrString(m, "_tzinfo_pickler");
5096 if (pickler == NULL) return;
5097 tzinfo_unpickler_object = PyObject_GetAttrString(m,
5098 "_tzinfo_unpickler");
5099 if (tzinfo_unpickler_object == NULL) return;
5100 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5101 &PyDateTime_TZInfoType,
5102 pickler,
5103 tzinfo_unpickler_object);
5104 if (x== NULL) return;
5105 Py_DECREF(x);
5106 Py_DECREF(pickler);
5107
5108 pickler = PyObject_GetAttrString(m, "_datetimetz_pickler");
5109 if (pickler == NULL) return;
5110 datetimetz_unpickler_object = PyObject_GetAttrString(m,
5111 "_datetimetz_unpickler");
5112 if (datetimetz_unpickler_object == NULL) return;
5113 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5114 &PyDateTime_DateTimeTZType,
5115 pickler,
5116 datetimetz_unpickler_object);
5117 if (x== NULL) return;
5118 Py_DECREF(x);
5119 Py_DECREF(pickler);
5120
5121 Py_DECREF(copyreg);
5122 }
5123
5124 /* timedelta values */
5125 d = PyDateTime_DeltaType.tp_dict;
5126
5127 if (PyDict_SetItem(d, safepickle, Py_True) < 0)
5128 return;
5129
5130 x = new_delta(0, 0, 1, 0);
5131 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5132 return;
5133 Py_DECREF(x);
5134
5135 x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0);
5136 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5137 return;
5138 Py_DECREF(x);
5139
5140 x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0);
5141 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5142 return;
5143 Py_DECREF(x);
5144
5145 /* date values */
5146 d = PyDateTime_DateType.tp_dict;
5147
5148 x = new_date(1, 1, 1);
5149 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5150 return;
5151 Py_DECREF(x);
5152
5153 x = new_date(MAXYEAR, 12, 31);
5154 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5155 return;
5156 Py_DECREF(x);
5157
5158 x = new_delta(1, 0, 0, 0);
5159 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5160 return;
5161 Py_DECREF(x);
5162
Tim Peters2a799bf2002-12-16 20:18:38 +00005163 /* timetz values */
5164 d = PyDateTime_TimeTZType.tp_dict;
5165
5166 x = new_timetz(0, 0, 0, 0, Py_None);
5167 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5168 return;
5169 Py_DECREF(x);
5170
5171 x = new_timetz(23, 59, 59, 999999, Py_None);
5172 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5173 return;
5174 Py_DECREF(x);
5175
5176 x = new_delta(0, 0, 1, 0);
5177 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5178 return;
5179 Py_DECREF(x);
5180
5181 /* datetimetz values */
5182 d = PyDateTime_DateTimeTZType.tp_dict;
5183
5184 x = new_datetimetz(1, 1, 1, 0, 0, 0, 0, Py_None);
5185 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5186 return;
5187 Py_DECREF(x);
5188
5189 x = new_datetimetz(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None);
5190 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5191 return;
5192 Py_DECREF(x);
5193
5194 x = new_delta(0, 0, 1, 0);
5195 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5196 return;
5197 Py_DECREF(x);
5198
5199 Py_DECREF(safepickle);
5200
5201 /* module initialization */
5202 PyModule_AddIntConstant(m, "MINYEAR", MINYEAR);
5203 PyModule_AddIntConstant(m, "MAXYEAR", MAXYEAR);
5204
5205 Py_INCREF(&PyDateTime_DateType);
5206 PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType);
5207
Tim Peters2a799bf2002-12-16 20:18:38 +00005208 Py_INCREF(&PyDateTime_DeltaType);
5209 PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType);
5210
Tim Peters2a799bf2002-12-16 20:18:38 +00005211 Py_INCREF(&PyDateTime_TZInfoType);
5212 PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
5213
5214 Py_INCREF(&PyDateTime_TimeTZType);
Tim Peters0bf60bd2003-01-08 20:40:01 +00005215 PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeTZType);
Tim Peters2a799bf2002-12-16 20:18:38 +00005216
5217 Py_INCREF(&PyDateTime_DateTimeTZType);
Tim Peters0bf60bd2003-01-08 20:40:01 +00005218 PyModule_AddObject(m, "datetime",
Tim Peters2a799bf2002-12-16 20:18:38 +00005219 (PyObject *)&PyDateTime_DateTimeTZType);
5220
5221 /* A 4-year cycle has an extra leap day over what we'd get from
5222 * pasting together 4 single years.
5223 */
5224 assert(DI4Y == 4 * 365 + 1);
5225 assert(DI4Y == days_before_year(4+1));
5226
5227 /* Similarly, a 400-year cycle has an extra leap day over what we'd
5228 * get from pasting together 4 100-year cycles.
5229 */
5230 assert(DI400Y == 4 * DI100Y + 1);
5231 assert(DI400Y == days_before_year(400+1));
5232
5233 /* OTOH, a 100-year cycle has one fewer leap day than we'd get from
5234 * pasting together 25 4-year cycles.
5235 */
5236 assert(DI100Y == 25 * DI4Y - 1);
5237 assert(DI100Y == days_before_year(100+1));
5238
5239 us_per_us = PyInt_FromLong(1);
5240 us_per_ms = PyInt_FromLong(1000);
5241 us_per_second = PyInt_FromLong(1000000);
5242 us_per_minute = PyInt_FromLong(60000000);
5243 seconds_per_day = PyInt_FromLong(24 * 3600);
5244 if (us_per_us == NULL || us_per_ms == NULL || us_per_second == NULL ||
5245 us_per_minute == NULL || seconds_per_day == NULL)
5246 return;
5247
5248 /* The rest are too big for 32-bit ints, but even
5249 * us_per_week fits in 40 bits, so doubles should be exact.
5250 */
5251 us_per_hour = PyLong_FromDouble(3600000000.0);
5252 us_per_day = PyLong_FromDouble(86400000000.0);
5253 us_per_week = PyLong_FromDouble(604800000000.0);
5254 if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL)
5255 return;
5256}
Tim Petersf3615152003-01-01 21:51:37 +00005257
5258/* ---------------------------------------------------------------------------
5259Some time zone algebra. For a datetimetz x, let
5260 x.n = x stripped of its timezone -- its naive time.
5261 x.o = x.utcoffset(), and assuming that doesn't raise an exception or
5262 return None
5263 x.d = x.dst(), and assuming that doesn't raise an exception or
5264 return None
5265 x.s = x's standard offset, x.o - x.d
5266
5267Now some derived rules, where k is a duration (timedelta).
5268
52691. x.o = x.s + x.d
5270 This follows from the definition of x.s.
5271
Tim Petersc5dc4da2003-01-02 17:55:03 +000052722. If x and y have the same tzinfo member, x.s = y.s.
Tim Petersf3615152003-01-01 21:51:37 +00005273 This is actually a requirement, an assumption we need to make about
5274 sane tzinfo classes.
5275
52763. The naive UTC time corresponding to x is x.n - x.o.
5277 This is again a requirement for a sane tzinfo class.
5278
52794. (x+k).s = x.s
5280 This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
5281
Tim Petersc5dc4da2003-01-02 17:55:03 +000052825. (x+k).n = x.n + k
Tim Petersf3615152003-01-01 21:51:37 +00005283 Again follows from how arithmetic is defined.
5284
5285Now we can explain x.astimezone(tz). Let's assume it's an interesting case
5286(meaning that the various tzinfo methods exist, and don't blow up or return
5287None when called).
5288
5289The function wants to return a datetimetz y with timezone tz, equivalent to x.
5290
5291By #3, we want
5292
5293 y.n - y.o = x.n - x.o [1]
5294
5295The algorithm starts by attaching tz to x.n, and calling that y. So
5296x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
5297becomes true; in effect, we want to solve [2] for k:
5298
5299 (y+k).n - (y+k).o = x.n - x.o [2]
5300
5301By #1, this is the same as
5302
5303 (y+k).n - ((y+k).s + (y+k).d) = x.n - x.o [3]
5304
5305By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
5306Substituting that into [3],
5307
5308 x.n + k - (y+k).s - (y+k).d = x.n - x.o; the x.n terms cancel, leaving
5309 k - (y+k).s - (y+k).d = - x.o; rearranging,
5310 k = (y+k).s - x.o - (y+k).d; by #4, (y+k).s == y.s, so
5311 k = y.s - x.o - (y+k).d; then by #1, y.s = y.o - y.d, so
5312 k = y.o - y.d - x.o - (y+k).d
5313
5314On the RHS, (y+k).d can't be computed directly, but all the rest can be, and
5315we approximate k by ignoring the (y+k).d term at first. Note that k can't
5316be very large, since all offset-returning methods return a duration of
5317magnitude less than 24 hours. For that reason, if y is firmly in std time,
5318(y+k).d must be 0, so ignoring it has no consequence then.
5319
5320In any case, the new value is
5321
Tim Petersc5dc4da2003-01-02 17:55:03 +00005322 z = y + y.o - y.d - x.o [4]
Tim Petersf3615152003-01-01 21:51:37 +00005323
Tim Petersc5dc4da2003-01-02 17:55:03 +00005324It's helpful to step back at look at [4] from a higher level: rewrite it as
Tim Petersf3615152003-01-01 21:51:37 +00005325
Tim Petersc5dc4da2003-01-02 17:55:03 +00005326 z = (y - x.o) + (y.o - y.d)
5327
5328(y - x.o).n = [by #5] y.n - x.o = [since y.n=x.n] x.n - x.o = [by #3] x's
5329UTC equivalent time. So the y-x.o part essentially converts x to UTC. Then
5330the y.o-y.d part essentially converts x's UTC equivalent into tz's standard
5331time (y.o-y.d=y.s by #1).
5332
5333At this point, if
5334
5335 z.n - z.o = x.n - x.o [5]
5336
5337we have an equivalent time, and are almost done. The insecurity here is
Tim Petersf3615152003-01-01 21:51:37 +00005338at the start of daylight time. Picture US Eastern for concreteness. The wall
5339time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
5340sense then. A sensible Eastern tzinfo class will consider such a time to be
5341EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST on the
5342day DST starts. We want to return the 1:MM EST spelling because that's
5343the only spelling that makes sense on the local wall clock.
5344
Tim Petersc5dc4da2003-01-02 17:55:03 +00005345In fact, if [5] holds at this point, we do have the standard-time spelling,
5346but that takes a bit of proof. We first prove a stronger result. What's the
5347difference between the LHS and RHS of [5]? Let
Tim Petersf3615152003-01-01 21:51:37 +00005348
Tim Petersc5dc4da2003-01-02 17:55:03 +00005349 diff = (x.n - x.o) - (z.n - z.o) [6]
Tim Petersf3615152003-01-01 21:51:37 +00005350
Tim Petersc5dc4da2003-01-02 17:55:03 +00005351Now
5352 z.n = by [4]
5353 (y + y.o - y.d - x.o).n = by #5
5354 y.n + y.o - y.d - x.o = since y.n = x.n
5355 x.n + y.o - y.d - x.o = since y.o = y.s + y.d by #1
5356 x.n + (y.s + y.d) - y.d - x.o = cancelling the y.d terms
5357 x.n + y.s - x.o = since z and y are have the same tzinfo member,
5358 y.s = z.s by #2
5359 x.n + z.s - x.o
Tim Petersf3615152003-01-01 21:51:37 +00005360
Tim Petersc5dc4da2003-01-02 17:55:03 +00005361Plugging that back into [6] gives
Tim Petersf3615152003-01-01 21:51:37 +00005362
Tim Petersc5dc4da2003-01-02 17:55:03 +00005363 diff =
5364 (x.n - x.o) - ((x.n + z.s - x.o) - z.o) = expanding
5365 x.n - x.o - x.n - z.s + x.o + z.o = cancelling
5366 - z.s + z.o = by #2
5367 z.d
Tim Petersf3615152003-01-01 21:51:37 +00005368
Tim Petersc5dc4da2003-01-02 17:55:03 +00005369So diff = z.d.
Tim Petersf3615152003-01-01 21:51:37 +00005370
Tim Petersc5dc4da2003-01-02 17:55:03 +00005371If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
5372spelling we wanted in the endcase described above. We're done.
Tim Petersf3615152003-01-01 21:51:37 +00005373
Tim Petersc5dc4da2003-01-02 17:55:03 +00005374If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
5375add to z (in effect, z is in tz's standard time, and we need to shift the
5376offset into tz's daylight time).
Tim Petersf3615152003-01-01 21:51:37 +00005377
Tim Petersc5dc4da2003-01-02 17:55:03 +00005378Let
Tim Petersf3615152003-01-01 21:51:37 +00005379
Tim Peters4fede1a2003-01-04 00:26:59 +00005380 z' = z + z.d = z + diff [7]
Tim Petersc3bb26a2003-01-02 03:14:59 +00005381
Tim Peters4fede1a2003-01-04 00:26:59 +00005382and we can again ask whether
Tim Petersc3bb26a2003-01-02 03:14:59 +00005383
Tim Peters4fede1a2003-01-04 00:26:59 +00005384 z'.n - z'.o = x.n - x.o [8]
Tim Petersc3bb26a2003-01-02 03:14:59 +00005385
5386If so, we're done. If not, the tzinfo class is insane, or we're trying to
Tim Peters4fede1a2003-01-04 00:26:59 +00005387convert to the hour that can't be spelled in tz. This also requires a
5388bit of proof. As before, let's compute the difference between the LHS and
5389RHS of [8] (and skipping some of the justifications for the kinds of
5390substitutions we've done several times already):
5391
5392 diff' = (x.n - x.o) - (z'.n - z'.o) = replacing z'.n via [7]
5393 (x.n - x.o) - (z.n + diff - z'.o) = replacing diff via [6]
5394 (x.n - x.o) - (z.n + (x.n - x.o) - (z.n - z.o) - z'.o) =
5395 x.n - x.o - z.n - x.n + x.o + z.n - z.o + z'.o = cancel x.n
5396 - x.o - z.n + x.o + z.n - z.o + z'.o = cancel x.o
5397 - z.n + z.n - z.o + z'.o = cancel z.n
5398 - z.o + z'.o = #1 twice
5399 -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
5400 z'.d - z.d
5401
5402So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
5403we've found the UTC-equivalent so are done.
5404
5405How could they differ? z' = z + z.d [7], so merely moving z' by a dst()
5406offset, and starting *from* a time already in DST (we know z.d != 0), would
5407have to change the result dst() returns: we start in DST, and moving a
5408little further into it takes us out of DST.
5409
5410There's (only) one sane case where this can happen: at the end of DST,
5411there's an hour in UTC with no spelling in a hybrid tzinfo class. In US
5412Eastern, that's 6:MM UTC = 1:MM EST = 2:MM EDT. During that hour, on an
5413Eastern clock 1:MM is taken as being in daylight time (5:MM UTC), but 2:MM is
5414taken as being in standard time (7:MM UTC). There is no local time mapping to
54156:MM UTC. The local clock jumps from 1:59 back to 1:00 again, and repeats the
54161:MM hour in standard time. Since that's what the local clock *does*, we want
5417to map both UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
5418in local time, but so it goes -- it's the way the local clock works.
5419
5420When x = 6:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
5421so z=1:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
5422z' = z + z.d = 2:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
5423(correctly) concludes that z' is not UTC-equivalent to x.
5424
5425Because we know z.d said z was in daylight time (else [5] would have held and
5426we would have stopped then), and we know z.d != z'.d (else [8] would have held
5427and we we have stopped then), and there are only 2 possible values dst() can
5428return in Eastern, it follows that z'.d must be 0 (which it is in the example,
5429but the reasoning doesn't depend on the example -- it depends on there being
5430two possible dst() outcomes, one zero and the other non-zero). Therefore
5431z' must be in standard time, and is not the spelling we want in this case.
5432z is in daylight time, and is the spelling we want. Note again that z is
5433not UTC-equivalent as far as the hybrid tzinfo class is concerned (because
5434it takes z as being in standard time rather than the daylight time we intend
5435here), but returning it gives the real-life "local clock repeats an hour"
5436behavior when mapping the "unspellable" UTC hour into tz.
Tim Petersf3615152003-01-01 21:51:37 +00005437--------------------------------------------------------------------------- */