blob: ea8302fa9ce757c0c6d35e61449341162e73e3eb [file] [log] [blame]
Tim Peters2a799bf2002-12-16 20:18:38 +00001/* C implementation for the date/time type documented at
2 * http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage
3 */
4
5#include "Python.h"
6#include "modsupport.h"
7#include "structmember.h"
8
9#include <time.h>
10
11#include "datetime.h"
12
13/* We require that C int be at least 32 bits, and use int virtually
14 * everywhere. In just a few cases we use a temp long, where a Python
15 * API returns a C long. In such cases, we have to ensure that the
16 * final result fits in a C int (this can be an issue on 64-bit boxes).
17 */
18#if SIZEOF_INT < 4
19# error "datetime.c requires that C int have at least 32 bits"
20#endif
21
22#define MINYEAR 1
23#define MAXYEAR 9999
24
25/* Nine decimal digits is easy to communicate, and leaves enough room
26 * so that two delta days can be added w/o fear of overflowing a signed
27 * 32-bit int, and with plenty of room left over to absorb any possible
28 * carries from adding seconds.
29 */
30#define MAX_DELTA_DAYS 999999999
31
32/* Rename the long macros in datetime.h to more reasonable short names. */
33#define GET_YEAR PyDateTime_GET_YEAR
34#define GET_MONTH PyDateTime_GET_MONTH
35#define GET_DAY PyDateTime_GET_DAY
36#define DATE_GET_HOUR PyDateTime_DATE_GET_HOUR
37#define DATE_GET_MINUTE PyDateTime_DATE_GET_MINUTE
38#define DATE_GET_SECOND PyDateTime_DATE_GET_SECOND
39#define DATE_GET_MICROSECOND PyDateTime_DATE_GET_MICROSECOND
40
41/* Date accessors for date and datetime. */
42#define SET_YEAR(o, v) (((o)->data[0] = ((v) & 0xff00) >> 8), \
43 ((o)->data[1] = ((v) & 0x00ff)))
44#define SET_MONTH(o, v) (PyDateTime_GET_MONTH(o) = (v))
45#define SET_DAY(o, v) (PyDateTime_GET_DAY(o) = (v))
46
47/* Date/Time accessors for datetime. */
48#define DATE_SET_HOUR(o, v) (PyDateTime_DATE_GET_HOUR(o) = (v))
49#define DATE_SET_MINUTE(o, v) (PyDateTime_DATE_GET_MINUTE(o) = (v))
50#define DATE_SET_SECOND(o, v) (PyDateTime_DATE_GET_SECOND(o) = (v))
51#define DATE_SET_MICROSECOND(o, v) \
52 (((o)->data[7] = ((v) & 0xff0000) >> 16), \
53 ((o)->data[8] = ((v) & 0x00ff00) >> 8), \
54 ((o)->data[9] = ((v) & 0x0000ff)))
55
56/* Time accessors for time. */
57#define TIME_GET_HOUR PyDateTime_TIME_GET_HOUR
58#define TIME_GET_MINUTE PyDateTime_TIME_GET_MINUTE
59#define TIME_GET_SECOND PyDateTime_TIME_GET_SECOND
60#define TIME_GET_MICROSECOND PyDateTime_TIME_GET_MICROSECOND
61#define TIME_SET_HOUR(o, v) (PyDateTime_TIME_GET_HOUR(o) = (v))
62#define TIME_SET_MINUTE(o, v) (PyDateTime_TIME_GET_MINUTE(o) = (v))
63#define TIME_SET_SECOND(o, v) (PyDateTime_TIME_GET_SECOND(o) = (v))
64#define TIME_SET_MICROSECOND(o, v) \
65 (((o)->data[3] = ((v) & 0xff0000) >> 16), \
66 ((o)->data[4] = ((v) & 0x00ff00) >> 8), \
67 ((o)->data[5] = ((v) & 0x0000ff)))
68
69/* Delta accessors for timedelta. */
70#define GET_TD_DAYS(o) (((PyDateTime_Delta *)(o))->days)
71#define GET_TD_SECONDS(o) (((PyDateTime_Delta *)(o))->seconds)
72#define GET_TD_MICROSECONDS(o) (((PyDateTime_Delta *)(o))->microseconds)
73
74#define SET_TD_DAYS(o, v) ((o)->days = (v))
75#define SET_TD_SECONDS(o, v) ((o)->seconds = (v))
76#define SET_TD_MICROSECONDS(o, v) ((o)->microseconds = (v))
77
78/* Forward declarations. */
79static PyTypeObject PyDateTime_DateType;
80static PyTypeObject PyDateTime_DateTimeType;
81static PyTypeObject PyDateTime_DateTimeTZType;
82static PyTypeObject PyDateTime_DeltaType;
83static PyTypeObject PyDateTime_TimeType;
84static PyTypeObject PyDateTime_TZInfoType;
85static PyTypeObject PyDateTime_TimeTZType;
86
87/* ---------------------------------------------------------------------------
88 * Math utilities.
89 */
90
91/* k = i+j overflows iff k differs in sign from both inputs,
92 * iff k^i has sign bit set and k^j has sign bit set,
93 * iff (k^i)&(k^j) has sign bit set.
94 */
95#define SIGNED_ADD_OVERFLOWED(RESULT, I, J) \
96 ((((RESULT) ^ (I)) & ((RESULT) ^ (J))) < 0)
97
98/* Compute Python divmod(x, y), returning the quotient and storing the
99 * remainder into *r. The quotient is the floor of x/y, and that's
100 * the real point of this. C will probably truncate instead (C99
101 * requires truncation; C89 left it implementation-defined).
102 * Simplification: we *require* that y > 0 here. That's appropriate
103 * for all the uses made of it. This simplifies the code and makes
104 * the overflow case impossible (divmod(LONG_MIN, -1) is the only
105 * overflow case).
106 */
107static int
108divmod(int x, int y, int *r)
109{
110 int quo;
111
112 assert(y > 0);
113 quo = x / y;
114 *r = x - quo * y;
115 if (*r < 0) {
116 --quo;
117 *r += y;
118 }
119 assert(0 <= *r && *r < y);
120 return quo;
121}
122
Tim Peters5d644dd2003-01-02 16:32:54 +0000123/* Round a double to the nearest long. |x| must be small enough to fit
124 * in a C long; this is not checked.
125 */
126static long
127round_to_long(double x)
128{
129 if (x >= 0.0)
130 x = floor(x + 0.5);
131 else
132 x = ceil(x - 0.5);
133 return (long)x;
134}
135
Tim Peters2a799bf2002-12-16 20:18:38 +0000136/* ---------------------------------------------------------------------------
137 * General calendrical helper functions
138 */
139
140/* For each month ordinal in 1..12, the number of days in that month,
141 * and the number of days before that month in the same year. These
142 * are correct for non-leap years only.
143 */
144static int _days_in_month[] = {
145 0, /* unused; this vector uses 1-based indexing */
146 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
147};
148
149static int _days_before_month[] = {
150 0, /* unused; this vector uses 1-based indexing */
151 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
152};
153
154/* year -> 1 if leap year, else 0. */
155static int
156is_leap(int year)
157{
158 /* Cast year to unsigned. The result is the same either way, but
159 * C can generate faster code for unsigned mod than for signed
160 * mod (especially for % 4 -- a good compiler should just grab
161 * the last 2 bits when the LHS is unsigned).
162 */
163 const unsigned int ayear = (unsigned int)year;
164 return ayear % 4 == 0 && (ayear % 100 != 0 || ayear % 400 == 0);
165}
166
167/* year, month -> number of days in that month in that year */
168static int
169days_in_month(int year, int month)
170{
171 assert(month >= 1);
172 assert(month <= 12);
173 if (month == 2 && is_leap(year))
174 return 29;
175 else
176 return _days_in_month[month];
177}
178
179/* year, month -> number of days in year preceeding first day of month */
180static int
181days_before_month(int year, int month)
182{
183 int days;
184
185 assert(month >= 1);
186 assert(month <= 12);
187 days = _days_before_month[month];
188 if (month > 2 && is_leap(year))
189 ++days;
190 return days;
191}
192
193/* year -> number of days before January 1st of year. Remember that we
194 * start with year 1, so days_before_year(1) == 0.
195 */
196static int
197days_before_year(int year)
198{
199 int y = year - 1;
200 /* This is incorrect if year <= 0; we really want the floor
201 * here. But so long as MINYEAR is 1, the smallest year this
202 * can see is 0 (this can happen in some normalization endcases),
203 * so we'll just special-case that.
204 */
205 assert (year >= 0);
206 if (y >= 0)
207 return y*365 + y/4 - y/100 + y/400;
208 else {
209 assert(y == -1);
210 return -366;
211 }
212}
213
214/* Number of days in 4, 100, and 400 year cycles. That these have
215 * the correct values is asserted in the module init function.
216 */
217#define DI4Y 1461 /* days_before_year(5); days in 4 years */
218#define DI100Y 36524 /* days_before_year(101); days in 100 years */
219#define DI400Y 146097 /* days_before_year(401); days in 400 years */
220
221/* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */
222static void
223ord_to_ymd(int ordinal, int *year, int *month, int *day)
224{
225 int n, n1, n4, n100, n400, leapyear, preceding;
226
227 /* ordinal is a 1-based index, starting at 1-Jan-1. The pattern of
228 * leap years repeats exactly every 400 years. The basic strategy is
229 * to find the closest 400-year boundary at or before ordinal, then
230 * work with the offset from that boundary to ordinal. Life is much
231 * clearer if we subtract 1 from ordinal first -- then the values
232 * of ordinal at 400-year boundaries are exactly those divisible
233 * by DI400Y:
234 *
235 * D M Y n n-1
236 * -- --- ---- ---------- ----------------
237 * 31 Dec -400 -DI400Y -DI400Y -1
238 * 1 Jan -399 -DI400Y +1 -DI400Y 400-year boundary
239 * ...
240 * 30 Dec 000 -1 -2
241 * 31 Dec 000 0 -1
242 * 1 Jan 001 1 0 400-year boundary
243 * 2 Jan 001 2 1
244 * 3 Jan 001 3 2
245 * ...
246 * 31 Dec 400 DI400Y DI400Y -1
247 * 1 Jan 401 DI400Y +1 DI400Y 400-year boundary
248 */
249 assert(ordinal >= 1);
250 --ordinal;
251 n400 = ordinal / DI400Y;
252 n = ordinal % DI400Y;
253 *year = n400 * 400 + 1;
254
255 /* Now n is the (non-negative) offset, in days, from January 1 of
256 * year, to the desired date. Now compute how many 100-year cycles
257 * precede n.
258 * Note that it's possible for n100 to equal 4! In that case 4 full
259 * 100-year cycles precede the desired day, which implies the
260 * desired day is December 31 at the end of a 400-year cycle.
261 */
262 n100 = n / DI100Y;
263 n = n % DI100Y;
264
265 /* Now compute how many 4-year cycles precede it. */
266 n4 = n / DI4Y;
267 n = n % DI4Y;
268
269 /* And now how many single years. Again n1 can be 4, and again
270 * meaning that the desired day is December 31 at the end of the
271 * 4-year cycle.
272 */
273 n1 = n / 365;
274 n = n % 365;
275
276 *year += n100 * 100 + n4 * 4 + n1;
277 if (n1 == 4 || n100 == 4) {
278 assert(n == 0);
279 *year -= 1;
280 *month = 12;
281 *day = 31;
282 return;
283 }
284
285 /* Now the year is correct, and n is the offset from January 1. We
286 * find the month via an estimate that's either exact or one too
287 * large.
288 */
289 leapyear = n1 == 3 && (n4 != 24 || n100 == 3);
290 assert(leapyear == is_leap(*year));
291 *month = (n + 50) >> 5;
292 preceding = (_days_before_month[*month] + (*month > 2 && leapyear));
293 if (preceding > n) {
294 /* estimate is too large */
295 *month -= 1;
296 preceding -= days_in_month(*year, *month);
297 }
298 n -= preceding;
299 assert(0 <= n);
300 assert(n < days_in_month(*year, *month));
301
302 *day = n + 1;
303}
304
305/* year, month, day -> ordinal, considering 01-Jan-0001 as day 1. */
306static int
307ymd_to_ord(int year, int month, int day)
308{
309 return days_before_year(year) + days_before_month(year, month) + day;
310}
311
312/* Day of week, where Monday==0, ..., Sunday==6. 1/1/1 was a Monday. */
313static int
314weekday(int year, int month, int day)
315{
316 return (ymd_to_ord(year, month, day) + 6) % 7;
317}
318
319/* Ordinal of the Monday starting week 1 of the ISO year. Week 1 is the
320 * first calendar week containing a Thursday.
321 */
322static int
323iso_week1_monday(int year)
324{
325 int first_day = ymd_to_ord(year, 1, 1); /* ord of 1/1 */
326 /* 0 if 1/1 is a Monday, 1 if a Tue, etc. */
327 int first_weekday = (first_day + 6) % 7;
328 /* ordinal of closest Monday at or before 1/1 */
329 int week1_monday = first_day - first_weekday;
330
331 if (first_weekday > 3) /* if 1/1 was Fri, Sat, Sun */
332 week1_monday += 7;
333 return week1_monday;
334}
335
336/* ---------------------------------------------------------------------------
337 * Range checkers.
338 */
339
340/* Check that -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS. If so, return 0.
341 * If not, raise OverflowError and return -1.
342 */
343static int
344check_delta_day_range(int days)
345{
346 if (-MAX_DELTA_DAYS <= days && days <= MAX_DELTA_DAYS)
347 return 0;
348 PyErr_Format(PyExc_OverflowError,
349 "days=%d; must have magnitude <= %d",
Guido van Rossumbd43e912002-12-16 20:34:55 +0000350 days, MAX_DELTA_DAYS);
Tim Peters2a799bf2002-12-16 20:18:38 +0000351 return -1;
352}
353
354/* Check that date arguments are in range. Return 0 if they are. If they
355 * aren't, raise ValueError and return -1.
356 */
357static int
358check_date_args(int year, int month, int day)
359{
360
361 if (year < MINYEAR || year > MAXYEAR) {
362 PyErr_SetString(PyExc_ValueError,
363 "year is out of range");
364 return -1;
365 }
366 if (month < 1 || month > 12) {
367 PyErr_SetString(PyExc_ValueError,
368 "month must be in 1..12");
369 return -1;
370 }
371 if (day < 1 || day > days_in_month(year, month)) {
372 PyErr_SetString(PyExc_ValueError,
373 "day is out of range for month");
374 return -1;
375 }
376 return 0;
377}
378
379/* Check that time arguments are in range. Return 0 if they are. If they
380 * aren't, raise ValueError and return -1.
381 */
382static int
383check_time_args(int h, int m, int s, int us)
384{
385 if (h < 0 || h > 23) {
386 PyErr_SetString(PyExc_ValueError,
387 "hour must be in 0..23");
388 return -1;
389 }
390 if (m < 0 || m > 59) {
391 PyErr_SetString(PyExc_ValueError,
392 "minute must be in 0..59");
393 return -1;
394 }
395 if (s < 0 || s > 59) {
396 PyErr_SetString(PyExc_ValueError,
397 "second must be in 0..59");
398 return -1;
399 }
400 if (us < 0 || us > 999999) {
401 PyErr_SetString(PyExc_ValueError,
402 "microsecond must be in 0..999999");
403 return -1;
404 }
405 return 0;
406}
407
408/* ---------------------------------------------------------------------------
409 * Normalization utilities.
410 */
411
412/* One step of a mixed-radix conversion. A "hi" unit is equivalent to
413 * factor "lo" units. factor must be > 0. If *lo is less than 0, or
414 * at least factor, enough of *lo is converted into "hi" units so that
415 * 0 <= *lo < factor. The input values must be such that int overflow
416 * is impossible.
417 */
418static void
419normalize_pair(int *hi, int *lo, int factor)
420{
421 assert(factor > 0);
422 assert(lo != hi);
423 if (*lo < 0 || *lo >= factor) {
424 const int num_hi = divmod(*lo, factor, lo);
425 const int new_hi = *hi + num_hi;
426 assert(! SIGNED_ADD_OVERFLOWED(new_hi, *hi, num_hi));
427 *hi = new_hi;
428 }
429 assert(0 <= *lo && *lo < factor);
430}
431
432/* Fiddle days (d), seconds (s), and microseconds (us) so that
433 * 0 <= *s < 24*3600
434 * 0 <= *us < 1000000
435 * The input values must be such that the internals don't overflow.
436 * The way this routine is used, we don't get close.
437 */
438static void
439normalize_d_s_us(int *d, int *s, int *us)
440{
441 if (*us < 0 || *us >= 1000000) {
442 normalize_pair(s, us, 1000000);
443 /* |s| can't be bigger than about
444 * |original s| + |original us|/1000000 now.
445 */
446
447 }
448 if (*s < 0 || *s >= 24*3600) {
449 normalize_pair(d, s, 24*3600);
450 /* |d| can't be bigger than about
451 * |original d| +
452 * (|original s| + |original us|/1000000) / (24*3600) now.
453 */
454 }
455 assert(0 <= *s && *s < 24*3600);
456 assert(0 <= *us && *us < 1000000);
457}
458
459/* Fiddle years (y), months (m), and days (d) so that
460 * 1 <= *m <= 12
461 * 1 <= *d <= days_in_month(*y, *m)
462 * The input values must be such that the internals don't overflow.
463 * The way this routine is used, we don't get close.
464 */
465static void
466normalize_y_m_d(int *y, int *m, int *d)
467{
468 int dim; /* # of days in month */
469
470 /* This gets muddy: the proper range for day can't be determined
471 * without knowing the correct month and year, but if day is, e.g.,
472 * plus or minus a million, the current month and year values make
473 * no sense (and may also be out of bounds themselves).
474 * Saying 12 months == 1 year should be non-controversial.
475 */
476 if (*m < 1 || *m > 12) {
477 --*m;
478 normalize_pair(y, m, 12);
479 ++*m;
480 /* |y| can't be bigger than about
481 * |original y| + |original m|/12 now.
482 */
483 }
484 assert(1 <= *m && *m <= 12);
485
486 /* Now only day can be out of bounds (year may also be out of bounds
487 * for a datetime object, but we don't care about that here).
488 * If day is out of bounds, what to do is arguable, but at least the
489 * method here is principled and explainable.
490 */
491 dim = days_in_month(*y, *m);
492 if (*d < 1 || *d > dim) {
493 /* Move day-1 days from the first of the month. First try to
494 * get off cheap if we're only one day out of range
495 * (adjustments for timezone alone can't be worse than that).
496 */
497 if (*d == 0) {
498 --*m;
499 if (*m > 0)
500 *d = days_in_month(*y, *m);
501 else {
502 --*y;
503 *m = 12;
504 *d = 31;
505 }
506 }
507 else if (*d == dim + 1) {
508 /* move forward a day */
509 ++*m;
510 *d = 1;
511 if (*m > 12) {
512 *m = 1;
513 ++*y;
514 }
515 }
516 else {
517 int ordinal = ymd_to_ord(*y, *m, 1) +
518 *d - 1;
519 ord_to_ymd(ordinal, y, m, d);
520 }
521 }
522 assert(*m > 0);
523 assert(*d > 0);
524}
525
526/* Fiddle out-of-bounds months and days so that the result makes some kind
527 * of sense. The parameters are both inputs and outputs. Returns < 0 on
528 * failure, where failure means the adjusted year is out of bounds.
529 */
530static int
531normalize_date(int *year, int *month, int *day)
532{
533 int result;
534
535 normalize_y_m_d(year, month, day);
536 if (MINYEAR <= *year && *year <= MAXYEAR)
537 result = 0;
538 else {
539 PyErr_SetString(PyExc_OverflowError,
540 "date value out of range");
541 result = -1;
542 }
543 return result;
544}
545
546/* Force all the datetime fields into range. The parameters are both
547 * inputs and outputs. Returns < 0 on error.
548 */
549static int
550normalize_datetime(int *year, int *month, int *day,
551 int *hour, int *minute, int *second,
552 int *microsecond)
553{
554 normalize_pair(second, microsecond, 1000000);
555 normalize_pair(minute, second, 60);
556 normalize_pair(hour, minute, 60);
557 normalize_pair(day, hour, 24);
558 return normalize_date(year, month, day);
559}
560
561/* ---------------------------------------------------------------------------
562 * tzinfo helpers.
563 */
564
Tim Peters855fe882002-12-22 03:43:39 +0000565/* Ensure that p is None or of a tzinfo subclass. Return 0 if OK; if not
566 * raise TypeError and return -1.
567 */
568static int
569check_tzinfo_subclass(PyObject *p)
570{
571 if (p == Py_None || PyTZInfo_Check(p))
572 return 0;
573 PyErr_Format(PyExc_TypeError,
574 "tzinfo argument must be None or of a tzinfo subclass, "
575 "not type '%s'",
576 p->ob_type->tp_name);
577 return -1;
578}
579
Tim Petersbad8ff02002-12-30 20:52:32 +0000580/* Return tzinfo.methname(tzinfoarg), without any checking of results.
Tim Peters855fe882002-12-22 03:43:39 +0000581 * If tzinfo is None, returns None.
582 */
583static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000584call_tzinfo_method(PyObject *tzinfo, char *methname, PyObject *tzinfoarg)
Tim Peters855fe882002-12-22 03:43:39 +0000585{
586 PyObject *result;
587
Tim Petersbad8ff02002-12-30 20:52:32 +0000588 assert(tzinfo && methname && tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000589 assert(check_tzinfo_subclass(tzinfo) >= 0);
590 if (tzinfo == Py_None) {
591 result = Py_None;
592 Py_INCREF(result);
593 }
594 else
Tim Petersbad8ff02002-12-30 20:52:32 +0000595 result = PyObject_CallMethod(tzinfo, methname, "O", tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000596 return result;
597}
598
Tim Peters2a799bf2002-12-16 20:18:38 +0000599/* If self has a tzinfo member, return a BORROWED reference to it. Else
600 * return NULL, which is NOT AN ERROR. There are no error returns here,
601 * and the caller must not decref the result.
602 */
603static PyObject *
604get_tzinfo_member(PyObject *self)
605{
606 PyObject *tzinfo = NULL;
607
608 if (PyDateTimeTZ_Check(self))
609 tzinfo = ((PyDateTime_DateTimeTZ *)self)->tzinfo;
610 else if (PyTimeTZ_Check(self))
611 tzinfo = ((PyDateTime_TimeTZ *)self)->tzinfo;
612
613 return tzinfo;
614}
615
Tim Peters80475bb2002-12-25 07:40:55 +0000616/* self is a datetimetz. Replace its tzinfo member. */
617void
618replace_tzinfo(PyObject *self, PyObject *newtzinfo)
619{
620 assert(self != NULL);
621 assert(PyDateTimeTZ_Check(self));
622 assert(check_tzinfo_subclass(newtzinfo) >= 0);
623 Py_INCREF(newtzinfo);
624 Py_DECREF(((PyDateTime_DateTimeTZ *)self)->tzinfo);
625 ((PyDateTime_DateTimeTZ *)self)->tzinfo = newtzinfo;
626}
627
Tim Petersbad8ff02002-12-30 20:52:32 +0000628
629/* Call getattr(tzinfo, name)(tzinfoarg), and extract an int from the
Tim Peters2a799bf2002-12-16 20:18:38 +0000630 * result. tzinfo must be an instance of the tzinfo class. If the method
631 * returns None, this returns 0 and sets *none to 1. If the method doesn't
Tim Peters397301e2003-01-02 21:28:08 +0000632 * return None or timedelta, TypeError is raised and this returns -1. If it
633 * returnsa timedelta and the value is out of range or isn't a whole number
634 * of minutes, ValueError is raised and this returns -1.
Tim Peters2a799bf2002-12-16 20:18:38 +0000635 * Else *none is set to 0 and the integer method result is returned.
636 */
637static int
638call_utc_tzinfo_method(PyObject *tzinfo, char *name, PyObject *tzinfoarg,
639 int *none)
640{
641 PyObject *u;
Tim Peters397301e2003-01-02 21:28:08 +0000642 int result = -1;
Tim Peters2a799bf2002-12-16 20:18:38 +0000643
644 assert(tzinfo != NULL);
645 assert(PyTZInfo_Check(tzinfo));
646 assert(tzinfoarg != NULL);
647
648 *none = 0;
Tim Petersbad8ff02002-12-30 20:52:32 +0000649 u = call_tzinfo_method(tzinfo, name, tzinfoarg);
Tim Peters2a799bf2002-12-16 20:18:38 +0000650 if (u == NULL)
651 return -1;
652
Tim Peters27362852002-12-23 16:17:39 +0000653 else if (u == Py_None) {
Tim Peters2a799bf2002-12-16 20:18:38 +0000654 result = 0;
655 *none = 1;
Tim Peters2a799bf2002-12-16 20:18:38 +0000656 }
Tim Peters855fe882002-12-22 03:43:39 +0000657 else if (PyDelta_Check(u)) {
658 const int days = GET_TD_DAYS(u);
659 if (days < -1 || days > 0)
660 result = 24*60; /* trigger ValueError below */
661 else {
662 /* next line can't overflow because we know days
663 * is -1 or 0 now
664 */
665 int ss = days * 24 * 3600 + GET_TD_SECONDS(u);
666 result = divmod(ss, 60, &ss);
667 if (ss || GET_TD_MICROSECONDS(u)) {
668 PyErr_Format(PyExc_ValueError,
669 "tzinfo.%s() must return a "
670 "whole number of minutes",
671 name);
672 result = -1;
Tim Peters855fe882002-12-22 03:43:39 +0000673 }
674 }
675 }
Tim Peters2a799bf2002-12-16 20:18:38 +0000676 else {
677 PyErr_Format(PyExc_TypeError,
Tim Peters397301e2003-01-02 21:28:08 +0000678 "tzinfo.%s() must return None or "
Tim Peters855fe882002-12-22 03:43:39 +0000679 "timedelta, not '%s'",
680 name, u->ob_type->tp_name);
Tim Peters2a799bf2002-12-16 20:18:38 +0000681 }
682
Tim Peters2a799bf2002-12-16 20:18:38 +0000683 Py_DECREF(u);
684 if (result < -1439 || result > 1439) {
685 PyErr_Format(PyExc_ValueError,
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;
1402static PyObject *datetime_unpickler_object = NULL;
1403static PyObject *datetimetz_unpickler_object = NULL;
1404static PyObject *tzinfo_unpickler_object = NULL;
1405static PyObject *time_unpickler_object = NULL;
1406static PyObject *timetz_unpickler_object = NULL;
1407
1408/* ---------------------------------------------------------------------------
1409 * Class implementations.
1410 */
1411
1412/*
1413 * PyDateTime_Delta implementation.
1414 */
1415
1416/* Convert a timedelta to a number of us,
1417 * (24*3600*self.days + self.seconds)*1000000 + self.microseconds
1418 * as a Python int or long.
1419 * Doing mixed-radix arithmetic by hand instead is excruciating in C,
1420 * due to ubiquitous overflow possibilities.
1421 */
1422static PyObject *
1423delta_to_microseconds(PyDateTime_Delta *self)
1424{
1425 PyObject *x1 = NULL;
1426 PyObject *x2 = NULL;
1427 PyObject *x3 = NULL;
1428 PyObject *result = NULL;
1429
1430 x1 = PyInt_FromLong(GET_TD_DAYS(self));
1431 if (x1 == NULL)
1432 goto Done;
1433 x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */
1434 if (x2 == NULL)
1435 goto Done;
1436 Py_DECREF(x1);
1437 x1 = NULL;
1438
1439 /* x2 has days in seconds */
1440 x1 = PyInt_FromLong(GET_TD_SECONDS(self)); /* seconds */
1441 if (x1 == NULL)
1442 goto Done;
1443 x3 = PyNumber_Add(x1, x2); /* days and seconds in seconds */
1444 if (x3 == NULL)
1445 goto Done;
1446 Py_DECREF(x1);
1447 Py_DECREF(x2);
1448 x1 = x2 = NULL;
1449
1450 /* x3 has days+seconds in seconds */
1451 x1 = PyNumber_Multiply(x3, us_per_second); /* us */
1452 if (x1 == NULL)
1453 goto Done;
1454 Py_DECREF(x3);
1455 x3 = NULL;
1456
1457 /* x1 has days+seconds in us */
1458 x2 = PyInt_FromLong(GET_TD_MICROSECONDS(self));
1459 if (x2 == NULL)
1460 goto Done;
1461 result = PyNumber_Add(x1, x2);
1462
1463Done:
1464 Py_XDECREF(x1);
1465 Py_XDECREF(x2);
1466 Py_XDECREF(x3);
1467 return result;
1468}
1469
1470/* Convert a number of us (as a Python int or long) to a timedelta.
1471 */
1472static PyObject *
1473microseconds_to_delta(PyObject *pyus)
1474{
1475 int us;
1476 int s;
1477 int d;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001478 long temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001479
1480 PyObject *tuple = NULL;
1481 PyObject *num = NULL;
1482 PyObject *result = NULL;
1483
1484 tuple = PyNumber_Divmod(pyus, us_per_second);
1485 if (tuple == NULL)
1486 goto Done;
1487
1488 num = PyTuple_GetItem(tuple, 1); /* us */
1489 if (num == NULL)
1490 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001491 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001492 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001493 if (temp == -1 && PyErr_Occurred())
1494 goto Done;
1495 assert(0 <= temp && temp < 1000000);
1496 us = (int)temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001497 if (us < 0) {
1498 /* The divisor was positive, so this must be an error. */
1499 assert(PyErr_Occurred());
1500 goto Done;
1501 }
1502
1503 num = PyTuple_GetItem(tuple, 0); /* leftover seconds */
1504 if (num == NULL)
1505 goto Done;
1506 Py_INCREF(num);
1507 Py_DECREF(tuple);
1508
1509 tuple = PyNumber_Divmod(num, seconds_per_day);
1510 if (tuple == NULL)
1511 goto Done;
1512 Py_DECREF(num);
1513
1514 num = PyTuple_GetItem(tuple, 1); /* seconds */
1515 if (num == NULL)
1516 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001517 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001518 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001519 if (temp == -1 && PyErr_Occurred())
1520 goto Done;
1521 assert(0 <= temp && temp < 24*3600);
1522 s = (int)temp;
1523
Tim Peters2a799bf2002-12-16 20:18:38 +00001524 if (s < 0) {
1525 /* The divisor was positive, so this must be an error. */
1526 assert(PyErr_Occurred());
1527 goto Done;
1528 }
1529
1530 num = PyTuple_GetItem(tuple, 0); /* leftover days */
1531 if (num == NULL)
1532 goto Done;
1533 Py_INCREF(num);
Tim Peters0b0f41c2002-12-19 01:44:38 +00001534 temp = PyLong_AsLong(num);
1535 if (temp == -1 && PyErr_Occurred())
Tim Peters2a799bf2002-12-16 20:18:38 +00001536 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001537 d = (int)temp;
1538 if ((long)d != temp) {
1539 PyErr_SetString(PyExc_OverflowError, "normalized days too "
1540 "large to fit in a C int");
1541 goto Done;
1542 }
Tim Peters2a799bf2002-12-16 20:18:38 +00001543 result = new_delta(d, s, us, 0);
1544
1545Done:
1546 Py_XDECREF(tuple);
1547 Py_XDECREF(num);
1548 return result;
1549}
1550
1551static PyObject *
1552multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
1553{
1554 PyObject *pyus_in;
1555 PyObject *pyus_out;
1556 PyObject *result;
1557
1558 pyus_in = delta_to_microseconds(delta);
1559 if (pyus_in == NULL)
1560 return NULL;
1561
1562 pyus_out = PyNumber_Multiply(pyus_in, intobj);
1563 Py_DECREF(pyus_in);
1564 if (pyus_out == NULL)
1565 return NULL;
1566
1567 result = microseconds_to_delta(pyus_out);
1568 Py_DECREF(pyus_out);
1569 return result;
1570}
1571
1572static PyObject *
1573divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj)
1574{
1575 PyObject *pyus_in;
1576 PyObject *pyus_out;
1577 PyObject *result;
1578
1579 pyus_in = delta_to_microseconds(delta);
1580 if (pyus_in == NULL)
1581 return NULL;
1582
1583 pyus_out = PyNumber_FloorDivide(pyus_in, intobj);
1584 Py_DECREF(pyus_in);
1585 if (pyus_out == NULL)
1586 return NULL;
1587
1588 result = microseconds_to_delta(pyus_out);
1589 Py_DECREF(pyus_out);
1590 return result;
1591}
1592
1593static PyObject *
1594delta_add(PyObject *left, PyObject *right)
1595{
1596 PyObject *result = Py_NotImplemented;
1597
1598 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1599 /* delta + delta */
1600 /* The C-level additions can't overflow because of the
1601 * invariant bounds.
1602 */
1603 int days = GET_TD_DAYS(left) + GET_TD_DAYS(right);
1604 int seconds = GET_TD_SECONDS(left) + GET_TD_SECONDS(right);
1605 int microseconds = GET_TD_MICROSECONDS(left) +
1606 GET_TD_MICROSECONDS(right);
1607 result = new_delta(days, seconds, microseconds, 1);
1608 }
1609
1610 if (result == Py_NotImplemented)
1611 Py_INCREF(result);
1612 return result;
1613}
1614
1615static PyObject *
1616delta_negative(PyDateTime_Delta *self)
1617{
1618 return new_delta(-GET_TD_DAYS(self),
1619 -GET_TD_SECONDS(self),
1620 -GET_TD_MICROSECONDS(self),
1621 1);
1622}
1623
1624static PyObject *
1625delta_positive(PyDateTime_Delta *self)
1626{
1627 /* Could optimize this (by returning self) if this isn't a
1628 * subclass -- but who uses unary + ? Approximately nobody.
1629 */
1630 return new_delta(GET_TD_DAYS(self),
1631 GET_TD_SECONDS(self),
1632 GET_TD_MICROSECONDS(self),
1633 0);
1634}
1635
1636static PyObject *
1637delta_abs(PyDateTime_Delta *self)
1638{
1639 PyObject *result;
1640
1641 assert(GET_TD_MICROSECONDS(self) >= 0);
1642 assert(GET_TD_SECONDS(self) >= 0);
1643
1644 if (GET_TD_DAYS(self) < 0)
1645 result = delta_negative(self);
1646 else
1647 result = delta_positive(self);
1648
1649 return result;
1650}
1651
1652static PyObject *
1653delta_subtract(PyObject *left, PyObject *right)
1654{
1655 PyObject *result = Py_NotImplemented;
1656
1657 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1658 /* delta - delta */
1659 PyObject *minus_right = PyNumber_Negative(right);
1660 if (minus_right) {
1661 result = delta_add(left, minus_right);
1662 Py_DECREF(minus_right);
1663 }
1664 else
1665 result = NULL;
1666 }
1667
1668 if (result == Py_NotImplemented)
1669 Py_INCREF(result);
1670 return result;
1671}
1672
1673/* This is more natural as a tp_compare, but doesn't work then: for whatever
1674 * reason, Python's try_3way_compare ignores tp_compare unless
1675 * PyInstance_Check returns true, but these aren't old-style classes.
1676 */
1677static PyObject *
1678delta_richcompare(PyDateTime_Delta *self, PyObject *other, int op)
1679{
1680 int diff;
1681
1682 if (! PyDelta_CheckExact(other)) {
1683 PyErr_Format(PyExc_TypeError,
1684 "can't compare %s to %s instance",
1685 self->ob_type->tp_name, other->ob_type->tp_name);
1686 return NULL;
1687 }
1688 diff = GET_TD_DAYS(self) - GET_TD_DAYS(other);
1689 if (diff == 0) {
1690 diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other);
1691 if (diff == 0)
1692 diff = GET_TD_MICROSECONDS(self) -
1693 GET_TD_MICROSECONDS(other);
1694 }
1695 return diff_to_bool(diff, op);
1696}
1697
1698static PyObject *delta_getstate(PyDateTime_Delta *self);
1699
1700static long
1701delta_hash(PyDateTime_Delta *self)
1702{
1703 if (self->hashcode == -1) {
1704 PyObject *temp = delta_getstate(self);
1705 if (temp != NULL) {
1706 self->hashcode = PyObject_Hash(temp);
1707 Py_DECREF(temp);
1708 }
1709 }
1710 return self->hashcode;
1711}
1712
1713static PyObject *
1714delta_multiply(PyObject *left, PyObject *right)
1715{
1716 PyObject *result = Py_NotImplemented;
1717
1718 if (PyDelta_Check(left)) {
1719 /* delta * ??? */
1720 if (PyInt_Check(right) || PyLong_Check(right))
1721 result = multiply_int_timedelta(right,
1722 (PyDateTime_Delta *) left);
1723 }
1724 else if (PyInt_Check(left) || PyLong_Check(left))
1725 result = multiply_int_timedelta(left,
1726 (PyDateTime_Delta *) right);
1727
1728 if (result == Py_NotImplemented)
1729 Py_INCREF(result);
1730 return result;
1731}
1732
1733static PyObject *
1734delta_divide(PyObject *left, PyObject *right)
1735{
1736 PyObject *result = Py_NotImplemented;
1737
1738 if (PyDelta_Check(left)) {
1739 /* delta * ??? */
1740 if (PyInt_Check(right) || PyLong_Check(right))
1741 result = divide_timedelta_int(
1742 (PyDateTime_Delta *)left,
1743 right);
1744 }
1745
1746 if (result == Py_NotImplemented)
1747 Py_INCREF(result);
1748 return result;
1749}
1750
1751/* Fold in the value of the tag ("seconds", "weeks", etc) component of a
1752 * timedelta constructor. sofar is the # of microseconds accounted for
1753 * so far, and there are factor microseconds per current unit, the number
1754 * of which is given by num. num * factor is added to sofar in a
1755 * numerically careful way, and that's the result. Any fractional
1756 * microseconds left over (this can happen if num is a float type) are
1757 * added into *leftover.
1758 * Note that there are many ways this can give an error (NULL) return.
1759 */
1760static PyObject *
1761accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
1762 double *leftover)
1763{
1764 PyObject *prod;
1765 PyObject *sum;
1766
1767 assert(num != NULL);
1768
1769 if (PyInt_Check(num) || PyLong_Check(num)) {
1770 prod = PyNumber_Multiply(num, factor);
1771 if (prod == NULL)
1772 return NULL;
1773 sum = PyNumber_Add(sofar, prod);
1774 Py_DECREF(prod);
1775 return sum;
1776 }
1777
1778 if (PyFloat_Check(num)) {
1779 double dnum;
1780 double fracpart;
1781 double intpart;
1782 PyObject *x;
1783 PyObject *y;
1784
1785 /* The Plan: decompose num into an integer part and a
1786 * fractional part, num = intpart + fracpart.
1787 * Then num * factor ==
1788 * intpart * factor + fracpart * factor
1789 * and the LHS can be computed exactly in long arithmetic.
1790 * The RHS is again broken into an int part and frac part.
1791 * and the frac part is added into *leftover.
1792 */
1793 dnum = PyFloat_AsDouble(num);
1794 if (dnum == -1.0 && PyErr_Occurred())
1795 return NULL;
1796 fracpart = modf(dnum, &intpart);
1797 x = PyLong_FromDouble(intpart);
1798 if (x == NULL)
1799 return NULL;
1800
1801 prod = PyNumber_Multiply(x, factor);
1802 Py_DECREF(x);
1803 if (prod == NULL)
1804 return NULL;
1805
1806 sum = PyNumber_Add(sofar, prod);
1807 Py_DECREF(prod);
1808 if (sum == NULL)
1809 return NULL;
1810
1811 if (fracpart == 0.0)
1812 return sum;
1813 /* So far we've lost no information. Dealing with the
1814 * fractional part requires float arithmetic, and may
1815 * lose a little info.
1816 */
1817 assert(PyInt_Check(factor) || PyLong_Check(factor));
1818 if (PyInt_Check(factor))
1819 dnum = (double)PyInt_AsLong(factor);
1820 else
1821 dnum = PyLong_AsDouble(factor);
1822
1823 dnum *= fracpart;
1824 fracpart = modf(dnum, &intpart);
1825 x = PyLong_FromDouble(intpart);
1826 if (x == NULL) {
1827 Py_DECREF(sum);
1828 return NULL;
1829 }
1830
1831 y = PyNumber_Add(sum, x);
1832 Py_DECREF(sum);
1833 Py_DECREF(x);
1834 *leftover += fracpart;
1835 return y;
1836 }
1837
1838 PyErr_Format(PyExc_TypeError,
1839 "unsupported type for timedelta %s component: %s",
1840 tag, num->ob_type->tp_name);
1841 return NULL;
1842}
1843
1844static PyObject *
1845delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1846{
1847 PyObject *self = NULL;
1848
1849 /* Argument objects. */
1850 PyObject *day = NULL;
1851 PyObject *second = NULL;
1852 PyObject *us = NULL;
1853 PyObject *ms = NULL;
1854 PyObject *minute = NULL;
1855 PyObject *hour = NULL;
1856 PyObject *week = NULL;
1857
1858 PyObject *x = NULL; /* running sum of microseconds */
1859 PyObject *y = NULL; /* temp sum of microseconds */
1860 double leftover_us = 0.0;
1861
1862 static char *keywords[] = {
1863 "days", "seconds", "microseconds", "milliseconds",
1864 "minutes", "hours", "weeks", NULL
1865 };
1866
1867 if (PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOO:__new__",
1868 keywords,
1869 &day, &second, &us,
1870 &ms, &minute, &hour, &week) == 0)
1871 goto Done;
1872
1873 x = PyInt_FromLong(0);
1874 if (x == NULL)
1875 goto Done;
1876
1877#define CLEANUP \
1878 Py_DECREF(x); \
1879 x = y; \
1880 if (x == NULL) \
1881 goto Done
1882
1883 if (us) {
1884 y = accum("microseconds", x, us, us_per_us, &leftover_us);
1885 CLEANUP;
1886 }
1887 if (ms) {
1888 y = accum("milliseconds", x, ms, us_per_ms, &leftover_us);
1889 CLEANUP;
1890 }
1891 if (second) {
1892 y = accum("seconds", x, second, us_per_second, &leftover_us);
1893 CLEANUP;
1894 }
1895 if (minute) {
1896 y = accum("minutes", x, minute, us_per_minute, &leftover_us);
1897 CLEANUP;
1898 }
1899 if (hour) {
1900 y = accum("hours", x, hour, us_per_hour, &leftover_us);
1901 CLEANUP;
1902 }
1903 if (day) {
1904 y = accum("days", x, day, us_per_day, &leftover_us);
1905 CLEANUP;
1906 }
1907 if (week) {
1908 y = accum("weeks", x, week, us_per_week, &leftover_us);
1909 CLEANUP;
1910 }
1911 if (leftover_us) {
1912 /* Round to nearest whole # of us, and add into x. */
Tim Peters5d644dd2003-01-02 16:32:54 +00001913 PyObject *temp = PyLong_FromLong(round_to_long(leftover_us));
Tim Peters2a799bf2002-12-16 20:18:38 +00001914 if (temp == NULL) {
1915 Py_DECREF(x);
1916 goto Done;
1917 }
1918 y = PyNumber_Add(x, temp);
1919 Py_DECREF(temp);
1920 CLEANUP;
1921 }
1922
1923 self = microseconds_to_delta(x);
1924 Py_DECREF(x);
1925Done:
1926 return self;
1927
1928#undef CLEANUP
1929}
1930
1931static int
1932delta_nonzero(PyDateTime_Delta *self)
1933{
1934 return (GET_TD_DAYS(self) != 0
1935 || GET_TD_SECONDS(self) != 0
1936 || GET_TD_MICROSECONDS(self) != 0);
1937}
1938
1939static PyObject *
1940delta_repr(PyDateTime_Delta *self)
1941{
1942 if (GET_TD_MICROSECONDS(self) != 0)
1943 return PyString_FromFormat("%s(%d, %d, %d)",
1944 self->ob_type->tp_name,
1945 GET_TD_DAYS(self),
1946 GET_TD_SECONDS(self),
1947 GET_TD_MICROSECONDS(self));
1948 if (GET_TD_SECONDS(self) != 0)
1949 return PyString_FromFormat("%s(%d, %d)",
1950 self->ob_type->tp_name,
1951 GET_TD_DAYS(self),
1952 GET_TD_SECONDS(self));
1953
1954 return PyString_FromFormat("%s(%d)",
1955 self->ob_type->tp_name,
1956 GET_TD_DAYS(self));
1957}
1958
1959static PyObject *
1960delta_str(PyDateTime_Delta *self)
1961{
1962 int days = GET_TD_DAYS(self);
1963 int seconds = GET_TD_SECONDS(self);
1964 int us = GET_TD_MICROSECONDS(self);
1965 int hours;
1966 int minutes;
Tim Petersba873472002-12-18 20:19:21 +00001967 char buf[100];
1968 char *pbuf = buf;
1969 size_t buflen = sizeof(buf);
1970 int n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001971
1972 minutes = divmod(seconds, 60, &seconds);
1973 hours = divmod(minutes, 60, &minutes);
1974
1975 if (days) {
Tim Petersba873472002-12-18 20:19:21 +00001976 n = PyOS_snprintf(pbuf, buflen, "%d day%s, ", days,
1977 (days == 1 || days == -1) ? "" : "s");
1978 if (n < 0 || (size_t)n >= buflen)
1979 goto Fail;
1980 pbuf += n;
1981 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001982 }
1983
Tim Petersba873472002-12-18 20:19:21 +00001984 n = PyOS_snprintf(pbuf, buflen, "%d:%02d:%02d",
1985 hours, minutes, seconds);
1986 if (n < 0 || (size_t)n >= buflen)
1987 goto Fail;
1988 pbuf += n;
1989 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001990
1991 if (us) {
Tim Petersba873472002-12-18 20:19:21 +00001992 n = PyOS_snprintf(pbuf, buflen, ".%06d", us);
1993 if (n < 0 || (size_t)n >= buflen)
1994 goto Fail;
1995 pbuf += n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001996 }
1997
Tim Petersba873472002-12-18 20:19:21 +00001998 return PyString_FromStringAndSize(buf, pbuf - buf);
1999
2000 Fail:
2001 PyErr_SetString(PyExc_SystemError, "goofy result from PyOS_snprintf");
2002 return NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00002003}
2004
2005/* Pickle support. Quite a maze! While __getstate__/__setstate__ sufficed
2006 * in the Python implementation, the C implementation also requires
2007 * __reduce__, and a __safe_for_unpickling__ attr in the type object.
2008 */
2009static PyObject *
2010delta_getstate(PyDateTime_Delta *self)
2011{
2012 return Py_BuildValue("iii", GET_TD_DAYS(self),
2013 GET_TD_SECONDS(self),
2014 GET_TD_MICROSECONDS(self));
2015}
2016
2017static PyObject *
2018delta_setstate(PyDateTime_Delta *self, PyObject *state)
2019{
2020 int day;
2021 int second;
2022 int us;
2023
2024 if (!PyArg_ParseTuple(state, "iii:__setstate__", &day, &second, &us))
2025 return NULL;
2026
2027 self->hashcode = -1;
2028 SET_TD_DAYS(self, day);
2029 SET_TD_SECONDS(self, second);
2030 SET_TD_MICROSECONDS(self, us);
2031
2032 Py_INCREF(Py_None);
2033 return Py_None;
2034}
2035
2036static PyObject *
2037delta_reduce(PyDateTime_Delta* self)
2038{
2039 PyObject* result = NULL;
2040 PyObject* state = delta_getstate(self);
2041
2042 if (state != NULL) {
2043 /* The funky "()" in the format string creates an empty
2044 * tuple as the 2nd component of the result 3-tuple.
2045 */
2046 result = Py_BuildValue("O()O", self->ob_type, state);
2047 Py_DECREF(state);
2048 }
2049 return result;
2050}
2051
2052#define OFFSET(field) offsetof(PyDateTime_Delta, field)
2053
2054static PyMemberDef delta_members[] = {
Neal Norwitzdfb80862002-12-19 02:30:56 +00002055 {"days", T_INT, OFFSET(days), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002056 PyDoc_STR("Number of days.")},
2057
Neal Norwitzdfb80862002-12-19 02:30:56 +00002058 {"seconds", T_INT, OFFSET(seconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002059 PyDoc_STR("Number of seconds (>= 0 and less than 1 day).")},
2060
Neal Norwitzdfb80862002-12-19 02:30:56 +00002061 {"microseconds", T_INT, OFFSET(microseconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002062 PyDoc_STR("Number of microseconds (>= 0 and less than 1 second).")},
2063 {NULL}
2064};
2065
2066static PyMethodDef delta_methods[] = {
2067 {"__setstate__", (PyCFunction)delta_setstate, METH_O,
2068 PyDoc_STR("__setstate__(state)")},
2069
2070 {"__reduce__", (PyCFunction)delta_reduce, METH_NOARGS,
2071 PyDoc_STR("__setstate__(state)")},
2072
2073 {"__getstate__", (PyCFunction)delta_getstate, METH_NOARGS,
2074 PyDoc_STR("__getstate__() -> state")},
2075 {NULL, NULL},
2076};
2077
2078static char delta_doc[] =
2079PyDoc_STR("Difference between two datetime values.");
2080
2081static PyNumberMethods delta_as_number = {
2082 delta_add, /* nb_add */
2083 delta_subtract, /* nb_subtract */
2084 delta_multiply, /* nb_multiply */
2085 delta_divide, /* nb_divide */
2086 0, /* nb_remainder */
2087 0, /* nb_divmod */
2088 0, /* nb_power */
2089 (unaryfunc)delta_negative, /* nb_negative */
2090 (unaryfunc)delta_positive, /* nb_positive */
2091 (unaryfunc)delta_abs, /* nb_absolute */
2092 (inquiry)delta_nonzero, /* nb_nonzero */
2093 0, /*nb_invert*/
2094 0, /*nb_lshift*/
2095 0, /*nb_rshift*/
2096 0, /*nb_and*/
2097 0, /*nb_xor*/
2098 0, /*nb_or*/
2099 0, /*nb_coerce*/
2100 0, /*nb_int*/
2101 0, /*nb_long*/
2102 0, /*nb_float*/
2103 0, /*nb_oct*/
2104 0, /*nb_hex*/
2105 0, /*nb_inplace_add*/
2106 0, /*nb_inplace_subtract*/
2107 0, /*nb_inplace_multiply*/
2108 0, /*nb_inplace_divide*/
2109 0, /*nb_inplace_remainder*/
2110 0, /*nb_inplace_power*/
2111 0, /*nb_inplace_lshift*/
2112 0, /*nb_inplace_rshift*/
2113 0, /*nb_inplace_and*/
2114 0, /*nb_inplace_xor*/
2115 0, /*nb_inplace_or*/
2116 delta_divide, /* nb_floor_divide */
2117 0, /* nb_true_divide */
2118 0, /* nb_inplace_floor_divide */
2119 0, /* nb_inplace_true_divide */
2120};
2121
2122static PyTypeObject PyDateTime_DeltaType = {
2123 PyObject_HEAD_INIT(NULL)
2124 0, /* ob_size */
2125 "datetime.timedelta", /* tp_name */
2126 sizeof(PyDateTime_Delta), /* tp_basicsize */
2127 0, /* tp_itemsize */
2128 0, /* tp_dealloc */
2129 0, /* tp_print */
2130 0, /* tp_getattr */
2131 0, /* tp_setattr */
2132 0, /* tp_compare */
2133 (reprfunc)delta_repr, /* tp_repr */
2134 &delta_as_number, /* tp_as_number */
2135 0, /* tp_as_sequence */
2136 0, /* tp_as_mapping */
2137 (hashfunc)delta_hash, /* tp_hash */
2138 0, /* tp_call */
2139 (reprfunc)delta_str, /* tp_str */
2140 PyObject_GenericGetAttr, /* tp_getattro */
2141 0, /* tp_setattro */
2142 0, /* tp_as_buffer */
2143 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
2144 delta_doc, /* tp_doc */
2145 0, /* tp_traverse */
2146 0, /* tp_clear */
2147 (richcmpfunc)delta_richcompare, /* tp_richcompare */
2148 0, /* tp_weaklistoffset */
2149 0, /* tp_iter */
2150 0, /* tp_iternext */
2151 delta_methods, /* tp_methods */
2152 delta_members, /* tp_members */
2153 0, /* tp_getset */
2154 0, /* tp_base */
2155 0, /* tp_dict */
2156 0, /* tp_descr_get */
2157 0, /* tp_descr_set */
2158 0, /* tp_dictoffset */
2159 0, /* tp_init */
2160 0, /* tp_alloc */
2161 delta_new, /* tp_new */
2162 _PyObject_Del, /* tp_free */
2163};
2164
2165/*
2166 * PyDateTime_Date implementation.
2167 */
2168
2169/* Accessor properties. */
2170
2171static PyObject *
2172date_year(PyDateTime_Date *self, void *unused)
2173{
2174 return PyInt_FromLong(GET_YEAR(self));
2175}
2176
2177static PyObject *
2178date_month(PyDateTime_Date *self, void *unused)
2179{
2180 return PyInt_FromLong(GET_MONTH(self));
2181}
2182
2183static PyObject *
2184date_day(PyDateTime_Date *self, void *unused)
2185{
2186 return PyInt_FromLong(GET_DAY(self));
2187}
2188
2189static PyGetSetDef date_getset[] = {
2190 {"year", (getter)date_year},
2191 {"month", (getter)date_month},
2192 {"day", (getter)date_day},
2193 {NULL}
2194};
2195
2196/* Constructors. */
2197
Tim Peters12bf3392002-12-24 05:41:27 +00002198static char *date_kws[] = {"year", "month", "day", NULL};
2199
Tim Peters2a799bf2002-12-16 20:18:38 +00002200static PyObject *
2201date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2202{
2203 PyObject *self = NULL;
2204 int year;
2205 int month;
2206 int day;
2207
Tim Peters12bf3392002-12-24 05:41:27 +00002208 if (PyArg_ParseTupleAndKeywords(args, kw, "iii", date_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002209 &year, &month, &day)) {
2210 if (check_date_args(year, month, day) < 0)
2211 return NULL;
2212 self = new_date(year, month, day);
2213 }
2214 return self;
2215}
2216
2217/* Return new date from localtime(t). */
2218static PyObject *
2219date_local_from_time_t(PyObject *cls, time_t t)
2220{
2221 struct tm *tm;
2222 PyObject *result = NULL;
2223
2224 tm = localtime(&t);
2225 if (tm)
2226 result = PyObject_CallFunction(cls, "iii",
2227 tm->tm_year + 1900,
2228 tm->tm_mon + 1,
2229 tm->tm_mday);
2230 else
2231 PyErr_SetString(PyExc_ValueError,
2232 "timestamp out of range for "
2233 "platform localtime() function");
2234 return result;
2235}
2236
2237/* Return new date from current time.
2238 * We say this is equivalent to fromtimestamp(time.time()), and the
2239 * only way to be sure of that is to *call* time.time(). That's not
2240 * generally the same as calling C's time.
2241 */
2242static PyObject *
2243date_today(PyObject *cls, PyObject *dummy)
2244{
2245 PyObject *time;
2246 PyObject *result;
2247
2248 time = time_time();
2249 if (time == NULL)
2250 return NULL;
2251
2252 /* Note well: today() is a class method, so this may not call
2253 * date.fromtimestamp. For example, it may call
2254 * datetime.fromtimestamp. That's why we need all the accuracy
2255 * time.time() delivers; if someone were gonzo about optimization,
2256 * date.today() could get away with plain C time().
2257 */
2258 result = PyObject_CallMethod(cls, "fromtimestamp", "O", time);
2259 Py_DECREF(time);
2260 return result;
2261}
2262
2263/* Return new date from given timestamp (Python timestamp -- a double). */
2264static PyObject *
2265date_fromtimestamp(PyObject *cls, PyObject *args)
2266{
2267 double timestamp;
2268 PyObject *result = NULL;
2269
2270 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2271 result = date_local_from_time_t(cls, (time_t)timestamp);
2272 return result;
2273}
2274
2275/* Return new date from proleptic Gregorian ordinal. Raises ValueError if
2276 * the ordinal is out of range.
2277 */
2278static PyObject *
2279date_fromordinal(PyObject *cls, PyObject *args)
2280{
2281 PyObject *result = NULL;
2282 int ordinal;
2283
2284 if (PyArg_ParseTuple(args, "i:fromordinal", &ordinal)) {
2285 int year;
2286 int month;
2287 int day;
2288
2289 if (ordinal < 1)
2290 PyErr_SetString(PyExc_ValueError, "ordinal must be "
2291 ">= 1");
2292 else {
2293 ord_to_ymd(ordinal, &year, &month, &day);
2294 result = PyObject_CallFunction(cls, "iii",
2295 year, month, day);
2296 }
2297 }
2298 return result;
2299}
2300
2301/*
2302 * Date arithmetic.
2303 */
2304
2305/* date + timedelta -> date. If arg negate is true, subtract the timedelta
2306 * instead.
2307 */
2308static PyObject *
2309add_date_timedelta(PyDateTime_Date *date, PyDateTime_Delta *delta, int negate)
2310{
2311 PyObject *result = NULL;
2312 int year = GET_YEAR(date);
2313 int month = GET_MONTH(date);
2314 int deltadays = GET_TD_DAYS(delta);
2315 /* C-level overflow is impossible because |deltadays| < 1e9. */
2316 int day = GET_DAY(date) + (negate ? -deltadays : deltadays);
2317
2318 if (normalize_date(&year, &month, &day) >= 0)
2319 result = new_date(year, month, day);
2320 return result;
2321}
2322
2323static PyObject *
2324date_add(PyObject *left, PyObject *right)
2325{
2326 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2327 Py_INCREF(Py_NotImplemented);
2328 return Py_NotImplemented;
2329 }
2330 if (PyDate_CheckExact(left)) {
2331 /* date + ??? */
2332 if (PyDelta_Check(right))
2333 /* date + delta */
2334 return add_date_timedelta((PyDateTime_Date *) left,
2335 (PyDateTime_Delta *) right,
2336 0);
2337 }
2338 else {
2339 /* ??? + date
2340 * 'right' must be one of us, or we wouldn't have been called
2341 */
2342 if (PyDelta_Check(left))
2343 /* delta + date */
2344 return add_date_timedelta((PyDateTime_Date *) right,
2345 (PyDateTime_Delta *) left,
2346 0);
2347 }
2348 Py_INCREF(Py_NotImplemented);
2349 return Py_NotImplemented;
2350}
2351
2352static PyObject *
2353date_subtract(PyObject *left, PyObject *right)
2354{
2355 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2356 Py_INCREF(Py_NotImplemented);
2357 return Py_NotImplemented;
2358 }
2359 if (PyDate_CheckExact(left)) {
2360 if (PyDate_CheckExact(right)) {
2361 /* date - date */
2362 int left_ord = ymd_to_ord(GET_YEAR(left),
2363 GET_MONTH(left),
2364 GET_DAY(left));
2365 int right_ord = ymd_to_ord(GET_YEAR(right),
2366 GET_MONTH(right),
2367 GET_DAY(right));
2368 return new_delta(left_ord - right_ord, 0, 0, 0);
2369 }
2370 if (PyDelta_Check(right)) {
2371 /* date - delta */
2372 return add_date_timedelta((PyDateTime_Date *) left,
2373 (PyDateTime_Delta *) right,
2374 1);
2375 }
2376 }
2377 Py_INCREF(Py_NotImplemented);
2378 return Py_NotImplemented;
2379}
2380
2381
2382/* Various ways to turn a date into a string. */
2383
2384static PyObject *
2385date_repr(PyDateTime_Date *self)
2386{
2387 char buffer[1028];
2388 char *typename;
2389
2390 typename = self->ob_type->tp_name;
2391 PyOS_snprintf(buffer, sizeof(buffer), "%s(%d, %d, %d)",
2392 typename,
2393 GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2394
2395 return PyString_FromString(buffer);
2396}
2397
2398static PyObject *
2399date_isoformat(PyDateTime_Date *self)
2400{
2401 char buffer[128];
2402
2403 isoformat_date(self, buffer, sizeof(buffer));
2404 return PyString_FromString(buffer);
2405}
2406
2407/* str() calls the appropriate isofomat() method. */
2408static PyObject *
2409date_str(PyDateTime_Date *self)
2410{
2411 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
2412}
2413
2414
2415static PyObject *
2416date_ctime(PyDateTime_Date *self)
2417{
2418 return format_ctime(self, 0, 0, 0);
2419}
2420
2421static PyObject *
2422date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2423{
2424 /* This method can be inherited, and needs to call the
2425 * timetuple() method appropriate to self's class.
2426 */
2427 PyObject *result;
2428 PyObject *format;
2429 PyObject *tuple;
2430 static char *keywords[] = {"format", NULL};
2431
2432 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
2433 &PyString_Type, &format))
2434 return NULL;
2435
2436 tuple = PyObject_CallMethod((PyObject *)self, "timetuple", "()");
2437 if (tuple == NULL)
2438 return NULL;
Tim Petersbad8ff02002-12-30 20:52:32 +00002439 result = wrap_strftime((PyObject *)self, format, tuple,
2440 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00002441 Py_DECREF(tuple);
2442 return result;
2443}
2444
2445/* ISO methods. */
2446
2447static PyObject *
2448date_isoweekday(PyDateTime_Date *self)
2449{
2450 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2451
2452 return PyInt_FromLong(dow + 1);
2453}
2454
2455static PyObject *
2456date_isocalendar(PyDateTime_Date *self)
2457{
2458 int year = GET_YEAR(self);
2459 int week1_monday = iso_week1_monday(year);
2460 int today = ymd_to_ord(year, GET_MONTH(self), GET_DAY(self));
2461 int week;
2462 int day;
2463
2464 week = divmod(today - week1_monday, 7, &day);
2465 if (week < 0) {
2466 --year;
2467 week1_monday = iso_week1_monday(year);
2468 week = divmod(today - week1_monday, 7, &day);
2469 }
2470 else if (week >= 52 && today >= iso_week1_monday(year + 1)) {
2471 ++year;
2472 week = 0;
2473 }
2474 return Py_BuildValue("iii", year, week + 1, day + 1);
2475}
2476
2477/* Miscellaneous methods. */
2478
2479/* This is more natural as a tp_compare, but doesn't work then: for whatever
2480 * reason, Python's try_3way_compare ignores tp_compare unless
2481 * PyInstance_Check returns true, but these aren't old-style classes.
2482 */
2483static PyObject *
2484date_richcompare(PyDateTime_Date *self, PyObject *other, int op)
2485{
2486 int diff;
2487
2488 if (! PyDate_Check(other)) {
2489 PyErr_Format(PyExc_TypeError,
2490 "can't compare date to %s instance",
2491 other->ob_type->tp_name);
2492 return NULL;
2493 }
2494 diff = memcmp(self->data, ((PyDateTime_Date *)other)->data,
2495 _PyDateTime_DATE_DATASIZE);
2496 return diff_to_bool(diff, op);
2497}
2498
2499static PyObject *
2500date_timetuple(PyDateTime_Date *self)
2501{
2502 return build_struct_time(GET_YEAR(self),
2503 GET_MONTH(self),
2504 GET_DAY(self),
2505 0, 0, 0, -1);
2506}
2507
Tim Peters12bf3392002-12-24 05:41:27 +00002508static PyObject *
2509date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2510{
2511 PyObject *clone;
2512 PyObject *tuple;
2513 int year = GET_YEAR(self);
2514 int month = GET_MONTH(self);
2515 int day = GET_DAY(self);
2516
2517 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iii:replace", date_kws,
2518 &year, &month, &day))
2519 return NULL;
2520 tuple = Py_BuildValue("iii", year, month, day);
2521 if (tuple == NULL)
2522 return NULL;
2523 clone = date_new(self->ob_type, tuple, NULL);
2524 Py_DECREF(tuple);
2525 return clone;
2526}
2527
Tim Peters2a799bf2002-12-16 20:18:38 +00002528static PyObject *date_getstate(PyDateTime_Date *self);
2529
2530static long
2531date_hash(PyDateTime_Date *self)
2532{
2533 if (self->hashcode == -1) {
2534 PyObject *temp = date_getstate(self);
2535 if (temp != NULL) {
2536 self->hashcode = PyObject_Hash(temp);
2537 Py_DECREF(temp);
2538 }
2539 }
2540 return self->hashcode;
2541}
2542
2543static PyObject *
2544date_toordinal(PyDateTime_Date *self)
2545{
2546 return PyInt_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self),
2547 GET_DAY(self)));
2548}
2549
2550static PyObject *
2551date_weekday(PyDateTime_Date *self)
2552{
2553 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2554
2555 return PyInt_FromLong(dow);
2556}
2557
2558/* Pickle support. Quite a maze! */
2559
2560static PyObject *
2561date_getstate(PyDateTime_Date *self)
2562{
Jack Jansenb8941f22003-01-08 16:28:45 +00002563 return PyString_FromStringAndSize((char *)self->data,
Tim Peters2a799bf2002-12-16 20:18:38 +00002564 _PyDateTime_DATE_DATASIZE);
2565}
2566
2567static PyObject *
2568date_setstate(PyDateTime_Date *self, PyObject *state)
2569{
2570 const int len = PyString_Size(state);
2571 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
2572
2573 if (! PyString_Check(state) ||
2574 len != _PyDateTime_DATE_DATASIZE) {
2575 PyErr_SetString(PyExc_TypeError,
2576 "bad argument to date.__setstate__");
2577 return NULL;
2578 }
2579 memcpy(self->data, pdata, _PyDateTime_DATE_DATASIZE);
2580 self->hashcode = -1;
2581
2582 Py_INCREF(Py_None);
2583 return Py_None;
2584}
2585
2586/* XXX This seems a ridiculously inefficient way to pickle a short string. */
2587static PyObject *
2588date_pickler(PyObject *module, PyDateTime_Date *date)
2589{
2590 PyObject *state;
2591 PyObject *result = NULL;
2592
2593 if (! PyDate_CheckExact(date)) {
2594 PyErr_Format(PyExc_TypeError,
2595 "bad type passed to date pickler: %s",
2596 date->ob_type->tp_name);
2597 return NULL;
2598 }
2599 state = date_getstate(date);
2600 if (state) {
2601 result = Py_BuildValue("O(O)", date_unpickler_object, state);
2602 Py_DECREF(state);
2603 }
2604 return result;
2605}
2606
2607static PyObject *
2608date_unpickler(PyObject *module, PyObject *arg)
2609{
2610 PyDateTime_Date *self;
2611
2612 if (! PyString_CheckExact(arg)) {
2613 PyErr_Format(PyExc_TypeError,
2614 "bad type passed to date unpickler: %s",
2615 arg->ob_type->tp_name);
2616 return NULL;
2617 }
2618 self = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
2619 if (self != NULL) {
2620 PyObject *res = date_setstate(self, arg);
2621 if (res == NULL) {
2622 Py_DECREF(self);
2623 return NULL;
2624 }
2625 Py_DECREF(res);
2626 }
2627 return (PyObject *)self;
2628}
2629
2630static PyMethodDef date_methods[] = {
2631 /* Class methods: */
2632 {"fromtimestamp", (PyCFunction)date_fromtimestamp, METH_VARARGS |
2633 METH_CLASS,
2634 PyDoc_STR("timestamp -> local date from a POSIX timestamp (like "
2635 "time.time()).")},
2636
2637 {"fromordinal", (PyCFunction)date_fromordinal, METH_VARARGS |
2638 METH_CLASS,
2639 PyDoc_STR("int -> date corresponding to a proleptic Gregorian "
2640 "ordinal.")},
2641
2642 {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS,
2643 PyDoc_STR("Current date or datetime: same as "
2644 "self.__class__.fromtimestamp(time.time()).")},
2645
2646 /* Instance methods: */
2647
2648 {"ctime", (PyCFunction)date_ctime, METH_NOARGS,
2649 PyDoc_STR("Return ctime() style string.")},
2650
2651 {"strftime", (PyCFunction)date_strftime, METH_KEYWORDS,
2652 PyDoc_STR("format -> strftime() style string.")},
2653
2654 {"timetuple", (PyCFunction)date_timetuple, METH_NOARGS,
2655 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
2656
2657 {"isocalendar", (PyCFunction)date_isocalendar, METH_NOARGS,
2658 PyDoc_STR("Return a 3-tuple containing ISO year, week number, and "
2659 "weekday.")},
2660
2661 {"isoformat", (PyCFunction)date_isoformat, METH_NOARGS,
2662 PyDoc_STR("Return string in ISO 8601 format, YYYY-MM-DD.")},
2663
2664 {"isoweekday", (PyCFunction)date_isoweekday, METH_NOARGS,
2665 PyDoc_STR("Return the day of the week represented by the date.\n"
2666 "Monday == 1 ... Sunday == 7")},
2667
2668 {"toordinal", (PyCFunction)date_toordinal, METH_NOARGS,
2669 PyDoc_STR("Return proleptic Gregorian ordinal. January 1 of year "
2670 "1 is day 1.")},
2671
2672 {"weekday", (PyCFunction)date_weekday, METH_NOARGS,
2673 PyDoc_STR("Return the day of the week represented by the date.\n"
2674 "Monday == 0 ... Sunday == 6")},
2675
Tim Peters12bf3392002-12-24 05:41:27 +00002676 {"replace", (PyCFunction)date_replace, METH_KEYWORDS,
2677 PyDoc_STR("Return date with new specified fields.")},
2678
Tim Peters2a799bf2002-12-16 20:18:38 +00002679 {"__setstate__", (PyCFunction)date_setstate, METH_O,
2680 PyDoc_STR("__setstate__(state)")},
2681
2682 {"__getstate__", (PyCFunction)date_getstate, METH_NOARGS,
2683 PyDoc_STR("__getstate__() -> state")},
2684
2685 {NULL, NULL}
2686};
2687
2688static char date_doc[] =
2689PyDoc_STR("Basic date type.");
2690
2691static PyNumberMethods date_as_number = {
2692 date_add, /* nb_add */
2693 date_subtract, /* nb_subtract */
2694 0, /* nb_multiply */
2695 0, /* nb_divide */
2696 0, /* nb_remainder */
2697 0, /* nb_divmod */
2698 0, /* nb_power */
2699 0, /* nb_negative */
2700 0, /* nb_positive */
2701 0, /* nb_absolute */
2702 0, /* nb_nonzero */
2703};
2704
2705static PyTypeObject PyDateTime_DateType = {
2706 PyObject_HEAD_INIT(NULL)
2707 0, /* ob_size */
2708 "datetime.date", /* tp_name */
2709 sizeof(PyDateTime_Date), /* tp_basicsize */
2710 0, /* tp_itemsize */
2711 (destructor)PyObject_Del, /* tp_dealloc */
2712 0, /* tp_print */
2713 0, /* tp_getattr */
2714 0, /* tp_setattr */
2715 0, /* tp_compare */
2716 (reprfunc)date_repr, /* tp_repr */
2717 &date_as_number, /* tp_as_number */
2718 0, /* tp_as_sequence */
2719 0, /* tp_as_mapping */
2720 (hashfunc)date_hash, /* tp_hash */
2721 0, /* tp_call */
2722 (reprfunc)date_str, /* tp_str */
2723 PyObject_GenericGetAttr, /* tp_getattro */
2724 0, /* tp_setattro */
2725 0, /* tp_as_buffer */
2726 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
2727 Py_TPFLAGS_BASETYPE, /* tp_flags */
2728 date_doc, /* tp_doc */
2729 0, /* tp_traverse */
2730 0, /* tp_clear */
2731 (richcmpfunc)date_richcompare, /* tp_richcompare */
2732 0, /* tp_weaklistoffset */
2733 0, /* tp_iter */
2734 0, /* tp_iternext */
2735 date_methods, /* tp_methods */
2736 0, /* tp_members */
2737 date_getset, /* tp_getset */
2738 0, /* tp_base */
2739 0, /* tp_dict */
2740 0, /* tp_descr_get */
2741 0, /* tp_descr_set */
2742 0, /* tp_dictoffset */
2743 0, /* tp_init */
2744 0, /* tp_alloc */
2745 date_new, /* tp_new */
2746 _PyObject_Del, /* tp_free */
2747};
2748
2749/*
2750 * PyDateTime_DateTime implementation.
2751 */
2752
2753/* Accessor properties. */
2754
2755static PyObject *
2756datetime_hour(PyDateTime_DateTime *self, void *unused)
2757{
2758 return PyInt_FromLong(DATE_GET_HOUR(self));
2759}
2760
2761static PyObject *
2762datetime_minute(PyDateTime_DateTime *self, void *unused)
2763{
2764 return PyInt_FromLong(DATE_GET_MINUTE(self));
2765}
2766
2767static PyObject *
2768datetime_second(PyDateTime_DateTime *self, void *unused)
2769{
2770 return PyInt_FromLong(DATE_GET_SECOND(self));
2771}
2772
2773static PyObject *
2774datetime_microsecond(PyDateTime_DateTime *self, void *unused)
2775{
2776 return PyInt_FromLong(DATE_GET_MICROSECOND(self));
2777}
2778
2779static PyGetSetDef datetime_getset[] = {
2780 {"hour", (getter)datetime_hour},
2781 {"minute", (getter)datetime_minute},
2782 {"second", (getter)datetime_second},
2783 {"microsecond", (getter)datetime_microsecond},
2784 {NULL}
2785};
2786
2787/* Constructors. */
2788
Tim Peters12bf3392002-12-24 05:41:27 +00002789
2790static char *datetime_kws[] = {"year", "month", "day",
2791 "hour", "minute", "second", "microsecond",
2792 NULL};
2793
Tim Peters2a799bf2002-12-16 20:18:38 +00002794static PyObject *
2795datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2796{
2797 PyObject *self = NULL;
2798 int year;
2799 int month;
2800 int day;
2801 int hour = 0;
2802 int minute = 0;
2803 int second = 0;
2804 int usecond = 0;
2805
Tim Peters12bf3392002-12-24 05:41:27 +00002806 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiii", datetime_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002807 &year, &month, &day, &hour, &minute,
2808 &second, &usecond)) {
2809 if (check_date_args(year, month, day) < 0)
2810 return NULL;
2811 if (check_time_args(hour, minute, second, usecond) < 0)
2812 return NULL;
2813 self = new_datetime(year, month, day,
2814 hour, minute, second, usecond);
2815 }
2816 return self;
2817}
2818
2819
2820/* TM_FUNC is the shared type of localtime() and gmtime(). */
2821typedef struct tm *(*TM_FUNC)(const time_t *timer);
2822
2823/* Internal helper.
2824 * Build datetime from a time_t and a distinct count of microseconds.
2825 * Pass localtime or gmtime for f, to control the interpretation of timet.
2826 */
2827static PyObject *
2828datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us)
2829{
2830 struct tm *tm;
2831 PyObject *result = NULL;
2832
2833 tm = f(&timet);
Tim Peters75a6e3b2003-01-04 18:17:36 +00002834 if (tm) {
2835 /* The platform localtime/gmtime may insert leap seconds,
2836 * indicated by tm->tm_sec > 59. We don't care about them,
2837 * except to the extent that passing them on to the datetime
2838 * constructor would raise ValueError for a reason that
2839 * made no sense to the user.
2840 */
2841 if (tm->tm_sec > 59)
2842 tm->tm_sec = 59;
Tim Peters2a799bf2002-12-16 20:18:38 +00002843 result = PyObject_CallFunction(cls, "iiiiiii",
2844 tm->tm_year + 1900,
2845 tm->tm_mon + 1,
2846 tm->tm_mday,
2847 tm->tm_hour,
2848 tm->tm_min,
2849 tm->tm_sec,
2850 us);
Tim Peters75a6e3b2003-01-04 18:17:36 +00002851 }
Tim Peters2a799bf2002-12-16 20:18:38 +00002852 else
2853 PyErr_SetString(PyExc_ValueError,
2854 "timestamp out of range for "
2855 "platform localtime()/gmtime() function");
2856 return result;
2857}
2858
2859/* Internal helper.
2860 * Build datetime from a Python timestamp. Pass localtime or gmtime for f,
2861 * to control the interpretation of the timestamp. Since a double doesn't
2862 * have enough bits to cover a datetime's full range of precision, it's
2863 * better to call datetime_from_timet_and_us provided you have a way
2864 * to get that much precision (e.g., C time() isn't good enough).
2865 */
2866static PyObject *
2867datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp)
2868{
2869 time_t timet = (time_t)timestamp;
Tim Peters5d644dd2003-01-02 16:32:54 +00002870 double fraction = timestamp - (double)timet;
2871 int us = (int)round_to_long(fraction * 1e6);
Tim Peters2a799bf2002-12-16 20:18:38 +00002872
2873 return datetime_from_timet_and_us(cls, f, timet, us);
2874}
2875
2876/* Internal helper.
2877 * Build most accurate possible datetime for current time. Pass localtime or
2878 * gmtime for f as appropriate.
2879 */
2880static PyObject *
2881datetime_best_possible(PyObject *cls, TM_FUNC f)
2882{
2883#ifdef HAVE_GETTIMEOFDAY
2884 struct timeval t;
2885
2886#ifdef GETTIMEOFDAY_NO_TZ
2887 gettimeofday(&t);
2888#else
2889 gettimeofday(&t, (struct timezone *)NULL);
2890#endif
2891 return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec);
2892
2893#else /* ! HAVE_GETTIMEOFDAY */
2894 /* No flavor of gettimeofday exists on this platform. Python's
2895 * time.time() does a lot of other platform tricks to get the
2896 * best time it can on the platform, and we're not going to do
2897 * better than that (if we could, the better code would belong
2898 * in time.time()!) We're limited by the precision of a double,
2899 * though.
2900 */
2901 PyObject *time;
2902 double dtime;
2903
2904 time = time_time();
2905 if (time == NULL)
2906 return NULL;
2907 dtime = PyFloat_AsDouble(time);
2908 Py_DECREF(time);
2909 if (dtime == -1.0 && PyErr_Occurred())
2910 return NULL;
2911 return datetime_from_timestamp(cls, f, dtime);
2912#endif /* ! HAVE_GETTIMEOFDAY */
2913}
2914
2915/* Return new local datetime from timestamp (Python timestamp -- a double). */
2916static PyObject *
2917datetime_fromtimestamp(PyObject *cls, PyObject *args)
2918{
2919 double timestamp;
2920 PyObject *result = NULL;
2921
2922 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2923 result = datetime_from_timestamp(cls, localtime, timestamp);
2924 return result;
2925}
2926
2927/* Return new UTC datetime from timestamp (Python timestamp -- a double). */
2928static PyObject *
2929datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
2930{
2931 double timestamp;
2932 PyObject *result = NULL;
2933
2934 if (PyArg_ParseTuple(args, "d:utcfromtimestamp", &timestamp))
2935 result = datetime_from_timestamp(cls, gmtime, timestamp);
2936 return result;
2937}
2938
2939/* Return best possible local time -- this isn't constrained by the
2940 * precision of a timestamp.
2941 */
2942static PyObject *
2943datetime_now(PyObject *cls, PyObject *dummy)
2944{
2945 return datetime_best_possible(cls, localtime);
2946}
2947
2948/* Return best possible UTC time -- this isn't constrained by the
2949 * precision of a timestamp.
2950 */
2951static PyObject *
2952datetime_utcnow(PyObject *cls, PyObject *dummy)
2953{
2954 return datetime_best_possible(cls, gmtime);
2955}
2956
2957/* Return new datetime or datetimetz from date/datetime/datetimetz and
2958 * time/timetz arguments.
2959 */
2960static PyObject *
2961datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
2962{
2963 static char *keywords[] = {"date", "time", NULL};
2964 PyObject *date;
2965 PyObject *time;
2966 PyObject *result = NULL;
2967
2968 if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!:combine", keywords,
2969 &PyDateTime_DateType, &date,
2970 &PyDateTime_TimeType, &time))
2971 result = PyObject_CallFunction(cls, "iiiiiii",
2972 GET_YEAR(date),
2973 GET_MONTH(date),
2974 GET_DAY(date),
2975 TIME_GET_HOUR(time),
2976 TIME_GET_MINUTE(time),
2977 TIME_GET_SECOND(time),
2978 TIME_GET_MICROSECOND(time));
2979 if (result && PyTimeTZ_Check(time) && PyDateTimeTZ_Check(result)) {
2980 /* Copy the tzinfo field. */
Tim Peters80475bb2002-12-25 07:40:55 +00002981 replace_tzinfo(result, ((PyDateTime_TimeTZ *)time)->tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00002982 }
2983 return result;
2984}
2985
2986/* datetime arithmetic. */
2987
2988static PyObject *
2989add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
2990{
2991 /* Note that the C-level additions can't overflow, because of
2992 * invariant bounds on the member values.
2993 */
2994 int year = GET_YEAR(date);
2995 int month = GET_MONTH(date);
2996 int day = GET_DAY(date) + GET_TD_DAYS(delta);
2997 int hour = DATE_GET_HOUR(date);
2998 int minute = DATE_GET_MINUTE(date);
2999 int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta);
3000 int microsecond = DATE_GET_MICROSECOND(date) +
3001 GET_TD_MICROSECONDS(delta);
3002
3003 if (normalize_datetime(&year, &month, &day,
3004 &hour, &minute, &second, &microsecond) < 0)
3005 return NULL;
3006 else
3007 return new_datetime(year, month, day,
3008 hour, minute, second, microsecond);
3009}
3010
3011static PyObject *
3012sub_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
3013{
3014 /* Note that the C-level subtractions can't overflow, because of
3015 * invariant bounds on the member values.
3016 */
3017 int year = GET_YEAR(date);
3018 int month = GET_MONTH(date);
3019 int day = GET_DAY(date) - GET_TD_DAYS(delta);
3020 int hour = DATE_GET_HOUR(date);
3021 int minute = DATE_GET_MINUTE(date);
3022 int second = DATE_GET_SECOND(date) - GET_TD_SECONDS(delta);
3023 int microsecond = DATE_GET_MICROSECOND(date) -
3024 GET_TD_MICROSECONDS(delta);
3025
3026 if (normalize_datetime(&year, &month, &day,
3027 &hour, &minute, &second, &microsecond) < 0)
3028 return NULL;
3029 else
3030 return new_datetime(year, month, day,
3031 hour, minute, second, microsecond);
3032}
3033
3034static PyObject *
3035sub_datetime_datetime(PyDateTime_DateTime *left, PyDateTime_DateTime *right)
3036{
3037 int days1 = ymd_to_ord(GET_YEAR(left), GET_MONTH(left), GET_DAY(left));
3038 int days2 = ymd_to_ord(GET_YEAR(right),
3039 GET_MONTH(right),
3040 GET_DAY(right));
3041 /* These can't overflow, since the values are normalized. At most
3042 * this gives the number of seconds in one day.
3043 */
3044 int delta_s = (DATE_GET_HOUR(left) - DATE_GET_HOUR(right)) * 3600 +
3045 (DATE_GET_MINUTE(left) - DATE_GET_MINUTE(right)) * 60 +
3046 DATE_GET_SECOND(left) - DATE_GET_SECOND(right);
3047 int delta_us = DATE_GET_MICROSECOND(left) -
3048 DATE_GET_MICROSECOND(right);
3049
3050 return new_delta(days1 - days2, delta_s, delta_us, 1);
3051}
3052
3053static PyObject *
3054datetime_add(PyObject *left, PyObject *right)
3055{
3056 if (PyDateTime_Check(left)) {
3057 /* datetime + ??? */
3058 if (PyDelta_Check(right))
3059 /* datetime + delta */
3060 return add_datetime_timedelta(
3061 (PyDateTime_DateTime *)left,
3062 (PyDateTime_Delta *)right);
3063 }
3064 else if (PyDelta_Check(left)) {
3065 /* delta + datetime */
3066 return add_datetime_timedelta((PyDateTime_DateTime *) right,
3067 (PyDateTime_Delta *) left);
3068 }
3069 Py_INCREF(Py_NotImplemented);
3070 return Py_NotImplemented;
3071}
3072
3073static PyObject *
3074datetime_subtract(PyObject *left, PyObject *right)
3075{
3076 PyObject *result = Py_NotImplemented;
3077
3078 if (PyDateTime_Check(left)) {
3079 /* datetime - ??? */
3080 if (PyDateTime_Check(right)) {
3081 /* datetime - datetime */
3082 result = sub_datetime_datetime(
3083 (PyDateTime_DateTime *)left,
3084 (PyDateTime_DateTime *)right);
3085 }
3086 else if (PyDelta_Check(right)) {
3087 /* datetime - delta */
3088 result = sub_datetime_timedelta(
3089 (PyDateTime_DateTime *)left,
3090 (PyDateTime_Delta *)right);
3091 }
3092 }
3093
3094 if (result == Py_NotImplemented)
3095 Py_INCREF(result);
3096 return result;
3097}
3098
3099/* Various ways to turn a datetime into a string. */
3100
3101static PyObject *
3102datetime_repr(PyDateTime_DateTime *self)
3103{
3104 char buffer[1000];
3105 char *typename = self->ob_type->tp_name;
3106
3107 if (DATE_GET_MICROSECOND(self)) {
3108 PyOS_snprintf(buffer, sizeof(buffer),
3109 "%s(%d, %d, %d, %d, %d, %d, %d)",
3110 typename,
3111 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3112 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3113 DATE_GET_SECOND(self),
3114 DATE_GET_MICROSECOND(self));
3115 }
3116 else if (DATE_GET_SECOND(self)) {
3117 PyOS_snprintf(buffer, sizeof(buffer),
3118 "%s(%d, %d, %d, %d, %d, %d)",
3119 typename,
3120 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3121 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3122 DATE_GET_SECOND(self));
3123 }
3124 else {
3125 PyOS_snprintf(buffer, sizeof(buffer),
3126 "%s(%d, %d, %d, %d, %d)",
3127 typename,
3128 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3129 DATE_GET_HOUR(self), DATE_GET_MINUTE(self));
3130 }
3131 return PyString_FromString(buffer);
3132}
3133
3134static PyObject *
3135datetime_str(PyDateTime_DateTime *self)
3136{
3137 return PyObject_CallMethod((PyObject *)self, "isoformat", "(s)", " ");
3138}
3139
3140static PyObject *
3141datetime_isoformat(PyDateTime_DateTime *self,
3142 PyObject *args, PyObject *kw)
3143{
3144 char sep = 'T';
3145 static char *keywords[] = {"sep", NULL};
3146 char buffer[100];
3147 char *cp;
3148
3149 if (!PyArg_ParseTupleAndKeywords(args, kw, "|c:isoformat", keywords,
3150 &sep))
3151 return NULL;
3152 cp = isoformat_date((PyDateTime_Date *)self, buffer, sizeof(buffer));
3153 assert(cp != NULL);
3154 *cp++ = sep;
3155 isoformat_time(self, cp, sizeof(buffer) - (cp - buffer));
3156 return PyString_FromString(buffer);
3157}
3158
3159static PyObject *
3160datetime_ctime(PyDateTime_DateTime *self)
3161{
3162 return format_ctime((PyDateTime_Date *)self,
3163 DATE_GET_HOUR(self),
3164 DATE_GET_MINUTE(self),
3165 DATE_GET_SECOND(self));
3166}
3167
3168/* Miscellaneous methods. */
3169
3170/* This is more natural as a tp_compare, but doesn't work then: for whatever
3171 * reason, Python's try_3way_compare ignores tp_compare unless
3172 * PyInstance_Check returns true, but these aren't old-style classes.
3173 * Note that this routine handles all comparisons for datetime and datetimetz.
3174 */
3175static PyObject *
3176datetime_richcompare(PyDateTime_DateTime *self, PyObject *other, int op)
3177{
3178 int diff;
3179 naivety n1, n2;
3180 int offset1, offset2;
3181
3182 if (! PyDateTime_Check(other)) {
3183 /* Stop this from falling back to address comparison. */
3184 PyErr_Format(PyExc_TypeError,
3185 "can't compare '%s' to '%s'",
3186 self->ob_type->tp_name,
3187 other->ob_type->tp_name);
3188 return NULL;
3189 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003190
Tim Peters00237032002-12-27 02:21:51 +00003191 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1,
Tim Peterse39a80c2002-12-30 21:28:52 +00003192 (PyObject *)self,
3193 other, &offset2, &n2,
3194 other) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003195 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003196 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters60c76e42002-12-27 00:41:11 +00003197 /* If they're both naive, or both aware and have the same offsets,
Tim Peters2a799bf2002-12-16 20:18:38 +00003198 * we get off cheap. Note that if they're both naive, offset1 ==
3199 * offset2 == 0 at this point.
3200 */
3201 if (n1 == n2 && offset1 == offset2) {
3202 diff = memcmp(self->data, ((PyDateTime_DateTime *)other)->data,
3203 _PyDateTime_DATETIME_DATASIZE);
3204 return diff_to_bool(diff, op);
3205 }
3206
3207 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3208 /* We want the sign of
3209 * (self - offset1 minutes) - (other - offset2 minutes) =
3210 * (self - other) + (offset2 - offset1) minutes.
3211 */
3212 PyDateTime_Delta *delta;
3213 int days, seconds, us;
3214
3215 assert(offset1 != offset2); /* else last "if" handled it */
3216 delta = (PyDateTime_Delta *)sub_datetime_datetime(self,
3217 (PyDateTime_DateTime *)other);
3218 if (delta == NULL)
3219 return NULL;
3220 days = delta->days;
3221 seconds = delta->seconds + (offset2 - offset1) * 60;
3222 us = delta->microseconds;
3223 Py_DECREF(delta);
3224 normalize_d_s_us(&days, &seconds, &us);
3225 diff = days;
3226 if (diff == 0)
3227 diff = seconds | us;
3228 return diff_to_bool(diff, op);
3229 }
3230
3231 assert(n1 != n2);
3232 PyErr_SetString(PyExc_TypeError,
3233 "can't compare offset-naive and "
3234 "offset-aware datetimes");
3235 return NULL;
3236}
3237
3238static PyObject *datetime_getstate(PyDateTime_DateTime *self);
3239
3240static long
3241datetime_hash(PyDateTime_DateTime *self)
3242{
3243 if (self->hashcode == -1) {
3244 naivety n;
3245 int offset;
3246 PyObject *temp;
3247
Tim Peterse39a80c2002-12-30 21:28:52 +00003248 n = classify_utcoffset((PyObject *)self, (PyObject *)self,
3249 &offset);
Tim Peters2a799bf2002-12-16 20:18:38 +00003250 assert(n != OFFSET_UNKNOWN);
3251 if (n == OFFSET_ERROR)
3252 return -1;
3253
3254 /* Reduce this to a hash of another object. */
3255 if (n == OFFSET_NAIVE)
3256 temp = datetime_getstate(self);
3257 else {
3258 int days;
3259 int seconds;
3260
3261 assert(n == OFFSET_AWARE);
3262 assert(PyDateTimeTZ_Check(self));
3263 days = ymd_to_ord(GET_YEAR(self),
3264 GET_MONTH(self),
3265 GET_DAY(self));
3266 seconds = DATE_GET_HOUR(self) * 3600 +
3267 (DATE_GET_MINUTE(self) - offset) * 60 +
3268 DATE_GET_SECOND(self);
3269 temp = new_delta(days,
3270 seconds,
3271 DATE_GET_MICROSECOND(self),
3272 1);
3273 }
3274 if (temp != NULL) {
3275 self->hashcode = PyObject_Hash(temp);
3276 Py_DECREF(temp);
3277 }
3278 }
3279 return self->hashcode;
3280}
3281
3282static PyObject *
Tim Peters12bf3392002-12-24 05:41:27 +00003283datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
3284{
3285 PyObject *clone;
3286 PyObject *tuple;
3287 int y = GET_YEAR(self);
3288 int m = GET_MONTH(self);
3289 int d = GET_DAY(self);
3290 int hh = DATE_GET_HOUR(self);
3291 int mm = DATE_GET_MINUTE(self);
3292 int ss = DATE_GET_SECOND(self);
3293 int us = DATE_GET_MICROSECOND(self);
3294
3295 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiii:replace",
3296 datetime_kws,
3297 &y, &m, &d, &hh, &mm, &ss, &us))
3298 return NULL;
3299 tuple = Py_BuildValue("iiiiiii", y, m, d, hh, mm, ss, us);
3300 if (tuple == NULL)
3301 return NULL;
3302 clone = datetime_new(self->ob_type, tuple, NULL);
3303 Py_DECREF(tuple);
3304 return clone;
3305}
3306
3307static PyObject *
Tim Peters80475bb2002-12-25 07:40:55 +00003308datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
3309{
3310 PyObject *tzinfo;
3311 static char *keywords[] = {"tz", NULL};
3312
3313 if (! PyArg_ParseTupleAndKeywords(args, kw, "O:astimezone", keywords,
3314 &tzinfo))
3315 return NULL;
3316 if (check_tzinfo_subclass(tzinfo) < 0)
3317 return NULL;
3318 return new_datetimetz(GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3319 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3320 DATE_GET_SECOND(self),
3321 DATE_GET_MICROSECOND(self),
3322 tzinfo);
3323}
3324
3325static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00003326datetime_timetuple(PyDateTime_DateTime *self)
3327{
3328 return build_struct_time(GET_YEAR(self),
3329 GET_MONTH(self),
3330 GET_DAY(self),
3331 DATE_GET_HOUR(self),
3332 DATE_GET_MINUTE(self),
3333 DATE_GET_SECOND(self),
3334 -1);
3335}
3336
3337static PyObject *
3338datetime_getdate(PyDateTime_DateTime *self)
3339{
3340 return new_date(GET_YEAR(self),
3341 GET_MONTH(self),
3342 GET_DAY(self));
3343}
3344
3345static PyObject *
3346datetime_gettime(PyDateTime_DateTime *self)
3347{
Tim Peters0bf60bd2003-01-08 20:40:01 +00003348 return new_timetz(DATE_GET_HOUR(self),
3349 DATE_GET_MINUTE(self),
3350 DATE_GET_SECOND(self),
3351 DATE_GET_MICROSECOND(self),
3352 Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003353}
3354
3355/* Pickle support. Quite a maze! */
3356
3357static PyObject *
3358datetime_getstate(PyDateTime_DateTime *self)
3359{
Jack Jansenb8941f22003-01-08 16:28:45 +00003360 return PyString_FromStringAndSize((char *)self->data,
Tim Peters2a799bf2002-12-16 20:18:38 +00003361 _PyDateTime_DATETIME_DATASIZE);
3362}
3363
3364static PyObject *
3365datetime_setstate(PyDateTime_DateTime *self, PyObject *state)
3366{
3367 const int len = PyString_Size(state);
3368 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
3369
3370 if (! PyString_Check(state) ||
3371 len != _PyDateTime_DATETIME_DATASIZE) {
3372 PyErr_SetString(PyExc_TypeError,
3373 "bad argument to datetime.__setstate__");
3374 return NULL;
3375 }
3376 memcpy(self->data, pdata, _PyDateTime_DATETIME_DATASIZE);
3377 self->hashcode = -1;
3378
3379 Py_INCREF(Py_None);
3380 return Py_None;
3381}
3382
3383/* XXX This seems a ridiculously inefficient way to pickle a short string. */
3384static PyObject *
3385datetime_pickler(PyObject *module, PyDateTime_DateTime *datetime)
3386{
3387 PyObject *state;
3388 PyObject *result = NULL;
3389
3390 if (! PyDateTime_CheckExact(datetime)) {
3391 PyErr_Format(PyExc_TypeError,
3392 "bad type passed to datetime pickler: %s",
3393 datetime->ob_type->tp_name);
3394 return NULL;
3395 }
3396 state = datetime_getstate(datetime);
3397 if (state) {
3398 result = Py_BuildValue("O(O)",
3399 datetime_unpickler_object,
3400 state);
3401 Py_DECREF(state);
3402 }
3403 return result;
3404}
3405
3406static PyObject *
3407datetime_unpickler(PyObject *module, PyObject *arg)
3408{
3409 PyDateTime_DateTime *self;
3410
3411 if (! PyString_CheckExact(arg)) {
3412 PyErr_Format(PyExc_TypeError,
3413 "bad type passed to datetime unpickler: %s",
3414 arg->ob_type->tp_name);
3415 return NULL;
3416 }
3417 self = PyObject_New(PyDateTime_DateTime, &PyDateTime_DateTimeType);
3418 if (self != NULL) {
3419 PyObject *res = datetime_setstate(self, arg);
3420 if (res == NULL) {
3421 Py_DECREF(self);
3422 return NULL;
3423 }
3424 Py_DECREF(res);
3425 }
3426 return (PyObject *)self;
3427}
3428
3429static PyMethodDef datetime_methods[] = {
3430 /* Class methods: */
3431 {"now", (PyCFunction)datetime_now,
3432 METH_NOARGS | METH_CLASS,
3433 PyDoc_STR("Return a new datetime representing local day and time.")},
3434
3435 {"utcnow", (PyCFunction)datetime_utcnow,
3436 METH_NOARGS | METH_CLASS,
3437 PyDoc_STR("Return a new datetime representing UTC day and time.")},
3438
3439 {"fromtimestamp", (PyCFunction)datetime_fromtimestamp,
3440 METH_VARARGS | METH_CLASS,
3441 PyDoc_STR("timestamp -> local datetime from a POSIX timestamp "
3442 "(like time.time()).")},
3443
3444 {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
3445 METH_VARARGS | METH_CLASS,
3446 PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp "
3447 "(like time.time()).")},
3448
3449 {"combine", (PyCFunction)datetime_combine,
3450 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
3451 PyDoc_STR("date, time -> datetime with same date and time fields")},
3452
3453 /* Instance methods: */
3454 {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS,
3455 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
3456
3457 {"date", (PyCFunction)datetime_getdate, METH_NOARGS,
3458 PyDoc_STR("Return date object with same year, month and day.")},
3459
3460 {"time", (PyCFunction)datetime_gettime, METH_NOARGS,
Tim Peters0bf60bd2003-01-08 20:40:01 +00003461 PyDoc_STR("Return time object with same time but with tzinfo=None.")},
Tim Peters2a799bf2002-12-16 20:18:38 +00003462
3463 {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
3464 PyDoc_STR("Return ctime() style string.")},
3465
3466 {"isoformat", (PyCFunction)datetime_isoformat, METH_KEYWORDS,
3467 PyDoc_STR("[sep] -> string in ISO 8601 format, "
3468 "YYYY-MM-DDTHH:MM:SS[.mmmmmm].\n\n"
3469 "sep is used to separate the year from the time, and "
3470 "defaults\n"
3471 "to 'T'.")},
3472
Tim Peters12bf3392002-12-24 05:41:27 +00003473 {"replace", (PyCFunction)datetime_replace, METH_KEYWORDS,
3474 PyDoc_STR("Return datetime with new specified fields.")},
3475
Tim Peters80475bb2002-12-25 07:40:55 +00003476 {"astimezone", (PyCFunction)datetime_astimezone, METH_KEYWORDS,
3477 PyDoc_STR("tz -> datetimetz with same date & time, and tzinfo=tz\n")},
3478
Tim Peters2a799bf2002-12-16 20:18:38 +00003479 {"__setstate__", (PyCFunction)datetime_setstate, METH_O,
3480 PyDoc_STR("__setstate__(state)")},
3481
3482 {"__getstate__", (PyCFunction)datetime_getstate, METH_NOARGS,
3483 PyDoc_STR("__getstate__() -> state")},
3484 {NULL, NULL}
3485};
3486
3487static char datetime_doc[] =
3488PyDoc_STR("Basic date/time type.");
3489
3490static PyNumberMethods datetime_as_number = {
3491 datetime_add, /* nb_add */
3492 datetime_subtract, /* nb_subtract */
3493 0, /* nb_multiply */
3494 0, /* nb_divide */
3495 0, /* nb_remainder */
3496 0, /* nb_divmod */
3497 0, /* nb_power */
3498 0, /* nb_negative */
3499 0, /* nb_positive */
3500 0, /* nb_absolute */
3501 0, /* nb_nonzero */
3502};
3503
3504statichere PyTypeObject PyDateTime_DateTimeType = {
3505 PyObject_HEAD_INIT(NULL)
3506 0, /* ob_size */
3507 "datetime.datetime", /* tp_name */
3508 sizeof(PyDateTime_DateTime), /* tp_basicsize */
3509 0, /* tp_itemsize */
3510 (destructor)PyObject_Del, /* tp_dealloc */
3511 0, /* tp_print */
3512 0, /* tp_getattr */
3513 0, /* tp_setattr */
3514 0, /* tp_compare */
3515 (reprfunc)datetime_repr, /* tp_repr */
3516 &datetime_as_number, /* tp_as_number */
3517 0, /* tp_as_sequence */
3518 0, /* tp_as_mapping */
3519 (hashfunc)datetime_hash, /* tp_hash */
3520 0, /* tp_call */
3521 (reprfunc)datetime_str, /* tp_str */
3522 PyObject_GenericGetAttr, /* tp_getattro */
3523 0, /* tp_setattro */
3524 0, /* tp_as_buffer */
3525 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3526 Py_TPFLAGS_BASETYPE, /* tp_flags */
3527 datetime_doc, /* tp_doc */
3528 0, /* tp_traverse */
3529 0, /* tp_clear */
3530 (richcmpfunc)datetime_richcompare, /* tp_richcompare */
3531 0, /* tp_weaklistoffset */
3532 0, /* tp_iter */
3533 0, /* tp_iternext */
3534 datetime_methods, /* tp_methods */
3535 0, /* tp_members */
3536 datetime_getset, /* tp_getset */
3537 &PyDateTime_DateType, /* tp_base */
3538 0, /* tp_dict */
3539 0, /* tp_descr_get */
3540 0, /* tp_descr_set */
3541 0, /* tp_dictoffset */
3542 0, /* tp_init */
3543 0, /* tp_alloc */
3544 datetime_new, /* tp_new */
3545 _PyObject_Del, /* tp_free */
3546};
3547
3548/*
3549 * PyDateTime_Time implementation.
3550 */
3551
3552/* Accessor properties. */
3553
3554static PyObject *
3555time_hour(PyDateTime_Time *self, void *unused)
3556{
3557 return PyInt_FromLong(TIME_GET_HOUR(self));
3558}
3559
3560static PyObject *
3561time_minute(PyDateTime_Time *self, void *unused)
3562{
3563 return PyInt_FromLong(TIME_GET_MINUTE(self));
3564}
3565
3566static PyObject *
Jack Jansen51cd8a22002-12-17 20:57:24 +00003567py_time_second(PyDateTime_Time *self, void *unused)
Tim Peters2a799bf2002-12-16 20:18:38 +00003568{
3569 return PyInt_FromLong(TIME_GET_SECOND(self));
3570}
3571
3572static PyObject *
3573time_microsecond(PyDateTime_Time *self, void *unused)
3574{
3575 return PyInt_FromLong(TIME_GET_MICROSECOND(self));
3576}
3577
3578static PyGetSetDef time_getset[] = {
3579 {"hour", (getter)time_hour},
3580 {"minute", (getter)time_minute},
Jack Jansen51cd8a22002-12-17 20:57:24 +00003581 {"second", (getter)py_time_second},
Tim Peters2a799bf2002-12-16 20:18:38 +00003582 {"microsecond", (getter)time_microsecond},
3583 {NULL}
3584};
3585
3586/* Constructors. */
3587
Tim Peters12bf3392002-12-24 05:41:27 +00003588static char *time_kws[] = {"hour", "minute", "second", "microsecond", NULL};
3589
Tim Peters2a799bf2002-12-16 20:18:38 +00003590static PyObject *
3591time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
3592{
3593 PyObject *self = NULL;
3594 int hour = 0;
3595 int minute = 0;
3596 int second = 0;
3597 int usecond = 0;
3598
Tim Peters2a799bf2002-12-16 20:18:38 +00003599
Tim Peters12bf3392002-12-24 05:41:27 +00003600 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiii", time_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00003601 &hour, &minute, &second, &usecond)) {
3602 if (check_time_args(hour, minute, second, usecond) < 0)
3603 return NULL;
3604 self = new_time(hour, minute, second, usecond);
3605 }
3606 return self;
3607}
3608
3609/* Various ways to turn a time into a string. */
3610
3611static PyObject *
3612time_repr(PyDateTime_Time *self)
3613{
3614 char buffer[100];
3615 char *typename = self->ob_type->tp_name;
3616 int h = TIME_GET_HOUR(self);
3617 int m = TIME_GET_MINUTE(self);
3618 int s = TIME_GET_SECOND(self);
3619 int us = TIME_GET_MICROSECOND(self);
3620
3621 if (us)
3622 PyOS_snprintf(buffer, sizeof(buffer),
3623 "%s(%d, %d, %d, %d)", typename, h, m, s, us);
3624 else if (s)
3625 PyOS_snprintf(buffer, sizeof(buffer),
3626 "%s(%d, %d, %d)", typename, h, m, s);
3627 else
3628 PyOS_snprintf(buffer, sizeof(buffer),
3629 "%s(%d, %d)", typename, h, m);
3630 return PyString_FromString(buffer);
3631}
3632
3633static PyObject *
3634time_str(PyDateTime_Time *self)
3635{
3636 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
3637}
3638
3639static PyObject *
3640time_isoformat(PyDateTime_Time *self)
3641{
3642 char buffer[100];
3643 /* Reuse the time format code from the datetime type. */
3644 PyDateTime_DateTime datetime;
3645 PyDateTime_DateTime *pdatetime = &datetime;
3646
3647 /* Copy over just the time bytes. */
3648 memcpy(pdatetime->data + _PyDateTime_DATE_DATASIZE,
3649 self->data,
3650 _PyDateTime_TIME_DATASIZE);
3651
3652 isoformat_time(pdatetime, buffer, sizeof(buffer));
3653 return PyString_FromString(buffer);
3654}
3655
3656static PyObject *
3657time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3658{
3659 PyObject *result;
3660 PyObject *format;
3661 PyObject *tuple;
3662 static char *keywords[] = {"format", NULL};
3663
3664 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
3665 &PyString_Type, &format))
3666 return NULL;
3667
Tim Peters83b85f12002-12-22 20:34:46 +00003668 /* Python's strftime does insane things with the year part of the
3669 * timetuple. The year is forced to (the otherwise nonsensical)
3670 * 1900 to worm around that.
3671 */
Tim Peters2a799bf2002-12-16 20:18:38 +00003672 tuple = Py_BuildValue("iiiiiiiii",
Tim Peters83b85f12002-12-22 20:34:46 +00003673 1900, 0, 0, /* year, month, day */
Tim Peters2a799bf2002-12-16 20:18:38 +00003674 TIME_GET_HOUR(self),
3675 TIME_GET_MINUTE(self),
3676 TIME_GET_SECOND(self),
3677 0, 0, -1); /* weekday, daynum, dst */
3678 if (tuple == NULL)
3679 return NULL;
3680 assert(PyTuple_Size(tuple) == 9);
Tim Petersbad8ff02002-12-30 20:52:32 +00003681 result = wrap_strftime((PyObject *)self, format, tuple, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003682 Py_DECREF(tuple);
3683 return result;
3684}
3685
3686/* Miscellaneous methods. */
3687
3688/* This is more natural as a tp_compare, but doesn't work then: for whatever
3689 * reason, Python's try_3way_compare ignores tp_compare unless
3690 * PyInstance_Check returns true, but these aren't old-style classes.
3691 * Note that this routine handles all comparisons for time and timetz.
3692 */
3693static PyObject *
3694time_richcompare(PyDateTime_Time *self, PyObject *other, int op)
3695{
3696 int diff;
3697 naivety n1, n2;
3698 int offset1, offset2;
3699
3700 if (! PyTime_Check(other)) {
3701 /* Stop this from falling back to address comparison. */
3702 PyErr_Format(PyExc_TypeError,
3703 "can't compare '%s' to '%s'",
3704 self->ob_type->tp_name,
3705 other->ob_type->tp_name);
3706 return NULL;
3707 }
Tim Peterse39a80c2002-12-30 21:28:52 +00003708 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1, Py_None,
3709 other, &offset2, &n2, Py_None) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003710 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003711 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00003712 /* If they're both naive, or both aware and have the same offsets,
3713 * we get off cheap. Note that if they're both naive, offset1 ==
3714 * offset2 == 0 at this point.
3715 */
3716 if (n1 == n2 && offset1 == offset2) {
3717 diff = memcmp(self->data, ((PyDateTime_Time *)other)->data,
3718 _PyDateTime_TIME_DATASIZE);
3719 return diff_to_bool(diff, op);
3720 }
3721
3722 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3723 assert(offset1 != offset2); /* else last "if" handled it */
3724 /* Convert everything except microseconds to seconds. These
3725 * can't overflow (no more than the # of seconds in 2 days).
3726 */
3727 offset1 = TIME_GET_HOUR(self) * 3600 +
3728 (TIME_GET_MINUTE(self) - offset1) * 60 +
3729 TIME_GET_SECOND(self);
3730 offset2 = TIME_GET_HOUR(other) * 3600 +
3731 (TIME_GET_MINUTE(other) - offset2) * 60 +
3732 TIME_GET_SECOND(other);
3733 diff = offset1 - offset2;
3734 if (diff == 0)
3735 diff = TIME_GET_MICROSECOND(self) -
3736 TIME_GET_MICROSECOND(other);
3737 return diff_to_bool(diff, op);
3738 }
3739
3740 assert(n1 != n2);
3741 PyErr_SetString(PyExc_TypeError,
3742 "can't compare offset-naive and "
3743 "offset-aware times");
3744 return NULL;
3745}
3746
3747static PyObject *time_getstate(PyDateTime_Time *self);
3748
3749static long
3750time_hash(PyDateTime_Time *self)
3751{
3752 if (self->hashcode == -1) {
3753 naivety n;
3754 int offset;
3755 PyObject *temp;
3756
Tim Peterse39a80c2002-12-30 21:28:52 +00003757 n = classify_utcoffset((PyObject *)self, Py_None, &offset);
Tim Peters2a799bf2002-12-16 20:18:38 +00003758 assert(n != OFFSET_UNKNOWN);
3759 if (n == OFFSET_ERROR)
3760 return -1;
3761
3762 /* Reduce this to a hash of another object. */
3763 if (offset == 0)
3764 temp = time_getstate(self);
3765 else {
3766 int hour;
3767 int minute;
3768
3769 assert(n == OFFSET_AWARE);
3770 assert(PyTimeTZ_Check(self));
3771 hour = divmod(TIME_GET_HOUR(self) * 60 +
3772 TIME_GET_MINUTE(self) - offset,
3773 60,
3774 &minute);
3775 if (0 <= hour && hour < 24)
3776 temp = new_time(hour, minute,
3777 TIME_GET_SECOND(self),
3778 TIME_GET_MICROSECOND(self));
3779 else
3780 temp = Py_BuildValue("iiii",
3781 hour, minute,
3782 TIME_GET_SECOND(self),
3783 TIME_GET_MICROSECOND(self));
3784 }
3785 if (temp != NULL) {
3786 self->hashcode = PyObject_Hash(temp);
3787 Py_DECREF(temp);
3788 }
3789 }
3790 return self->hashcode;
3791}
3792
Tim Peters12bf3392002-12-24 05:41:27 +00003793static PyObject *
3794time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3795{
3796 PyObject *clone;
3797 PyObject *tuple;
3798 int hh = TIME_GET_HOUR(self);
3799 int mm = TIME_GET_MINUTE(self);
3800 int ss = TIME_GET_SECOND(self);
3801 int us = TIME_GET_MICROSECOND(self);
3802
3803 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiii:replace",
3804 time_kws,
3805 &hh, &mm, &ss, &us))
3806 return NULL;
3807 tuple = Py_BuildValue("iiii", hh, mm, ss, us);
3808 if (tuple == NULL)
3809 return NULL;
3810 clone = time_new(self->ob_type, tuple, NULL);
3811 Py_DECREF(tuple);
3812 return clone;
3813}
3814
Tim Peters2a799bf2002-12-16 20:18:38 +00003815static int
3816time_nonzero(PyDateTime_Time *self)
3817{
3818 return TIME_GET_HOUR(self) ||
3819 TIME_GET_MINUTE(self) ||
3820 TIME_GET_SECOND(self) ||
3821 TIME_GET_MICROSECOND(self);
3822}
3823
3824/* Pickle support. Quite a maze! */
3825
3826static PyObject *
3827time_getstate(PyDateTime_Time *self)
3828{
Jack Jansenb8941f22003-01-08 16:28:45 +00003829 return PyString_FromStringAndSize((char *)self->data,
Tim Peters2a799bf2002-12-16 20:18:38 +00003830 _PyDateTime_TIME_DATASIZE);
3831}
3832
3833static PyObject *
3834time_setstate(PyDateTime_Time *self, PyObject *state)
3835{
3836 const int len = PyString_Size(state);
3837 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
3838
3839 if (! PyString_Check(state) ||
3840 len != _PyDateTime_TIME_DATASIZE) {
3841 PyErr_SetString(PyExc_TypeError,
3842 "bad argument to time.__setstate__");
3843 return NULL;
3844 }
3845 memcpy(self->data, pdata, _PyDateTime_TIME_DATASIZE);
3846 self->hashcode = -1;
3847
3848 Py_INCREF(Py_None);
3849 return Py_None;
3850}
3851
3852/* XXX This seems a ridiculously inefficient way to pickle a short string. */
3853static PyObject *
3854time_pickler(PyObject *module, PyDateTime_Time *time)
3855{
3856 PyObject *state;
3857 PyObject *result = NULL;
3858
3859 if (! PyTime_CheckExact(time)) {
3860 PyErr_Format(PyExc_TypeError,
3861 "bad type passed to time pickler: %s",
3862 time->ob_type->tp_name);
3863 return NULL;
3864 }
3865 state = time_getstate(time);
3866 if (state) {
3867 result = Py_BuildValue("O(O)",
3868 time_unpickler_object,
3869 state);
3870 Py_DECREF(state);
3871 }
3872 return result;
3873}
3874
3875static PyObject *
3876time_unpickler(PyObject *module, PyObject *arg)
3877{
3878 PyDateTime_Time *self;
3879
3880 if (! PyString_CheckExact(arg)) {
3881 PyErr_Format(PyExc_TypeError,
3882 "bad type passed to time unpickler: %s",
3883 arg->ob_type->tp_name);
3884 return NULL;
3885 }
3886 self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
3887 if (self != NULL) {
3888 PyObject *res = time_setstate(self, arg);
3889 if (res == NULL) {
3890 Py_DECREF(self);
3891 return NULL;
3892 }
3893 Py_DECREF(res);
3894 }
3895 return (PyObject *)self;
3896}
3897
3898static PyMethodDef time_methods[] = {
3899 {"isoformat", (PyCFunction)time_isoformat, METH_KEYWORDS,
3900 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm].")},
3901
3902 {"strftime", (PyCFunction)time_strftime, METH_KEYWORDS,
3903 PyDoc_STR("format -> strftime() style string.")},
3904
Tim Peters12bf3392002-12-24 05:41:27 +00003905 {"replace", (PyCFunction)time_replace, METH_KEYWORDS,
3906 PyDoc_STR("Return datetime with new specified fields.")},
3907
Tim Peters2a799bf2002-12-16 20:18:38 +00003908 {"__setstate__", (PyCFunction)time_setstate, METH_O,
3909 PyDoc_STR("__setstate__(state)")},
3910
3911 {"__getstate__", (PyCFunction)time_getstate, METH_NOARGS,
3912 PyDoc_STR("__getstate__() -> state")},
3913 {NULL, NULL}
3914};
3915
3916static char time_doc[] =
3917PyDoc_STR("Basic time type.");
3918
3919static PyNumberMethods time_as_number = {
3920 0, /* nb_add */
3921 0, /* nb_subtract */
3922 0, /* nb_multiply */
3923 0, /* nb_divide */
3924 0, /* nb_remainder */
3925 0, /* nb_divmod */
3926 0, /* nb_power */
3927 0, /* nb_negative */
3928 0, /* nb_positive */
3929 0, /* nb_absolute */
3930 (inquiry)time_nonzero, /* nb_nonzero */
3931};
3932
3933statichere PyTypeObject PyDateTime_TimeType = {
3934 PyObject_HEAD_INIT(NULL)
3935 0, /* ob_size */
3936 "datetime.time", /* tp_name */
3937 sizeof(PyDateTime_Time), /* tp_basicsize */
3938 0, /* tp_itemsize */
3939 (destructor)PyObject_Del, /* tp_dealloc */
3940 0, /* tp_print */
3941 0, /* tp_getattr */
3942 0, /* tp_setattr */
3943 0, /* tp_compare */
3944 (reprfunc)time_repr, /* tp_repr */
3945 &time_as_number, /* tp_as_number */
3946 0, /* tp_as_sequence */
3947 0, /* tp_as_mapping */
3948 (hashfunc)time_hash, /* tp_hash */
3949 0, /* tp_call */
3950 (reprfunc)time_str, /* tp_str */
3951 PyObject_GenericGetAttr, /* tp_getattro */
3952 0, /* tp_setattro */
3953 0, /* tp_as_buffer */
3954 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3955 Py_TPFLAGS_BASETYPE, /* tp_flags */
3956 time_doc, /* tp_doc */
3957 0, /* tp_traverse */
3958 0, /* tp_clear */
3959 (richcmpfunc)time_richcompare, /* tp_richcompare */
3960 0, /* tp_weaklistoffset */
3961 0, /* tp_iter */
3962 0, /* tp_iternext */
3963 time_methods, /* tp_methods */
3964 0, /* tp_members */
3965 time_getset, /* tp_getset */
3966 0, /* tp_base */
3967 0, /* tp_dict */
3968 0, /* tp_descr_get */
3969 0, /* tp_descr_set */
3970 0, /* tp_dictoffset */
3971 0, /* tp_init */
3972 0, /* tp_alloc */
3973 time_new, /* tp_new */
3974 _PyObject_Del, /* tp_free */
3975};
3976
3977/*
3978 * PyDateTime_TZInfo implementation.
3979 */
3980
3981/* This is a pure abstract base class, so doesn't do anything beyond
3982 * raising NotImplemented exceptions. Real tzinfo classes need
3983 * to derive from this. This is mostly for clarity, and for efficiency in
3984 * datetimetz and timetz constructors (their tzinfo arguments need to
3985 * be subclasses of this tzinfo class, which is easy and quick to check).
3986 *
3987 * Note: For reasons having to do with pickling of subclasses, we have
3988 * to allow tzinfo objects to be instantiated. This wasn't an issue
3989 * in the Python implementation (__init__() could raise NotImplementedError
3990 * there without ill effect), but doing so in the C implementation hit a
3991 * brick wall.
3992 */
3993
3994static PyObject *
3995tzinfo_nogo(const char* methodname)
3996{
3997 PyErr_Format(PyExc_NotImplementedError,
3998 "a tzinfo subclass must implement %s()",
3999 methodname);
4000 return NULL;
4001}
4002
4003/* Methods. A subclass must implement these. */
4004
4005static PyObject*
4006tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt)
4007{
4008 return tzinfo_nogo("tzname");
4009}
4010
4011static PyObject*
4012tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt)
4013{
4014 return tzinfo_nogo("utcoffset");
4015}
4016
4017static PyObject*
4018tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
4019{
4020 return tzinfo_nogo("dst");
4021}
4022
4023/*
4024 * Pickle support. This is solely so that tzinfo subclasses can use
4025 * pickling -- tzinfo itself is supposed to be uninstantiable. The
4026 * pickler and unpickler functions are given module-level private
4027 * names, and registered with copy_reg, by the module init function.
4028 */
4029
4030static PyObject*
4031tzinfo_pickler(PyDateTime_TZInfo *self) {
4032 return Py_BuildValue("O()", tzinfo_unpickler_object);
4033}
4034
4035static PyObject*
4036tzinfo_unpickler(PyObject * unused) {
4037 return PyType_GenericNew(&PyDateTime_TZInfoType, NULL, NULL);
4038}
4039
4040
4041static PyMethodDef tzinfo_methods[] = {
4042 {"tzname", (PyCFunction)tzinfo_tzname, METH_O,
4043 PyDoc_STR("datetime -> string name of time zone.")},
4044
4045 {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
4046 PyDoc_STR("datetime -> minutes east of UTC (negative for "
4047 "west of UTC).")},
4048
4049 {"dst", (PyCFunction)tzinfo_dst, METH_O,
4050 PyDoc_STR("datetime -> DST offset in minutes east of UTC.")},
4051
4052 {NULL, NULL}
4053};
4054
4055static char tzinfo_doc[] =
4056PyDoc_STR("Abstract base class for time zone info objects.");
4057
4058 statichere PyTypeObject PyDateTime_TZInfoType = {
4059 PyObject_HEAD_INIT(NULL)
4060 0, /* ob_size */
4061 "datetime.tzinfo", /* tp_name */
4062 sizeof(PyDateTime_TZInfo), /* tp_basicsize */
4063 0, /* tp_itemsize */
4064 0, /* tp_dealloc */
4065 0, /* tp_print */
4066 0, /* tp_getattr */
4067 0, /* tp_setattr */
4068 0, /* tp_compare */
4069 0, /* tp_repr */
4070 0, /* tp_as_number */
4071 0, /* tp_as_sequence */
4072 0, /* tp_as_mapping */
4073 0, /* tp_hash */
4074 0, /* tp_call */
4075 0, /* tp_str */
4076 PyObject_GenericGetAttr, /* tp_getattro */
4077 0, /* tp_setattro */
4078 0, /* tp_as_buffer */
4079 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4080 Py_TPFLAGS_BASETYPE, /* tp_flags */
4081 tzinfo_doc, /* tp_doc */
4082 0, /* tp_traverse */
4083 0, /* tp_clear */
4084 0, /* tp_richcompare */
4085 0, /* tp_weaklistoffset */
4086 0, /* tp_iter */
4087 0, /* tp_iternext */
4088 tzinfo_methods, /* tp_methods */
4089 0, /* tp_members */
4090 0, /* tp_getset */
4091 0, /* tp_base */
4092 0, /* tp_dict */
4093 0, /* tp_descr_get */
4094 0, /* tp_descr_set */
4095 0, /* tp_dictoffset */
4096 0, /* tp_init */
4097 0, /* tp_alloc */
4098 PyType_GenericNew, /* tp_new */
4099 0, /* tp_free */
4100};
4101
4102/*
4103 * PyDateTime_TimeTZ implementation.
4104 */
4105
4106/* Accessor properties. Properties for hour, minute, second and microsecond
4107 * are inherited from time.
4108 */
4109
4110static PyObject *
4111timetz_tzinfo(PyDateTime_TimeTZ *self, void *unused)
4112{
4113 Py_INCREF(self->tzinfo);
4114 return self->tzinfo;
4115}
4116
4117static PyGetSetDef timetz_getset[] = {
4118 {"tzinfo", (getter)timetz_tzinfo},
4119 {NULL}
4120};
4121
4122/*
4123 * Constructors.
4124 */
4125
Tim Peters12bf3392002-12-24 05:41:27 +00004126static char *timetz_kws[] = {"hour", "minute", "second", "microsecond",
4127 "tzinfo", NULL};
4128
Tim Peters2a799bf2002-12-16 20:18:38 +00004129static PyObject *
4130timetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4131{
4132 PyObject *self = NULL;
4133 int hour = 0;
4134 int minute = 0;
4135 int second = 0;
4136 int usecond = 0;
4137 PyObject *tzinfo = Py_None;
4138
Tim Peters12bf3392002-12-24 05:41:27 +00004139 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", timetz_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00004140 &hour, &minute, &second, &usecond,
4141 &tzinfo)) {
4142 if (check_time_args(hour, minute, second, usecond) < 0)
4143 return NULL;
4144 if (check_tzinfo_subclass(tzinfo) < 0)
4145 return NULL;
4146 self = new_timetz(hour, minute, second, usecond, tzinfo);
4147 }
4148 return self;
4149}
4150
4151/*
4152 * Destructor.
4153 */
4154
4155static void
4156timetz_dealloc(PyDateTime_TimeTZ *self)
4157{
4158 Py_XDECREF(self->tzinfo);
4159 self->ob_type->tp_free((PyObject *)self);
4160}
4161
4162/*
Tim Peters855fe882002-12-22 03:43:39 +00004163 * Indirect access to tzinfo methods.
Tim Peters2a799bf2002-12-16 20:18:38 +00004164 */
4165
Tim Peters2a799bf2002-12-16 20:18:38 +00004166/* These are all METH_NOARGS, so don't need to check the arglist. */
4167static PyObject *
4168timetz_utcoffset(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004169 return offset_as_timedelta(self->tzinfo, "utcoffset", Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004170}
4171
4172static PyObject *
4173timetz_dst(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004174 return offset_as_timedelta(self->tzinfo, "dst", Py_None);
Tim Peters855fe882002-12-22 03:43:39 +00004175}
4176
4177static PyObject *
4178timetz_tzname(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004179 return call_tzname(self->tzinfo, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004180}
4181
4182/*
4183 * Various ways to turn a timetz into a string.
4184 */
4185
4186static PyObject *
4187timetz_repr(PyDateTime_TimeTZ *self)
4188{
4189 PyObject *baserepr = time_repr((PyDateTime_Time *)self);
4190
4191 if (baserepr == NULL)
4192 return NULL;
4193 return append_keyword_tzinfo(baserepr, self->tzinfo);
4194}
4195
4196/* Note: tp_str is inherited from time. */
4197
4198static PyObject *
4199timetz_isoformat(PyDateTime_TimeTZ *self)
4200{
4201 char buf[100];
4202 PyObject *result = time_isoformat((PyDateTime_Time *)self);
4203
4204 if (result == NULL || self->tzinfo == Py_None)
4205 return result;
4206
4207 /* We need to append the UTC offset. */
4208 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00004209 Py_None) < 0) {
Tim Peters2a799bf2002-12-16 20:18:38 +00004210 Py_DECREF(result);
4211 return NULL;
4212 }
4213 PyString_ConcatAndDel(&result, PyString_FromString(buf));
4214 return result;
4215}
4216
4217/* Note: strftime() is inherited from time. */
4218
4219/*
4220 * Miscellaneous methods.
4221 */
4222
4223/* Note: tp_richcompare and tp_hash are inherited from time. */
4224
Tim Peters12bf3392002-12-24 05:41:27 +00004225static PyObject *
4226timetz_replace(PyDateTime_TimeTZ *self, PyObject *args, PyObject *kw)
4227{
4228 PyObject *clone;
4229 PyObject *tuple;
4230 int hh = TIME_GET_HOUR(self);
4231 int mm = TIME_GET_MINUTE(self);
4232 int ss = TIME_GET_SECOND(self);
4233 int us = TIME_GET_MICROSECOND(self);
4234 PyObject *tzinfo = self->tzinfo;
4235
4236 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
4237 timetz_kws,
4238 &hh, &mm, &ss, &us, &tzinfo))
4239 return NULL;
4240 tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
4241 if (tuple == NULL)
4242 return NULL;
4243 clone = timetz_new(self->ob_type, tuple, NULL);
4244 Py_DECREF(tuple);
4245 return clone;
4246}
4247
Tim Peters2a799bf2002-12-16 20:18:38 +00004248static int
4249timetz_nonzero(PyDateTime_TimeTZ *self)
4250{
4251 int offset;
4252 int none;
4253
4254 if (TIME_GET_SECOND(self) || TIME_GET_MICROSECOND(self)) {
4255 /* Since utcoffset is in whole minutes, nothing can
4256 * alter the conclusion that this is nonzero.
4257 */
4258 return 1;
4259 }
4260 offset = 0;
4261 if (self->tzinfo != Py_None) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004262 offset = call_utcoffset(self->tzinfo, Py_None, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +00004263 if (offset == -1 && PyErr_Occurred())
4264 return -1;
4265 }
4266 return (TIME_GET_MINUTE(self) - offset + TIME_GET_HOUR(self)*60) != 0;
4267}
4268
4269/*
4270 * Pickle support. Quite a maze!
4271 */
4272
4273/* Let basestate be the state string returned by time_getstate.
4274 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4275 * So it's a tuple in any (non-error) case.
4276 */
4277static PyObject *
4278timetz_getstate(PyDateTime_TimeTZ *self)
4279{
4280 PyObject *basestate;
4281 PyObject *result = NULL;
4282
4283 basestate = time_getstate((PyDateTime_Time *)self);
4284 if (basestate != NULL) {
4285 if (self->tzinfo == Py_None)
4286 result = Py_BuildValue("(O)", basestate);
4287 else
4288 result = Py_BuildValue("OO", basestate, self->tzinfo);
4289 Py_DECREF(basestate);
4290 }
4291 return result;
4292}
4293
4294static PyObject *
4295timetz_setstate(PyDateTime_TimeTZ *self, PyObject *state)
4296{
4297 PyObject *temp;
4298 PyObject *basestate;
4299 PyObject *tzinfo = Py_None;
4300
4301 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
4302 &PyString_Type, &basestate,
4303 &tzinfo))
4304 return NULL;
4305 temp = time_setstate((PyDateTime_Time *)self, basestate);
4306 if (temp == NULL)
4307 return NULL;
4308 Py_DECREF(temp);
4309
4310 Py_INCREF(tzinfo);
4311 Py_XDECREF(self->tzinfo);
4312 self->tzinfo = tzinfo;
4313
4314 Py_INCREF(Py_None);
4315 return Py_None;
4316}
4317
4318static PyObject *
4319timetz_pickler(PyObject *module, PyDateTime_TimeTZ *timetz)
4320{
4321 PyObject *state;
4322 PyObject *result = NULL;
4323
4324 if (! PyTimeTZ_CheckExact(timetz)) {
4325 PyErr_Format(PyExc_TypeError,
4326 "bad type passed to timetz pickler: %s",
4327 timetz->ob_type->tp_name);
4328 return NULL;
4329 }
4330 state = timetz_getstate(timetz);
4331 if (state) {
4332 result = Py_BuildValue("O(O)",
4333 timetz_unpickler_object,
4334 state);
4335 Py_DECREF(state);
4336 }
4337 return result;
4338}
4339
4340static PyObject *
4341timetz_unpickler(PyObject *module, PyObject *arg)
4342{
4343 PyDateTime_TimeTZ *self;
4344
4345 self = PyObject_New(PyDateTime_TimeTZ, &PyDateTime_TimeTZType);
4346 if (self != NULL) {
4347 PyObject *res;
4348
4349 self->tzinfo = NULL;
4350 res = timetz_setstate(self, arg);
4351 if (res == NULL) {
4352 Py_DECREF(self);
4353 return NULL;
4354 }
4355 Py_DECREF(res);
4356 }
4357 return (PyObject *)self;
4358}
4359
4360static PyMethodDef timetz_methods[] = {
4361 {"isoformat", (PyCFunction)timetz_isoformat, METH_KEYWORDS,
4362 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]"
4363 "[+HH:MM].")},
4364
4365 {"utcoffset", (PyCFunction)timetz_utcoffset, METH_NOARGS,
4366 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
4367
4368 {"tzname", (PyCFunction)timetz_tzname, METH_NOARGS,
4369 PyDoc_STR("Return self.tzinfo.tzname(self).")},
4370
4371 {"dst", (PyCFunction)timetz_dst, METH_NOARGS,
4372 PyDoc_STR("Return self.tzinfo.dst(self).")},
4373
Tim Peters12bf3392002-12-24 05:41:27 +00004374 {"replace", (PyCFunction)timetz_replace, METH_KEYWORDS,
4375 PyDoc_STR("Return timetz with new specified fields.")},
4376
Tim Peters2a799bf2002-12-16 20:18:38 +00004377 {"__setstate__", (PyCFunction)timetz_setstate, METH_O,
4378 PyDoc_STR("__setstate__(state)")},
4379
4380 {"__getstate__", (PyCFunction)timetz_getstate, METH_NOARGS,
4381 PyDoc_STR("__getstate__() -> state")},
4382 {NULL, NULL}
4383
4384};
4385
4386static char timetz_doc[] =
4387PyDoc_STR("Time type.");
4388
4389static PyNumberMethods timetz_as_number = {
4390 0, /* nb_add */
4391 0, /* nb_subtract */
4392 0, /* nb_multiply */
4393 0, /* nb_divide */
4394 0, /* nb_remainder */
4395 0, /* nb_divmod */
4396 0, /* nb_power */
4397 0, /* nb_negative */
4398 0, /* nb_positive */
4399 0, /* nb_absolute */
4400 (inquiry)timetz_nonzero, /* nb_nonzero */
4401};
4402
4403statichere PyTypeObject PyDateTime_TimeTZType = {
4404 PyObject_HEAD_INIT(NULL)
4405 0, /* ob_size */
Tim Peters0bf60bd2003-01-08 20:40:01 +00004406 "datetime.time", /* tp_name */
Tim Peters2a799bf2002-12-16 20:18:38 +00004407 sizeof(PyDateTime_TimeTZ), /* tp_basicsize */
4408 0, /* tp_itemsize */
4409 (destructor)timetz_dealloc, /* tp_dealloc */
4410 0, /* tp_print */
4411 0, /* tp_getattr */
4412 0, /* tp_setattr */
4413 0, /* tp_compare */
4414 (reprfunc)timetz_repr, /* tp_repr */
4415 &timetz_as_number, /* tp_as_number */
4416 0, /* tp_as_sequence */
4417 0, /* tp_as_mapping */
4418 0, /* tp_hash */
4419 0, /* tp_call */
4420 0, /* tp_str */
4421 PyObject_GenericGetAttr, /* tp_getattro */
4422 0, /* tp_setattro */
4423 0, /* tp_as_buffer */
4424 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4425 Py_TPFLAGS_BASETYPE, /* tp_flags */
Guido van Rossumbd43e912002-12-16 20:34:55 +00004426 timetz_doc, /* tp_doc */
Tim Peters2a799bf2002-12-16 20:18:38 +00004427 0, /* tp_traverse */
4428 0, /* tp_clear */
4429 0, /* tp_richcompare */
4430 0, /* tp_weaklistoffset */
4431 0, /* tp_iter */
4432 0, /* tp_iternext */
4433 timetz_methods, /* tp_methods */
4434 0, /* tp_members */
4435 timetz_getset, /* tp_getset */
4436 &PyDateTime_TimeType, /* tp_base */
4437 0, /* tp_dict */
4438 0, /* tp_descr_get */
4439 0, /* tp_descr_set */
4440 0, /* tp_dictoffset */
4441 0, /* tp_init */
4442 0, /* tp_alloc */
4443 timetz_new, /* tp_new */
4444 _PyObject_Del, /* tp_free */
4445};
4446
4447/*
4448 * PyDateTime_DateTimeTZ implementation.
4449 */
4450
4451/* Accessor properties. Properties for day, month, year, hour, minute,
4452 * second and microsecond are inherited from datetime.
4453 */
4454
4455static PyObject *
4456datetimetz_tzinfo(PyDateTime_DateTimeTZ *self, void *unused)
4457{
4458 Py_INCREF(self->tzinfo);
4459 return self->tzinfo;
4460}
4461
4462static PyGetSetDef datetimetz_getset[] = {
4463 {"tzinfo", (getter)datetimetz_tzinfo},
4464 {NULL}
4465};
4466
4467/*
4468 * Constructors.
4469 * These are like the datetime methods of the same names, but allow an
4470 * optional tzinfo argument.
4471 */
4472
Tim Peters12bf3392002-12-24 05:41:27 +00004473static char *datetimetz_kws[] = {
4474 "year", "month", "day", "hour", "minute", "second",
4475 "microsecond", "tzinfo", NULL
4476};
4477
Tim Peters2a799bf2002-12-16 20:18:38 +00004478static PyObject *
4479datetimetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4480{
4481 PyObject *self = NULL;
4482 int year;
4483 int month;
4484 int day;
4485 int hour = 0;
4486 int minute = 0;
4487 int second = 0;
4488 int usecond = 0;
4489 PyObject *tzinfo = Py_None;
4490
Tim Peters12bf3392002-12-24 05:41:27 +00004491 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO", datetimetz_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00004492 &year, &month, &day, &hour, &minute,
4493 &second, &usecond, &tzinfo)) {
4494 if (check_date_args(year, month, day) < 0)
4495 return NULL;
4496 if (check_time_args(hour, minute, second, usecond) < 0)
4497 return NULL;
4498 if (check_tzinfo_subclass(tzinfo) < 0)
4499 return NULL;
4500 self = new_datetimetz(year, month, day,
4501 hour, minute, second, usecond,
4502 tzinfo);
4503 }
4504 return self;
4505}
4506
4507/* Return best possible local time -- this isn't constrained by the
4508 * precision of a timestamp.
4509 */
4510static PyObject *
4511datetimetz_now(PyObject *cls, PyObject *args, PyObject *kw)
4512{
4513 PyObject *self = NULL;
4514 PyObject *tzinfo = Py_None;
4515 static char *keywords[] = {"tzinfo", NULL};
4516
4517 if (PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords,
4518 &tzinfo)) {
4519 if (check_tzinfo_subclass(tzinfo) < 0)
4520 return NULL;
4521 self = datetime_best_possible(cls, localtime);
4522 if (self != NULL)
4523 replace_tzinfo(self, tzinfo);
4524 }
4525 return self;
4526}
4527
4528/* Return new local datetime from timestamp (Python timestamp -- a double). */
4529static PyObject *
4530datetimetz_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
4531{
4532 PyObject *self = NULL;
4533 double timestamp;
4534 PyObject *tzinfo = Py_None;
4535 static char *keywords[] = {"timestamp", "tzinfo", NULL};
4536
4537 if (PyArg_ParseTupleAndKeywords(args, kw, "d|O:fromtimestamp",
4538 keywords, &timestamp, &tzinfo)) {
4539 if (check_tzinfo_subclass(tzinfo) < 0)
4540 return NULL;
4541 self = datetime_from_timestamp(cls, localtime, timestamp);
4542 if (self != NULL)
4543 replace_tzinfo(self, tzinfo);
4544 }
4545 return self;
4546}
4547
4548/* Note: utcnow() is inherited, and doesn't accept tzinfo.
4549 * Ditto utcfromtimestamp(). Ditto combine().
4550 */
4551
4552
4553/*
4554 * Destructor.
4555 */
4556
4557static void
4558datetimetz_dealloc(PyDateTime_DateTimeTZ *self)
4559{
4560 Py_XDECREF(self->tzinfo);
4561 self->ob_type->tp_free((PyObject *)self);
4562}
4563
4564/*
4565 * Indirect access to tzinfo methods.
4566 */
4567
Tim Peters2a799bf2002-12-16 20:18:38 +00004568/* These are all METH_NOARGS, so don't need to check the arglist. */
4569static PyObject *
4570datetimetz_utcoffset(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004571 return offset_as_timedelta(self->tzinfo, "utcoffset",
4572 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00004573}
4574
4575static PyObject *
4576datetimetz_dst(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004577 return offset_as_timedelta(self->tzinfo, "dst", (PyObject *)self);
Tim Peters855fe882002-12-22 03:43:39 +00004578}
4579
4580static PyObject *
4581datetimetz_tzname(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004582 return call_tzname(self->tzinfo, (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00004583}
4584
4585/*
4586 * datetimetz arithmetic.
4587 */
4588
4589/* If base is Py_NotImplemented or NULL, just return it.
4590 * Else base is a datetime, exactly one of {left, right} is a datetimetz,
4591 * and we want to create a datetimetz with the same date and time fields
4592 * as base, and with the tzinfo field from left or right. Do that,
4593 * return it, and decref base. This is used to transform the result of
4594 * a binary datetime operation (base) into a datetimetz result.
4595 */
4596static PyObject *
4597attach_tzinfo(PyObject *base, PyObject *left, PyObject *right)
4598{
4599 PyDateTime_DateTimeTZ *self;
4600 PyDateTime_DateTimeTZ *result;
4601
4602 if (base == NULL || base == Py_NotImplemented)
4603 return base;
4604
4605 assert(PyDateTime_CheckExact(base));
4606
4607 if (PyDateTimeTZ_Check(left)) {
4608 assert(! PyDateTimeTZ_Check(right));
4609 self = (PyDateTime_DateTimeTZ *)left;
4610 }
4611 else {
4612 assert(PyDateTimeTZ_Check(right));
4613 self = (PyDateTime_DateTimeTZ *)right;
4614 }
4615 result = PyObject_New(PyDateTime_DateTimeTZ,
4616 &PyDateTime_DateTimeTZType);
4617 if (result != NULL) {
4618 memcpy(result->data, ((PyDateTime_DateTime *)base)->data,
4619 _PyDateTime_DATETIME_DATASIZE);
4620 Py_INCREF(self->tzinfo);
4621 result->tzinfo = self->tzinfo;
4622 }
4623 Py_DECREF(base);
4624 return (PyObject *)result;
4625}
4626
4627static PyObject *
4628datetimetz_add(PyObject *left, PyObject *right)
4629{
4630 return attach_tzinfo(datetime_add(left, right), left, right);
4631}
4632
4633static PyObject *
4634datetimetz_subtract(PyObject *left, PyObject *right)
4635{
4636 PyObject *result = Py_NotImplemented;
4637
4638 if (PyDateTime_Check(left)) {
4639 /* datetime - ??? */
4640 if (PyDateTime_Check(right)) {
4641 /* datetime - datetime */
4642 naivety n1, n2;
4643 int offset1, offset2;
4644 PyDateTime_Delta *delta;
4645
Tim Peterse39a80c2002-12-30 21:28:52 +00004646 if (classify_two_utcoffsets(left, &offset1, &n1, left,
4647 right, &offset2, &n2,
4648 right) < 0)
Tim Peters00237032002-12-27 02:21:51 +00004649 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00004650 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00004651 if (n1 != n2) {
4652 PyErr_SetString(PyExc_TypeError,
4653 "can't subtract offset-naive and "
4654 "offset-aware datetimes");
4655 return NULL;
4656 }
4657 delta = (PyDateTime_Delta *)sub_datetime_datetime(
4658 (PyDateTime_DateTime *)left,
4659 (PyDateTime_DateTime *)right);
4660 if (delta == NULL || offset1 == offset2)
4661 return (PyObject *)delta;
4662 /* (left - offset1) - (right - offset2) =
4663 * (left - right) + (offset2 - offset1)
4664 */
4665 result = new_delta(delta->days,
4666 delta->seconds +
4667 (offset2 - offset1) * 60,
4668 delta->microseconds,
4669 1);
4670 Py_DECREF(delta);
4671 }
4672 else if (PyDelta_Check(right)) {
4673 /* datetimetz - delta */
4674 result = sub_datetime_timedelta(
4675 (PyDateTime_DateTime *)left,
4676 (PyDateTime_Delta *)right);
4677 result = attach_tzinfo(result, left, right);
4678 }
4679 }
4680
4681 if (result == Py_NotImplemented)
4682 Py_INCREF(result);
4683 return result;
4684}
4685
4686/* Various ways to turn a datetime into a string. */
4687
4688static PyObject *
4689datetimetz_repr(PyDateTime_DateTimeTZ *self)
4690{
4691 PyObject *baserepr = datetime_repr((PyDateTime_DateTime *)self);
4692
4693 if (baserepr == NULL)
4694 return NULL;
4695 return append_keyword_tzinfo(baserepr, self->tzinfo);
4696}
4697
4698/* Note: tp_str is inherited from datetime. */
4699
4700static PyObject *
4701datetimetz_isoformat(PyDateTime_DateTimeTZ *self,
4702 PyObject *args, PyObject *kw)
4703{
4704 char buf[100];
4705 PyObject *result = datetime_isoformat((PyDateTime_DateTime *)self,
4706 args, kw);
4707
4708 if (result == NULL || self->tzinfo == Py_None)
4709 return result;
4710
4711 /* We need to append the UTC offset. */
4712 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
4713 (PyObject *)self) < 0) {
4714 Py_DECREF(result);
4715 return NULL;
4716 }
4717 PyString_ConcatAndDel(&result, PyString_FromString(buf));
4718 return result;
4719}
4720
4721/* Miscellaneous methods. */
4722
4723/* Note: tp_richcompare and tp_hash are inherited from datetime. */
4724
4725static PyObject *
Tim Peters12bf3392002-12-24 05:41:27 +00004726datetimetz_replace(PyDateTime_DateTimeTZ *self, PyObject *args, PyObject *kw)
4727{
4728 PyObject *clone;
4729 PyObject *tuple;
4730 int y = GET_YEAR(self);
4731 int m = GET_MONTH(self);
4732 int d = GET_DAY(self);
4733 int hh = DATE_GET_HOUR(self);
4734 int mm = DATE_GET_MINUTE(self);
4735 int ss = DATE_GET_SECOND(self);
4736 int us = DATE_GET_MICROSECOND(self);
4737 PyObject *tzinfo = self->tzinfo;
4738
4739 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO:replace",
4740 datetimetz_kws,
4741 &y, &m, &d, &hh, &mm, &ss, &us,
4742 &tzinfo))
4743 return NULL;
4744 tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
4745 if (tuple == NULL)
4746 return NULL;
4747 clone = datetimetz_new(self->ob_type, tuple, NULL);
4748 Py_DECREF(tuple);
4749 return clone;
4750}
4751
4752static PyObject *
Tim Peters80475bb2002-12-25 07:40:55 +00004753datetimetz_astimezone(PyDateTime_DateTimeTZ *self, PyObject *args,
4754 PyObject *kw)
4755{
4756 int y = GET_YEAR(self);
4757 int m = GET_MONTH(self);
4758 int d = GET_DAY(self);
4759 int hh = DATE_GET_HOUR(self);
4760 int mm = DATE_GET_MINUTE(self);
4761 int ss = DATE_GET_SECOND(self);
4762 int us = DATE_GET_MICROSECOND(self);
4763
Tim Peters521fc152002-12-31 17:36:56 +00004764 PyObject *result;
4765 PyObject *temp;
Tim Petersadf64202003-01-04 06:03:15 +00004766 int selfoff, resoff, dst1, dst2;
Tim Peters521fc152002-12-31 17:36:56 +00004767 int none;
Tim Petersf3615152003-01-01 21:51:37 +00004768 int delta;
Tim Peters521fc152002-12-31 17:36:56 +00004769
Tim Peters80475bb2002-12-25 07:40:55 +00004770 PyObject *tzinfo;
4771 static char *keywords[] = {"tz", NULL};
4772
4773 if (! PyArg_ParseTupleAndKeywords(args, kw, "O:astimezone", keywords,
4774 &tzinfo))
4775 return NULL;
4776 if (check_tzinfo_subclass(tzinfo) < 0)
4777 return NULL;
4778
Tim Peters521fc152002-12-31 17:36:56 +00004779 /* Don't call utcoffset unless necessary. */
4780 result = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4781 if (result == NULL ||
4782 tzinfo == Py_None ||
4783 self->tzinfo == Py_None ||
4784 self->tzinfo == tzinfo)
4785 return result;
4786
4787 /* Get the offsets. If either object turns out to be naive, again
4788 * there's no conversion of date or time fields.
4789 */
Tim Petersb5a16f32003-01-01 04:48:01 +00004790 selfoff = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4791 if (selfoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004792 goto Fail;
4793 if (none)
4794 return result;
4795
Tim Petersb5a16f32003-01-01 04:48:01 +00004796 resoff = call_utcoffset(tzinfo, result, &none);
4797 if (resoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004798 goto Fail;
4799 if (none)
4800 return result;
4801
Tim Petersf3615152003-01-01 21:51:37 +00004802 /* See the long comment block at the end of this file for an
4803 * explanation of this algorithm. That it always works requires a
Tim Petersadf64202003-01-04 06:03:15 +00004804 * pretty intricate proof. There are many equivalent ways to code
4805 * up the proof as an algorithm. This way favors calling dst() over
4806 * calling utcoffset(), because "the usual" utcoffset() calls dst()
4807 * itself, and calling the latter instead saves a Python-level
4808 * function call. This way of coding it also follows the proof
4809 * closely, w/ x=self, y=result, z=result, and z'=temp.
Tim Peters521fc152002-12-31 17:36:56 +00004810 */
Tim Petersadf64202003-01-04 06:03:15 +00004811 dst1 = call_dst(tzinfo, result, &none);
4812 if (dst1 == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004813 goto Fail;
Tim Peters710fb152003-01-02 19:35:54 +00004814 if (none) {
4815 PyErr_SetString(PyExc_ValueError, "astimezone(): utcoffset() "
4816 "returned a duration but dst() returned None");
4817 goto Fail;
4818 }
Tim Petersadf64202003-01-04 06:03:15 +00004819 delta = resoff - dst1 - selfoff;
4820 if (delta) {
4821 mm += delta;
Tim Petersb5a16f32003-01-01 04:48:01 +00004822 if ((mm < 0 || mm >= 60) &&
4823 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters521fc152002-12-31 17:36:56 +00004824 goto Fail;
4825 temp = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4826 if (temp == NULL)
4827 goto Fail;
4828 Py_DECREF(result);
4829 result = temp;
4830
Tim Petersadf64202003-01-04 06:03:15 +00004831 dst1 = call_dst(tzinfo, result, &none);
4832 if (dst1 == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004833 goto Fail;
4834 if (none)
4835 goto Inconsistent;
Tim Petersf3615152003-01-01 21:51:37 +00004836 }
Tim Petersadf64202003-01-04 06:03:15 +00004837 if (dst1 == 0)
Tim Petersf3615152003-01-01 21:51:37 +00004838 return result;
4839
Tim Petersadf64202003-01-04 06:03:15 +00004840 mm += dst1;
Tim Petersf3615152003-01-01 21:51:37 +00004841 if ((mm < 0 || mm >= 60) &&
4842 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters521fc152002-12-31 17:36:56 +00004843 goto Fail;
4844 temp = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4845 if (temp == NULL)
4846 goto Fail;
Tim Peters521fc152002-12-31 17:36:56 +00004847
Tim Petersadf64202003-01-04 06:03:15 +00004848 dst2 = call_dst(tzinfo, temp, &none);
4849 if (dst2 == -1 && PyErr_Occurred()) {
4850 Py_DECREF(temp);
Tim Petersf3615152003-01-01 21:51:37 +00004851 goto Fail;
Tim Petersadf64202003-01-04 06:03:15 +00004852 }
4853 if (none) {
4854 Py_DECREF(temp);
Tim Petersf3615152003-01-01 21:51:37 +00004855 goto Inconsistent;
Tim Petersadf64202003-01-04 06:03:15 +00004856 }
Tim Petersf3615152003-01-01 21:51:37 +00004857
Tim Petersadf64202003-01-04 06:03:15 +00004858 if (dst1 == dst2) {
4859 /* The normal case: we want temp, not result. */
4860 Py_DECREF(result);
4861 result = temp;
4862 }
4863 else {
4864 /* The "unspellable hour" at the end of DST. */
4865 Py_DECREF(temp);
4866 }
4867 return result;
Tim Peters521fc152002-12-31 17:36:56 +00004868
4869Inconsistent:
Tim Petersadf64202003-01-04 06:03:15 +00004870 PyErr_SetString(PyExc_ValueError, "astimezone(): tz.dst() gave"
4871 "inconsistent results; cannot convert");
Tim Peters521fc152002-12-31 17:36:56 +00004872
4873 /* fall thru to failure */
4874Fail:
4875 Py_DECREF(result);
4876 return NULL;
Tim Peters80475bb2002-12-25 07:40:55 +00004877}
4878
4879static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00004880datetimetz_timetuple(PyDateTime_DateTimeTZ *self)
4881{
4882 int dstflag = -1;
4883
4884 if (self->tzinfo != Py_None) {
4885 int none;
4886
4887 dstflag = call_dst(self->tzinfo, (PyObject *)self, &none);
4888 if (dstflag == -1 && PyErr_Occurred())
4889 return NULL;
4890
4891 if (none)
4892 dstflag = -1;
4893 else if (dstflag != 0)
4894 dstflag = 1;
4895
4896 }
4897 return build_struct_time(GET_YEAR(self),
4898 GET_MONTH(self),
4899 GET_DAY(self),
4900 DATE_GET_HOUR(self),
4901 DATE_GET_MINUTE(self),
4902 DATE_GET_SECOND(self),
4903 dstflag);
4904}
4905
4906static PyObject *
4907datetimetz_utctimetuple(PyDateTime_DateTimeTZ *self)
4908{
4909 int y = GET_YEAR(self);
4910 int m = GET_MONTH(self);
4911 int d = GET_DAY(self);
4912 int hh = DATE_GET_HOUR(self);
4913 int mm = DATE_GET_MINUTE(self);
4914 int ss = DATE_GET_SECOND(self);
4915 int us = 0; /* microseconds are ignored in a timetuple */
4916 int offset = 0;
4917
4918 if (self->tzinfo != Py_None) {
4919 int none;
4920
4921 offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4922 if (offset == -1 && PyErr_Occurred())
4923 return NULL;
4924 }
4925 /* Even if offset is 0, don't call timetuple() -- tm_isdst should be
4926 * 0 in a UTC timetuple regardless of what dst() says.
4927 */
4928 if (offset) {
4929 /* Subtract offset minutes & normalize. */
4930 int stat;
4931
4932 mm -= offset;
4933 stat = normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us);
4934 if (stat < 0) {
4935 /* At the edges, it's possible we overflowed
4936 * beyond MINYEAR or MAXYEAR.
4937 */
4938 if (PyErr_ExceptionMatches(PyExc_OverflowError))
4939 PyErr_Clear();
4940 else
4941 return NULL;
4942 }
4943 }
4944 return build_struct_time(y, m, d, hh, mm, ss, 0);
4945}
4946
4947static PyObject *
4948datetimetz_gettimetz(PyDateTime_DateTimeTZ *self)
4949{
4950 return new_timetz(DATE_GET_HOUR(self),
4951 DATE_GET_MINUTE(self),
4952 DATE_GET_SECOND(self),
4953 DATE_GET_MICROSECOND(self),
4954 self->tzinfo);
4955}
4956
4957/*
4958 * Pickle support. Quite a maze!
4959 */
4960
4961/* Let basestate be the state string returned by datetime_getstate.
4962 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4963 * So it's a tuple in any (non-error) case.
4964 */
4965static PyObject *
4966datetimetz_getstate(PyDateTime_DateTimeTZ *self)
4967{
4968 PyObject *basestate;
4969 PyObject *result = NULL;
4970
4971 basestate = datetime_getstate((PyDateTime_DateTime *)self);
4972 if (basestate != NULL) {
4973 if (self->tzinfo == Py_None)
4974 result = Py_BuildValue("(O)", basestate);
4975 else
4976 result = Py_BuildValue("OO", basestate, self->tzinfo);
4977 Py_DECREF(basestate);
4978 }
4979 return result;
4980}
4981
4982static PyObject *
4983datetimetz_setstate(PyDateTime_DateTimeTZ *self, PyObject *state)
4984{
4985 PyObject *temp;
4986 PyObject *basestate;
4987 PyObject *tzinfo = Py_None;
4988
4989 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
4990 &PyString_Type, &basestate,
4991 &tzinfo))
4992 return NULL;
4993 temp = datetime_setstate((PyDateTime_DateTime *)self, basestate);
4994 if (temp == NULL)
4995 return NULL;
4996 Py_DECREF(temp);
4997
4998 Py_INCREF(tzinfo);
4999 Py_XDECREF(self->tzinfo);
5000 self->tzinfo = tzinfo;
5001
5002 Py_INCREF(Py_None);
5003 return Py_None;
5004}
5005
5006static PyObject *
5007datetimetz_pickler(PyObject *module, PyDateTime_DateTimeTZ *datetimetz)
5008{
5009 PyObject *state;
5010 PyObject *result = NULL;
5011
5012 if (! PyDateTimeTZ_CheckExact(datetimetz)) {
5013 PyErr_Format(PyExc_TypeError,
5014 "bad type passed to datetimetz pickler: %s",
5015 datetimetz->ob_type->tp_name);
5016 return NULL;
5017 }
5018 state = datetimetz_getstate(datetimetz);
5019 if (state) {
5020 result = Py_BuildValue("O(O)",
5021 datetimetz_unpickler_object,
5022 state);
5023 Py_DECREF(state);
5024 }
5025 return result;
5026}
5027
5028static PyObject *
5029datetimetz_unpickler(PyObject *module, PyObject *arg)
5030{
5031 PyDateTime_DateTimeTZ *self;
5032
5033 self = PyObject_New(PyDateTime_DateTimeTZ, &PyDateTime_DateTimeTZType);
5034 if (self != NULL) {
5035 PyObject *res;
5036
5037 self->tzinfo = NULL;
5038 res = datetimetz_setstate(self, arg);
5039 if (res == NULL) {
5040 Py_DECREF(self);
5041 return NULL;
5042 }
5043 Py_DECREF(res);
5044 }
5045 return (PyObject *)self;
5046}
5047
5048
5049static PyMethodDef datetimetz_methods[] = {
5050 /* Class methods: */
5051 /* Inherited: combine(), utcnow(), utcfromtimestamp() */
5052
5053 {"now", (PyCFunction)datetimetz_now,
5054 METH_KEYWORDS | METH_CLASS,
5055 PyDoc_STR("[tzinfo] -> new datetimetz with local day and time.")},
5056
5057 {"fromtimestamp", (PyCFunction)datetimetz_fromtimestamp,
5058 METH_KEYWORDS | METH_CLASS,
5059 PyDoc_STR("timestamp[, tzinfo] -> local time from POSIX timestamp.")},
5060
5061 /* Instance methods: */
5062 /* Inherited: date(), time(), ctime(). */
5063 {"timetuple", (PyCFunction)datetimetz_timetuple, METH_NOARGS,
5064 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
5065
5066 {"utctimetuple", (PyCFunction)datetimetz_utctimetuple, METH_NOARGS,
5067 PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")},
5068
5069 {"timetz", (PyCFunction)datetimetz_gettimetz, METH_NOARGS,
5070 PyDoc_STR("Return timetz object with same hour, minute, second, "
5071 "microsecond, and tzinfo.")},
5072
5073 {"isoformat", (PyCFunction)datetimetz_isoformat, METH_KEYWORDS,
5074 PyDoc_STR("[sep] -> string in ISO 8601 format, "
5075 "YYYY-MM-DDTHH:MM:SS[.mmmmmm][+HH:MM].\n\n"
5076 "sep is used to separate the year from the time, and "
5077 "defaults to 'T'.")},
5078
5079 {"utcoffset", (PyCFunction)datetimetz_utcoffset, METH_NOARGS,
5080 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
5081
5082 {"tzname", (PyCFunction)datetimetz_tzname, METH_NOARGS,
5083 PyDoc_STR("Return self.tzinfo.tzname(self).")},
5084
5085 {"dst", (PyCFunction)datetimetz_dst, METH_NOARGS,
5086 PyDoc_STR("Return self.tzinfo.dst(self).")},
5087
Tim Peters12bf3392002-12-24 05:41:27 +00005088 {"replace", (PyCFunction)datetimetz_replace, METH_KEYWORDS,
5089 PyDoc_STR("Return datetimetz with new specified fields.")},
5090
Tim Peters80475bb2002-12-25 07:40:55 +00005091 {"astimezone", (PyCFunction)datetimetz_astimezone, METH_KEYWORDS,
5092 PyDoc_STR("tz -> convert to local time in new timezone tz\n")},
5093
Tim Peters2a799bf2002-12-16 20:18:38 +00005094 {"__setstate__", (PyCFunction)datetimetz_setstate, METH_O,
5095 PyDoc_STR("__setstate__(state)")},
5096
5097 {"__getstate__", (PyCFunction)datetimetz_getstate, METH_NOARGS,
5098 PyDoc_STR("__getstate__() -> state")},
5099 {NULL, NULL}
5100};
5101
5102static char datetimetz_doc[] =
5103PyDoc_STR("date/time type.");
5104
5105static PyNumberMethods datetimetz_as_number = {
5106 datetimetz_add, /* nb_add */
5107 datetimetz_subtract, /* nb_subtract */
5108 0, /* nb_multiply */
5109 0, /* nb_divide */
5110 0, /* nb_remainder */
5111 0, /* nb_divmod */
5112 0, /* nb_power */
5113 0, /* nb_negative */
5114 0, /* nb_positive */
5115 0, /* nb_absolute */
5116 0, /* nb_nonzero */
5117};
5118
5119statichere PyTypeObject PyDateTime_DateTimeTZType = {
5120 PyObject_HEAD_INIT(NULL)
5121 0, /* ob_size */
Tim Peters0bf60bd2003-01-08 20:40:01 +00005122 "datetime.datetime", /* tp_name */
Tim Peters2a799bf2002-12-16 20:18:38 +00005123 sizeof(PyDateTime_DateTimeTZ), /* tp_basicsize */
5124 0, /* tp_itemsize */
5125 (destructor)datetimetz_dealloc, /* tp_dealloc */
5126 0, /* tp_print */
5127 0, /* tp_getattr */
5128 0, /* tp_setattr */
5129 0, /* tp_compare */
5130 (reprfunc)datetimetz_repr, /* tp_repr */
5131 &datetimetz_as_number, /* tp_as_number */
5132 0, /* tp_as_sequence */
5133 0, /* tp_as_mapping */
5134 0, /* tp_hash */
5135 0, /* tp_call */
5136 0, /* tp_str */
5137 PyObject_GenericGetAttr, /* tp_getattro */
5138 0, /* tp_setattro */
5139 0, /* tp_as_buffer */
5140 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
5141 Py_TPFLAGS_BASETYPE, /* tp_flags */
5142 datetimetz_doc, /* tp_doc */
5143 0, /* tp_traverse */
5144 0, /* tp_clear */
5145 0, /* tp_richcompare */
5146 0, /* tp_weaklistoffset */
5147 0, /* tp_iter */
5148 0, /* tp_iternext */
5149 datetimetz_methods, /* tp_methods */
5150 0, /* tp_members */
5151 datetimetz_getset, /* tp_getset */
5152 &PyDateTime_DateTimeType, /* tp_base */
5153 0, /* tp_dict */
5154 0, /* tp_descr_get */
5155 0, /* tp_descr_set */
5156 0, /* tp_dictoffset */
5157 0, /* tp_init */
5158 0, /* tp_alloc */
5159 datetimetz_new, /* tp_new */
5160 _PyObject_Del, /* tp_free */
5161};
5162
5163/* ---------------------------------------------------------------------------
5164 * Module methods and initialization.
5165 */
5166
5167static PyMethodDef module_methods[] = {
5168 /* Private functions for pickling support, registered with the
5169 * copy_reg module by the module init function.
5170 */
5171 {"_date_pickler", (PyCFunction)date_pickler, METH_O, NULL},
5172 {"_date_unpickler", (PyCFunction)date_unpickler, METH_O, NULL},
5173 {"_datetime_pickler", (PyCFunction)datetime_pickler, METH_O, NULL},
5174 {"_datetime_unpickler", (PyCFunction)datetime_unpickler,METH_O, NULL},
5175 {"_datetimetz_pickler", (PyCFunction)datetimetz_pickler,METH_O, NULL},
5176 {"_datetimetz_unpickler",(PyCFunction)datetimetz_unpickler,METH_O, NULL},
5177 {"_time_pickler", (PyCFunction)time_pickler, METH_O, NULL},
5178 {"_time_unpickler", (PyCFunction)time_unpickler, METH_O, NULL},
5179 {"_timetz_pickler", (PyCFunction)timetz_pickler, METH_O, NULL},
5180 {"_timetz_unpickler", (PyCFunction)timetz_unpickler, METH_O, NULL},
5181 {"_tzinfo_pickler", (PyCFunction)tzinfo_pickler, METH_O, NULL},
5182 {"_tzinfo_unpickler", (PyCFunction)tzinfo_unpickler, METH_NOARGS,
5183 NULL},
5184 {NULL, NULL}
5185};
5186
5187PyMODINIT_FUNC
5188initdatetime(void)
5189{
5190 PyObject *m; /* a module object */
5191 PyObject *d; /* its dict */
5192 PyObject *x;
5193
5194 /* Types that use __reduce__ for pickling need to set the following
5195 * magical attr in the type dict, with a true value.
5196 */
5197 PyObject *safepickle = PyString_FromString("__safe_for_unpickling__");
5198 if (safepickle == NULL)
5199 return;
5200
5201 m = Py_InitModule3("datetime", module_methods,
5202 "Fast implementation of the datetime type.");
5203
5204 if (PyType_Ready(&PyDateTime_DateType) < 0)
5205 return;
5206 if (PyType_Ready(&PyDateTime_DateTimeType) < 0)
5207 return;
5208 if (PyType_Ready(&PyDateTime_DeltaType) < 0)
5209 return;
5210 if (PyType_Ready(&PyDateTime_TimeType) < 0)
5211 return;
5212 if (PyType_Ready(&PyDateTime_TZInfoType) < 0)
5213 return;
5214 if (PyType_Ready(&PyDateTime_TimeTZType) < 0)
5215 return;
5216 if (PyType_Ready(&PyDateTime_DateTimeTZType) < 0)
5217 return;
5218
5219 /* Pickling support, via registering functions with copy_reg. */
5220 {
5221 PyObject *pickler;
5222 PyObject *copyreg = PyImport_ImportModule("copy_reg");
5223
5224 if (copyreg == NULL) return;
5225
5226 pickler = PyObject_GetAttrString(m, "_date_pickler");
5227 if (pickler == NULL) return;
5228 date_unpickler_object = PyObject_GetAttrString(m,
5229 "_date_unpickler");
5230 if (date_unpickler_object == NULL) return;
5231 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5232 &PyDateTime_DateType,
5233 pickler,
5234 date_unpickler_object);
5235 if (x == NULL) return;
5236 Py_DECREF(x);
5237 Py_DECREF(pickler);
5238
5239 pickler = PyObject_GetAttrString(m, "_datetime_pickler");
5240 if (pickler == NULL) return;
5241 datetime_unpickler_object = PyObject_GetAttrString(m,
5242 "_datetime_unpickler");
5243 if (datetime_unpickler_object == NULL) return;
5244 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5245 &PyDateTime_DateTimeType,
5246 pickler,
5247 datetime_unpickler_object);
5248 if (x == NULL) return;
5249 Py_DECREF(x);
5250 Py_DECREF(pickler);
5251
5252 pickler = PyObject_GetAttrString(m, "_time_pickler");
5253 if (pickler == NULL) return;
5254 time_unpickler_object = PyObject_GetAttrString(m,
5255 "_time_unpickler");
5256 if (time_unpickler_object == NULL) return;
5257 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5258 &PyDateTime_TimeType,
5259 pickler,
5260 time_unpickler_object);
5261 if (x == NULL) return;
5262 Py_DECREF(x);
5263 Py_DECREF(pickler);
5264
5265 pickler = PyObject_GetAttrString(m, "_timetz_pickler");
5266 if (pickler == NULL) return;
5267 timetz_unpickler_object = PyObject_GetAttrString(m,
5268 "_timetz_unpickler");
5269 if (timetz_unpickler_object == NULL) return;
5270 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5271 &PyDateTime_TimeTZType,
5272 pickler,
5273 timetz_unpickler_object);
5274 if (x == NULL) return;
5275 Py_DECREF(x);
5276 Py_DECREF(pickler);
5277
5278 pickler = PyObject_GetAttrString(m, "_tzinfo_pickler");
5279 if (pickler == NULL) return;
5280 tzinfo_unpickler_object = PyObject_GetAttrString(m,
5281 "_tzinfo_unpickler");
5282 if (tzinfo_unpickler_object == NULL) return;
5283 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5284 &PyDateTime_TZInfoType,
5285 pickler,
5286 tzinfo_unpickler_object);
5287 if (x== NULL) return;
5288 Py_DECREF(x);
5289 Py_DECREF(pickler);
5290
5291 pickler = PyObject_GetAttrString(m, "_datetimetz_pickler");
5292 if (pickler == NULL) return;
5293 datetimetz_unpickler_object = PyObject_GetAttrString(m,
5294 "_datetimetz_unpickler");
5295 if (datetimetz_unpickler_object == NULL) return;
5296 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5297 &PyDateTime_DateTimeTZType,
5298 pickler,
5299 datetimetz_unpickler_object);
5300 if (x== NULL) return;
5301 Py_DECREF(x);
5302 Py_DECREF(pickler);
5303
5304 Py_DECREF(copyreg);
5305 }
5306
5307 /* timedelta values */
5308 d = PyDateTime_DeltaType.tp_dict;
5309
5310 if (PyDict_SetItem(d, safepickle, Py_True) < 0)
5311 return;
5312
5313 x = new_delta(0, 0, 1, 0);
5314 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5315 return;
5316 Py_DECREF(x);
5317
5318 x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0);
5319 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5320 return;
5321 Py_DECREF(x);
5322
5323 x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0);
5324 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5325 return;
5326 Py_DECREF(x);
5327
5328 /* date values */
5329 d = PyDateTime_DateType.tp_dict;
5330
5331 x = new_date(1, 1, 1);
5332 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5333 return;
5334 Py_DECREF(x);
5335
5336 x = new_date(MAXYEAR, 12, 31);
5337 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5338 return;
5339 Py_DECREF(x);
5340
5341 x = new_delta(1, 0, 0, 0);
5342 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5343 return;
5344 Py_DECREF(x);
5345
5346 /* datetime values */
5347 d = PyDateTime_DateTimeType.tp_dict;
5348
5349 x = new_datetime(1, 1, 1, 0, 0, 0, 0);
5350 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5351 return;
5352 Py_DECREF(x);
5353
5354 x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999);
5355 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5356 return;
5357 Py_DECREF(x);
5358
5359 x = new_delta(0, 0, 1, 0);
5360 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5361 return;
5362 Py_DECREF(x);
5363
5364 /* time values */
5365 d = PyDateTime_TimeType.tp_dict;
5366
5367 x = new_time(0, 0, 0, 0);
5368 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5369 return;
5370 Py_DECREF(x);
5371
5372 x = new_time(23, 59, 59, 999999);
5373 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5374 return;
5375 Py_DECREF(x);
5376
5377 x = new_delta(0, 0, 1, 0);
5378 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5379 return;
5380 Py_DECREF(x);
5381
5382 /* timetz values */
5383 d = PyDateTime_TimeTZType.tp_dict;
5384
5385 x = new_timetz(0, 0, 0, 0, Py_None);
5386 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5387 return;
5388 Py_DECREF(x);
5389
5390 x = new_timetz(23, 59, 59, 999999, Py_None);
5391 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5392 return;
5393 Py_DECREF(x);
5394
5395 x = new_delta(0, 0, 1, 0);
5396 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5397 return;
5398 Py_DECREF(x);
5399
5400 /* datetimetz values */
5401 d = PyDateTime_DateTimeTZType.tp_dict;
5402
5403 x = new_datetimetz(1, 1, 1, 0, 0, 0, 0, Py_None);
5404 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5405 return;
5406 Py_DECREF(x);
5407
5408 x = new_datetimetz(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None);
5409 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5410 return;
5411 Py_DECREF(x);
5412
5413 x = new_delta(0, 0, 1, 0);
5414 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5415 return;
5416 Py_DECREF(x);
5417
5418 Py_DECREF(safepickle);
5419
5420 /* module initialization */
5421 PyModule_AddIntConstant(m, "MINYEAR", MINYEAR);
5422 PyModule_AddIntConstant(m, "MAXYEAR", MAXYEAR);
5423
5424 Py_INCREF(&PyDateTime_DateType);
5425 PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType);
5426
Tim Peters2a799bf2002-12-16 20:18:38 +00005427 Py_INCREF(&PyDateTime_DeltaType);
5428 PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType);
5429
Tim Peters2a799bf2002-12-16 20:18:38 +00005430 Py_INCREF(&PyDateTime_TZInfoType);
5431 PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
5432
5433 Py_INCREF(&PyDateTime_TimeTZType);
Tim Peters0bf60bd2003-01-08 20:40:01 +00005434 PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeTZType);
Tim Peters2a799bf2002-12-16 20:18:38 +00005435
5436 Py_INCREF(&PyDateTime_DateTimeTZType);
Tim Peters0bf60bd2003-01-08 20:40:01 +00005437 PyModule_AddObject(m, "datetime",
Tim Peters2a799bf2002-12-16 20:18:38 +00005438 (PyObject *)&PyDateTime_DateTimeTZType);
5439
5440 /* A 4-year cycle has an extra leap day over what we'd get from
5441 * pasting together 4 single years.
5442 */
5443 assert(DI4Y == 4 * 365 + 1);
5444 assert(DI4Y == days_before_year(4+1));
5445
5446 /* Similarly, a 400-year cycle has an extra leap day over what we'd
5447 * get from pasting together 4 100-year cycles.
5448 */
5449 assert(DI400Y == 4 * DI100Y + 1);
5450 assert(DI400Y == days_before_year(400+1));
5451
5452 /* OTOH, a 100-year cycle has one fewer leap day than we'd get from
5453 * pasting together 25 4-year cycles.
5454 */
5455 assert(DI100Y == 25 * DI4Y - 1);
5456 assert(DI100Y == days_before_year(100+1));
5457
5458 us_per_us = PyInt_FromLong(1);
5459 us_per_ms = PyInt_FromLong(1000);
5460 us_per_second = PyInt_FromLong(1000000);
5461 us_per_minute = PyInt_FromLong(60000000);
5462 seconds_per_day = PyInt_FromLong(24 * 3600);
5463 if (us_per_us == NULL || us_per_ms == NULL || us_per_second == NULL ||
5464 us_per_minute == NULL || seconds_per_day == NULL)
5465 return;
5466
5467 /* The rest are too big for 32-bit ints, but even
5468 * us_per_week fits in 40 bits, so doubles should be exact.
5469 */
5470 us_per_hour = PyLong_FromDouble(3600000000.0);
5471 us_per_day = PyLong_FromDouble(86400000000.0);
5472 us_per_week = PyLong_FromDouble(604800000000.0);
5473 if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL)
5474 return;
5475}
Tim Petersf3615152003-01-01 21:51:37 +00005476
5477/* ---------------------------------------------------------------------------
5478Some time zone algebra. For a datetimetz x, let
5479 x.n = x stripped of its timezone -- its naive time.
5480 x.o = x.utcoffset(), and assuming that doesn't raise an exception or
5481 return None
5482 x.d = x.dst(), and assuming that doesn't raise an exception or
5483 return None
5484 x.s = x's standard offset, x.o - x.d
5485
5486Now some derived rules, where k is a duration (timedelta).
5487
54881. x.o = x.s + x.d
5489 This follows from the definition of x.s.
5490
Tim Petersc5dc4da2003-01-02 17:55:03 +000054912. If x and y have the same tzinfo member, x.s = y.s.
Tim Petersf3615152003-01-01 21:51:37 +00005492 This is actually a requirement, an assumption we need to make about
5493 sane tzinfo classes.
5494
54953. The naive UTC time corresponding to x is x.n - x.o.
5496 This is again a requirement for a sane tzinfo class.
5497
54984. (x+k).s = x.s
5499 This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
5500
Tim Petersc5dc4da2003-01-02 17:55:03 +000055015. (x+k).n = x.n + k
Tim Petersf3615152003-01-01 21:51:37 +00005502 Again follows from how arithmetic is defined.
5503
5504Now we can explain x.astimezone(tz). Let's assume it's an interesting case
5505(meaning that the various tzinfo methods exist, and don't blow up or return
5506None when called).
5507
5508The function wants to return a datetimetz y with timezone tz, equivalent to x.
5509
5510By #3, we want
5511
5512 y.n - y.o = x.n - x.o [1]
5513
5514The algorithm starts by attaching tz to x.n, and calling that y. So
5515x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
5516becomes true; in effect, we want to solve [2] for k:
5517
5518 (y+k).n - (y+k).o = x.n - x.o [2]
5519
5520By #1, this is the same as
5521
5522 (y+k).n - ((y+k).s + (y+k).d) = x.n - x.o [3]
5523
5524By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
5525Substituting that into [3],
5526
5527 x.n + k - (y+k).s - (y+k).d = x.n - x.o; the x.n terms cancel, leaving
5528 k - (y+k).s - (y+k).d = - x.o; rearranging,
5529 k = (y+k).s - x.o - (y+k).d; by #4, (y+k).s == y.s, so
5530 k = y.s - x.o - (y+k).d; then by #1, y.s = y.o - y.d, so
5531 k = y.o - y.d - x.o - (y+k).d
5532
5533On the RHS, (y+k).d can't be computed directly, but all the rest can be, and
5534we approximate k by ignoring the (y+k).d term at first. Note that k can't
5535be very large, since all offset-returning methods return a duration of
5536magnitude less than 24 hours. For that reason, if y is firmly in std time,
5537(y+k).d must be 0, so ignoring it has no consequence then.
5538
5539In any case, the new value is
5540
Tim Petersc5dc4da2003-01-02 17:55:03 +00005541 z = y + y.o - y.d - x.o [4]
Tim Petersf3615152003-01-01 21:51:37 +00005542
Tim Petersc5dc4da2003-01-02 17:55:03 +00005543It's helpful to step back at look at [4] from a higher level: rewrite it as
Tim Petersf3615152003-01-01 21:51:37 +00005544
Tim Petersc5dc4da2003-01-02 17:55:03 +00005545 z = (y - x.o) + (y.o - y.d)
5546
5547(y - x.o).n = [by #5] y.n - x.o = [since y.n=x.n] x.n - x.o = [by #3] x's
5548UTC equivalent time. So the y-x.o part essentially converts x to UTC. Then
5549the y.o-y.d part essentially converts x's UTC equivalent into tz's standard
5550time (y.o-y.d=y.s by #1).
5551
5552At this point, if
5553
5554 z.n - z.o = x.n - x.o [5]
5555
5556we have an equivalent time, and are almost done. The insecurity here is
Tim Petersf3615152003-01-01 21:51:37 +00005557at the start of daylight time. Picture US Eastern for concreteness. The wall
5558time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
5559sense then. A sensible Eastern tzinfo class will consider such a time to be
5560EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST on the
5561day DST starts. We want to return the 1:MM EST spelling because that's
5562the only spelling that makes sense on the local wall clock.
5563
Tim Petersc5dc4da2003-01-02 17:55:03 +00005564In fact, if [5] holds at this point, we do have the standard-time spelling,
5565but that takes a bit of proof. We first prove a stronger result. What's the
5566difference between the LHS and RHS of [5]? Let
Tim Petersf3615152003-01-01 21:51:37 +00005567
Tim Petersc5dc4da2003-01-02 17:55:03 +00005568 diff = (x.n - x.o) - (z.n - z.o) [6]
Tim Petersf3615152003-01-01 21:51:37 +00005569
Tim Petersc5dc4da2003-01-02 17:55:03 +00005570Now
5571 z.n = by [4]
5572 (y + y.o - y.d - x.o).n = by #5
5573 y.n + y.o - y.d - x.o = since y.n = x.n
5574 x.n + y.o - y.d - x.o = since y.o = y.s + y.d by #1
5575 x.n + (y.s + y.d) - y.d - x.o = cancelling the y.d terms
5576 x.n + y.s - x.o = since z and y are have the same tzinfo member,
5577 y.s = z.s by #2
5578 x.n + z.s - x.o
Tim Petersf3615152003-01-01 21:51:37 +00005579
Tim Petersc5dc4da2003-01-02 17:55:03 +00005580Plugging that back into [6] gives
Tim Petersf3615152003-01-01 21:51:37 +00005581
Tim Petersc5dc4da2003-01-02 17:55:03 +00005582 diff =
5583 (x.n - x.o) - ((x.n + z.s - x.o) - z.o) = expanding
5584 x.n - x.o - x.n - z.s + x.o + z.o = cancelling
5585 - z.s + z.o = by #2
5586 z.d
Tim Petersf3615152003-01-01 21:51:37 +00005587
Tim Petersc5dc4da2003-01-02 17:55:03 +00005588So diff = z.d.
Tim Petersf3615152003-01-01 21:51:37 +00005589
Tim Petersc5dc4da2003-01-02 17:55:03 +00005590If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
5591spelling we wanted in the endcase described above. We're done.
Tim Petersf3615152003-01-01 21:51:37 +00005592
Tim Petersc5dc4da2003-01-02 17:55:03 +00005593If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
5594add to z (in effect, z is in tz's standard time, and we need to shift the
5595offset into tz's daylight time).
Tim Petersf3615152003-01-01 21:51:37 +00005596
Tim Petersc5dc4da2003-01-02 17:55:03 +00005597Let
Tim Petersf3615152003-01-01 21:51:37 +00005598
Tim Peters4fede1a2003-01-04 00:26:59 +00005599 z' = z + z.d = z + diff [7]
Tim Petersc3bb26a2003-01-02 03:14:59 +00005600
Tim Peters4fede1a2003-01-04 00:26:59 +00005601and we can again ask whether
Tim Petersc3bb26a2003-01-02 03:14:59 +00005602
Tim Peters4fede1a2003-01-04 00:26:59 +00005603 z'.n - z'.o = x.n - x.o [8]
Tim Petersc3bb26a2003-01-02 03:14:59 +00005604
5605If so, we're done. If not, the tzinfo class is insane, or we're trying to
Tim Peters4fede1a2003-01-04 00:26:59 +00005606convert to the hour that can't be spelled in tz. This also requires a
5607bit of proof. As before, let's compute the difference between the LHS and
5608RHS of [8] (and skipping some of the justifications for the kinds of
5609substitutions we've done several times already):
5610
5611 diff' = (x.n - x.o) - (z'.n - z'.o) = replacing z'.n via [7]
5612 (x.n - x.o) - (z.n + diff - z'.o) = replacing diff via [6]
5613 (x.n - x.o) - (z.n + (x.n - x.o) - (z.n - z.o) - z'.o) =
5614 x.n - x.o - z.n - x.n + x.o + z.n - z.o + z'.o = cancel x.n
5615 - x.o - z.n + x.o + z.n - z.o + z'.o = cancel x.o
5616 - z.n + z.n - z.o + z'.o = cancel z.n
5617 - z.o + z'.o = #1 twice
5618 -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
5619 z'.d - z.d
5620
5621So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
5622we've found the UTC-equivalent so are done.
5623
5624How could they differ? z' = z + z.d [7], so merely moving z' by a dst()
5625offset, and starting *from* a time already in DST (we know z.d != 0), would
5626have to change the result dst() returns: we start in DST, and moving a
5627little further into it takes us out of DST.
5628
5629There's (only) one sane case where this can happen: at the end of DST,
5630there's an hour in UTC with no spelling in a hybrid tzinfo class. In US
5631Eastern, that's 6:MM UTC = 1:MM EST = 2:MM EDT. During that hour, on an
5632Eastern clock 1:MM is taken as being in daylight time (5:MM UTC), but 2:MM is
5633taken as being in standard time (7:MM UTC). There is no local time mapping to
56346:MM UTC. The local clock jumps from 1:59 back to 1:00 again, and repeats the
56351:MM hour in standard time. Since that's what the local clock *does*, we want
5636to map both UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
5637in local time, but so it goes -- it's the way the local clock works.
5638
5639When x = 6:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
5640so z=1:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
5641z' = z + z.d = 2:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
5642(correctly) concludes that z' is not UTC-equivalent to x.
5643
5644Because we know z.d said z was in daylight time (else [5] would have held and
5645we would have stopped then), and we know z.d != z'.d (else [8] would have held
5646and we we have stopped then), and there are only 2 possible values dst() can
5647return in Eastern, it follows that z'.d must be 0 (which it is in the example,
5648but the reasoning doesn't depend on the example -- it depends on there being
5649two possible dst() outcomes, one zero and the other non-zero). Therefore
5650z' must be in standard time, and is not the spelling we want in this case.
5651z is in daylight time, and is the spelling we want. Note again that z is
5652not UTC-equivalent as far as the hybrid tzinfo class is concerned (because
5653it takes z as being in standard time rather than the daylight time we intend
5654here), but returning it gives the real-life "local clock repeats an hour"
5655behavior when mapping the "unspellable" UTC hour into tz.
Tim Petersf3615152003-01-01 21:51:37 +00005656--------------------------------------------------------------------------- */