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