blob: 96c3e6df4f560ece48245e80eec151a7c61b1440 [file] [log] [blame]
Tim Peters2a799bf2002-12-16 20:18:38 +00001/* C implementation for the date/time type documented at
2 * http://www.zope.org/Members/fdrake/DateTimeWiki/FrontPage
3 */
4
5#include "Python.h"
6#include "modsupport.h"
7#include "structmember.h"
8
9#include <time.h>
10
11#include "datetime.h"
12
13/* We require that C int be at least 32 bits, and use int virtually
14 * everywhere. In just a few cases we use a temp long, where a Python
15 * API returns a C long. In such cases, we have to ensure that the
16 * final result fits in a C int (this can be an issue on 64-bit boxes).
17 */
18#if SIZEOF_INT < 4
19# error "datetime.c requires that C int have at least 32 bits"
20#endif
21
22#define MINYEAR 1
23#define MAXYEAR 9999
24
25/* Nine decimal digits is easy to communicate, and leaves enough room
26 * so that two delta days can be added w/o fear of overflowing a signed
27 * 32-bit int, and with plenty of room left over to absorb any possible
28 * carries from adding seconds.
29 */
30#define MAX_DELTA_DAYS 999999999
31
32/* Rename the long macros in datetime.h to more reasonable short names. */
33#define GET_YEAR PyDateTime_GET_YEAR
34#define GET_MONTH PyDateTime_GET_MONTH
35#define GET_DAY PyDateTime_GET_DAY
36#define DATE_GET_HOUR PyDateTime_DATE_GET_HOUR
37#define DATE_GET_MINUTE PyDateTime_DATE_GET_MINUTE
38#define DATE_GET_SECOND PyDateTime_DATE_GET_SECOND
39#define DATE_GET_MICROSECOND PyDateTime_DATE_GET_MICROSECOND
40
41/* Date accessors for date and datetime. */
42#define SET_YEAR(o, v) (((o)->data[0] = ((v) & 0xff00) >> 8), \
43 ((o)->data[1] = ((v) & 0x00ff)))
44#define SET_MONTH(o, v) (PyDateTime_GET_MONTH(o) = (v))
45#define SET_DAY(o, v) (PyDateTime_GET_DAY(o) = (v))
46
47/* Date/Time accessors for datetime. */
48#define DATE_SET_HOUR(o, v) (PyDateTime_DATE_GET_HOUR(o) = (v))
49#define DATE_SET_MINUTE(o, v) (PyDateTime_DATE_GET_MINUTE(o) = (v))
50#define DATE_SET_SECOND(o, v) (PyDateTime_DATE_GET_SECOND(o) = (v))
51#define DATE_SET_MICROSECOND(o, v) \
52 (((o)->data[7] = ((v) & 0xff0000) >> 16), \
53 ((o)->data[8] = ((v) & 0x00ff00) >> 8), \
54 ((o)->data[9] = ((v) & 0x0000ff)))
55
56/* Time accessors for time. */
57#define TIME_GET_HOUR PyDateTime_TIME_GET_HOUR
58#define TIME_GET_MINUTE PyDateTime_TIME_GET_MINUTE
59#define TIME_GET_SECOND PyDateTime_TIME_GET_SECOND
60#define TIME_GET_MICROSECOND PyDateTime_TIME_GET_MICROSECOND
61#define TIME_SET_HOUR(o, v) (PyDateTime_TIME_GET_HOUR(o) = (v))
62#define TIME_SET_MINUTE(o, v) (PyDateTime_TIME_GET_MINUTE(o) = (v))
63#define TIME_SET_SECOND(o, v) (PyDateTime_TIME_GET_SECOND(o) = (v))
64#define TIME_SET_MICROSECOND(o, v) \
65 (((o)->data[3] = ((v) & 0xff0000) >> 16), \
66 ((o)->data[4] = ((v) & 0x00ff00) >> 8), \
67 ((o)->data[5] = ((v) & 0x0000ff)))
68
69/* Delta accessors for timedelta. */
70#define GET_TD_DAYS(o) (((PyDateTime_Delta *)(o))->days)
71#define GET_TD_SECONDS(o) (((PyDateTime_Delta *)(o))->seconds)
72#define GET_TD_MICROSECONDS(o) (((PyDateTime_Delta *)(o))->microseconds)
73
74#define SET_TD_DAYS(o, v) ((o)->days = (v))
75#define SET_TD_SECONDS(o, v) ((o)->seconds = (v))
76#define SET_TD_MICROSECONDS(o, v) ((o)->microseconds = (v))
77
78/* Forward declarations. */
79static PyTypeObject PyDateTime_DateType;
80static PyTypeObject PyDateTime_DateTimeType;
81static PyTypeObject PyDateTime_DateTimeTZType;
82static PyTypeObject PyDateTime_DeltaType;
83static PyTypeObject PyDateTime_TimeType;
84static PyTypeObject PyDateTime_TZInfoType;
85static PyTypeObject PyDateTime_TimeTZType;
86
87/* ---------------------------------------------------------------------------
88 * Math utilities.
89 */
90
91/* k = i+j overflows iff k differs in sign from both inputs,
92 * iff k^i has sign bit set and k^j has sign bit set,
93 * iff (k^i)&(k^j) has sign bit set.
94 */
95#define SIGNED_ADD_OVERFLOWED(RESULT, I, J) \
96 ((((RESULT) ^ (I)) & ((RESULT) ^ (J))) < 0)
97
98/* Compute Python divmod(x, y), returning the quotient and storing the
99 * remainder into *r. The quotient is the floor of x/y, and that's
100 * the real point of this. C will probably truncate instead (C99
101 * requires truncation; C89 left it implementation-defined).
102 * Simplification: we *require* that y > 0 here. That's appropriate
103 * for all the uses made of it. This simplifies the code and makes
104 * the overflow case impossible (divmod(LONG_MIN, -1) is the only
105 * overflow case).
106 */
107static int
108divmod(int x, int y, int *r)
109{
110 int quo;
111
112 assert(y > 0);
113 quo = x / y;
114 *r = x - quo * y;
115 if (*r < 0) {
116 --quo;
117 *r += y;
118 }
119 assert(0 <= *r && *r < y);
120 return quo;
121}
122
Tim Peters5d644dd2003-01-02 16:32:54 +0000123/* Round a double to the nearest long. |x| must be small enough to fit
124 * in a C long; this is not checked.
125 */
126static long
127round_to_long(double x)
128{
129 if (x >= 0.0)
130 x = floor(x + 0.5);
131 else
132 x = ceil(x - 0.5);
133 return (long)x;
134}
135
Tim Peters2a799bf2002-12-16 20:18:38 +0000136/* ---------------------------------------------------------------------------
137 * General calendrical helper functions
138 */
139
140/* For each month ordinal in 1..12, the number of days in that month,
141 * and the number of days before that month in the same year. These
142 * are correct for non-leap years only.
143 */
144static int _days_in_month[] = {
145 0, /* unused; this vector uses 1-based indexing */
146 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
147};
148
149static int _days_before_month[] = {
150 0, /* unused; this vector uses 1-based indexing */
151 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
152};
153
154/* year -> 1 if leap year, else 0. */
155static int
156is_leap(int year)
157{
158 /* Cast year to unsigned. The result is the same either way, but
159 * C can generate faster code for unsigned mod than for signed
160 * mod (especially for % 4 -- a good compiler should just grab
161 * the last 2 bits when the LHS is unsigned).
162 */
163 const unsigned int ayear = (unsigned int)year;
164 return ayear % 4 == 0 && (ayear % 100 != 0 || ayear % 400 == 0);
165}
166
167/* year, month -> number of days in that month in that year */
168static int
169days_in_month(int year, int month)
170{
171 assert(month >= 1);
172 assert(month <= 12);
173 if (month == 2 && is_leap(year))
174 return 29;
175 else
176 return _days_in_month[month];
177}
178
179/* year, month -> number of days in year preceeding first day of month */
180static int
181days_before_month(int year, int month)
182{
183 int days;
184
185 assert(month >= 1);
186 assert(month <= 12);
187 days = _days_before_month[month];
188 if (month > 2 && is_leap(year))
189 ++days;
190 return days;
191}
192
193/* year -> number of days before January 1st of year. Remember that we
194 * start with year 1, so days_before_year(1) == 0.
195 */
196static int
197days_before_year(int year)
198{
199 int y = year - 1;
200 /* This is incorrect if year <= 0; we really want the floor
201 * here. But so long as MINYEAR is 1, the smallest year this
202 * can see is 0 (this can happen in some normalization endcases),
203 * so we'll just special-case that.
204 */
205 assert (year >= 0);
206 if (y >= 0)
207 return y*365 + y/4 - y/100 + y/400;
208 else {
209 assert(y == -1);
210 return -366;
211 }
212}
213
214/* Number of days in 4, 100, and 400 year cycles. That these have
215 * the correct values is asserted in the module init function.
216 */
217#define DI4Y 1461 /* days_before_year(5); days in 4 years */
218#define DI100Y 36524 /* days_before_year(101); days in 100 years */
219#define DI400Y 146097 /* days_before_year(401); days in 400 years */
220
221/* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */
222static void
223ord_to_ymd(int ordinal, int *year, int *month, int *day)
224{
225 int n, n1, n4, n100, n400, leapyear, preceding;
226
227 /* ordinal is a 1-based index, starting at 1-Jan-1. The pattern of
228 * leap years repeats exactly every 400 years. The basic strategy is
229 * to find the closest 400-year boundary at or before ordinal, then
230 * work with the offset from that boundary to ordinal. Life is much
231 * clearer if we subtract 1 from ordinal first -- then the values
232 * of ordinal at 400-year boundaries are exactly those divisible
233 * by DI400Y:
234 *
235 * D M Y n n-1
236 * -- --- ---- ---------- ----------------
237 * 31 Dec -400 -DI400Y -DI400Y -1
238 * 1 Jan -399 -DI400Y +1 -DI400Y 400-year boundary
239 * ...
240 * 30 Dec 000 -1 -2
241 * 31 Dec 000 0 -1
242 * 1 Jan 001 1 0 400-year boundary
243 * 2 Jan 001 2 1
244 * 3 Jan 001 3 2
245 * ...
246 * 31 Dec 400 DI400Y DI400Y -1
247 * 1 Jan 401 DI400Y +1 DI400Y 400-year boundary
248 */
249 assert(ordinal >= 1);
250 --ordinal;
251 n400 = ordinal / DI400Y;
252 n = ordinal % DI400Y;
253 *year = n400 * 400 + 1;
254
255 /* Now n is the (non-negative) offset, in days, from January 1 of
256 * year, to the desired date. Now compute how many 100-year cycles
257 * precede n.
258 * Note that it's possible for n100 to equal 4! In that case 4 full
259 * 100-year cycles precede the desired day, which implies the
260 * desired day is December 31 at the end of a 400-year cycle.
261 */
262 n100 = n / DI100Y;
263 n = n % DI100Y;
264
265 /* Now compute how many 4-year cycles precede it. */
266 n4 = n / DI4Y;
267 n = n % DI4Y;
268
269 /* And now how many single years. Again n1 can be 4, and again
270 * meaning that the desired day is December 31 at the end of the
271 * 4-year cycle.
272 */
273 n1 = n / 365;
274 n = n % 365;
275
276 *year += n100 * 100 + n4 * 4 + n1;
277 if (n1 == 4 || n100 == 4) {
278 assert(n == 0);
279 *year -= 1;
280 *month = 12;
281 *day = 31;
282 return;
283 }
284
285 /* Now the year is correct, and n is the offset from January 1. We
286 * find the month via an estimate that's either exact or one too
287 * large.
288 */
289 leapyear = n1 == 3 && (n4 != 24 || n100 == 3);
290 assert(leapyear == is_leap(*year));
291 *month = (n + 50) >> 5;
292 preceding = (_days_before_month[*month] + (*month > 2 && leapyear));
293 if (preceding > n) {
294 /* estimate is too large */
295 *month -= 1;
296 preceding -= days_in_month(*year, *month);
297 }
298 n -= preceding;
299 assert(0 <= n);
300 assert(n < days_in_month(*year, *month));
301
302 *day = n + 1;
303}
304
305/* year, month, day -> ordinal, considering 01-Jan-0001 as day 1. */
306static int
307ymd_to_ord(int year, int month, int day)
308{
309 return days_before_year(year) + days_before_month(year, month) + day;
310}
311
312/* Day of week, where Monday==0, ..., Sunday==6. 1/1/1 was a Monday. */
313static int
314weekday(int year, int month, int day)
315{
316 return (ymd_to_ord(year, month, day) + 6) % 7;
317}
318
319/* Ordinal of the Monday starting week 1 of the ISO year. Week 1 is the
320 * first calendar week containing a Thursday.
321 */
322static int
323iso_week1_monday(int year)
324{
325 int first_day = ymd_to_ord(year, 1, 1); /* ord of 1/1 */
326 /* 0 if 1/1 is a Monday, 1 if a Tue, etc. */
327 int first_weekday = (first_day + 6) % 7;
328 /* ordinal of closest Monday at or before 1/1 */
329 int week1_monday = first_day - first_weekday;
330
331 if (first_weekday > 3) /* if 1/1 was Fri, Sat, Sun */
332 week1_monday += 7;
333 return week1_monday;
334}
335
336/* ---------------------------------------------------------------------------
337 * Range checkers.
338 */
339
340/* Check that -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS. If so, return 0.
341 * If not, raise OverflowError and return -1.
342 */
343static int
344check_delta_day_range(int days)
345{
346 if (-MAX_DELTA_DAYS <= days && days <= MAX_DELTA_DAYS)
347 return 0;
348 PyErr_Format(PyExc_OverflowError,
349 "days=%d; must have magnitude <= %d",
Guido van Rossumbd43e912002-12-16 20:34:55 +0000350 days, MAX_DELTA_DAYS);
Tim Peters2a799bf2002-12-16 20:18:38 +0000351 return -1;
352}
353
354/* Check that date arguments are in range. Return 0 if they are. If they
355 * aren't, raise ValueError and return -1.
356 */
357static int
358check_date_args(int year, int month, int day)
359{
360
361 if (year < MINYEAR || year > MAXYEAR) {
362 PyErr_SetString(PyExc_ValueError,
363 "year is out of range");
364 return -1;
365 }
366 if (month < 1 || month > 12) {
367 PyErr_SetString(PyExc_ValueError,
368 "month must be in 1..12");
369 return -1;
370 }
371 if (day < 1 || day > days_in_month(year, month)) {
372 PyErr_SetString(PyExc_ValueError,
373 "day is out of range for month");
374 return -1;
375 }
376 return 0;
377}
378
379/* Check that time arguments are in range. Return 0 if they are. If they
380 * aren't, raise ValueError and return -1.
381 */
382static int
383check_time_args(int h, int m, int s, int us)
384{
385 if (h < 0 || h > 23) {
386 PyErr_SetString(PyExc_ValueError,
387 "hour must be in 0..23");
388 return -1;
389 }
390 if (m < 0 || m > 59) {
391 PyErr_SetString(PyExc_ValueError,
392 "minute must be in 0..59");
393 return -1;
394 }
395 if (s < 0 || s > 59) {
396 PyErr_SetString(PyExc_ValueError,
397 "second must be in 0..59");
398 return -1;
399 }
400 if (us < 0 || us > 999999) {
401 PyErr_SetString(PyExc_ValueError,
402 "microsecond must be in 0..999999");
403 return -1;
404 }
405 return 0;
406}
407
408/* ---------------------------------------------------------------------------
409 * Normalization utilities.
410 */
411
412/* One step of a mixed-radix conversion. A "hi" unit is equivalent to
413 * factor "lo" units. factor must be > 0. If *lo is less than 0, or
414 * at least factor, enough of *lo is converted into "hi" units so that
415 * 0 <= *lo < factor. The input values must be such that int overflow
416 * is impossible.
417 */
418static void
419normalize_pair(int *hi, int *lo, int factor)
420{
421 assert(factor > 0);
422 assert(lo != hi);
423 if (*lo < 0 || *lo >= factor) {
424 const int num_hi = divmod(*lo, factor, lo);
425 const int new_hi = *hi + num_hi;
426 assert(! SIGNED_ADD_OVERFLOWED(new_hi, *hi, num_hi));
427 *hi = new_hi;
428 }
429 assert(0 <= *lo && *lo < factor);
430}
431
432/* Fiddle days (d), seconds (s), and microseconds (us) so that
433 * 0 <= *s < 24*3600
434 * 0 <= *us < 1000000
435 * The input values must be such that the internals don't overflow.
436 * The way this routine is used, we don't get close.
437 */
438static void
439normalize_d_s_us(int *d, int *s, int *us)
440{
441 if (*us < 0 || *us >= 1000000) {
442 normalize_pair(s, us, 1000000);
443 /* |s| can't be bigger than about
444 * |original s| + |original us|/1000000 now.
445 */
446
447 }
448 if (*s < 0 || *s >= 24*3600) {
449 normalize_pair(d, s, 24*3600);
450 /* |d| can't be bigger than about
451 * |original d| +
452 * (|original s| + |original us|/1000000) / (24*3600) now.
453 */
454 }
455 assert(0 <= *s && *s < 24*3600);
456 assert(0 <= *us && *us < 1000000);
457}
458
459/* Fiddle years (y), months (m), and days (d) so that
460 * 1 <= *m <= 12
461 * 1 <= *d <= days_in_month(*y, *m)
462 * The input values must be such that the internals don't overflow.
463 * The way this routine is used, we don't get close.
464 */
465static void
466normalize_y_m_d(int *y, int *m, int *d)
467{
468 int dim; /* # of days in month */
469
470 /* This gets muddy: the proper range for day can't be determined
471 * without knowing the correct month and year, but if day is, e.g.,
472 * plus or minus a million, the current month and year values make
473 * no sense (and may also be out of bounds themselves).
474 * Saying 12 months == 1 year should be non-controversial.
475 */
476 if (*m < 1 || *m > 12) {
477 --*m;
478 normalize_pair(y, m, 12);
479 ++*m;
480 /* |y| can't be bigger than about
481 * |original y| + |original m|/12 now.
482 */
483 }
484 assert(1 <= *m && *m <= 12);
485
486 /* Now only day can be out of bounds (year may also be out of bounds
487 * for a datetime object, but we don't care about that here).
488 * If day is out of bounds, what to do is arguable, but at least the
489 * method here is principled and explainable.
490 */
491 dim = days_in_month(*y, *m);
492 if (*d < 1 || *d > dim) {
493 /* Move day-1 days from the first of the month. First try to
494 * get off cheap if we're only one day out of range
495 * (adjustments for timezone alone can't be worse than that).
496 */
497 if (*d == 0) {
498 --*m;
499 if (*m > 0)
500 *d = days_in_month(*y, *m);
501 else {
502 --*y;
503 *m = 12;
504 *d = 31;
505 }
506 }
507 else if (*d == dim + 1) {
508 /* move forward a day */
509 ++*m;
510 *d = 1;
511 if (*m > 12) {
512 *m = 1;
513 ++*y;
514 }
515 }
516 else {
517 int ordinal = ymd_to_ord(*y, *m, 1) +
518 *d - 1;
519 ord_to_ymd(ordinal, y, m, d);
520 }
521 }
522 assert(*m > 0);
523 assert(*d > 0);
524}
525
526/* Fiddle out-of-bounds months and days so that the result makes some kind
527 * of sense. The parameters are both inputs and outputs. Returns < 0 on
528 * failure, where failure means the adjusted year is out of bounds.
529 */
530static int
531normalize_date(int *year, int *month, int *day)
532{
533 int result;
534
535 normalize_y_m_d(year, month, day);
536 if (MINYEAR <= *year && *year <= MAXYEAR)
537 result = 0;
538 else {
539 PyErr_SetString(PyExc_OverflowError,
540 "date value out of range");
541 result = -1;
542 }
543 return result;
544}
545
546/* Force all the datetime fields into range. The parameters are both
547 * inputs and outputs. Returns < 0 on error.
548 */
549static int
550normalize_datetime(int *year, int *month, int *day,
551 int *hour, int *minute, int *second,
552 int *microsecond)
553{
554 normalize_pair(second, microsecond, 1000000);
555 normalize_pair(minute, second, 60);
556 normalize_pair(hour, minute, 60);
557 normalize_pair(day, hour, 24);
558 return normalize_date(year, month, day);
559}
560
561/* ---------------------------------------------------------------------------
562 * tzinfo helpers.
563 */
564
Tim Peters855fe882002-12-22 03:43:39 +0000565/* Ensure that p is None or of a tzinfo subclass. Return 0 if OK; if not
566 * raise TypeError and return -1.
567 */
568static int
569check_tzinfo_subclass(PyObject *p)
570{
571 if (p == Py_None || PyTZInfo_Check(p))
572 return 0;
573 PyErr_Format(PyExc_TypeError,
574 "tzinfo argument must be None or of a tzinfo subclass, "
575 "not type '%s'",
576 p->ob_type->tp_name);
577 return -1;
578}
579
Tim Petersbad8ff02002-12-30 20:52:32 +0000580/* Return tzinfo.methname(tzinfoarg), without any checking of results.
Tim Peters855fe882002-12-22 03:43:39 +0000581 * If tzinfo is None, returns None.
582 */
583static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000584call_tzinfo_method(PyObject *tzinfo, char *methname, PyObject *tzinfoarg)
Tim Peters855fe882002-12-22 03:43:39 +0000585{
586 PyObject *result;
587
Tim Petersbad8ff02002-12-30 20:52:32 +0000588 assert(tzinfo && methname && tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000589 assert(check_tzinfo_subclass(tzinfo) >= 0);
590 if (tzinfo == Py_None) {
591 result = Py_None;
592 Py_INCREF(result);
593 }
594 else
Tim Petersbad8ff02002-12-30 20:52:32 +0000595 result = PyObject_CallMethod(tzinfo, methname, "O", tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000596 return result;
597}
598
Tim Peters2a799bf2002-12-16 20:18:38 +0000599/* If self has a tzinfo member, return a BORROWED reference to it. Else
600 * return NULL, which is NOT AN ERROR. There are no error returns here,
601 * and the caller must not decref the result.
602 */
603static PyObject *
604get_tzinfo_member(PyObject *self)
605{
606 PyObject *tzinfo = NULL;
607
608 if (PyDateTimeTZ_Check(self))
609 tzinfo = ((PyDateTime_DateTimeTZ *)self)->tzinfo;
610 else if (PyTimeTZ_Check(self))
611 tzinfo = ((PyDateTime_TimeTZ *)self)->tzinfo;
612
613 return tzinfo;
614}
615
Tim Peters80475bb2002-12-25 07:40:55 +0000616/* self is a datetimetz. Replace its tzinfo member. */
617void
618replace_tzinfo(PyObject *self, PyObject *newtzinfo)
619{
620 assert(self != NULL);
621 assert(PyDateTimeTZ_Check(self));
622 assert(check_tzinfo_subclass(newtzinfo) >= 0);
623 Py_INCREF(newtzinfo);
624 Py_DECREF(((PyDateTime_DateTimeTZ *)self)->tzinfo);
625 ((PyDateTime_DateTimeTZ *)self)->tzinfo = newtzinfo;
626}
627
Tim Petersbad8ff02002-12-30 20:52:32 +0000628
629/* Call getattr(tzinfo, name)(tzinfoarg), and extract an int from the
Tim Peters2a799bf2002-12-16 20:18:38 +0000630 * result. tzinfo must be an instance of the tzinfo class. If the method
631 * returns None, this returns 0 and sets *none to 1. If the method doesn't
Tim Peters855fe882002-12-22 03:43:39 +0000632 * return a Python int or long or timedelta, TypeError is raised and this
633 * returns -1. If it returns an int or long, but is outside the valid
634 * range for a UTC minute offset, or it returns a timedelta and the value is
635 * out of range or isn't a whole number of minutes, ValueError is raised and
636 * this returns -1.
Tim Peters2a799bf2002-12-16 20:18:38 +0000637 * Else *none is set to 0 and the integer method result is returned.
638 */
639static int
640call_utc_tzinfo_method(PyObject *tzinfo, char *name, PyObject *tzinfoarg,
641 int *none)
642{
643 PyObject *u;
644 long result = -1; /* Py{Int,Long}_AsLong return long */
645
646 assert(tzinfo != NULL);
647 assert(PyTZInfo_Check(tzinfo));
648 assert(tzinfoarg != NULL);
649
650 *none = 0;
Tim Petersbad8ff02002-12-30 20:52:32 +0000651 u = call_tzinfo_method(tzinfo, name, tzinfoarg);
Tim Peters2a799bf2002-12-16 20:18:38 +0000652 if (u == NULL)
653 return -1;
654
Tim Peters27362852002-12-23 16:17:39 +0000655 else if (u == Py_None) {
Tim Peters2a799bf2002-12-16 20:18:38 +0000656 result = 0;
657 *none = 1;
Tim Peters2a799bf2002-12-16 20:18:38 +0000658 }
Tim Peters27362852002-12-23 16:17:39 +0000659 else if (PyInt_Check(u))
Tim Peters2a799bf2002-12-16 20:18:38 +0000660 result = PyInt_AS_LONG(u);
Tim Peters855fe882002-12-22 03:43:39 +0000661
Tim Peters2a799bf2002-12-16 20:18:38 +0000662 else if (PyLong_Check(u))
663 result = PyLong_AsLong(u);
Tim Peters855fe882002-12-22 03:43:39 +0000664
665 else if (PyDelta_Check(u)) {
666 const int days = GET_TD_DAYS(u);
667 if (days < -1 || days > 0)
668 result = 24*60; /* trigger ValueError below */
669 else {
670 /* next line can't overflow because we know days
671 * is -1 or 0 now
672 */
673 int ss = days * 24 * 3600 + GET_TD_SECONDS(u);
674 result = divmod(ss, 60, &ss);
675 if (ss || GET_TD_MICROSECONDS(u)) {
676 PyErr_Format(PyExc_ValueError,
677 "tzinfo.%s() must return a "
678 "whole number of minutes",
679 name);
680 result = -1;
Tim Peters855fe882002-12-22 03:43:39 +0000681 }
682 }
683 }
Tim Peters2a799bf2002-12-16 20:18:38 +0000684 else {
685 PyErr_Format(PyExc_TypeError,
Tim Peters855fe882002-12-22 03:43:39 +0000686 "tzinfo.%s() must return None, integer or "
687 "timedelta, not '%s'",
688 name, u->ob_type->tp_name);
Tim Peters2a799bf2002-12-16 20:18:38 +0000689 }
690
Tim Peters2a799bf2002-12-16 20:18:38 +0000691 Py_DECREF(u);
692 if (result < -1439 || result > 1439) {
693 PyErr_Format(PyExc_ValueError,
694 "tzinfo.%s() returned %ld; must be in "
695 "-1439 .. 1439",
696 name, result);
697 result = -1;
698 }
699 return (int)result;
700}
701
702/* Call tzinfo.utcoffset(tzinfoarg), and extract an integer from the
703 * result. tzinfo must be an instance of the tzinfo class. If utcoffset()
704 * returns None, call_utcoffset returns 0 and sets *none to 1. If uctoffset()
705 & doesn't return a Python int or long, TypeError is raised and this
706 * returns -1. If utcoffset() returns an int outside the legitimate range
707 * for a UTC offset, ValueError is raised and this returns -1. Else
708 * *none is set to 0 and the offset is returned.
709 */
710static int
711call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
712{
713 return call_utc_tzinfo_method(tzinfo, "utcoffset", tzinfoarg, none);
714}
715
Tim Peters855fe882002-12-22 03:43:39 +0000716static PyObject *new_delta(int d, int sec, int usec, int normalize);
717
Tim Petersbad8ff02002-12-30 20:52:32 +0000718/* Call tzinfo.name(tzinfoarg), and return the offset as a timedelta or None.
719 */
Tim Peters855fe882002-12-22 03:43:39 +0000720static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000721offset_as_timedelta(PyObject *tzinfo, char *name, PyObject *tzinfoarg) {
Tim Peters855fe882002-12-22 03:43:39 +0000722 PyObject *result;
723
Tim Petersbad8ff02002-12-30 20:52:32 +0000724 assert(tzinfo && name && tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000725 if (tzinfo == Py_None) {
726 result = Py_None;
727 Py_INCREF(result);
728 }
729 else {
730 int none;
Tim Petersbad8ff02002-12-30 20:52:32 +0000731 int offset = call_utc_tzinfo_method(tzinfo, name, tzinfoarg,
732 &none);
Tim Peters855fe882002-12-22 03:43:39 +0000733 if (offset < 0 && PyErr_Occurred())
734 return NULL;
735 if (none) {
736 result = Py_None;
737 Py_INCREF(result);
738 }
739 else
740 result = new_delta(0, offset * 60, 0, 1);
741 }
742 return result;
743}
744
Tim Peters2a799bf2002-12-16 20:18:38 +0000745/* Call tzinfo.dst(tzinfoarg), and extract an integer from the
746 * result. tzinfo must be an instance of the tzinfo class. If dst()
747 * returns None, call_dst returns 0 and sets *none to 1. If dst()
748 & doesn't return a Python int or long, TypeError is raised and this
749 * returns -1. If dst() returns an int outside the legitimate range
750 * for a UTC offset, ValueError is raised and this returns -1. Else
751 * *none is set to 0 and the offset is returned.
752 */
753static int
754call_dst(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
755{
756 return call_utc_tzinfo_method(tzinfo, "dst", tzinfoarg, none);
757}
758
Tim Petersbad8ff02002-12-30 20:52:32 +0000759/* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be
Tim Peters855fe882002-12-22 03:43:39 +0000760 * an instance of the tzinfo class or None. If tzinfo isn't None, and
Tim Petersbad8ff02002-12-30 20:52:32 +0000761 * tzname() doesn't return None or a string, TypeError is raised and this
Tim Peters855fe882002-12-22 03:43:39 +0000762 * returns NULL.
Tim Peters2a799bf2002-12-16 20:18:38 +0000763 */
764static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000765call_tzname(PyObject *tzinfo, PyObject *tzinfoarg)
Tim Peters2a799bf2002-12-16 20:18:38 +0000766{
767 PyObject *result;
768
769 assert(tzinfo != NULL);
Tim Peters855fe882002-12-22 03:43:39 +0000770 assert(check_tzinfo_subclass(tzinfo) >= 0);
Tim Petersbad8ff02002-12-30 20:52:32 +0000771 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +0000772
Tim Peters855fe882002-12-22 03:43:39 +0000773 if (tzinfo == Py_None) {
774 result = Py_None;
775 Py_INCREF(result);
776 }
777 else
Tim Petersbad8ff02002-12-30 20:52:32 +0000778 result = PyObject_CallMethod(tzinfo, "tzname", "O", tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000779
780 if (result != NULL && result != Py_None && ! PyString_Check(result)) {
781 PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must "
Tim Peters2a799bf2002-12-16 20:18:38 +0000782 "return None or a string, not '%s'",
783 result->ob_type->tp_name);
784 Py_DECREF(result);
785 result = NULL;
786 }
787 return result;
788}
789
790typedef enum {
791 /* an exception has been set; the caller should pass it on */
792 OFFSET_ERROR,
793
794 /* type isn't date, datetime, datetimetz subclass, time, or
795 * timetz subclass
796 */
797 OFFSET_UNKNOWN,
798
799 /* date,
800 * datetime,
801 * datetimetz with None tzinfo,
Tim Peters855fe882002-12-22 03:43:39 +0000802 * datetimetz where utcoffset() returns None
Tim Peters2a799bf2002-12-16 20:18:38 +0000803 * time,
804 * timetz with None tzinfo,
805 * timetz where utcoffset() returns None
806 */
807 OFFSET_NAIVE,
808
809 /* timetz where utcoffset() doesn't return None,
810 * datetimetz where utcoffset() doesn't return None
811 */
812 OFFSET_AWARE,
813} naivety;
814
Tim Peters14b69412002-12-22 18:10:22 +0000815/* Classify an object as to whether it's naive or offset-aware. See
Tim Peters2a799bf2002-12-16 20:18:38 +0000816 * the "naivety" typedef for details. If the type is aware, *offset is set
817 * to minutes east of UTC (as returned by the tzinfo.utcoffset() method).
Tim Peters14b69412002-12-22 18:10:22 +0000818 * If the type is offset-naive (or unknown, or error), *offset is set to 0.
Tim Peterse39a80c2002-12-30 21:28:52 +0000819 * tzinfoarg is the argument to pass to the tzinfo.utcoffset() method.
Tim Peters2a799bf2002-12-16 20:18:38 +0000820 */
821static naivety
Tim Peterse39a80c2002-12-30 21:28:52 +0000822classify_utcoffset(PyObject *op, PyObject *tzinfoarg, int *offset)
Tim Peters2a799bf2002-12-16 20:18:38 +0000823{
824 int none;
825 PyObject *tzinfo;
826
Tim Peterse39a80c2002-12-30 21:28:52 +0000827 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +0000828 *offset = 0;
Tim Peters14b69412002-12-22 18:10:22 +0000829 tzinfo = get_tzinfo_member(op); /* NULL means no tzinfo, not error */
Tim Peters2a799bf2002-12-16 20:18:38 +0000830 if (tzinfo == Py_None)
831 return OFFSET_NAIVE;
Tim Peters14b69412002-12-22 18:10:22 +0000832 if (tzinfo == NULL) {
833 /* note that a datetime passes the PyDate_Check test */
834 return (PyTime_Check(op) || PyDate_Check(op)) ?
835 OFFSET_NAIVE : OFFSET_UNKNOWN;
836 }
Tim Peterse39a80c2002-12-30 21:28:52 +0000837 *offset = call_utcoffset(tzinfo, tzinfoarg, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +0000838 if (*offset == -1 && PyErr_Occurred())
839 return OFFSET_ERROR;
840 return none ? OFFSET_NAIVE : OFFSET_AWARE;
841}
842
Tim Peters00237032002-12-27 02:21:51 +0000843/* Classify two objects as to whether they're naive or offset-aware.
844 * This isn't quite the same as calling classify_utcoffset() twice: for
845 * binary operations (comparison and subtraction), we generally want to
846 * ignore the tzinfo members if they're identical. This is by design,
847 * so that results match "naive" expectations when mixing objects from a
848 * single timezone. So in that case, this sets both offsets to 0 and
849 * both naiveties to OFFSET_NAIVE.
850 * The function returns 0 if everything's OK, and -1 on error.
851 */
852static int
853classify_two_utcoffsets(PyObject *o1, int *offset1, naivety *n1,
Tim Peterse39a80c2002-12-30 21:28:52 +0000854 PyObject *tzinfoarg1,
855 PyObject *o2, int *offset2, naivety *n2,
856 PyObject *tzinfoarg2)
Tim Peters00237032002-12-27 02:21:51 +0000857{
858 if (get_tzinfo_member(o1) == get_tzinfo_member(o2)) {
859 *offset1 = *offset2 = 0;
860 *n1 = *n2 = OFFSET_NAIVE;
861 }
862 else {
Tim Peterse39a80c2002-12-30 21:28:52 +0000863 *n1 = classify_utcoffset(o1, tzinfoarg1, offset1);
Tim Peters00237032002-12-27 02:21:51 +0000864 if (*n1 == OFFSET_ERROR)
865 return -1;
Tim Peterse39a80c2002-12-30 21:28:52 +0000866 *n2 = classify_utcoffset(o2, tzinfoarg2, offset2);
Tim Peters00237032002-12-27 02:21:51 +0000867 if (*n2 == OFFSET_ERROR)
868 return -1;
869 }
870 return 0;
871}
872
Tim Peters2a799bf2002-12-16 20:18:38 +0000873/* repr is like "someclass(arg1, arg2)". If tzinfo isn't None,
874 * stuff
875 * ", tzinfo=" + repr(tzinfo)
876 * before the closing ")".
877 */
878static PyObject *
879append_keyword_tzinfo(PyObject *repr, PyObject *tzinfo)
880{
881 PyObject *temp;
882
883 assert(PyString_Check(repr));
884 assert(tzinfo);
885 if (tzinfo == Py_None)
886 return repr;
887 /* Get rid of the trailing ')'. */
888 assert(PyString_AsString(repr)[PyString_Size(repr)-1] == ')');
889 temp = PyString_FromStringAndSize(PyString_AsString(repr),
890 PyString_Size(repr) - 1);
891 Py_DECREF(repr);
892 if (temp == NULL)
893 return NULL;
894 repr = temp;
895
896 /* Append ", tzinfo=". */
897 PyString_ConcatAndDel(&repr, PyString_FromString(", tzinfo="));
898
899 /* Append repr(tzinfo). */
900 PyString_ConcatAndDel(&repr, PyObject_Repr(tzinfo));
901
902 /* Add a closing paren. */
903 PyString_ConcatAndDel(&repr, PyString_FromString(")"));
904 return repr;
905}
906
907/* ---------------------------------------------------------------------------
908 * String format helpers.
909 */
910
911static PyObject *
912format_ctime(PyDateTime_Date *date,
913 int hours, int minutes, int seconds)
914{
915 static char *DayNames[] = {
916 "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
917 };
918 static char *MonthNames[] = {
919 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
920 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
921 };
922
923 char buffer[128];
924 int wday = weekday(GET_YEAR(date), GET_MONTH(date), GET_DAY(date));
925
926 PyOS_snprintf(buffer, sizeof(buffer), "%s %s %2d %02d:%02d:%02d %04d",
927 DayNames[wday], MonthNames[GET_MONTH(date) - 1],
928 GET_DAY(date), hours, minutes, seconds,
929 GET_YEAR(date));
930 return PyString_FromString(buffer);
931}
932
933/* Add an hours & minutes UTC offset string to buf. buf has no more than
934 * buflen bytes remaining. The UTC offset is gotten by calling
935 * tzinfo.uctoffset(tzinfoarg). If that returns None, \0 is stored into
936 * *buf, and that's all. Else the returned value is checked for sanity (an
937 * integer in range), and if that's OK it's converted to an hours & minutes
938 * string of the form
939 * sign HH sep MM
940 * Returns 0 if everything is OK. If the return value from utcoffset() is
941 * bogus, an appropriate exception is set and -1 is returned.
942 */
943static int
Tim Peters328fff72002-12-20 01:31:27 +0000944format_utcoffset(char *buf, size_t buflen, const char *sep,
Tim Peters2a799bf2002-12-16 20:18:38 +0000945 PyObject *tzinfo, PyObject *tzinfoarg)
946{
947 int offset;
948 int hours;
949 int minutes;
950 char sign;
951 int none;
952
953 offset = call_utcoffset(tzinfo, tzinfoarg, &none);
954 if (offset == -1 && PyErr_Occurred())
955 return -1;
956 if (none) {
957 *buf = '\0';
958 return 0;
959 }
960 sign = '+';
961 if (offset < 0) {
962 sign = '-';
963 offset = - offset;
964 }
965 hours = divmod(offset, 60, &minutes);
966 PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes);
967 return 0;
968}
969
970/* I sure don't want to reproduce the strftime code from the time module,
971 * so this imports the module and calls it. All the hair is due to
972 * giving special meanings to the %z and %Z format codes via a preprocessing
973 * step on the format string.
Tim Petersbad8ff02002-12-30 20:52:32 +0000974 * tzinfoarg is the argument to pass to the object's tzinfo method, if
975 * needed.
Tim Peters2a799bf2002-12-16 20:18:38 +0000976 */
977static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000978wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
979 PyObject *tzinfoarg)
Tim Peters2a799bf2002-12-16 20:18:38 +0000980{
981 PyObject *result = NULL; /* guilty until proved innocent */
982
983 PyObject *zreplacement = NULL; /* py string, replacement for %z */
984 PyObject *Zreplacement = NULL; /* py string, replacement for %Z */
985
986 char *pin; /* pointer to next char in input format */
987 char ch; /* next char in input format */
988
989 PyObject *newfmt = NULL; /* py string, the output format */
990 char *pnew; /* pointer to available byte in output format */
991 char totalnew; /* number bytes total in output format buffer,
992 exclusive of trailing \0 */
993 char usednew; /* number bytes used so far in output format buffer */
994
995 char *ptoappend; /* pointer to string to append to output buffer */
996 int ntoappend; /* # of bytes to append to output buffer */
997
Tim Peters2a799bf2002-12-16 20:18:38 +0000998 assert(object && format && timetuple);
999 assert(PyString_Check(format));
1000
Tim Petersd6844152002-12-22 20:58:42 +00001001 /* Give up if the year is before 1900.
1002 * Python strftime() plays games with the year, and different
1003 * games depending on whether envar PYTHON2K is set. This makes
1004 * years before 1900 a nightmare, even if the platform strftime
1005 * supports them (and not all do).
1006 * We could get a lot farther here by avoiding Python's strftime
1007 * wrapper and calling the C strftime() directly, but that isn't
1008 * an option in the Python implementation of this module.
1009 */
1010 {
1011 long year;
1012 PyObject *pyyear = PySequence_GetItem(timetuple, 0);
1013 if (pyyear == NULL) return NULL;
1014 assert(PyInt_Check(pyyear));
1015 year = PyInt_AsLong(pyyear);
1016 Py_DECREF(pyyear);
1017 if (year < 1900) {
1018 PyErr_Format(PyExc_ValueError, "year=%ld is before "
1019 "1900; the datetime strftime() "
1020 "methods require year >= 1900",
1021 year);
1022 return NULL;
1023 }
1024 }
1025
Tim Peters2a799bf2002-12-16 20:18:38 +00001026 /* Scan the input format, looking for %z and %Z escapes, building
Tim Peters328fff72002-12-20 01:31:27 +00001027 * a new format. Since computing the replacements for those codes
1028 * is expensive, don't unless they're actually used.
Tim Peters2a799bf2002-12-16 20:18:38 +00001029 */
1030 totalnew = PyString_Size(format); /* realistic if no %z/%Z */
1031 newfmt = PyString_FromStringAndSize(NULL, totalnew);
1032 if (newfmt == NULL) goto Done;
1033 pnew = PyString_AsString(newfmt);
1034 usednew = 0;
1035
1036 pin = PyString_AsString(format);
1037 while ((ch = *pin++) != '\0') {
1038 if (ch != '%') {
Tim Peters328fff72002-12-20 01:31:27 +00001039 ptoappend = pin - 1;
Tim Peters2a799bf2002-12-16 20:18:38 +00001040 ntoappend = 1;
1041 }
1042 else if ((ch = *pin++) == '\0') {
1043 /* There's a lone trailing %; doesn't make sense. */
1044 PyErr_SetString(PyExc_ValueError, "strftime format "
1045 "ends with raw %");
1046 goto Done;
1047 }
1048 /* A % has been seen and ch is the character after it. */
1049 else if (ch == 'z') {
1050 if (zreplacement == NULL) {
1051 /* format utcoffset */
Tim Peters328fff72002-12-20 01:31:27 +00001052 char buf[100];
Tim Peters2a799bf2002-12-16 20:18:38 +00001053 PyObject *tzinfo = get_tzinfo_member(object);
1054 zreplacement = PyString_FromString("");
1055 if (zreplacement == NULL) goto Done;
1056 if (tzinfo != Py_None && tzinfo != NULL) {
Tim Petersbad8ff02002-12-30 20:52:32 +00001057 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +00001058 if (format_utcoffset(buf,
Tim Peters328fff72002-12-20 01:31:27 +00001059 sizeof(buf),
Tim Peters2a799bf2002-12-16 20:18:38 +00001060 "",
1061 tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00001062 tzinfoarg) < 0)
Tim Peters2a799bf2002-12-16 20:18:38 +00001063 goto Done;
1064 Py_DECREF(zreplacement);
1065 zreplacement = PyString_FromString(buf);
1066 if (zreplacement == NULL) goto Done;
1067 }
1068 }
1069 assert(zreplacement != NULL);
1070 ptoappend = PyString_AsString(zreplacement);
1071 ntoappend = PyString_Size(zreplacement);
1072 }
1073 else if (ch == 'Z') {
1074 /* format tzname */
1075 if (Zreplacement == NULL) {
1076 PyObject *tzinfo = get_tzinfo_member(object);
1077 Zreplacement = PyString_FromString("");
1078 if (Zreplacement == NULL) goto Done;
1079 if (tzinfo != Py_None && tzinfo != NULL) {
Tim Petersbad8ff02002-12-30 20:52:32 +00001080 PyObject *temp;
1081 assert(tzinfoarg != NULL);
1082 temp = call_tzname(tzinfo, tzinfoarg);
Tim Peters2a799bf2002-12-16 20:18:38 +00001083 if (temp == NULL) goto Done;
1084 if (temp != Py_None) {
1085 assert(PyString_Check(temp));
1086 /* Since the tzname is getting
1087 * stuffed into the format, we
1088 * have to double any % signs
1089 * so that strftime doesn't
1090 * treat them as format codes.
1091 */
1092 Py_DECREF(Zreplacement);
1093 Zreplacement = PyObject_CallMethod(
1094 temp, "replace",
1095 "ss", "%", "%%");
1096 Py_DECREF(temp);
1097 if (Zreplacement == NULL)
1098 goto Done;
1099 }
1100 else
1101 Py_DECREF(temp);
1102 }
1103 }
1104 assert(Zreplacement != NULL);
1105 ptoappend = PyString_AsString(Zreplacement);
1106 ntoappend = PyString_Size(Zreplacement);
1107 }
1108 else {
Tim Peters328fff72002-12-20 01:31:27 +00001109 /* percent followed by neither z nor Z */
1110 ptoappend = pin - 2;
Tim Peters2a799bf2002-12-16 20:18:38 +00001111 ntoappend = 2;
1112 }
1113
1114 /* Append the ntoappend chars starting at ptoappend to
1115 * the new format.
1116 */
1117 assert(ntoappend >= 0);
1118 if (ntoappend == 0)
1119 continue;
1120 while (usednew + ntoappend > totalnew) {
1121 int bigger = totalnew << 1;
1122 if ((bigger >> 1) != totalnew) { /* overflow */
1123 PyErr_NoMemory();
1124 goto Done;
1125 }
1126 if (_PyString_Resize(&newfmt, bigger) < 0)
1127 goto Done;
1128 totalnew = bigger;
1129 pnew = PyString_AsString(newfmt) + usednew;
1130 }
1131 memcpy(pnew, ptoappend, ntoappend);
1132 pnew += ntoappend;
1133 usednew += ntoappend;
1134 assert(usednew <= totalnew);
1135 } /* end while() */
1136
1137 if (_PyString_Resize(&newfmt, usednew) < 0)
1138 goto Done;
1139 {
1140 PyObject *time = PyImport_ImportModule("time");
1141 if (time == NULL)
1142 goto Done;
1143 result = PyObject_CallMethod(time, "strftime", "OO",
1144 newfmt, timetuple);
1145 Py_DECREF(time);
1146 }
1147 Done:
1148 Py_XDECREF(zreplacement);
1149 Py_XDECREF(Zreplacement);
1150 Py_XDECREF(newfmt);
1151 return result;
1152}
1153
1154static char *
1155isoformat_date(PyDateTime_Date *dt, char buffer[], int bufflen)
1156{
1157 int x;
1158 x = PyOS_snprintf(buffer, bufflen,
1159 "%04d-%02d-%02d",
1160 GET_YEAR(dt), GET_MONTH(dt), GET_DAY(dt));
1161 return buffer + x;
1162}
1163
1164static void
1165isoformat_time(PyDateTime_DateTime *dt, char buffer[], int bufflen)
1166{
1167 int us = DATE_GET_MICROSECOND(dt);
1168
1169 PyOS_snprintf(buffer, bufflen,
1170 "%02d:%02d:%02d", /* 8 characters */
1171 DATE_GET_HOUR(dt),
1172 DATE_GET_MINUTE(dt),
1173 DATE_GET_SECOND(dt));
1174 if (us)
1175 PyOS_snprintf(buffer + 8, bufflen - 8, ".%06d", us);
1176}
1177
1178/* ---------------------------------------------------------------------------
1179 * Wrap functions from the time module. These aren't directly available
1180 * from C. Perhaps they should be.
1181 */
1182
1183/* Call time.time() and return its result (a Python float). */
1184static PyObject *
Guido van Rossumbd43e912002-12-16 20:34:55 +00001185time_time(void)
Tim Peters2a799bf2002-12-16 20:18:38 +00001186{
1187 PyObject *result = NULL;
1188 PyObject *time = PyImport_ImportModule("time");
1189
1190 if (time != NULL) {
1191 result = PyObject_CallMethod(time, "time", "()");
1192 Py_DECREF(time);
1193 }
1194 return result;
1195}
1196
1197/* Build a time.struct_time. The weekday and day number are automatically
1198 * computed from the y,m,d args.
1199 */
1200static PyObject *
1201build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
1202{
1203 PyObject *time;
1204 PyObject *result = NULL;
1205
1206 time = PyImport_ImportModule("time");
1207 if (time != NULL) {
1208 result = PyObject_CallMethod(time, "struct_time",
1209 "((iiiiiiiii))",
1210 y, m, d,
1211 hh, mm, ss,
1212 weekday(y, m, d),
1213 days_before_month(y, m) + d,
1214 dstflag);
1215 Py_DECREF(time);
1216 }
1217 return result;
1218}
1219
1220/* ---------------------------------------------------------------------------
1221 * Miscellaneous helpers.
1222 */
1223
1224/* For obscure reasons, we need to use tp_richcompare instead of tp_compare.
1225 * The comparisons here all most naturally compute a cmp()-like result.
1226 * This little helper turns that into a bool result for rich comparisons.
1227 */
1228static PyObject *
1229diff_to_bool(int diff, int op)
1230{
1231 PyObject *result;
1232 int istrue;
1233
1234 switch (op) {
1235 case Py_EQ: istrue = diff == 0; break;
1236 case Py_NE: istrue = diff != 0; break;
1237 case Py_LE: istrue = diff <= 0; break;
1238 case Py_GE: istrue = diff >= 0; break;
1239 case Py_LT: istrue = diff < 0; break;
1240 case Py_GT: istrue = diff > 0; break;
1241 default:
1242 assert(! "op unknown");
1243 istrue = 0; /* To shut up compiler */
1244 }
1245 result = istrue ? Py_True : Py_False;
1246 Py_INCREF(result);
1247 return result;
1248}
1249
1250/* ---------------------------------------------------------------------------
1251 * Helpers for setting object fields. These work on pointers to the
1252 * appropriate base class.
1253 */
1254
1255/* For date, datetime and datetimetz. */
1256static void
1257set_date_fields(PyDateTime_Date *self, int y, int m, int d)
1258{
1259 self->hashcode = -1;
1260 SET_YEAR(self, y);
1261 SET_MONTH(self, m);
1262 SET_DAY(self, d);
1263}
1264
1265/* For datetime and datetimetz. */
1266static void
1267set_datetime_time_fields(PyDateTime_Date *self, int h, int m, int s, int us)
1268{
1269 DATE_SET_HOUR(self, h);
1270 DATE_SET_MINUTE(self, m);
1271 DATE_SET_SECOND(self, s);
1272 DATE_SET_MICROSECOND(self, us);
1273}
1274
1275/* For time and timetz. */
1276static void
1277set_time_fields(PyDateTime_Time *self, int h, int m, int s, int us)
1278{
1279 self->hashcode = -1;
1280 TIME_SET_HOUR(self, h);
1281 TIME_SET_MINUTE(self, m);
1282 TIME_SET_SECOND(self, s);
1283 TIME_SET_MICROSECOND(self, us);
1284}
1285
1286/* ---------------------------------------------------------------------------
1287 * Create various objects, mostly without range checking.
1288 */
1289
1290/* Create a date instance with no range checking. */
1291static PyObject *
1292new_date(int year, int month, int day)
1293{
1294 PyDateTime_Date *self;
1295
1296 self = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
1297 if (self != NULL)
1298 set_date_fields(self, year, month, day);
1299 return (PyObject *) self;
1300}
1301
1302/* Create a datetime instance with no range checking. */
1303static PyObject *
1304new_datetime(int year, int month, int day, int hour, int minute,
1305 int second, int usecond)
1306{
1307 PyDateTime_DateTime *self;
1308
1309 self = PyObject_New(PyDateTime_DateTime, &PyDateTime_DateTimeType);
1310 if (self != NULL) {
1311 set_date_fields((PyDateTime_Date *)self, year, month, day);
1312 set_datetime_time_fields((PyDateTime_Date *)self,
1313 hour, minute, second, usecond);
1314 }
1315 return (PyObject *) self;
1316}
1317
1318/* Create a datetimetz instance with no range checking. */
1319static PyObject *
1320new_datetimetz(int year, int month, int day, int hour, int minute,
1321 int second, int usecond, PyObject *tzinfo)
1322{
1323 PyDateTime_DateTimeTZ *self;
1324
1325 self = PyObject_New(PyDateTime_DateTimeTZ, &PyDateTime_DateTimeTZType);
1326 if (self != NULL) {
1327 set_date_fields((PyDateTime_Date *)self, year, month, day);
1328 set_datetime_time_fields((PyDateTime_Date *)self,
1329 hour, minute, second, usecond);
1330 Py_INCREF(tzinfo);
1331 self->tzinfo = tzinfo;
1332 }
1333 return (PyObject *) self;
1334}
1335
1336/* Create a time instance with no range checking. */
1337static PyObject *
1338new_time(int hour, int minute, int second, int usecond)
1339{
1340 PyDateTime_Time *self;
1341
1342 self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
1343 if (self != NULL)
1344 set_time_fields(self, hour, minute, second, usecond);
1345 return (PyObject *) self;
1346}
1347
1348/* Create a timetz instance with no range checking. */
1349static PyObject *
1350new_timetz(int hour, int minute, int second, int usecond, PyObject *tzinfo)
1351{
1352 PyDateTime_TimeTZ *self;
1353
1354 self = PyObject_New(PyDateTime_TimeTZ, &PyDateTime_TimeTZType);
1355 if (self != NULL) {
1356 set_time_fields((PyDateTime_Time *)self,
1357 hour, minute, second, usecond);
1358 Py_INCREF(tzinfo);
1359 self->tzinfo = tzinfo;
1360 }
1361 return (PyObject *) self;
1362}
1363
1364/* Create a timedelta instance. Normalize the members iff normalize is
1365 * true. Passing false is a speed optimization, if you know for sure
1366 * that seconds and microseconds are already in their proper ranges. In any
1367 * case, raises OverflowError and returns NULL if the normalized days is out
1368 * of range).
1369 */
1370static PyObject *
1371new_delta(int days, int seconds, int microseconds, int normalize)
1372{
1373 PyDateTime_Delta *self;
1374
1375 if (normalize)
1376 normalize_d_s_us(&days, &seconds, &microseconds);
1377 assert(0 <= seconds && seconds < 24*3600);
1378 assert(0 <= microseconds && microseconds < 1000000);
1379
1380 if (check_delta_day_range(days) < 0)
1381 return NULL;
1382
1383 self = PyObject_New(PyDateTime_Delta, &PyDateTime_DeltaType);
1384 if (self != NULL) {
1385 self->hashcode = -1;
1386 SET_TD_DAYS(self, days);
1387 SET_TD_SECONDS(self, seconds);
1388 SET_TD_MICROSECONDS(self, microseconds);
1389 }
1390 return (PyObject *) self;
1391}
1392
1393
1394/* ---------------------------------------------------------------------------
1395 * Cached Python objects; these are set by the module init function.
1396 */
1397
1398/* Conversion factors. */
1399static PyObject *us_per_us = NULL; /* 1 */
1400static PyObject *us_per_ms = NULL; /* 1000 */
1401static PyObject *us_per_second = NULL; /* 1000000 */
1402static PyObject *us_per_minute = NULL; /* 1e6 * 60 as Python int */
1403static PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python long */
1404static PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python long */
1405static PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python long */
1406static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */
1407
1408/* Callables to support unpickling. */
1409static PyObject *date_unpickler_object = NULL;
1410static PyObject *datetime_unpickler_object = NULL;
1411static PyObject *datetimetz_unpickler_object = NULL;
1412static PyObject *tzinfo_unpickler_object = NULL;
1413static PyObject *time_unpickler_object = NULL;
1414static PyObject *timetz_unpickler_object = NULL;
1415
1416/* ---------------------------------------------------------------------------
1417 * Class implementations.
1418 */
1419
1420/*
1421 * PyDateTime_Delta implementation.
1422 */
1423
1424/* Convert a timedelta to a number of us,
1425 * (24*3600*self.days + self.seconds)*1000000 + self.microseconds
1426 * as a Python int or long.
1427 * Doing mixed-radix arithmetic by hand instead is excruciating in C,
1428 * due to ubiquitous overflow possibilities.
1429 */
1430static PyObject *
1431delta_to_microseconds(PyDateTime_Delta *self)
1432{
1433 PyObject *x1 = NULL;
1434 PyObject *x2 = NULL;
1435 PyObject *x3 = NULL;
1436 PyObject *result = NULL;
1437
1438 x1 = PyInt_FromLong(GET_TD_DAYS(self));
1439 if (x1 == NULL)
1440 goto Done;
1441 x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */
1442 if (x2 == NULL)
1443 goto Done;
1444 Py_DECREF(x1);
1445 x1 = NULL;
1446
1447 /* x2 has days in seconds */
1448 x1 = PyInt_FromLong(GET_TD_SECONDS(self)); /* seconds */
1449 if (x1 == NULL)
1450 goto Done;
1451 x3 = PyNumber_Add(x1, x2); /* days and seconds in seconds */
1452 if (x3 == NULL)
1453 goto Done;
1454 Py_DECREF(x1);
1455 Py_DECREF(x2);
1456 x1 = x2 = NULL;
1457
1458 /* x3 has days+seconds in seconds */
1459 x1 = PyNumber_Multiply(x3, us_per_second); /* us */
1460 if (x1 == NULL)
1461 goto Done;
1462 Py_DECREF(x3);
1463 x3 = NULL;
1464
1465 /* x1 has days+seconds in us */
1466 x2 = PyInt_FromLong(GET_TD_MICROSECONDS(self));
1467 if (x2 == NULL)
1468 goto Done;
1469 result = PyNumber_Add(x1, x2);
1470
1471Done:
1472 Py_XDECREF(x1);
1473 Py_XDECREF(x2);
1474 Py_XDECREF(x3);
1475 return result;
1476}
1477
1478/* Convert a number of us (as a Python int or long) to a timedelta.
1479 */
1480static PyObject *
1481microseconds_to_delta(PyObject *pyus)
1482{
1483 int us;
1484 int s;
1485 int d;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001486 long temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001487
1488 PyObject *tuple = NULL;
1489 PyObject *num = NULL;
1490 PyObject *result = NULL;
1491
1492 tuple = PyNumber_Divmod(pyus, us_per_second);
1493 if (tuple == NULL)
1494 goto Done;
1495
1496 num = PyTuple_GetItem(tuple, 1); /* us */
1497 if (num == NULL)
1498 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001499 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001500 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001501 if (temp == -1 && PyErr_Occurred())
1502 goto Done;
1503 assert(0 <= temp && temp < 1000000);
1504 us = (int)temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001505 if (us < 0) {
1506 /* The divisor was positive, so this must be an error. */
1507 assert(PyErr_Occurred());
1508 goto Done;
1509 }
1510
1511 num = PyTuple_GetItem(tuple, 0); /* leftover seconds */
1512 if (num == NULL)
1513 goto Done;
1514 Py_INCREF(num);
1515 Py_DECREF(tuple);
1516
1517 tuple = PyNumber_Divmod(num, seconds_per_day);
1518 if (tuple == NULL)
1519 goto Done;
1520 Py_DECREF(num);
1521
1522 num = PyTuple_GetItem(tuple, 1); /* seconds */
1523 if (num == NULL)
1524 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001525 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001526 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001527 if (temp == -1 && PyErr_Occurred())
1528 goto Done;
1529 assert(0 <= temp && temp < 24*3600);
1530 s = (int)temp;
1531
Tim Peters2a799bf2002-12-16 20:18:38 +00001532 if (s < 0) {
1533 /* The divisor was positive, so this must be an error. */
1534 assert(PyErr_Occurred());
1535 goto Done;
1536 }
1537
1538 num = PyTuple_GetItem(tuple, 0); /* leftover days */
1539 if (num == NULL)
1540 goto Done;
1541 Py_INCREF(num);
Tim Peters0b0f41c2002-12-19 01:44:38 +00001542 temp = PyLong_AsLong(num);
1543 if (temp == -1 && PyErr_Occurred())
Tim Peters2a799bf2002-12-16 20:18:38 +00001544 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001545 d = (int)temp;
1546 if ((long)d != temp) {
1547 PyErr_SetString(PyExc_OverflowError, "normalized days too "
1548 "large to fit in a C int");
1549 goto Done;
1550 }
Tim Peters2a799bf2002-12-16 20:18:38 +00001551 result = new_delta(d, s, us, 0);
1552
1553Done:
1554 Py_XDECREF(tuple);
1555 Py_XDECREF(num);
1556 return result;
1557}
1558
1559static PyObject *
1560multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
1561{
1562 PyObject *pyus_in;
1563 PyObject *pyus_out;
1564 PyObject *result;
1565
1566 pyus_in = delta_to_microseconds(delta);
1567 if (pyus_in == NULL)
1568 return NULL;
1569
1570 pyus_out = PyNumber_Multiply(pyus_in, intobj);
1571 Py_DECREF(pyus_in);
1572 if (pyus_out == NULL)
1573 return NULL;
1574
1575 result = microseconds_to_delta(pyus_out);
1576 Py_DECREF(pyus_out);
1577 return result;
1578}
1579
1580static PyObject *
1581divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj)
1582{
1583 PyObject *pyus_in;
1584 PyObject *pyus_out;
1585 PyObject *result;
1586
1587 pyus_in = delta_to_microseconds(delta);
1588 if (pyus_in == NULL)
1589 return NULL;
1590
1591 pyus_out = PyNumber_FloorDivide(pyus_in, intobj);
1592 Py_DECREF(pyus_in);
1593 if (pyus_out == NULL)
1594 return NULL;
1595
1596 result = microseconds_to_delta(pyus_out);
1597 Py_DECREF(pyus_out);
1598 return result;
1599}
1600
1601static PyObject *
1602delta_add(PyObject *left, PyObject *right)
1603{
1604 PyObject *result = Py_NotImplemented;
1605
1606 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1607 /* delta + delta */
1608 /* The C-level additions can't overflow because of the
1609 * invariant bounds.
1610 */
1611 int days = GET_TD_DAYS(left) + GET_TD_DAYS(right);
1612 int seconds = GET_TD_SECONDS(left) + GET_TD_SECONDS(right);
1613 int microseconds = GET_TD_MICROSECONDS(left) +
1614 GET_TD_MICROSECONDS(right);
1615 result = new_delta(days, seconds, microseconds, 1);
1616 }
1617
1618 if (result == Py_NotImplemented)
1619 Py_INCREF(result);
1620 return result;
1621}
1622
1623static PyObject *
1624delta_negative(PyDateTime_Delta *self)
1625{
1626 return new_delta(-GET_TD_DAYS(self),
1627 -GET_TD_SECONDS(self),
1628 -GET_TD_MICROSECONDS(self),
1629 1);
1630}
1631
1632static PyObject *
1633delta_positive(PyDateTime_Delta *self)
1634{
1635 /* Could optimize this (by returning self) if this isn't a
1636 * subclass -- but who uses unary + ? Approximately nobody.
1637 */
1638 return new_delta(GET_TD_DAYS(self),
1639 GET_TD_SECONDS(self),
1640 GET_TD_MICROSECONDS(self),
1641 0);
1642}
1643
1644static PyObject *
1645delta_abs(PyDateTime_Delta *self)
1646{
1647 PyObject *result;
1648
1649 assert(GET_TD_MICROSECONDS(self) >= 0);
1650 assert(GET_TD_SECONDS(self) >= 0);
1651
1652 if (GET_TD_DAYS(self) < 0)
1653 result = delta_negative(self);
1654 else
1655 result = delta_positive(self);
1656
1657 return result;
1658}
1659
1660static PyObject *
1661delta_subtract(PyObject *left, PyObject *right)
1662{
1663 PyObject *result = Py_NotImplemented;
1664
1665 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1666 /* delta - delta */
1667 PyObject *minus_right = PyNumber_Negative(right);
1668 if (minus_right) {
1669 result = delta_add(left, minus_right);
1670 Py_DECREF(minus_right);
1671 }
1672 else
1673 result = NULL;
1674 }
1675
1676 if (result == Py_NotImplemented)
1677 Py_INCREF(result);
1678 return result;
1679}
1680
1681/* This is more natural as a tp_compare, but doesn't work then: for whatever
1682 * reason, Python's try_3way_compare ignores tp_compare unless
1683 * PyInstance_Check returns true, but these aren't old-style classes.
1684 */
1685static PyObject *
1686delta_richcompare(PyDateTime_Delta *self, PyObject *other, int op)
1687{
1688 int diff;
1689
1690 if (! PyDelta_CheckExact(other)) {
1691 PyErr_Format(PyExc_TypeError,
1692 "can't compare %s to %s instance",
1693 self->ob_type->tp_name, other->ob_type->tp_name);
1694 return NULL;
1695 }
1696 diff = GET_TD_DAYS(self) - GET_TD_DAYS(other);
1697 if (diff == 0) {
1698 diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other);
1699 if (diff == 0)
1700 diff = GET_TD_MICROSECONDS(self) -
1701 GET_TD_MICROSECONDS(other);
1702 }
1703 return diff_to_bool(diff, op);
1704}
1705
1706static PyObject *delta_getstate(PyDateTime_Delta *self);
1707
1708static long
1709delta_hash(PyDateTime_Delta *self)
1710{
1711 if (self->hashcode == -1) {
1712 PyObject *temp = delta_getstate(self);
1713 if (temp != NULL) {
1714 self->hashcode = PyObject_Hash(temp);
1715 Py_DECREF(temp);
1716 }
1717 }
1718 return self->hashcode;
1719}
1720
1721static PyObject *
1722delta_multiply(PyObject *left, PyObject *right)
1723{
1724 PyObject *result = Py_NotImplemented;
1725
1726 if (PyDelta_Check(left)) {
1727 /* delta * ??? */
1728 if (PyInt_Check(right) || PyLong_Check(right))
1729 result = multiply_int_timedelta(right,
1730 (PyDateTime_Delta *) left);
1731 }
1732 else if (PyInt_Check(left) || PyLong_Check(left))
1733 result = multiply_int_timedelta(left,
1734 (PyDateTime_Delta *) right);
1735
1736 if (result == Py_NotImplemented)
1737 Py_INCREF(result);
1738 return result;
1739}
1740
1741static PyObject *
1742delta_divide(PyObject *left, PyObject *right)
1743{
1744 PyObject *result = Py_NotImplemented;
1745
1746 if (PyDelta_Check(left)) {
1747 /* delta * ??? */
1748 if (PyInt_Check(right) || PyLong_Check(right))
1749 result = divide_timedelta_int(
1750 (PyDateTime_Delta *)left,
1751 right);
1752 }
1753
1754 if (result == Py_NotImplemented)
1755 Py_INCREF(result);
1756 return result;
1757}
1758
1759/* Fold in the value of the tag ("seconds", "weeks", etc) component of a
1760 * timedelta constructor. sofar is the # of microseconds accounted for
1761 * so far, and there are factor microseconds per current unit, the number
1762 * of which is given by num. num * factor is added to sofar in a
1763 * numerically careful way, and that's the result. Any fractional
1764 * microseconds left over (this can happen if num is a float type) are
1765 * added into *leftover.
1766 * Note that there are many ways this can give an error (NULL) return.
1767 */
1768static PyObject *
1769accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
1770 double *leftover)
1771{
1772 PyObject *prod;
1773 PyObject *sum;
1774
1775 assert(num != NULL);
1776
1777 if (PyInt_Check(num) || PyLong_Check(num)) {
1778 prod = PyNumber_Multiply(num, factor);
1779 if (prod == NULL)
1780 return NULL;
1781 sum = PyNumber_Add(sofar, prod);
1782 Py_DECREF(prod);
1783 return sum;
1784 }
1785
1786 if (PyFloat_Check(num)) {
1787 double dnum;
1788 double fracpart;
1789 double intpart;
1790 PyObject *x;
1791 PyObject *y;
1792
1793 /* The Plan: decompose num into an integer part and a
1794 * fractional part, num = intpart + fracpart.
1795 * Then num * factor ==
1796 * intpart * factor + fracpart * factor
1797 * and the LHS can be computed exactly in long arithmetic.
1798 * The RHS is again broken into an int part and frac part.
1799 * and the frac part is added into *leftover.
1800 */
1801 dnum = PyFloat_AsDouble(num);
1802 if (dnum == -1.0 && PyErr_Occurred())
1803 return NULL;
1804 fracpart = modf(dnum, &intpart);
1805 x = PyLong_FromDouble(intpart);
1806 if (x == NULL)
1807 return NULL;
1808
1809 prod = PyNumber_Multiply(x, factor);
1810 Py_DECREF(x);
1811 if (prod == NULL)
1812 return NULL;
1813
1814 sum = PyNumber_Add(sofar, prod);
1815 Py_DECREF(prod);
1816 if (sum == NULL)
1817 return NULL;
1818
1819 if (fracpart == 0.0)
1820 return sum;
1821 /* So far we've lost no information. Dealing with the
1822 * fractional part requires float arithmetic, and may
1823 * lose a little info.
1824 */
1825 assert(PyInt_Check(factor) || PyLong_Check(factor));
1826 if (PyInt_Check(factor))
1827 dnum = (double)PyInt_AsLong(factor);
1828 else
1829 dnum = PyLong_AsDouble(factor);
1830
1831 dnum *= fracpart;
1832 fracpart = modf(dnum, &intpart);
1833 x = PyLong_FromDouble(intpart);
1834 if (x == NULL) {
1835 Py_DECREF(sum);
1836 return NULL;
1837 }
1838
1839 y = PyNumber_Add(sum, x);
1840 Py_DECREF(sum);
1841 Py_DECREF(x);
1842 *leftover += fracpart;
1843 return y;
1844 }
1845
1846 PyErr_Format(PyExc_TypeError,
1847 "unsupported type for timedelta %s component: %s",
1848 tag, num->ob_type->tp_name);
1849 return NULL;
1850}
1851
1852static PyObject *
1853delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1854{
1855 PyObject *self = NULL;
1856
1857 /* Argument objects. */
1858 PyObject *day = NULL;
1859 PyObject *second = NULL;
1860 PyObject *us = NULL;
1861 PyObject *ms = NULL;
1862 PyObject *minute = NULL;
1863 PyObject *hour = NULL;
1864 PyObject *week = NULL;
1865
1866 PyObject *x = NULL; /* running sum of microseconds */
1867 PyObject *y = NULL; /* temp sum of microseconds */
1868 double leftover_us = 0.0;
1869
1870 static char *keywords[] = {
1871 "days", "seconds", "microseconds", "milliseconds",
1872 "minutes", "hours", "weeks", NULL
1873 };
1874
1875 if (PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOO:__new__",
1876 keywords,
1877 &day, &second, &us,
1878 &ms, &minute, &hour, &week) == 0)
1879 goto Done;
1880
1881 x = PyInt_FromLong(0);
1882 if (x == NULL)
1883 goto Done;
1884
1885#define CLEANUP \
1886 Py_DECREF(x); \
1887 x = y; \
1888 if (x == NULL) \
1889 goto Done
1890
1891 if (us) {
1892 y = accum("microseconds", x, us, us_per_us, &leftover_us);
1893 CLEANUP;
1894 }
1895 if (ms) {
1896 y = accum("milliseconds", x, ms, us_per_ms, &leftover_us);
1897 CLEANUP;
1898 }
1899 if (second) {
1900 y = accum("seconds", x, second, us_per_second, &leftover_us);
1901 CLEANUP;
1902 }
1903 if (minute) {
1904 y = accum("minutes", x, minute, us_per_minute, &leftover_us);
1905 CLEANUP;
1906 }
1907 if (hour) {
1908 y = accum("hours", x, hour, us_per_hour, &leftover_us);
1909 CLEANUP;
1910 }
1911 if (day) {
1912 y = accum("days", x, day, us_per_day, &leftover_us);
1913 CLEANUP;
1914 }
1915 if (week) {
1916 y = accum("weeks", x, week, us_per_week, &leftover_us);
1917 CLEANUP;
1918 }
1919 if (leftover_us) {
1920 /* Round to nearest whole # of us, and add into x. */
Tim Peters5d644dd2003-01-02 16:32:54 +00001921 PyObject *temp = PyLong_FromLong(round_to_long(leftover_us));
Tim Peters2a799bf2002-12-16 20:18:38 +00001922 if (temp == NULL) {
1923 Py_DECREF(x);
1924 goto Done;
1925 }
1926 y = PyNumber_Add(x, temp);
1927 Py_DECREF(temp);
1928 CLEANUP;
1929 }
1930
1931 self = microseconds_to_delta(x);
1932 Py_DECREF(x);
1933Done:
1934 return self;
1935
1936#undef CLEANUP
1937}
1938
1939static int
1940delta_nonzero(PyDateTime_Delta *self)
1941{
1942 return (GET_TD_DAYS(self) != 0
1943 || GET_TD_SECONDS(self) != 0
1944 || GET_TD_MICROSECONDS(self) != 0);
1945}
1946
1947static PyObject *
1948delta_repr(PyDateTime_Delta *self)
1949{
1950 if (GET_TD_MICROSECONDS(self) != 0)
1951 return PyString_FromFormat("%s(%d, %d, %d)",
1952 self->ob_type->tp_name,
1953 GET_TD_DAYS(self),
1954 GET_TD_SECONDS(self),
1955 GET_TD_MICROSECONDS(self));
1956 if (GET_TD_SECONDS(self) != 0)
1957 return PyString_FromFormat("%s(%d, %d)",
1958 self->ob_type->tp_name,
1959 GET_TD_DAYS(self),
1960 GET_TD_SECONDS(self));
1961
1962 return PyString_FromFormat("%s(%d)",
1963 self->ob_type->tp_name,
1964 GET_TD_DAYS(self));
1965}
1966
1967static PyObject *
1968delta_str(PyDateTime_Delta *self)
1969{
1970 int days = GET_TD_DAYS(self);
1971 int seconds = GET_TD_SECONDS(self);
1972 int us = GET_TD_MICROSECONDS(self);
1973 int hours;
1974 int minutes;
Tim Petersba873472002-12-18 20:19:21 +00001975 char buf[100];
1976 char *pbuf = buf;
1977 size_t buflen = sizeof(buf);
1978 int n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001979
1980 minutes = divmod(seconds, 60, &seconds);
1981 hours = divmod(minutes, 60, &minutes);
1982
1983 if (days) {
Tim Petersba873472002-12-18 20:19:21 +00001984 n = PyOS_snprintf(pbuf, buflen, "%d day%s, ", days,
1985 (days == 1 || days == -1) ? "" : "s");
1986 if (n < 0 || (size_t)n >= buflen)
1987 goto Fail;
1988 pbuf += n;
1989 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001990 }
1991
Tim Petersba873472002-12-18 20:19:21 +00001992 n = PyOS_snprintf(pbuf, buflen, "%d:%02d:%02d",
1993 hours, minutes, seconds);
1994 if (n < 0 || (size_t)n >= buflen)
1995 goto Fail;
1996 pbuf += n;
1997 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001998
1999 if (us) {
Tim Petersba873472002-12-18 20:19:21 +00002000 n = PyOS_snprintf(pbuf, buflen, ".%06d", us);
2001 if (n < 0 || (size_t)n >= buflen)
2002 goto Fail;
2003 pbuf += n;
Tim Peters2a799bf2002-12-16 20:18:38 +00002004 }
2005
Tim Petersba873472002-12-18 20:19:21 +00002006 return PyString_FromStringAndSize(buf, pbuf - buf);
2007
2008 Fail:
2009 PyErr_SetString(PyExc_SystemError, "goofy result from PyOS_snprintf");
2010 return NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00002011}
2012
2013/* Pickle support. Quite a maze! While __getstate__/__setstate__ sufficed
2014 * in the Python implementation, the C implementation also requires
2015 * __reduce__, and a __safe_for_unpickling__ attr in the type object.
2016 */
2017static PyObject *
2018delta_getstate(PyDateTime_Delta *self)
2019{
2020 return Py_BuildValue("iii", GET_TD_DAYS(self),
2021 GET_TD_SECONDS(self),
2022 GET_TD_MICROSECONDS(self));
2023}
2024
2025static PyObject *
2026delta_setstate(PyDateTime_Delta *self, PyObject *state)
2027{
2028 int day;
2029 int second;
2030 int us;
2031
2032 if (!PyArg_ParseTuple(state, "iii:__setstate__", &day, &second, &us))
2033 return NULL;
2034
2035 self->hashcode = -1;
2036 SET_TD_DAYS(self, day);
2037 SET_TD_SECONDS(self, second);
2038 SET_TD_MICROSECONDS(self, us);
2039
2040 Py_INCREF(Py_None);
2041 return Py_None;
2042}
2043
2044static PyObject *
2045delta_reduce(PyDateTime_Delta* self)
2046{
2047 PyObject* result = NULL;
2048 PyObject* state = delta_getstate(self);
2049
2050 if (state != NULL) {
2051 /* The funky "()" in the format string creates an empty
2052 * tuple as the 2nd component of the result 3-tuple.
2053 */
2054 result = Py_BuildValue("O()O", self->ob_type, state);
2055 Py_DECREF(state);
2056 }
2057 return result;
2058}
2059
2060#define OFFSET(field) offsetof(PyDateTime_Delta, field)
2061
2062static PyMemberDef delta_members[] = {
Neal Norwitzdfb80862002-12-19 02:30:56 +00002063 {"days", T_INT, OFFSET(days), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002064 PyDoc_STR("Number of days.")},
2065
Neal Norwitzdfb80862002-12-19 02:30:56 +00002066 {"seconds", T_INT, OFFSET(seconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002067 PyDoc_STR("Number of seconds (>= 0 and less than 1 day).")},
2068
Neal Norwitzdfb80862002-12-19 02:30:56 +00002069 {"microseconds", T_INT, OFFSET(microseconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002070 PyDoc_STR("Number of microseconds (>= 0 and less than 1 second).")},
2071 {NULL}
2072};
2073
2074static PyMethodDef delta_methods[] = {
2075 {"__setstate__", (PyCFunction)delta_setstate, METH_O,
2076 PyDoc_STR("__setstate__(state)")},
2077
2078 {"__reduce__", (PyCFunction)delta_reduce, METH_NOARGS,
2079 PyDoc_STR("__setstate__(state)")},
2080
2081 {"__getstate__", (PyCFunction)delta_getstate, METH_NOARGS,
2082 PyDoc_STR("__getstate__() -> state")},
2083 {NULL, NULL},
2084};
2085
2086static char delta_doc[] =
2087PyDoc_STR("Difference between two datetime values.");
2088
2089static PyNumberMethods delta_as_number = {
2090 delta_add, /* nb_add */
2091 delta_subtract, /* nb_subtract */
2092 delta_multiply, /* nb_multiply */
2093 delta_divide, /* nb_divide */
2094 0, /* nb_remainder */
2095 0, /* nb_divmod */
2096 0, /* nb_power */
2097 (unaryfunc)delta_negative, /* nb_negative */
2098 (unaryfunc)delta_positive, /* nb_positive */
2099 (unaryfunc)delta_abs, /* nb_absolute */
2100 (inquiry)delta_nonzero, /* nb_nonzero */
2101 0, /*nb_invert*/
2102 0, /*nb_lshift*/
2103 0, /*nb_rshift*/
2104 0, /*nb_and*/
2105 0, /*nb_xor*/
2106 0, /*nb_or*/
2107 0, /*nb_coerce*/
2108 0, /*nb_int*/
2109 0, /*nb_long*/
2110 0, /*nb_float*/
2111 0, /*nb_oct*/
2112 0, /*nb_hex*/
2113 0, /*nb_inplace_add*/
2114 0, /*nb_inplace_subtract*/
2115 0, /*nb_inplace_multiply*/
2116 0, /*nb_inplace_divide*/
2117 0, /*nb_inplace_remainder*/
2118 0, /*nb_inplace_power*/
2119 0, /*nb_inplace_lshift*/
2120 0, /*nb_inplace_rshift*/
2121 0, /*nb_inplace_and*/
2122 0, /*nb_inplace_xor*/
2123 0, /*nb_inplace_or*/
2124 delta_divide, /* nb_floor_divide */
2125 0, /* nb_true_divide */
2126 0, /* nb_inplace_floor_divide */
2127 0, /* nb_inplace_true_divide */
2128};
2129
2130static PyTypeObject PyDateTime_DeltaType = {
2131 PyObject_HEAD_INIT(NULL)
2132 0, /* ob_size */
2133 "datetime.timedelta", /* tp_name */
2134 sizeof(PyDateTime_Delta), /* tp_basicsize */
2135 0, /* tp_itemsize */
2136 0, /* tp_dealloc */
2137 0, /* tp_print */
2138 0, /* tp_getattr */
2139 0, /* tp_setattr */
2140 0, /* tp_compare */
2141 (reprfunc)delta_repr, /* tp_repr */
2142 &delta_as_number, /* tp_as_number */
2143 0, /* tp_as_sequence */
2144 0, /* tp_as_mapping */
2145 (hashfunc)delta_hash, /* tp_hash */
2146 0, /* tp_call */
2147 (reprfunc)delta_str, /* tp_str */
2148 PyObject_GenericGetAttr, /* tp_getattro */
2149 0, /* tp_setattro */
2150 0, /* tp_as_buffer */
2151 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
2152 delta_doc, /* tp_doc */
2153 0, /* tp_traverse */
2154 0, /* tp_clear */
2155 (richcmpfunc)delta_richcompare, /* tp_richcompare */
2156 0, /* tp_weaklistoffset */
2157 0, /* tp_iter */
2158 0, /* tp_iternext */
2159 delta_methods, /* tp_methods */
2160 delta_members, /* tp_members */
2161 0, /* tp_getset */
2162 0, /* tp_base */
2163 0, /* tp_dict */
2164 0, /* tp_descr_get */
2165 0, /* tp_descr_set */
2166 0, /* tp_dictoffset */
2167 0, /* tp_init */
2168 0, /* tp_alloc */
2169 delta_new, /* tp_new */
2170 _PyObject_Del, /* tp_free */
2171};
2172
2173/*
2174 * PyDateTime_Date implementation.
2175 */
2176
2177/* Accessor properties. */
2178
2179static PyObject *
2180date_year(PyDateTime_Date *self, void *unused)
2181{
2182 return PyInt_FromLong(GET_YEAR(self));
2183}
2184
2185static PyObject *
2186date_month(PyDateTime_Date *self, void *unused)
2187{
2188 return PyInt_FromLong(GET_MONTH(self));
2189}
2190
2191static PyObject *
2192date_day(PyDateTime_Date *self, void *unused)
2193{
2194 return PyInt_FromLong(GET_DAY(self));
2195}
2196
2197static PyGetSetDef date_getset[] = {
2198 {"year", (getter)date_year},
2199 {"month", (getter)date_month},
2200 {"day", (getter)date_day},
2201 {NULL}
2202};
2203
2204/* Constructors. */
2205
Tim Peters12bf3392002-12-24 05:41:27 +00002206static char *date_kws[] = {"year", "month", "day", NULL};
2207
Tim Peters2a799bf2002-12-16 20:18:38 +00002208static PyObject *
2209date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2210{
2211 PyObject *self = NULL;
2212 int year;
2213 int month;
2214 int day;
2215
Tim Peters12bf3392002-12-24 05:41:27 +00002216 if (PyArg_ParseTupleAndKeywords(args, kw, "iii", date_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002217 &year, &month, &day)) {
2218 if (check_date_args(year, month, day) < 0)
2219 return NULL;
2220 self = new_date(year, month, day);
2221 }
2222 return self;
2223}
2224
2225/* Return new date from localtime(t). */
2226static PyObject *
2227date_local_from_time_t(PyObject *cls, time_t t)
2228{
2229 struct tm *tm;
2230 PyObject *result = NULL;
2231
2232 tm = localtime(&t);
2233 if (tm)
2234 result = PyObject_CallFunction(cls, "iii",
2235 tm->tm_year + 1900,
2236 tm->tm_mon + 1,
2237 tm->tm_mday);
2238 else
2239 PyErr_SetString(PyExc_ValueError,
2240 "timestamp out of range for "
2241 "platform localtime() function");
2242 return result;
2243}
2244
2245/* Return new date from current time.
2246 * We say this is equivalent to fromtimestamp(time.time()), and the
2247 * only way to be sure of that is to *call* time.time(). That's not
2248 * generally the same as calling C's time.
2249 */
2250static PyObject *
2251date_today(PyObject *cls, PyObject *dummy)
2252{
2253 PyObject *time;
2254 PyObject *result;
2255
2256 time = time_time();
2257 if (time == NULL)
2258 return NULL;
2259
2260 /* Note well: today() is a class method, so this may not call
2261 * date.fromtimestamp. For example, it may call
2262 * datetime.fromtimestamp. That's why we need all the accuracy
2263 * time.time() delivers; if someone were gonzo about optimization,
2264 * date.today() could get away with plain C time().
2265 */
2266 result = PyObject_CallMethod(cls, "fromtimestamp", "O", time);
2267 Py_DECREF(time);
2268 return result;
2269}
2270
2271/* Return new date from given timestamp (Python timestamp -- a double). */
2272static PyObject *
2273date_fromtimestamp(PyObject *cls, PyObject *args)
2274{
2275 double timestamp;
2276 PyObject *result = NULL;
2277
2278 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2279 result = date_local_from_time_t(cls, (time_t)timestamp);
2280 return result;
2281}
2282
2283/* Return new date from proleptic Gregorian ordinal. Raises ValueError if
2284 * the ordinal is out of range.
2285 */
2286static PyObject *
2287date_fromordinal(PyObject *cls, PyObject *args)
2288{
2289 PyObject *result = NULL;
2290 int ordinal;
2291
2292 if (PyArg_ParseTuple(args, "i:fromordinal", &ordinal)) {
2293 int year;
2294 int month;
2295 int day;
2296
2297 if (ordinal < 1)
2298 PyErr_SetString(PyExc_ValueError, "ordinal must be "
2299 ">= 1");
2300 else {
2301 ord_to_ymd(ordinal, &year, &month, &day);
2302 result = PyObject_CallFunction(cls, "iii",
2303 year, month, day);
2304 }
2305 }
2306 return result;
2307}
2308
2309/*
2310 * Date arithmetic.
2311 */
2312
2313/* date + timedelta -> date. If arg negate is true, subtract the timedelta
2314 * instead.
2315 */
2316static PyObject *
2317add_date_timedelta(PyDateTime_Date *date, PyDateTime_Delta *delta, int negate)
2318{
2319 PyObject *result = NULL;
2320 int year = GET_YEAR(date);
2321 int month = GET_MONTH(date);
2322 int deltadays = GET_TD_DAYS(delta);
2323 /* C-level overflow is impossible because |deltadays| < 1e9. */
2324 int day = GET_DAY(date) + (negate ? -deltadays : deltadays);
2325
2326 if (normalize_date(&year, &month, &day) >= 0)
2327 result = new_date(year, month, day);
2328 return result;
2329}
2330
2331static PyObject *
2332date_add(PyObject *left, PyObject *right)
2333{
2334 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2335 Py_INCREF(Py_NotImplemented);
2336 return Py_NotImplemented;
2337 }
2338 if (PyDate_CheckExact(left)) {
2339 /* date + ??? */
2340 if (PyDelta_Check(right))
2341 /* date + delta */
2342 return add_date_timedelta((PyDateTime_Date *) left,
2343 (PyDateTime_Delta *) right,
2344 0);
2345 }
2346 else {
2347 /* ??? + date
2348 * 'right' must be one of us, or we wouldn't have been called
2349 */
2350 if (PyDelta_Check(left))
2351 /* delta + date */
2352 return add_date_timedelta((PyDateTime_Date *) right,
2353 (PyDateTime_Delta *) left,
2354 0);
2355 }
2356 Py_INCREF(Py_NotImplemented);
2357 return Py_NotImplemented;
2358}
2359
2360static PyObject *
2361date_subtract(PyObject *left, PyObject *right)
2362{
2363 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2364 Py_INCREF(Py_NotImplemented);
2365 return Py_NotImplemented;
2366 }
2367 if (PyDate_CheckExact(left)) {
2368 if (PyDate_CheckExact(right)) {
2369 /* date - date */
2370 int left_ord = ymd_to_ord(GET_YEAR(left),
2371 GET_MONTH(left),
2372 GET_DAY(left));
2373 int right_ord = ymd_to_ord(GET_YEAR(right),
2374 GET_MONTH(right),
2375 GET_DAY(right));
2376 return new_delta(left_ord - right_ord, 0, 0, 0);
2377 }
2378 if (PyDelta_Check(right)) {
2379 /* date - delta */
2380 return add_date_timedelta((PyDateTime_Date *) left,
2381 (PyDateTime_Delta *) right,
2382 1);
2383 }
2384 }
2385 Py_INCREF(Py_NotImplemented);
2386 return Py_NotImplemented;
2387}
2388
2389
2390/* Various ways to turn a date into a string. */
2391
2392static PyObject *
2393date_repr(PyDateTime_Date *self)
2394{
2395 char buffer[1028];
2396 char *typename;
2397
2398 typename = self->ob_type->tp_name;
2399 PyOS_snprintf(buffer, sizeof(buffer), "%s(%d, %d, %d)",
2400 typename,
2401 GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2402
2403 return PyString_FromString(buffer);
2404}
2405
2406static PyObject *
2407date_isoformat(PyDateTime_Date *self)
2408{
2409 char buffer[128];
2410
2411 isoformat_date(self, buffer, sizeof(buffer));
2412 return PyString_FromString(buffer);
2413}
2414
2415/* str() calls the appropriate isofomat() method. */
2416static PyObject *
2417date_str(PyDateTime_Date *self)
2418{
2419 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
2420}
2421
2422
2423static PyObject *
2424date_ctime(PyDateTime_Date *self)
2425{
2426 return format_ctime(self, 0, 0, 0);
2427}
2428
2429static PyObject *
2430date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2431{
2432 /* This method can be inherited, and needs to call the
2433 * timetuple() method appropriate to self's class.
2434 */
2435 PyObject *result;
2436 PyObject *format;
2437 PyObject *tuple;
2438 static char *keywords[] = {"format", NULL};
2439
2440 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
2441 &PyString_Type, &format))
2442 return NULL;
2443
2444 tuple = PyObject_CallMethod((PyObject *)self, "timetuple", "()");
2445 if (tuple == NULL)
2446 return NULL;
Tim Petersbad8ff02002-12-30 20:52:32 +00002447 result = wrap_strftime((PyObject *)self, format, tuple,
2448 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00002449 Py_DECREF(tuple);
2450 return result;
2451}
2452
2453/* ISO methods. */
2454
2455static PyObject *
2456date_isoweekday(PyDateTime_Date *self)
2457{
2458 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2459
2460 return PyInt_FromLong(dow + 1);
2461}
2462
2463static PyObject *
2464date_isocalendar(PyDateTime_Date *self)
2465{
2466 int year = GET_YEAR(self);
2467 int week1_monday = iso_week1_monday(year);
2468 int today = ymd_to_ord(year, GET_MONTH(self), GET_DAY(self));
2469 int week;
2470 int day;
2471
2472 week = divmod(today - week1_monday, 7, &day);
2473 if (week < 0) {
2474 --year;
2475 week1_monday = iso_week1_monday(year);
2476 week = divmod(today - week1_monday, 7, &day);
2477 }
2478 else if (week >= 52 && today >= iso_week1_monday(year + 1)) {
2479 ++year;
2480 week = 0;
2481 }
2482 return Py_BuildValue("iii", year, week + 1, day + 1);
2483}
2484
2485/* Miscellaneous methods. */
2486
2487/* This is more natural as a tp_compare, but doesn't work then: for whatever
2488 * reason, Python's try_3way_compare ignores tp_compare unless
2489 * PyInstance_Check returns true, but these aren't old-style classes.
2490 */
2491static PyObject *
2492date_richcompare(PyDateTime_Date *self, PyObject *other, int op)
2493{
2494 int diff;
2495
2496 if (! PyDate_Check(other)) {
2497 PyErr_Format(PyExc_TypeError,
2498 "can't compare date to %s instance",
2499 other->ob_type->tp_name);
2500 return NULL;
2501 }
2502 diff = memcmp(self->data, ((PyDateTime_Date *)other)->data,
2503 _PyDateTime_DATE_DATASIZE);
2504 return diff_to_bool(diff, op);
2505}
2506
2507static PyObject *
2508date_timetuple(PyDateTime_Date *self)
2509{
2510 return build_struct_time(GET_YEAR(self),
2511 GET_MONTH(self),
2512 GET_DAY(self),
2513 0, 0, 0, -1);
2514}
2515
Tim Peters12bf3392002-12-24 05:41:27 +00002516static PyObject *
2517date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2518{
2519 PyObject *clone;
2520 PyObject *tuple;
2521 int year = GET_YEAR(self);
2522 int month = GET_MONTH(self);
2523 int day = GET_DAY(self);
2524
2525 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iii:replace", date_kws,
2526 &year, &month, &day))
2527 return NULL;
2528 tuple = Py_BuildValue("iii", year, month, day);
2529 if (tuple == NULL)
2530 return NULL;
2531 clone = date_new(self->ob_type, tuple, NULL);
2532 Py_DECREF(tuple);
2533 return clone;
2534}
2535
Tim Peters2a799bf2002-12-16 20:18:38 +00002536static PyObject *date_getstate(PyDateTime_Date *self);
2537
2538static long
2539date_hash(PyDateTime_Date *self)
2540{
2541 if (self->hashcode == -1) {
2542 PyObject *temp = date_getstate(self);
2543 if (temp != NULL) {
2544 self->hashcode = PyObject_Hash(temp);
2545 Py_DECREF(temp);
2546 }
2547 }
2548 return self->hashcode;
2549}
2550
2551static PyObject *
2552date_toordinal(PyDateTime_Date *self)
2553{
2554 return PyInt_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self),
2555 GET_DAY(self)));
2556}
2557
2558static PyObject *
2559date_weekday(PyDateTime_Date *self)
2560{
2561 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2562
2563 return PyInt_FromLong(dow);
2564}
2565
2566/* Pickle support. Quite a maze! */
2567
2568static PyObject *
2569date_getstate(PyDateTime_Date *self)
2570{
2571 return PyString_FromStringAndSize(self->data,
2572 _PyDateTime_DATE_DATASIZE);
2573}
2574
2575static PyObject *
2576date_setstate(PyDateTime_Date *self, PyObject *state)
2577{
2578 const int len = PyString_Size(state);
2579 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
2580
2581 if (! PyString_Check(state) ||
2582 len != _PyDateTime_DATE_DATASIZE) {
2583 PyErr_SetString(PyExc_TypeError,
2584 "bad argument to date.__setstate__");
2585 return NULL;
2586 }
2587 memcpy(self->data, pdata, _PyDateTime_DATE_DATASIZE);
2588 self->hashcode = -1;
2589
2590 Py_INCREF(Py_None);
2591 return Py_None;
2592}
2593
2594/* XXX This seems a ridiculously inefficient way to pickle a short string. */
2595static PyObject *
2596date_pickler(PyObject *module, PyDateTime_Date *date)
2597{
2598 PyObject *state;
2599 PyObject *result = NULL;
2600
2601 if (! PyDate_CheckExact(date)) {
2602 PyErr_Format(PyExc_TypeError,
2603 "bad type passed to date pickler: %s",
2604 date->ob_type->tp_name);
2605 return NULL;
2606 }
2607 state = date_getstate(date);
2608 if (state) {
2609 result = Py_BuildValue("O(O)", date_unpickler_object, state);
2610 Py_DECREF(state);
2611 }
2612 return result;
2613}
2614
2615static PyObject *
2616date_unpickler(PyObject *module, PyObject *arg)
2617{
2618 PyDateTime_Date *self;
2619
2620 if (! PyString_CheckExact(arg)) {
2621 PyErr_Format(PyExc_TypeError,
2622 "bad type passed to date unpickler: %s",
2623 arg->ob_type->tp_name);
2624 return NULL;
2625 }
2626 self = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
2627 if (self != NULL) {
2628 PyObject *res = date_setstate(self, arg);
2629 if (res == NULL) {
2630 Py_DECREF(self);
2631 return NULL;
2632 }
2633 Py_DECREF(res);
2634 }
2635 return (PyObject *)self;
2636}
2637
2638static PyMethodDef date_methods[] = {
2639 /* Class methods: */
2640 {"fromtimestamp", (PyCFunction)date_fromtimestamp, METH_VARARGS |
2641 METH_CLASS,
2642 PyDoc_STR("timestamp -> local date from a POSIX timestamp (like "
2643 "time.time()).")},
2644
2645 {"fromordinal", (PyCFunction)date_fromordinal, METH_VARARGS |
2646 METH_CLASS,
2647 PyDoc_STR("int -> date corresponding to a proleptic Gregorian "
2648 "ordinal.")},
2649
2650 {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS,
2651 PyDoc_STR("Current date or datetime: same as "
2652 "self.__class__.fromtimestamp(time.time()).")},
2653
2654 /* Instance methods: */
2655
2656 {"ctime", (PyCFunction)date_ctime, METH_NOARGS,
2657 PyDoc_STR("Return ctime() style string.")},
2658
2659 {"strftime", (PyCFunction)date_strftime, METH_KEYWORDS,
2660 PyDoc_STR("format -> strftime() style string.")},
2661
2662 {"timetuple", (PyCFunction)date_timetuple, METH_NOARGS,
2663 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
2664
2665 {"isocalendar", (PyCFunction)date_isocalendar, METH_NOARGS,
2666 PyDoc_STR("Return a 3-tuple containing ISO year, week number, and "
2667 "weekday.")},
2668
2669 {"isoformat", (PyCFunction)date_isoformat, METH_NOARGS,
2670 PyDoc_STR("Return string in ISO 8601 format, YYYY-MM-DD.")},
2671
2672 {"isoweekday", (PyCFunction)date_isoweekday, METH_NOARGS,
2673 PyDoc_STR("Return the day of the week represented by the date.\n"
2674 "Monday == 1 ... Sunday == 7")},
2675
2676 {"toordinal", (PyCFunction)date_toordinal, METH_NOARGS,
2677 PyDoc_STR("Return proleptic Gregorian ordinal. January 1 of year "
2678 "1 is day 1.")},
2679
2680 {"weekday", (PyCFunction)date_weekday, METH_NOARGS,
2681 PyDoc_STR("Return the day of the week represented by the date.\n"
2682 "Monday == 0 ... Sunday == 6")},
2683
Tim Peters12bf3392002-12-24 05:41:27 +00002684 {"replace", (PyCFunction)date_replace, METH_KEYWORDS,
2685 PyDoc_STR("Return date with new specified fields.")},
2686
Tim Peters2a799bf2002-12-16 20:18:38 +00002687 {"__setstate__", (PyCFunction)date_setstate, METH_O,
2688 PyDoc_STR("__setstate__(state)")},
2689
2690 {"__getstate__", (PyCFunction)date_getstate, METH_NOARGS,
2691 PyDoc_STR("__getstate__() -> state")},
2692
2693 {NULL, NULL}
2694};
2695
2696static char date_doc[] =
2697PyDoc_STR("Basic date type.");
2698
2699static PyNumberMethods date_as_number = {
2700 date_add, /* nb_add */
2701 date_subtract, /* nb_subtract */
2702 0, /* nb_multiply */
2703 0, /* nb_divide */
2704 0, /* nb_remainder */
2705 0, /* nb_divmod */
2706 0, /* nb_power */
2707 0, /* nb_negative */
2708 0, /* nb_positive */
2709 0, /* nb_absolute */
2710 0, /* nb_nonzero */
2711};
2712
2713static PyTypeObject PyDateTime_DateType = {
2714 PyObject_HEAD_INIT(NULL)
2715 0, /* ob_size */
2716 "datetime.date", /* tp_name */
2717 sizeof(PyDateTime_Date), /* tp_basicsize */
2718 0, /* tp_itemsize */
2719 (destructor)PyObject_Del, /* tp_dealloc */
2720 0, /* tp_print */
2721 0, /* tp_getattr */
2722 0, /* tp_setattr */
2723 0, /* tp_compare */
2724 (reprfunc)date_repr, /* tp_repr */
2725 &date_as_number, /* tp_as_number */
2726 0, /* tp_as_sequence */
2727 0, /* tp_as_mapping */
2728 (hashfunc)date_hash, /* tp_hash */
2729 0, /* tp_call */
2730 (reprfunc)date_str, /* tp_str */
2731 PyObject_GenericGetAttr, /* tp_getattro */
2732 0, /* tp_setattro */
2733 0, /* tp_as_buffer */
2734 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
2735 Py_TPFLAGS_BASETYPE, /* tp_flags */
2736 date_doc, /* tp_doc */
2737 0, /* tp_traverse */
2738 0, /* tp_clear */
2739 (richcmpfunc)date_richcompare, /* tp_richcompare */
2740 0, /* tp_weaklistoffset */
2741 0, /* tp_iter */
2742 0, /* tp_iternext */
2743 date_methods, /* tp_methods */
2744 0, /* tp_members */
2745 date_getset, /* tp_getset */
2746 0, /* tp_base */
2747 0, /* tp_dict */
2748 0, /* tp_descr_get */
2749 0, /* tp_descr_set */
2750 0, /* tp_dictoffset */
2751 0, /* tp_init */
2752 0, /* tp_alloc */
2753 date_new, /* tp_new */
2754 _PyObject_Del, /* tp_free */
2755};
2756
2757/*
2758 * PyDateTime_DateTime implementation.
2759 */
2760
2761/* Accessor properties. */
2762
2763static PyObject *
2764datetime_hour(PyDateTime_DateTime *self, void *unused)
2765{
2766 return PyInt_FromLong(DATE_GET_HOUR(self));
2767}
2768
2769static PyObject *
2770datetime_minute(PyDateTime_DateTime *self, void *unused)
2771{
2772 return PyInt_FromLong(DATE_GET_MINUTE(self));
2773}
2774
2775static PyObject *
2776datetime_second(PyDateTime_DateTime *self, void *unused)
2777{
2778 return PyInt_FromLong(DATE_GET_SECOND(self));
2779}
2780
2781static PyObject *
2782datetime_microsecond(PyDateTime_DateTime *self, void *unused)
2783{
2784 return PyInt_FromLong(DATE_GET_MICROSECOND(self));
2785}
2786
2787static PyGetSetDef datetime_getset[] = {
2788 {"hour", (getter)datetime_hour},
2789 {"minute", (getter)datetime_minute},
2790 {"second", (getter)datetime_second},
2791 {"microsecond", (getter)datetime_microsecond},
2792 {NULL}
2793};
2794
2795/* Constructors. */
2796
Tim Peters12bf3392002-12-24 05:41:27 +00002797
2798static char *datetime_kws[] = {"year", "month", "day",
2799 "hour", "minute", "second", "microsecond",
2800 NULL};
2801
Tim Peters2a799bf2002-12-16 20:18:38 +00002802static PyObject *
2803datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2804{
2805 PyObject *self = NULL;
2806 int year;
2807 int month;
2808 int day;
2809 int hour = 0;
2810 int minute = 0;
2811 int second = 0;
2812 int usecond = 0;
2813
Tim Peters12bf3392002-12-24 05:41:27 +00002814 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiii", datetime_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002815 &year, &month, &day, &hour, &minute,
2816 &second, &usecond)) {
2817 if (check_date_args(year, month, day) < 0)
2818 return NULL;
2819 if (check_time_args(hour, minute, second, usecond) < 0)
2820 return NULL;
2821 self = new_datetime(year, month, day,
2822 hour, minute, second, usecond);
2823 }
2824 return self;
2825}
2826
2827
2828/* TM_FUNC is the shared type of localtime() and gmtime(). */
2829typedef struct tm *(*TM_FUNC)(const time_t *timer);
2830
2831/* Internal helper.
2832 * Build datetime from a time_t and a distinct count of microseconds.
2833 * Pass localtime or gmtime for f, to control the interpretation of timet.
2834 */
2835static PyObject *
2836datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us)
2837{
2838 struct tm *tm;
2839 PyObject *result = NULL;
2840
2841 tm = f(&timet);
2842 if (tm)
2843 result = PyObject_CallFunction(cls, "iiiiiii",
2844 tm->tm_year + 1900,
2845 tm->tm_mon + 1,
2846 tm->tm_mday,
2847 tm->tm_hour,
2848 tm->tm_min,
2849 tm->tm_sec,
2850 us);
2851 else
2852 PyErr_SetString(PyExc_ValueError,
2853 "timestamp out of range for "
2854 "platform localtime()/gmtime() function");
2855 return result;
2856}
2857
2858/* Internal helper.
2859 * Build datetime from a Python timestamp. Pass localtime or gmtime for f,
2860 * to control the interpretation of the timestamp. Since a double doesn't
2861 * have enough bits to cover a datetime's full range of precision, it's
2862 * better to call datetime_from_timet_and_us provided you have a way
2863 * to get that much precision (e.g., C time() isn't good enough).
2864 */
2865static PyObject *
2866datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp)
2867{
2868 time_t timet = (time_t)timestamp;
Tim Peters5d644dd2003-01-02 16:32:54 +00002869 double fraction = timestamp - (double)timet;
2870 int us = (int)round_to_long(fraction * 1e6);
Tim Peters2a799bf2002-12-16 20:18:38 +00002871
2872 return datetime_from_timet_and_us(cls, f, timet, us);
2873}
2874
2875/* Internal helper.
2876 * Build most accurate possible datetime for current time. Pass localtime or
2877 * gmtime for f as appropriate.
2878 */
2879static PyObject *
2880datetime_best_possible(PyObject *cls, TM_FUNC f)
2881{
2882#ifdef HAVE_GETTIMEOFDAY
2883 struct timeval t;
2884
2885#ifdef GETTIMEOFDAY_NO_TZ
2886 gettimeofday(&t);
2887#else
2888 gettimeofday(&t, (struct timezone *)NULL);
2889#endif
2890 return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec);
2891
2892#else /* ! HAVE_GETTIMEOFDAY */
2893 /* No flavor of gettimeofday exists on this platform. Python's
2894 * time.time() does a lot of other platform tricks to get the
2895 * best time it can on the platform, and we're not going to do
2896 * better than that (if we could, the better code would belong
2897 * in time.time()!) We're limited by the precision of a double,
2898 * though.
2899 */
2900 PyObject *time;
2901 double dtime;
2902
2903 time = time_time();
2904 if (time == NULL)
2905 return NULL;
2906 dtime = PyFloat_AsDouble(time);
2907 Py_DECREF(time);
2908 if (dtime == -1.0 && PyErr_Occurred())
2909 return NULL;
2910 return datetime_from_timestamp(cls, f, dtime);
2911#endif /* ! HAVE_GETTIMEOFDAY */
2912}
2913
2914/* Return new local datetime from timestamp (Python timestamp -- a double). */
2915static PyObject *
2916datetime_fromtimestamp(PyObject *cls, PyObject *args)
2917{
2918 double timestamp;
2919 PyObject *result = NULL;
2920
2921 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2922 result = datetime_from_timestamp(cls, localtime, timestamp);
2923 return result;
2924}
2925
2926/* Return new UTC datetime from timestamp (Python timestamp -- a double). */
2927static PyObject *
2928datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
2929{
2930 double timestamp;
2931 PyObject *result = NULL;
2932
2933 if (PyArg_ParseTuple(args, "d:utcfromtimestamp", &timestamp))
2934 result = datetime_from_timestamp(cls, gmtime, timestamp);
2935 return result;
2936}
2937
2938/* Return best possible local time -- this isn't constrained by the
2939 * precision of a timestamp.
2940 */
2941static PyObject *
2942datetime_now(PyObject *cls, PyObject *dummy)
2943{
2944 return datetime_best_possible(cls, localtime);
2945}
2946
2947/* Return best possible UTC time -- this isn't constrained by the
2948 * precision of a timestamp.
2949 */
2950static PyObject *
2951datetime_utcnow(PyObject *cls, PyObject *dummy)
2952{
2953 return datetime_best_possible(cls, gmtime);
2954}
2955
2956/* Return new datetime or datetimetz from date/datetime/datetimetz and
2957 * time/timetz arguments.
2958 */
2959static PyObject *
2960datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
2961{
2962 static char *keywords[] = {"date", "time", NULL};
2963 PyObject *date;
2964 PyObject *time;
2965 PyObject *result = NULL;
2966
2967 if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!:combine", keywords,
2968 &PyDateTime_DateType, &date,
2969 &PyDateTime_TimeType, &time))
2970 result = PyObject_CallFunction(cls, "iiiiiii",
2971 GET_YEAR(date),
2972 GET_MONTH(date),
2973 GET_DAY(date),
2974 TIME_GET_HOUR(time),
2975 TIME_GET_MINUTE(time),
2976 TIME_GET_SECOND(time),
2977 TIME_GET_MICROSECOND(time));
2978 if (result && PyTimeTZ_Check(time) && PyDateTimeTZ_Check(result)) {
2979 /* Copy the tzinfo field. */
Tim Peters80475bb2002-12-25 07:40:55 +00002980 replace_tzinfo(result, ((PyDateTime_TimeTZ *)time)->tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00002981 }
2982 return result;
2983}
2984
2985/* datetime arithmetic. */
2986
2987static PyObject *
2988add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
2989{
2990 /* Note that the C-level additions can't overflow, because of
2991 * invariant bounds on the member values.
2992 */
2993 int year = GET_YEAR(date);
2994 int month = GET_MONTH(date);
2995 int day = GET_DAY(date) + GET_TD_DAYS(delta);
2996 int hour = DATE_GET_HOUR(date);
2997 int minute = DATE_GET_MINUTE(date);
2998 int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta);
2999 int microsecond = DATE_GET_MICROSECOND(date) +
3000 GET_TD_MICROSECONDS(delta);
3001
3002 if (normalize_datetime(&year, &month, &day,
3003 &hour, &minute, &second, &microsecond) < 0)
3004 return NULL;
3005 else
3006 return new_datetime(year, month, day,
3007 hour, minute, second, microsecond);
3008}
3009
3010static PyObject *
3011sub_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta)
3012{
3013 /* Note that the C-level subtractions can't overflow, because of
3014 * invariant bounds on the member values.
3015 */
3016 int year = GET_YEAR(date);
3017 int month = GET_MONTH(date);
3018 int day = GET_DAY(date) - GET_TD_DAYS(delta);
3019 int hour = DATE_GET_HOUR(date);
3020 int minute = DATE_GET_MINUTE(date);
3021 int second = DATE_GET_SECOND(date) - GET_TD_SECONDS(delta);
3022 int microsecond = DATE_GET_MICROSECOND(date) -
3023 GET_TD_MICROSECONDS(delta);
3024
3025 if (normalize_datetime(&year, &month, &day,
3026 &hour, &minute, &second, &microsecond) < 0)
3027 return NULL;
3028 else
3029 return new_datetime(year, month, day,
3030 hour, minute, second, microsecond);
3031}
3032
3033static PyObject *
3034sub_datetime_datetime(PyDateTime_DateTime *left, PyDateTime_DateTime *right)
3035{
3036 int days1 = ymd_to_ord(GET_YEAR(left), GET_MONTH(left), GET_DAY(left));
3037 int days2 = ymd_to_ord(GET_YEAR(right),
3038 GET_MONTH(right),
3039 GET_DAY(right));
3040 /* These can't overflow, since the values are normalized. At most
3041 * this gives the number of seconds in one day.
3042 */
3043 int delta_s = (DATE_GET_HOUR(left) - DATE_GET_HOUR(right)) * 3600 +
3044 (DATE_GET_MINUTE(left) - DATE_GET_MINUTE(right)) * 60 +
3045 DATE_GET_SECOND(left) - DATE_GET_SECOND(right);
3046 int delta_us = DATE_GET_MICROSECOND(left) -
3047 DATE_GET_MICROSECOND(right);
3048
3049 return new_delta(days1 - days2, delta_s, delta_us, 1);
3050}
3051
3052static PyObject *
3053datetime_add(PyObject *left, PyObject *right)
3054{
3055 if (PyDateTime_Check(left)) {
3056 /* datetime + ??? */
3057 if (PyDelta_Check(right))
3058 /* datetime + delta */
3059 return add_datetime_timedelta(
3060 (PyDateTime_DateTime *)left,
3061 (PyDateTime_Delta *)right);
3062 }
3063 else if (PyDelta_Check(left)) {
3064 /* delta + datetime */
3065 return add_datetime_timedelta((PyDateTime_DateTime *) right,
3066 (PyDateTime_Delta *) left);
3067 }
3068 Py_INCREF(Py_NotImplemented);
3069 return Py_NotImplemented;
3070}
3071
3072static PyObject *
3073datetime_subtract(PyObject *left, PyObject *right)
3074{
3075 PyObject *result = Py_NotImplemented;
3076
3077 if (PyDateTime_Check(left)) {
3078 /* datetime - ??? */
3079 if (PyDateTime_Check(right)) {
3080 /* datetime - datetime */
3081 result = sub_datetime_datetime(
3082 (PyDateTime_DateTime *)left,
3083 (PyDateTime_DateTime *)right);
3084 }
3085 else if (PyDelta_Check(right)) {
3086 /* datetime - delta */
3087 result = sub_datetime_timedelta(
3088 (PyDateTime_DateTime *)left,
3089 (PyDateTime_Delta *)right);
3090 }
3091 }
3092
3093 if (result == Py_NotImplemented)
3094 Py_INCREF(result);
3095 return result;
3096}
3097
3098/* Various ways to turn a datetime into a string. */
3099
3100static PyObject *
3101datetime_repr(PyDateTime_DateTime *self)
3102{
3103 char buffer[1000];
3104 char *typename = self->ob_type->tp_name;
3105
3106 if (DATE_GET_MICROSECOND(self)) {
3107 PyOS_snprintf(buffer, sizeof(buffer),
3108 "%s(%d, %d, %d, %d, %d, %d, %d)",
3109 typename,
3110 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3111 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3112 DATE_GET_SECOND(self),
3113 DATE_GET_MICROSECOND(self));
3114 }
3115 else if (DATE_GET_SECOND(self)) {
3116 PyOS_snprintf(buffer, sizeof(buffer),
3117 "%s(%d, %d, %d, %d, %d, %d)",
3118 typename,
3119 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3120 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3121 DATE_GET_SECOND(self));
3122 }
3123 else {
3124 PyOS_snprintf(buffer, sizeof(buffer),
3125 "%s(%d, %d, %d, %d, %d)",
3126 typename,
3127 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3128 DATE_GET_HOUR(self), DATE_GET_MINUTE(self));
3129 }
3130 return PyString_FromString(buffer);
3131}
3132
3133static PyObject *
3134datetime_str(PyDateTime_DateTime *self)
3135{
3136 return PyObject_CallMethod((PyObject *)self, "isoformat", "(s)", " ");
3137}
3138
3139static PyObject *
3140datetime_isoformat(PyDateTime_DateTime *self,
3141 PyObject *args, PyObject *kw)
3142{
3143 char sep = 'T';
3144 static char *keywords[] = {"sep", NULL};
3145 char buffer[100];
3146 char *cp;
3147
3148 if (!PyArg_ParseTupleAndKeywords(args, kw, "|c:isoformat", keywords,
3149 &sep))
3150 return NULL;
3151 cp = isoformat_date((PyDateTime_Date *)self, buffer, sizeof(buffer));
3152 assert(cp != NULL);
3153 *cp++ = sep;
3154 isoformat_time(self, cp, sizeof(buffer) - (cp - buffer));
3155 return PyString_FromString(buffer);
3156}
3157
3158static PyObject *
3159datetime_ctime(PyDateTime_DateTime *self)
3160{
3161 return format_ctime((PyDateTime_Date *)self,
3162 DATE_GET_HOUR(self),
3163 DATE_GET_MINUTE(self),
3164 DATE_GET_SECOND(self));
3165}
3166
3167/* Miscellaneous methods. */
3168
3169/* This is more natural as a tp_compare, but doesn't work then: for whatever
3170 * reason, Python's try_3way_compare ignores tp_compare unless
3171 * PyInstance_Check returns true, but these aren't old-style classes.
3172 * Note that this routine handles all comparisons for datetime and datetimetz.
3173 */
3174static PyObject *
3175datetime_richcompare(PyDateTime_DateTime *self, PyObject *other, int op)
3176{
3177 int diff;
3178 naivety n1, n2;
3179 int offset1, offset2;
3180
3181 if (! PyDateTime_Check(other)) {
3182 /* Stop this from falling back to address comparison. */
3183 PyErr_Format(PyExc_TypeError,
3184 "can't compare '%s' to '%s'",
3185 self->ob_type->tp_name,
3186 other->ob_type->tp_name);
3187 return NULL;
3188 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003189
Tim Peters00237032002-12-27 02:21:51 +00003190 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1,
Tim Peterse39a80c2002-12-30 21:28:52 +00003191 (PyObject *)self,
3192 other, &offset2, &n2,
3193 other) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003194 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003195 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters60c76e42002-12-27 00:41:11 +00003196 /* If they're both naive, or both aware and have the same offsets,
Tim Peters2a799bf2002-12-16 20:18:38 +00003197 * we get off cheap. Note that if they're both naive, offset1 ==
3198 * offset2 == 0 at this point.
3199 */
3200 if (n1 == n2 && offset1 == offset2) {
3201 diff = memcmp(self->data, ((PyDateTime_DateTime *)other)->data,
3202 _PyDateTime_DATETIME_DATASIZE);
3203 return diff_to_bool(diff, op);
3204 }
3205
3206 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3207 /* We want the sign of
3208 * (self - offset1 minutes) - (other - offset2 minutes) =
3209 * (self - other) + (offset2 - offset1) minutes.
3210 */
3211 PyDateTime_Delta *delta;
3212 int days, seconds, us;
3213
3214 assert(offset1 != offset2); /* else last "if" handled it */
3215 delta = (PyDateTime_Delta *)sub_datetime_datetime(self,
3216 (PyDateTime_DateTime *)other);
3217 if (delta == NULL)
3218 return NULL;
3219 days = delta->days;
3220 seconds = delta->seconds + (offset2 - offset1) * 60;
3221 us = delta->microseconds;
3222 Py_DECREF(delta);
3223 normalize_d_s_us(&days, &seconds, &us);
3224 diff = days;
3225 if (diff == 0)
3226 diff = seconds | us;
3227 return diff_to_bool(diff, op);
3228 }
3229
3230 assert(n1 != n2);
3231 PyErr_SetString(PyExc_TypeError,
3232 "can't compare offset-naive and "
3233 "offset-aware datetimes");
3234 return NULL;
3235}
3236
3237static PyObject *datetime_getstate(PyDateTime_DateTime *self);
3238
3239static long
3240datetime_hash(PyDateTime_DateTime *self)
3241{
3242 if (self->hashcode == -1) {
3243 naivety n;
3244 int offset;
3245 PyObject *temp;
3246
Tim Peterse39a80c2002-12-30 21:28:52 +00003247 n = classify_utcoffset((PyObject *)self, (PyObject *)self,
3248 &offset);
Tim Peters2a799bf2002-12-16 20:18:38 +00003249 assert(n != OFFSET_UNKNOWN);
3250 if (n == OFFSET_ERROR)
3251 return -1;
3252
3253 /* Reduce this to a hash of another object. */
3254 if (n == OFFSET_NAIVE)
3255 temp = datetime_getstate(self);
3256 else {
3257 int days;
3258 int seconds;
3259
3260 assert(n == OFFSET_AWARE);
3261 assert(PyDateTimeTZ_Check(self));
3262 days = ymd_to_ord(GET_YEAR(self),
3263 GET_MONTH(self),
3264 GET_DAY(self));
3265 seconds = DATE_GET_HOUR(self) * 3600 +
3266 (DATE_GET_MINUTE(self) - offset) * 60 +
3267 DATE_GET_SECOND(self);
3268 temp = new_delta(days,
3269 seconds,
3270 DATE_GET_MICROSECOND(self),
3271 1);
3272 }
3273 if (temp != NULL) {
3274 self->hashcode = PyObject_Hash(temp);
3275 Py_DECREF(temp);
3276 }
3277 }
3278 return self->hashcode;
3279}
3280
3281static PyObject *
Tim Peters12bf3392002-12-24 05:41:27 +00003282datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
3283{
3284 PyObject *clone;
3285 PyObject *tuple;
3286 int y = GET_YEAR(self);
3287 int m = GET_MONTH(self);
3288 int d = GET_DAY(self);
3289 int hh = DATE_GET_HOUR(self);
3290 int mm = DATE_GET_MINUTE(self);
3291 int ss = DATE_GET_SECOND(self);
3292 int us = DATE_GET_MICROSECOND(self);
3293
3294 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiii:replace",
3295 datetime_kws,
3296 &y, &m, &d, &hh, &mm, &ss, &us))
3297 return NULL;
3298 tuple = Py_BuildValue("iiiiiii", y, m, d, hh, mm, ss, us);
3299 if (tuple == NULL)
3300 return NULL;
3301 clone = datetime_new(self->ob_type, tuple, NULL);
3302 Py_DECREF(tuple);
3303 return clone;
3304}
3305
3306static PyObject *
Tim Peters80475bb2002-12-25 07:40:55 +00003307datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
3308{
3309 PyObject *tzinfo;
3310 static char *keywords[] = {"tz", NULL};
3311
3312 if (! PyArg_ParseTupleAndKeywords(args, kw, "O:astimezone", keywords,
3313 &tzinfo))
3314 return NULL;
3315 if (check_tzinfo_subclass(tzinfo) < 0)
3316 return NULL;
3317 return new_datetimetz(GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3318 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3319 DATE_GET_SECOND(self),
3320 DATE_GET_MICROSECOND(self),
3321 tzinfo);
3322}
3323
3324static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00003325datetime_timetuple(PyDateTime_DateTime *self)
3326{
3327 return build_struct_time(GET_YEAR(self),
3328 GET_MONTH(self),
3329 GET_DAY(self),
3330 DATE_GET_HOUR(self),
3331 DATE_GET_MINUTE(self),
3332 DATE_GET_SECOND(self),
3333 -1);
3334}
3335
3336static PyObject *
3337datetime_getdate(PyDateTime_DateTime *self)
3338{
3339 return new_date(GET_YEAR(self),
3340 GET_MONTH(self),
3341 GET_DAY(self));
3342}
3343
3344static PyObject *
3345datetime_gettime(PyDateTime_DateTime *self)
3346{
3347 return new_time(DATE_GET_HOUR(self),
3348 DATE_GET_MINUTE(self),
3349 DATE_GET_SECOND(self),
3350 DATE_GET_MICROSECOND(self));
3351}
3352
3353/* Pickle support. Quite a maze! */
3354
3355static PyObject *
3356datetime_getstate(PyDateTime_DateTime *self)
3357{
3358 return PyString_FromStringAndSize(self->data,
3359 _PyDateTime_DATETIME_DATASIZE);
3360}
3361
3362static PyObject *
3363datetime_setstate(PyDateTime_DateTime *self, PyObject *state)
3364{
3365 const int len = PyString_Size(state);
3366 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
3367
3368 if (! PyString_Check(state) ||
3369 len != _PyDateTime_DATETIME_DATASIZE) {
3370 PyErr_SetString(PyExc_TypeError,
3371 "bad argument to datetime.__setstate__");
3372 return NULL;
3373 }
3374 memcpy(self->data, pdata, _PyDateTime_DATETIME_DATASIZE);
3375 self->hashcode = -1;
3376
3377 Py_INCREF(Py_None);
3378 return Py_None;
3379}
3380
3381/* XXX This seems a ridiculously inefficient way to pickle a short string. */
3382static PyObject *
3383datetime_pickler(PyObject *module, PyDateTime_DateTime *datetime)
3384{
3385 PyObject *state;
3386 PyObject *result = NULL;
3387
3388 if (! PyDateTime_CheckExact(datetime)) {
3389 PyErr_Format(PyExc_TypeError,
3390 "bad type passed to datetime pickler: %s",
3391 datetime->ob_type->tp_name);
3392 return NULL;
3393 }
3394 state = datetime_getstate(datetime);
3395 if (state) {
3396 result = Py_BuildValue("O(O)",
3397 datetime_unpickler_object,
3398 state);
3399 Py_DECREF(state);
3400 }
3401 return result;
3402}
3403
3404static PyObject *
3405datetime_unpickler(PyObject *module, PyObject *arg)
3406{
3407 PyDateTime_DateTime *self;
3408
3409 if (! PyString_CheckExact(arg)) {
3410 PyErr_Format(PyExc_TypeError,
3411 "bad type passed to datetime unpickler: %s",
3412 arg->ob_type->tp_name);
3413 return NULL;
3414 }
3415 self = PyObject_New(PyDateTime_DateTime, &PyDateTime_DateTimeType);
3416 if (self != NULL) {
3417 PyObject *res = datetime_setstate(self, arg);
3418 if (res == NULL) {
3419 Py_DECREF(self);
3420 return NULL;
3421 }
3422 Py_DECREF(res);
3423 }
3424 return (PyObject *)self;
3425}
3426
3427static PyMethodDef datetime_methods[] = {
3428 /* Class methods: */
3429 {"now", (PyCFunction)datetime_now,
3430 METH_NOARGS | METH_CLASS,
3431 PyDoc_STR("Return a new datetime representing local day and time.")},
3432
3433 {"utcnow", (PyCFunction)datetime_utcnow,
3434 METH_NOARGS | METH_CLASS,
3435 PyDoc_STR("Return a new datetime representing UTC day and time.")},
3436
3437 {"fromtimestamp", (PyCFunction)datetime_fromtimestamp,
3438 METH_VARARGS | METH_CLASS,
3439 PyDoc_STR("timestamp -> local datetime from a POSIX timestamp "
3440 "(like time.time()).")},
3441
3442 {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
3443 METH_VARARGS | METH_CLASS,
3444 PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp "
3445 "(like time.time()).")},
3446
3447 {"combine", (PyCFunction)datetime_combine,
3448 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
3449 PyDoc_STR("date, time -> datetime with same date and time fields")},
3450
3451 /* Instance methods: */
3452 {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS,
3453 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
3454
3455 {"date", (PyCFunction)datetime_getdate, METH_NOARGS,
3456 PyDoc_STR("Return date object with same year, month and day.")},
3457
3458 {"time", (PyCFunction)datetime_gettime, METH_NOARGS,
3459 PyDoc_STR("Return time object with same hour, minute, second and "
3460 "microsecond.")},
3461
3462 {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
3463 PyDoc_STR("Return ctime() style string.")},
3464
3465 {"isoformat", (PyCFunction)datetime_isoformat, METH_KEYWORDS,
3466 PyDoc_STR("[sep] -> string in ISO 8601 format, "
3467 "YYYY-MM-DDTHH:MM:SS[.mmmmmm].\n\n"
3468 "sep is used to separate the year from the time, and "
3469 "defaults\n"
3470 "to 'T'.")},
3471
Tim Peters12bf3392002-12-24 05:41:27 +00003472 {"replace", (PyCFunction)datetime_replace, METH_KEYWORDS,
3473 PyDoc_STR("Return datetime with new specified fields.")},
3474
Tim Peters80475bb2002-12-25 07:40:55 +00003475 {"astimezone", (PyCFunction)datetime_astimezone, METH_KEYWORDS,
3476 PyDoc_STR("tz -> datetimetz with same date & time, and tzinfo=tz\n")},
3477
Tim Peters2a799bf2002-12-16 20:18:38 +00003478 {"__setstate__", (PyCFunction)datetime_setstate, METH_O,
3479 PyDoc_STR("__setstate__(state)")},
3480
3481 {"__getstate__", (PyCFunction)datetime_getstate, METH_NOARGS,
3482 PyDoc_STR("__getstate__() -> state")},
3483 {NULL, NULL}
3484};
3485
3486static char datetime_doc[] =
3487PyDoc_STR("Basic date/time type.");
3488
3489static PyNumberMethods datetime_as_number = {
3490 datetime_add, /* nb_add */
3491 datetime_subtract, /* nb_subtract */
3492 0, /* nb_multiply */
3493 0, /* nb_divide */
3494 0, /* nb_remainder */
3495 0, /* nb_divmod */
3496 0, /* nb_power */
3497 0, /* nb_negative */
3498 0, /* nb_positive */
3499 0, /* nb_absolute */
3500 0, /* nb_nonzero */
3501};
3502
3503statichere PyTypeObject PyDateTime_DateTimeType = {
3504 PyObject_HEAD_INIT(NULL)
3505 0, /* ob_size */
3506 "datetime.datetime", /* tp_name */
3507 sizeof(PyDateTime_DateTime), /* tp_basicsize */
3508 0, /* tp_itemsize */
3509 (destructor)PyObject_Del, /* tp_dealloc */
3510 0, /* tp_print */
3511 0, /* tp_getattr */
3512 0, /* tp_setattr */
3513 0, /* tp_compare */
3514 (reprfunc)datetime_repr, /* tp_repr */
3515 &datetime_as_number, /* tp_as_number */
3516 0, /* tp_as_sequence */
3517 0, /* tp_as_mapping */
3518 (hashfunc)datetime_hash, /* tp_hash */
3519 0, /* tp_call */
3520 (reprfunc)datetime_str, /* tp_str */
3521 PyObject_GenericGetAttr, /* tp_getattro */
3522 0, /* tp_setattro */
3523 0, /* tp_as_buffer */
3524 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3525 Py_TPFLAGS_BASETYPE, /* tp_flags */
3526 datetime_doc, /* tp_doc */
3527 0, /* tp_traverse */
3528 0, /* tp_clear */
3529 (richcmpfunc)datetime_richcompare, /* tp_richcompare */
3530 0, /* tp_weaklistoffset */
3531 0, /* tp_iter */
3532 0, /* tp_iternext */
3533 datetime_methods, /* tp_methods */
3534 0, /* tp_members */
3535 datetime_getset, /* tp_getset */
3536 &PyDateTime_DateType, /* tp_base */
3537 0, /* tp_dict */
3538 0, /* tp_descr_get */
3539 0, /* tp_descr_set */
3540 0, /* tp_dictoffset */
3541 0, /* tp_init */
3542 0, /* tp_alloc */
3543 datetime_new, /* tp_new */
3544 _PyObject_Del, /* tp_free */
3545};
3546
3547/*
3548 * PyDateTime_Time implementation.
3549 */
3550
3551/* Accessor properties. */
3552
3553static PyObject *
3554time_hour(PyDateTime_Time *self, void *unused)
3555{
3556 return PyInt_FromLong(TIME_GET_HOUR(self));
3557}
3558
3559static PyObject *
3560time_minute(PyDateTime_Time *self, void *unused)
3561{
3562 return PyInt_FromLong(TIME_GET_MINUTE(self));
3563}
3564
3565static PyObject *
Jack Jansen51cd8a22002-12-17 20:57:24 +00003566py_time_second(PyDateTime_Time *self, void *unused)
Tim Peters2a799bf2002-12-16 20:18:38 +00003567{
3568 return PyInt_FromLong(TIME_GET_SECOND(self));
3569}
3570
3571static PyObject *
3572time_microsecond(PyDateTime_Time *self, void *unused)
3573{
3574 return PyInt_FromLong(TIME_GET_MICROSECOND(self));
3575}
3576
3577static PyGetSetDef time_getset[] = {
3578 {"hour", (getter)time_hour},
3579 {"minute", (getter)time_minute},
Jack Jansen51cd8a22002-12-17 20:57:24 +00003580 {"second", (getter)py_time_second},
Tim Peters2a799bf2002-12-16 20:18:38 +00003581 {"microsecond", (getter)time_microsecond},
3582 {NULL}
3583};
3584
3585/* Constructors. */
3586
Tim Peters12bf3392002-12-24 05:41:27 +00003587static char *time_kws[] = {"hour", "minute", "second", "microsecond", NULL};
3588
Tim Peters2a799bf2002-12-16 20:18:38 +00003589static PyObject *
3590time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
3591{
3592 PyObject *self = NULL;
3593 int hour = 0;
3594 int minute = 0;
3595 int second = 0;
3596 int usecond = 0;
3597
Tim Peters2a799bf2002-12-16 20:18:38 +00003598
Tim Peters12bf3392002-12-24 05:41:27 +00003599 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiii", time_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00003600 &hour, &minute, &second, &usecond)) {
3601 if (check_time_args(hour, minute, second, usecond) < 0)
3602 return NULL;
3603 self = new_time(hour, minute, second, usecond);
3604 }
3605 return self;
3606}
3607
3608/* Various ways to turn a time into a string. */
3609
3610static PyObject *
3611time_repr(PyDateTime_Time *self)
3612{
3613 char buffer[100];
3614 char *typename = self->ob_type->tp_name;
3615 int h = TIME_GET_HOUR(self);
3616 int m = TIME_GET_MINUTE(self);
3617 int s = TIME_GET_SECOND(self);
3618 int us = TIME_GET_MICROSECOND(self);
3619
3620 if (us)
3621 PyOS_snprintf(buffer, sizeof(buffer),
3622 "%s(%d, %d, %d, %d)", typename, h, m, s, us);
3623 else if (s)
3624 PyOS_snprintf(buffer, sizeof(buffer),
3625 "%s(%d, %d, %d)", typename, h, m, s);
3626 else
3627 PyOS_snprintf(buffer, sizeof(buffer),
3628 "%s(%d, %d)", typename, h, m);
3629 return PyString_FromString(buffer);
3630}
3631
3632static PyObject *
3633time_str(PyDateTime_Time *self)
3634{
3635 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
3636}
3637
3638static PyObject *
3639time_isoformat(PyDateTime_Time *self)
3640{
3641 char buffer[100];
3642 /* Reuse the time format code from the datetime type. */
3643 PyDateTime_DateTime datetime;
3644 PyDateTime_DateTime *pdatetime = &datetime;
3645
3646 /* Copy over just the time bytes. */
3647 memcpy(pdatetime->data + _PyDateTime_DATE_DATASIZE,
3648 self->data,
3649 _PyDateTime_TIME_DATASIZE);
3650
3651 isoformat_time(pdatetime, buffer, sizeof(buffer));
3652 return PyString_FromString(buffer);
3653}
3654
3655static PyObject *
3656time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3657{
3658 PyObject *result;
3659 PyObject *format;
3660 PyObject *tuple;
3661 static char *keywords[] = {"format", NULL};
3662
3663 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
3664 &PyString_Type, &format))
3665 return NULL;
3666
Tim Peters83b85f12002-12-22 20:34:46 +00003667 /* Python's strftime does insane things with the year part of the
3668 * timetuple. The year is forced to (the otherwise nonsensical)
3669 * 1900 to worm around that.
3670 */
Tim Peters2a799bf2002-12-16 20:18:38 +00003671 tuple = Py_BuildValue("iiiiiiiii",
Tim Peters83b85f12002-12-22 20:34:46 +00003672 1900, 0, 0, /* year, month, day */
Tim Peters2a799bf2002-12-16 20:18:38 +00003673 TIME_GET_HOUR(self),
3674 TIME_GET_MINUTE(self),
3675 TIME_GET_SECOND(self),
3676 0, 0, -1); /* weekday, daynum, dst */
3677 if (tuple == NULL)
3678 return NULL;
3679 assert(PyTuple_Size(tuple) == 9);
Tim Petersbad8ff02002-12-30 20:52:32 +00003680 result = wrap_strftime((PyObject *)self, format, tuple, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003681 Py_DECREF(tuple);
3682 return result;
3683}
3684
3685/* Miscellaneous methods. */
3686
3687/* This is more natural as a tp_compare, but doesn't work then: for whatever
3688 * reason, Python's try_3way_compare ignores tp_compare unless
3689 * PyInstance_Check returns true, but these aren't old-style classes.
3690 * Note that this routine handles all comparisons for time and timetz.
3691 */
3692static PyObject *
3693time_richcompare(PyDateTime_Time *self, PyObject *other, int op)
3694{
3695 int diff;
3696 naivety n1, n2;
3697 int offset1, offset2;
3698
3699 if (! PyTime_Check(other)) {
3700 /* Stop this from falling back to address comparison. */
3701 PyErr_Format(PyExc_TypeError,
3702 "can't compare '%s' to '%s'",
3703 self->ob_type->tp_name,
3704 other->ob_type->tp_name);
3705 return NULL;
3706 }
Tim Peterse39a80c2002-12-30 21:28:52 +00003707 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1, Py_None,
3708 other, &offset2, &n2, Py_None) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003709 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003710 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00003711 /* If they're both naive, or both aware and have the same offsets,
3712 * we get off cheap. Note that if they're both naive, offset1 ==
3713 * offset2 == 0 at this point.
3714 */
3715 if (n1 == n2 && offset1 == offset2) {
3716 diff = memcmp(self->data, ((PyDateTime_Time *)other)->data,
3717 _PyDateTime_TIME_DATASIZE);
3718 return diff_to_bool(diff, op);
3719 }
3720
3721 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3722 assert(offset1 != offset2); /* else last "if" handled it */
3723 /* Convert everything except microseconds to seconds. These
3724 * can't overflow (no more than the # of seconds in 2 days).
3725 */
3726 offset1 = TIME_GET_HOUR(self) * 3600 +
3727 (TIME_GET_MINUTE(self) - offset1) * 60 +
3728 TIME_GET_SECOND(self);
3729 offset2 = TIME_GET_HOUR(other) * 3600 +
3730 (TIME_GET_MINUTE(other) - offset2) * 60 +
3731 TIME_GET_SECOND(other);
3732 diff = offset1 - offset2;
3733 if (diff == 0)
3734 diff = TIME_GET_MICROSECOND(self) -
3735 TIME_GET_MICROSECOND(other);
3736 return diff_to_bool(diff, op);
3737 }
3738
3739 assert(n1 != n2);
3740 PyErr_SetString(PyExc_TypeError,
3741 "can't compare offset-naive and "
3742 "offset-aware times");
3743 return NULL;
3744}
3745
3746static PyObject *time_getstate(PyDateTime_Time *self);
3747
3748static long
3749time_hash(PyDateTime_Time *self)
3750{
3751 if (self->hashcode == -1) {
3752 naivety n;
3753 int offset;
3754 PyObject *temp;
3755
Tim Peterse39a80c2002-12-30 21:28:52 +00003756 n = classify_utcoffset((PyObject *)self, Py_None, &offset);
Tim Peters2a799bf2002-12-16 20:18:38 +00003757 assert(n != OFFSET_UNKNOWN);
3758 if (n == OFFSET_ERROR)
3759 return -1;
3760
3761 /* Reduce this to a hash of another object. */
3762 if (offset == 0)
3763 temp = time_getstate(self);
3764 else {
3765 int hour;
3766 int minute;
3767
3768 assert(n == OFFSET_AWARE);
3769 assert(PyTimeTZ_Check(self));
3770 hour = divmod(TIME_GET_HOUR(self) * 60 +
3771 TIME_GET_MINUTE(self) - offset,
3772 60,
3773 &minute);
3774 if (0 <= hour && hour < 24)
3775 temp = new_time(hour, minute,
3776 TIME_GET_SECOND(self),
3777 TIME_GET_MICROSECOND(self));
3778 else
3779 temp = Py_BuildValue("iiii",
3780 hour, minute,
3781 TIME_GET_SECOND(self),
3782 TIME_GET_MICROSECOND(self));
3783 }
3784 if (temp != NULL) {
3785 self->hashcode = PyObject_Hash(temp);
3786 Py_DECREF(temp);
3787 }
3788 }
3789 return self->hashcode;
3790}
3791
Tim Peters12bf3392002-12-24 05:41:27 +00003792static PyObject *
3793time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3794{
3795 PyObject *clone;
3796 PyObject *tuple;
3797 int hh = TIME_GET_HOUR(self);
3798 int mm = TIME_GET_MINUTE(self);
3799 int ss = TIME_GET_SECOND(self);
3800 int us = TIME_GET_MICROSECOND(self);
3801
3802 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiii:replace",
3803 time_kws,
3804 &hh, &mm, &ss, &us))
3805 return NULL;
3806 tuple = Py_BuildValue("iiii", hh, mm, ss, us);
3807 if (tuple == NULL)
3808 return NULL;
3809 clone = time_new(self->ob_type, tuple, NULL);
3810 Py_DECREF(tuple);
3811 return clone;
3812}
3813
Tim Peters2a799bf2002-12-16 20:18:38 +00003814static int
3815time_nonzero(PyDateTime_Time *self)
3816{
3817 return TIME_GET_HOUR(self) ||
3818 TIME_GET_MINUTE(self) ||
3819 TIME_GET_SECOND(self) ||
3820 TIME_GET_MICROSECOND(self);
3821}
3822
3823/* Pickle support. Quite a maze! */
3824
3825static PyObject *
3826time_getstate(PyDateTime_Time *self)
3827{
3828 return PyString_FromStringAndSize(self->data,
3829 _PyDateTime_TIME_DATASIZE);
3830}
3831
3832static PyObject *
3833time_setstate(PyDateTime_Time *self, PyObject *state)
3834{
3835 const int len = PyString_Size(state);
3836 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
3837
3838 if (! PyString_Check(state) ||
3839 len != _PyDateTime_TIME_DATASIZE) {
3840 PyErr_SetString(PyExc_TypeError,
3841 "bad argument to time.__setstate__");
3842 return NULL;
3843 }
3844 memcpy(self->data, pdata, _PyDateTime_TIME_DATASIZE);
3845 self->hashcode = -1;
3846
3847 Py_INCREF(Py_None);
3848 return Py_None;
3849}
3850
3851/* XXX This seems a ridiculously inefficient way to pickle a short string. */
3852static PyObject *
3853time_pickler(PyObject *module, PyDateTime_Time *time)
3854{
3855 PyObject *state;
3856 PyObject *result = NULL;
3857
3858 if (! PyTime_CheckExact(time)) {
3859 PyErr_Format(PyExc_TypeError,
3860 "bad type passed to time pickler: %s",
3861 time->ob_type->tp_name);
3862 return NULL;
3863 }
3864 state = time_getstate(time);
3865 if (state) {
3866 result = Py_BuildValue("O(O)",
3867 time_unpickler_object,
3868 state);
3869 Py_DECREF(state);
3870 }
3871 return result;
3872}
3873
3874static PyObject *
3875time_unpickler(PyObject *module, PyObject *arg)
3876{
3877 PyDateTime_Time *self;
3878
3879 if (! PyString_CheckExact(arg)) {
3880 PyErr_Format(PyExc_TypeError,
3881 "bad type passed to time unpickler: %s",
3882 arg->ob_type->tp_name);
3883 return NULL;
3884 }
3885 self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
3886 if (self != NULL) {
3887 PyObject *res = time_setstate(self, arg);
3888 if (res == NULL) {
3889 Py_DECREF(self);
3890 return NULL;
3891 }
3892 Py_DECREF(res);
3893 }
3894 return (PyObject *)self;
3895}
3896
3897static PyMethodDef time_methods[] = {
3898 {"isoformat", (PyCFunction)time_isoformat, METH_KEYWORDS,
3899 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm].")},
3900
3901 {"strftime", (PyCFunction)time_strftime, METH_KEYWORDS,
3902 PyDoc_STR("format -> strftime() style string.")},
3903
Tim Peters12bf3392002-12-24 05:41:27 +00003904 {"replace", (PyCFunction)time_replace, METH_KEYWORDS,
3905 PyDoc_STR("Return datetime with new specified fields.")},
3906
Tim Peters2a799bf2002-12-16 20:18:38 +00003907 {"__setstate__", (PyCFunction)time_setstate, METH_O,
3908 PyDoc_STR("__setstate__(state)")},
3909
3910 {"__getstate__", (PyCFunction)time_getstate, METH_NOARGS,
3911 PyDoc_STR("__getstate__() -> state")},
3912 {NULL, NULL}
3913};
3914
3915static char time_doc[] =
3916PyDoc_STR("Basic time type.");
3917
3918static PyNumberMethods time_as_number = {
3919 0, /* nb_add */
3920 0, /* nb_subtract */
3921 0, /* nb_multiply */
3922 0, /* nb_divide */
3923 0, /* nb_remainder */
3924 0, /* nb_divmod */
3925 0, /* nb_power */
3926 0, /* nb_negative */
3927 0, /* nb_positive */
3928 0, /* nb_absolute */
3929 (inquiry)time_nonzero, /* nb_nonzero */
3930};
3931
3932statichere PyTypeObject PyDateTime_TimeType = {
3933 PyObject_HEAD_INIT(NULL)
3934 0, /* ob_size */
3935 "datetime.time", /* tp_name */
3936 sizeof(PyDateTime_Time), /* tp_basicsize */
3937 0, /* tp_itemsize */
3938 (destructor)PyObject_Del, /* tp_dealloc */
3939 0, /* tp_print */
3940 0, /* tp_getattr */
3941 0, /* tp_setattr */
3942 0, /* tp_compare */
3943 (reprfunc)time_repr, /* tp_repr */
3944 &time_as_number, /* tp_as_number */
3945 0, /* tp_as_sequence */
3946 0, /* tp_as_mapping */
3947 (hashfunc)time_hash, /* tp_hash */
3948 0, /* tp_call */
3949 (reprfunc)time_str, /* tp_str */
3950 PyObject_GenericGetAttr, /* tp_getattro */
3951 0, /* tp_setattro */
3952 0, /* tp_as_buffer */
3953 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3954 Py_TPFLAGS_BASETYPE, /* tp_flags */
3955 time_doc, /* tp_doc */
3956 0, /* tp_traverse */
3957 0, /* tp_clear */
3958 (richcmpfunc)time_richcompare, /* tp_richcompare */
3959 0, /* tp_weaklistoffset */
3960 0, /* tp_iter */
3961 0, /* tp_iternext */
3962 time_methods, /* tp_methods */
3963 0, /* tp_members */
3964 time_getset, /* tp_getset */
3965 0, /* tp_base */
3966 0, /* tp_dict */
3967 0, /* tp_descr_get */
3968 0, /* tp_descr_set */
3969 0, /* tp_dictoffset */
3970 0, /* tp_init */
3971 0, /* tp_alloc */
3972 time_new, /* tp_new */
3973 _PyObject_Del, /* tp_free */
3974};
3975
3976/*
3977 * PyDateTime_TZInfo implementation.
3978 */
3979
3980/* This is a pure abstract base class, so doesn't do anything beyond
3981 * raising NotImplemented exceptions. Real tzinfo classes need
3982 * to derive from this. This is mostly for clarity, and for efficiency in
3983 * datetimetz and timetz constructors (their tzinfo arguments need to
3984 * be subclasses of this tzinfo class, which is easy and quick to check).
3985 *
3986 * Note: For reasons having to do with pickling of subclasses, we have
3987 * to allow tzinfo objects to be instantiated. This wasn't an issue
3988 * in the Python implementation (__init__() could raise NotImplementedError
3989 * there without ill effect), but doing so in the C implementation hit a
3990 * brick wall.
3991 */
3992
3993static PyObject *
3994tzinfo_nogo(const char* methodname)
3995{
3996 PyErr_Format(PyExc_NotImplementedError,
3997 "a tzinfo subclass must implement %s()",
3998 methodname);
3999 return NULL;
4000}
4001
4002/* Methods. A subclass must implement these. */
4003
4004static PyObject*
4005tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt)
4006{
4007 return tzinfo_nogo("tzname");
4008}
4009
4010static PyObject*
4011tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt)
4012{
4013 return tzinfo_nogo("utcoffset");
4014}
4015
4016static PyObject*
4017tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
4018{
4019 return tzinfo_nogo("dst");
4020}
4021
4022/*
4023 * Pickle support. This is solely so that tzinfo subclasses can use
4024 * pickling -- tzinfo itself is supposed to be uninstantiable. The
4025 * pickler and unpickler functions are given module-level private
4026 * names, and registered with copy_reg, by the module init function.
4027 */
4028
4029static PyObject*
4030tzinfo_pickler(PyDateTime_TZInfo *self) {
4031 return Py_BuildValue("O()", tzinfo_unpickler_object);
4032}
4033
4034static PyObject*
4035tzinfo_unpickler(PyObject * unused) {
4036 return PyType_GenericNew(&PyDateTime_TZInfoType, NULL, NULL);
4037}
4038
4039
4040static PyMethodDef tzinfo_methods[] = {
4041 {"tzname", (PyCFunction)tzinfo_tzname, METH_O,
4042 PyDoc_STR("datetime -> string name of time zone.")},
4043
4044 {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
4045 PyDoc_STR("datetime -> minutes east of UTC (negative for "
4046 "west of UTC).")},
4047
4048 {"dst", (PyCFunction)tzinfo_dst, METH_O,
4049 PyDoc_STR("datetime -> DST offset in minutes east of UTC.")},
4050
4051 {NULL, NULL}
4052};
4053
4054static char tzinfo_doc[] =
4055PyDoc_STR("Abstract base class for time zone info objects.");
4056
4057 statichere PyTypeObject PyDateTime_TZInfoType = {
4058 PyObject_HEAD_INIT(NULL)
4059 0, /* ob_size */
4060 "datetime.tzinfo", /* tp_name */
4061 sizeof(PyDateTime_TZInfo), /* tp_basicsize */
4062 0, /* tp_itemsize */
4063 0, /* tp_dealloc */
4064 0, /* tp_print */
4065 0, /* tp_getattr */
4066 0, /* tp_setattr */
4067 0, /* tp_compare */
4068 0, /* tp_repr */
4069 0, /* tp_as_number */
4070 0, /* tp_as_sequence */
4071 0, /* tp_as_mapping */
4072 0, /* tp_hash */
4073 0, /* tp_call */
4074 0, /* tp_str */
4075 PyObject_GenericGetAttr, /* tp_getattro */
4076 0, /* tp_setattro */
4077 0, /* tp_as_buffer */
4078 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4079 Py_TPFLAGS_BASETYPE, /* tp_flags */
4080 tzinfo_doc, /* tp_doc */
4081 0, /* tp_traverse */
4082 0, /* tp_clear */
4083 0, /* tp_richcompare */
4084 0, /* tp_weaklistoffset */
4085 0, /* tp_iter */
4086 0, /* tp_iternext */
4087 tzinfo_methods, /* tp_methods */
4088 0, /* tp_members */
4089 0, /* tp_getset */
4090 0, /* tp_base */
4091 0, /* tp_dict */
4092 0, /* tp_descr_get */
4093 0, /* tp_descr_set */
4094 0, /* tp_dictoffset */
4095 0, /* tp_init */
4096 0, /* tp_alloc */
4097 PyType_GenericNew, /* tp_new */
4098 0, /* tp_free */
4099};
4100
4101/*
4102 * PyDateTime_TimeTZ implementation.
4103 */
4104
4105/* Accessor properties. Properties for hour, minute, second and microsecond
4106 * are inherited from time.
4107 */
4108
4109static PyObject *
4110timetz_tzinfo(PyDateTime_TimeTZ *self, void *unused)
4111{
4112 Py_INCREF(self->tzinfo);
4113 return self->tzinfo;
4114}
4115
4116static PyGetSetDef timetz_getset[] = {
4117 {"tzinfo", (getter)timetz_tzinfo},
4118 {NULL}
4119};
4120
4121/*
4122 * Constructors.
4123 */
4124
Tim Peters12bf3392002-12-24 05:41:27 +00004125static char *timetz_kws[] = {"hour", "minute", "second", "microsecond",
4126 "tzinfo", NULL};
4127
Tim Peters2a799bf2002-12-16 20:18:38 +00004128static PyObject *
4129timetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4130{
4131 PyObject *self = NULL;
4132 int hour = 0;
4133 int minute = 0;
4134 int second = 0;
4135 int usecond = 0;
4136 PyObject *tzinfo = Py_None;
4137
Tim Peters12bf3392002-12-24 05:41:27 +00004138 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", timetz_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00004139 &hour, &minute, &second, &usecond,
4140 &tzinfo)) {
4141 if (check_time_args(hour, minute, second, usecond) < 0)
4142 return NULL;
4143 if (check_tzinfo_subclass(tzinfo) < 0)
4144 return NULL;
4145 self = new_timetz(hour, minute, second, usecond, tzinfo);
4146 }
4147 return self;
4148}
4149
4150/*
4151 * Destructor.
4152 */
4153
4154static void
4155timetz_dealloc(PyDateTime_TimeTZ *self)
4156{
4157 Py_XDECREF(self->tzinfo);
4158 self->ob_type->tp_free((PyObject *)self);
4159}
4160
4161/*
Tim Peters855fe882002-12-22 03:43:39 +00004162 * Indirect access to tzinfo methods.
Tim Peters2a799bf2002-12-16 20:18:38 +00004163 */
4164
Tim Peters2a799bf2002-12-16 20:18:38 +00004165/* These are all METH_NOARGS, so don't need to check the arglist. */
4166static PyObject *
4167timetz_utcoffset(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004168 return offset_as_timedelta(self->tzinfo, "utcoffset", Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004169}
4170
4171static PyObject *
4172timetz_dst(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004173 return offset_as_timedelta(self->tzinfo, "dst", Py_None);
Tim Peters855fe882002-12-22 03:43:39 +00004174}
4175
4176static PyObject *
4177timetz_tzname(PyDateTime_TimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004178 return call_tzname(self->tzinfo, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004179}
4180
4181/*
4182 * Various ways to turn a timetz into a string.
4183 */
4184
4185static PyObject *
4186timetz_repr(PyDateTime_TimeTZ *self)
4187{
4188 PyObject *baserepr = time_repr((PyDateTime_Time *)self);
4189
4190 if (baserepr == NULL)
4191 return NULL;
4192 return append_keyword_tzinfo(baserepr, self->tzinfo);
4193}
4194
4195/* Note: tp_str is inherited from time. */
4196
4197static PyObject *
4198timetz_isoformat(PyDateTime_TimeTZ *self)
4199{
4200 char buf[100];
4201 PyObject *result = time_isoformat((PyDateTime_Time *)self);
4202
4203 if (result == NULL || self->tzinfo == Py_None)
4204 return result;
4205
4206 /* We need to append the UTC offset. */
4207 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00004208 Py_None) < 0) {
Tim Peters2a799bf2002-12-16 20:18:38 +00004209 Py_DECREF(result);
4210 return NULL;
4211 }
4212 PyString_ConcatAndDel(&result, PyString_FromString(buf));
4213 return result;
4214}
4215
4216/* Note: strftime() is inherited from time. */
4217
4218/*
4219 * Miscellaneous methods.
4220 */
4221
4222/* Note: tp_richcompare and tp_hash are inherited from time. */
4223
Tim Peters12bf3392002-12-24 05:41:27 +00004224static PyObject *
4225timetz_replace(PyDateTime_TimeTZ *self, PyObject *args, PyObject *kw)
4226{
4227 PyObject *clone;
4228 PyObject *tuple;
4229 int hh = TIME_GET_HOUR(self);
4230 int mm = TIME_GET_MINUTE(self);
4231 int ss = TIME_GET_SECOND(self);
4232 int us = TIME_GET_MICROSECOND(self);
4233 PyObject *tzinfo = self->tzinfo;
4234
4235 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
4236 timetz_kws,
4237 &hh, &mm, &ss, &us, &tzinfo))
4238 return NULL;
4239 tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
4240 if (tuple == NULL)
4241 return NULL;
4242 clone = timetz_new(self->ob_type, tuple, NULL);
4243 Py_DECREF(tuple);
4244 return clone;
4245}
4246
Tim Peters2a799bf2002-12-16 20:18:38 +00004247static int
4248timetz_nonzero(PyDateTime_TimeTZ *self)
4249{
4250 int offset;
4251 int none;
4252
4253 if (TIME_GET_SECOND(self) || TIME_GET_MICROSECOND(self)) {
4254 /* Since utcoffset is in whole minutes, nothing can
4255 * alter the conclusion that this is nonzero.
4256 */
4257 return 1;
4258 }
4259 offset = 0;
4260 if (self->tzinfo != Py_None) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004261 offset = call_utcoffset(self->tzinfo, Py_None, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +00004262 if (offset == -1 && PyErr_Occurred())
4263 return -1;
4264 }
4265 return (TIME_GET_MINUTE(self) - offset + TIME_GET_HOUR(self)*60) != 0;
4266}
4267
4268/*
4269 * Pickle support. Quite a maze!
4270 */
4271
4272/* Let basestate be the state string returned by time_getstate.
4273 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4274 * So it's a tuple in any (non-error) case.
4275 */
4276static PyObject *
4277timetz_getstate(PyDateTime_TimeTZ *self)
4278{
4279 PyObject *basestate;
4280 PyObject *result = NULL;
4281
4282 basestate = time_getstate((PyDateTime_Time *)self);
4283 if (basestate != NULL) {
4284 if (self->tzinfo == Py_None)
4285 result = Py_BuildValue("(O)", basestate);
4286 else
4287 result = Py_BuildValue("OO", basestate, self->tzinfo);
4288 Py_DECREF(basestate);
4289 }
4290 return result;
4291}
4292
4293static PyObject *
4294timetz_setstate(PyDateTime_TimeTZ *self, PyObject *state)
4295{
4296 PyObject *temp;
4297 PyObject *basestate;
4298 PyObject *tzinfo = Py_None;
4299
4300 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
4301 &PyString_Type, &basestate,
4302 &tzinfo))
4303 return NULL;
4304 temp = time_setstate((PyDateTime_Time *)self, basestate);
4305 if (temp == NULL)
4306 return NULL;
4307 Py_DECREF(temp);
4308
4309 Py_INCREF(tzinfo);
4310 Py_XDECREF(self->tzinfo);
4311 self->tzinfo = tzinfo;
4312
4313 Py_INCREF(Py_None);
4314 return Py_None;
4315}
4316
4317static PyObject *
4318timetz_pickler(PyObject *module, PyDateTime_TimeTZ *timetz)
4319{
4320 PyObject *state;
4321 PyObject *result = NULL;
4322
4323 if (! PyTimeTZ_CheckExact(timetz)) {
4324 PyErr_Format(PyExc_TypeError,
4325 "bad type passed to timetz pickler: %s",
4326 timetz->ob_type->tp_name);
4327 return NULL;
4328 }
4329 state = timetz_getstate(timetz);
4330 if (state) {
4331 result = Py_BuildValue("O(O)",
4332 timetz_unpickler_object,
4333 state);
4334 Py_DECREF(state);
4335 }
4336 return result;
4337}
4338
4339static PyObject *
4340timetz_unpickler(PyObject *module, PyObject *arg)
4341{
4342 PyDateTime_TimeTZ *self;
4343
4344 self = PyObject_New(PyDateTime_TimeTZ, &PyDateTime_TimeTZType);
4345 if (self != NULL) {
4346 PyObject *res;
4347
4348 self->tzinfo = NULL;
4349 res = timetz_setstate(self, arg);
4350 if (res == NULL) {
4351 Py_DECREF(self);
4352 return NULL;
4353 }
4354 Py_DECREF(res);
4355 }
4356 return (PyObject *)self;
4357}
4358
4359static PyMethodDef timetz_methods[] = {
4360 {"isoformat", (PyCFunction)timetz_isoformat, METH_KEYWORDS,
4361 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]"
4362 "[+HH:MM].")},
4363
4364 {"utcoffset", (PyCFunction)timetz_utcoffset, METH_NOARGS,
4365 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
4366
4367 {"tzname", (PyCFunction)timetz_tzname, METH_NOARGS,
4368 PyDoc_STR("Return self.tzinfo.tzname(self).")},
4369
4370 {"dst", (PyCFunction)timetz_dst, METH_NOARGS,
4371 PyDoc_STR("Return self.tzinfo.dst(self).")},
4372
Tim Peters12bf3392002-12-24 05:41:27 +00004373 {"replace", (PyCFunction)timetz_replace, METH_KEYWORDS,
4374 PyDoc_STR("Return timetz with new specified fields.")},
4375
Tim Peters2a799bf2002-12-16 20:18:38 +00004376 {"__setstate__", (PyCFunction)timetz_setstate, METH_O,
4377 PyDoc_STR("__setstate__(state)")},
4378
4379 {"__getstate__", (PyCFunction)timetz_getstate, METH_NOARGS,
4380 PyDoc_STR("__getstate__() -> state")},
4381 {NULL, NULL}
4382
4383};
4384
4385static char timetz_doc[] =
4386PyDoc_STR("Time type.");
4387
4388static PyNumberMethods timetz_as_number = {
4389 0, /* nb_add */
4390 0, /* nb_subtract */
4391 0, /* nb_multiply */
4392 0, /* nb_divide */
4393 0, /* nb_remainder */
4394 0, /* nb_divmod */
4395 0, /* nb_power */
4396 0, /* nb_negative */
4397 0, /* nb_positive */
4398 0, /* nb_absolute */
4399 (inquiry)timetz_nonzero, /* nb_nonzero */
4400};
4401
4402statichere PyTypeObject PyDateTime_TimeTZType = {
4403 PyObject_HEAD_INIT(NULL)
4404 0, /* ob_size */
4405 "datetime.timetz", /* tp_name */
4406 sizeof(PyDateTime_TimeTZ), /* tp_basicsize */
4407 0, /* tp_itemsize */
4408 (destructor)timetz_dealloc, /* tp_dealloc */
4409 0, /* tp_print */
4410 0, /* tp_getattr */
4411 0, /* tp_setattr */
4412 0, /* tp_compare */
4413 (reprfunc)timetz_repr, /* tp_repr */
4414 &timetz_as_number, /* tp_as_number */
4415 0, /* tp_as_sequence */
4416 0, /* tp_as_mapping */
4417 0, /* tp_hash */
4418 0, /* tp_call */
4419 0, /* tp_str */
4420 PyObject_GenericGetAttr, /* tp_getattro */
4421 0, /* tp_setattro */
4422 0, /* tp_as_buffer */
4423 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4424 Py_TPFLAGS_BASETYPE, /* tp_flags */
Guido van Rossumbd43e912002-12-16 20:34:55 +00004425 timetz_doc, /* tp_doc */
Tim Peters2a799bf2002-12-16 20:18:38 +00004426 0, /* tp_traverse */
4427 0, /* tp_clear */
4428 0, /* tp_richcompare */
4429 0, /* tp_weaklistoffset */
4430 0, /* tp_iter */
4431 0, /* tp_iternext */
4432 timetz_methods, /* tp_methods */
4433 0, /* tp_members */
4434 timetz_getset, /* tp_getset */
4435 &PyDateTime_TimeType, /* tp_base */
4436 0, /* tp_dict */
4437 0, /* tp_descr_get */
4438 0, /* tp_descr_set */
4439 0, /* tp_dictoffset */
4440 0, /* tp_init */
4441 0, /* tp_alloc */
4442 timetz_new, /* tp_new */
4443 _PyObject_Del, /* tp_free */
4444};
4445
4446/*
4447 * PyDateTime_DateTimeTZ implementation.
4448 */
4449
4450/* Accessor properties. Properties for day, month, year, hour, minute,
4451 * second and microsecond are inherited from datetime.
4452 */
4453
4454static PyObject *
4455datetimetz_tzinfo(PyDateTime_DateTimeTZ *self, void *unused)
4456{
4457 Py_INCREF(self->tzinfo);
4458 return self->tzinfo;
4459}
4460
4461static PyGetSetDef datetimetz_getset[] = {
4462 {"tzinfo", (getter)datetimetz_tzinfo},
4463 {NULL}
4464};
4465
4466/*
4467 * Constructors.
4468 * These are like the datetime methods of the same names, but allow an
4469 * optional tzinfo argument.
4470 */
4471
Tim Peters12bf3392002-12-24 05:41:27 +00004472static char *datetimetz_kws[] = {
4473 "year", "month", "day", "hour", "minute", "second",
4474 "microsecond", "tzinfo", NULL
4475};
4476
Tim Peters2a799bf2002-12-16 20:18:38 +00004477static PyObject *
4478datetimetz_new(PyTypeObject *type, PyObject *args, PyObject *kw)
4479{
4480 PyObject *self = NULL;
4481 int year;
4482 int month;
4483 int day;
4484 int hour = 0;
4485 int minute = 0;
4486 int second = 0;
4487 int usecond = 0;
4488 PyObject *tzinfo = Py_None;
4489
Tim Peters12bf3392002-12-24 05:41:27 +00004490 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO", datetimetz_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00004491 &year, &month, &day, &hour, &minute,
4492 &second, &usecond, &tzinfo)) {
4493 if (check_date_args(year, month, day) < 0)
4494 return NULL;
4495 if (check_time_args(hour, minute, second, usecond) < 0)
4496 return NULL;
4497 if (check_tzinfo_subclass(tzinfo) < 0)
4498 return NULL;
4499 self = new_datetimetz(year, month, day,
4500 hour, minute, second, usecond,
4501 tzinfo);
4502 }
4503 return self;
4504}
4505
4506/* Return best possible local time -- this isn't constrained by the
4507 * precision of a timestamp.
4508 */
4509static PyObject *
4510datetimetz_now(PyObject *cls, PyObject *args, PyObject *kw)
4511{
4512 PyObject *self = NULL;
4513 PyObject *tzinfo = Py_None;
4514 static char *keywords[] = {"tzinfo", NULL};
4515
4516 if (PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords,
4517 &tzinfo)) {
4518 if (check_tzinfo_subclass(tzinfo) < 0)
4519 return NULL;
4520 self = datetime_best_possible(cls, localtime);
4521 if (self != NULL)
4522 replace_tzinfo(self, tzinfo);
4523 }
4524 return self;
4525}
4526
4527/* Return new local datetime from timestamp (Python timestamp -- a double). */
4528static PyObject *
4529datetimetz_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
4530{
4531 PyObject *self = NULL;
4532 double timestamp;
4533 PyObject *tzinfo = Py_None;
4534 static char *keywords[] = {"timestamp", "tzinfo", NULL};
4535
4536 if (PyArg_ParseTupleAndKeywords(args, kw, "d|O:fromtimestamp",
4537 keywords, &timestamp, &tzinfo)) {
4538 if (check_tzinfo_subclass(tzinfo) < 0)
4539 return NULL;
4540 self = datetime_from_timestamp(cls, localtime, timestamp);
4541 if (self != NULL)
4542 replace_tzinfo(self, tzinfo);
4543 }
4544 return self;
4545}
4546
4547/* Note: utcnow() is inherited, and doesn't accept tzinfo.
4548 * Ditto utcfromtimestamp(). Ditto combine().
4549 */
4550
4551
4552/*
4553 * Destructor.
4554 */
4555
4556static void
4557datetimetz_dealloc(PyDateTime_DateTimeTZ *self)
4558{
4559 Py_XDECREF(self->tzinfo);
4560 self->ob_type->tp_free((PyObject *)self);
4561}
4562
4563/*
4564 * Indirect access to tzinfo methods.
4565 */
4566
Tim Peters2a799bf2002-12-16 20:18:38 +00004567/* These are all METH_NOARGS, so don't need to check the arglist. */
4568static PyObject *
4569datetimetz_utcoffset(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004570 return offset_as_timedelta(self->tzinfo, "utcoffset",
4571 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00004572}
4573
4574static PyObject *
4575datetimetz_dst(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004576 return offset_as_timedelta(self->tzinfo, "dst", (PyObject *)self);
Tim Peters855fe882002-12-22 03:43:39 +00004577}
4578
4579static PyObject *
4580datetimetz_tzname(PyDateTime_DateTimeTZ *self, PyObject *unused) {
Tim Petersbad8ff02002-12-30 20:52:32 +00004581 return call_tzname(self->tzinfo, (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00004582}
4583
4584/*
4585 * datetimetz arithmetic.
4586 */
4587
4588/* If base is Py_NotImplemented or NULL, just return it.
4589 * Else base is a datetime, exactly one of {left, right} is a datetimetz,
4590 * and we want to create a datetimetz with the same date and time fields
4591 * as base, and with the tzinfo field from left or right. Do that,
4592 * return it, and decref base. This is used to transform the result of
4593 * a binary datetime operation (base) into a datetimetz result.
4594 */
4595static PyObject *
4596attach_tzinfo(PyObject *base, PyObject *left, PyObject *right)
4597{
4598 PyDateTime_DateTimeTZ *self;
4599 PyDateTime_DateTimeTZ *result;
4600
4601 if (base == NULL || base == Py_NotImplemented)
4602 return base;
4603
4604 assert(PyDateTime_CheckExact(base));
4605
4606 if (PyDateTimeTZ_Check(left)) {
4607 assert(! PyDateTimeTZ_Check(right));
4608 self = (PyDateTime_DateTimeTZ *)left;
4609 }
4610 else {
4611 assert(PyDateTimeTZ_Check(right));
4612 self = (PyDateTime_DateTimeTZ *)right;
4613 }
4614 result = PyObject_New(PyDateTime_DateTimeTZ,
4615 &PyDateTime_DateTimeTZType);
4616 if (result != NULL) {
4617 memcpy(result->data, ((PyDateTime_DateTime *)base)->data,
4618 _PyDateTime_DATETIME_DATASIZE);
4619 Py_INCREF(self->tzinfo);
4620 result->tzinfo = self->tzinfo;
4621 }
4622 Py_DECREF(base);
4623 return (PyObject *)result;
4624}
4625
4626static PyObject *
4627datetimetz_add(PyObject *left, PyObject *right)
4628{
4629 return attach_tzinfo(datetime_add(left, right), left, right);
4630}
4631
4632static PyObject *
4633datetimetz_subtract(PyObject *left, PyObject *right)
4634{
4635 PyObject *result = Py_NotImplemented;
4636
4637 if (PyDateTime_Check(left)) {
4638 /* datetime - ??? */
4639 if (PyDateTime_Check(right)) {
4640 /* datetime - datetime */
4641 naivety n1, n2;
4642 int offset1, offset2;
4643 PyDateTime_Delta *delta;
4644
Tim Peterse39a80c2002-12-30 21:28:52 +00004645 if (classify_two_utcoffsets(left, &offset1, &n1, left,
4646 right, &offset2, &n2,
4647 right) < 0)
Tim Peters00237032002-12-27 02:21:51 +00004648 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00004649 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00004650 if (n1 != n2) {
4651 PyErr_SetString(PyExc_TypeError,
4652 "can't subtract offset-naive and "
4653 "offset-aware datetimes");
4654 return NULL;
4655 }
4656 delta = (PyDateTime_Delta *)sub_datetime_datetime(
4657 (PyDateTime_DateTime *)left,
4658 (PyDateTime_DateTime *)right);
4659 if (delta == NULL || offset1 == offset2)
4660 return (PyObject *)delta;
4661 /* (left - offset1) - (right - offset2) =
4662 * (left - right) + (offset2 - offset1)
4663 */
4664 result = new_delta(delta->days,
4665 delta->seconds +
4666 (offset2 - offset1) * 60,
4667 delta->microseconds,
4668 1);
4669 Py_DECREF(delta);
4670 }
4671 else if (PyDelta_Check(right)) {
4672 /* datetimetz - delta */
4673 result = sub_datetime_timedelta(
4674 (PyDateTime_DateTime *)left,
4675 (PyDateTime_Delta *)right);
4676 result = attach_tzinfo(result, left, right);
4677 }
4678 }
4679
4680 if (result == Py_NotImplemented)
4681 Py_INCREF(result);
4682 return result;
4683}
4684
4685/* Various ways to turn a datetime into a string. */
4686
4687static PyObject *
4688datetimetz_repr(PyDateTime_DateTimeTZ *self)
4689{
4690 PyObject *baserepr = datetime_repr((PyDateTime_DateTime *)self);
4691
4692 if (baserepr == NULL)
4693 return NULL;
4694 return append_keyword_tzinfo(baserepr, self->tzinfo);
4695}
4696
4697/* Note: tp_str is inherited from datetime. */
4698
4699static PyObject *
4700datetimetz_isoformat(PyDateTime_DateTimeTZ *self,
4701 PyObject *args, PyObject *kw)
4702{
4703 char buf[100];
4704 PyObject *result = datetime_isoformat((PyDateTime_DateTime *)self,
4705 args, kw);
4706
4707 if (result == NULL || self->tzinfo == Py_None)
4708 return result;
4709
4710 /* We need to append the UTC offset. */
4711 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
4712 (PyObject *)self) < 0) {
4713 Py_DECREF(result);
4714 return NULL;
4715 }
4716 PyString_ConcatAndDel(&result, PyString_FromString(buf));
4717 return result;
4718}
4719
4720/* Miscellaneous methods. */
4721
4722/* Note: tp_richcompare and tp_hash are inherited from datetime. */
4723
4724static PyObject *
Tim Peters12bf3392002-12-24 05:41:27 +00004725datetimetz_replace(PyDateTime_DateTimeTZ *self, PyObject *args, PyObject *kw)
4726{
4727 PyObject *clone;
4728 PyObject *tuple;
4729 int y = GET_YEAR(self);
4730 int m = GET_MONTH(self);
4731 int d = GET_DAY(self);
4732 int hh = DATE_GET_HOUR(self);
4733 int mm = DATE_GET_MINUTE(self);
4734 int ss = DATE_GET_SECOND(self);
4735 int us = DATE_GET_MICROSECOND(self);
4736 PyObject *tzinfo = self->tzinfo;
4737
4738 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO:replace",
4739 datetimetz_kws,
4740 &y, &m, &d, &hh, &mm, &ss, &us,
4741 &tzinfo))
4742 return NULL;
4743 tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
4744 if (tuple == NULL)
4745 return NULL;
4746 clone = datetimetz_new(self->ob_type, tuple, NULL);
4747 Py_DECREF(tuple);
4748 return clone;
4749}
4750
4751static PyObject *
Tim Peters80475bb2002-12-25 07:40:55 +00004752datetimetz_astimezone(PyDateTime_DateTimeTZ *self, PyObject *args,
4753 PyObject *kw)
4754{
4755 int y = GET_YEAR(self);
4756 int m = GET_MONTH(self);
4757 int d = GET_DAY(self);
4758 int hh = DATE_GET_HOUR(self);
4759 int mm = DATE_GET_MINUTE(self);
4760 int ss = DATE_GET_SECOND(self);
4761 int us = DATE_GET_MICROSECOND(self);
4762
Tim Peters521fc152002-12-31 17:36:56 +00004763 PyObject *result;
4764 PyObject *temp;
Tim Petersf3615152003-01-01 21:51:37 +00004765 int selfoff, resoff, resdst, total_added_to_result;
Tim Peters521fc152002-12-31 17:36:56 +00004766 int none;
Tim Petersf3615152003-01-01 21:51:37 +00004767 int delta;
Tim Peters521fc152002-12-31 17:36:56 +00004768
Tim Peters80475bb2002-12-25 07:40:55 +00004769 PyObject *tzinfo;
4770 static char *keywords[] = {"tz", NULL};
4771
4772 if (! PyArg_ParseTupleAndKeywords(args, kw, "O:astimezone", keywords,
4773 &tzinfo))
4774 return NULL;
4775 if (check_tzinfo_subclass(tzinfo) < 0)
4776 return NULL;
4777
Tim Peters521fc152002-12-31 17:36:56 +00004778 /* Don't call utcoffset unless necessary. */
4779 result = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4780 if (result == NULL ||
4781 tzinfo == Py_None ||
4782 self->tzinfo == Py_None ||
4783 self->tzinfo == tzinfo)
4784 return result;
4785
4786 /* Get the offsets. If either object turns out to be naive, again
4787 * there's no conversion of date or time fields.
4788 */
Tim Petersb5a16f32003-01-01 04:48:01 +00004789 selfoff = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4790 if (selfoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004791 goto Fail;
4792 if (none)
4793 return result;
4794
Tim Petersb5a16f32003-01-01 04:48:01 +00004795 resoff = call_utcoffset(tzinfo, result, &none);
4796 if (resoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004797 goto Fail;
4798 if (none)
4799 return result;
4800
Tim Petersf3615152003-01-01 21:51:37 +00004801 /* See the long comment block at the end of this file for an
4802 * explanation of this algorithm. That it always works requires a
4803 * pretty intricate proof.
Tim Peters521fc152002-12-31 17:36:56 +00004804 */
Tim Petersf3615152003-01-01 21:51:37 +00004805 resdst = call_dst(tzinfo, result, &none);
4806 if (resdst == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004807 goto Fail;
Tim Peters710fb152003-01-02 19:35:54 +00004808 if (none) {
4809 PyErr_SetString(PyExc_ValueError, "astimezone(): utcoffset() "
4810 "returned a duration but dst() returned None");
4811 goto Fail;
4812 }
Tim Petersf3615152003-01-01 21:51:37 +00004813 total_added_to_result = resoff - resdst - selfoff;
4814 if (total_added_to_result != 0) {
4815 mm += total_added_to_result;
Tim Petersb5a16f32003-01-01 04:48:01 +00004816 if ((mm < 0 || mm >= 60) &&
4817 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters521fc152002-12-31 17:36:56 +00004818 goto Fail;
4819 temp = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4820 if (temp == NULL)
4821 goto Fail;
4822 Py_DECREF(result);
4823 result = temp;
4824
Tim Petersb5a16f32003-01-01 04:48:01 +00004825 resoff = call_utcoffset(tzinfo, result, &none);
4826 if (resoff == -1 && PyErr_Occurred())
Tim Peters521fc152002-12-31 17:36:56 +00004827 goto Fail;
4828 if (none)
4829 goto Inconsistent;
Tim Petersf3615152003-01-01 21:51:37 +00004830 }
4831
4832 /* The distance now from self to result is
4833 * self - result == naive(self) - selfoff - (naive(result) - resoff) ==
4834 * naive(self) - selfoff -
4835 * ((naive(self) + total_added_to_result - resoff) ==
4836 * - selfoff - total_added_to_result + resoff.
Tim Peters521fc152002-12-31 17:36:56 +00004837 */
Tim Petersf3615152003-01-01 21:51:37 +00004838 delta = resoff - selfoff - total_added_to_result;
4839
4840 /* Now self and result are the same UTC time iff delta is 0.
4841 * If it is 0, we're done, although that takes some proving.
4842 */
4843 if (delta == 0)
4844 return result;
4845
4846 total_added_to_result += delta;
4847 mm += delta;
4848 if ((mm < 0 || mm >= 60) &&
4849 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters521fc152002-12-31 17:36:56 +00004850 goto Fail;
Tim Petersf3615152003-01-01 21:51:37 +00004851
Tim Peters521fc152002-12-31 17:36:56 +00004852 temp = new_datetimetz(y, m, d, hh, mm, ss, us, tzinfo);
4853 if (temp == NULL)
4854 goto Fail;
Tim Petersf3615152003-01-01 21:51:37 +00004855 Py_DECREF(result);
4856 result = temp;
Tim Peters521fc152002-12-31 17:36:56 +00004857
Tim Petersf3615152003-01-01 21:51:37 +00004858 resoff = call_utcoffset(tzinfo, result, &none);
4859 if (resoff == -1 && PyErr_Occurred())
4860 goto Fail;
4861 if (none)
4862 goto Inconsistent;
4863
4864 if (resoff - selfoff == total_added_to_result)
4865 /* self and result are the same UTC time */
Tim Peters521fc152002-12-31 17:36:56 +00004866 return result;
Tim Petersb5a16f32003-01-01 04:48:01 +00004867
4868 /* Else there's no way to spell self in zone tzinfo. */
Tim Peters521fc152002-12-31 17:36:56 +00004869 PyErr_SetString(PyExc_ValueError, "astimezone(): the source "
4870 "datetimetz can't be expressed in the target "
4871 "timezone's local time");
4872 goto Fail;
4873
4874Inconsistent:
4875 PyErr_SetString(PyExc_ValueError, "astimezone(): tz.utcoffset() "
4876 "gave inconsistent results; cannot convert");
4877
4878 /* fall thru to failure */
4879Fail:
4880 Py_DECREF(result);
4881 return NULL;
Tim Peters80475bb2002-12-25 07:40:55 +00004882}
4883
4884static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00004885datetimetz_timetuple(PyDateTime_DateTimeTZ *self)
4886{
4887 int dstflag = -1;
4888
4889 if (self->tzinfo != Py_None) {
4890 int none;
4891
4892 dstflag = call_dst(self->tzinfo, (PyObject *)self, &none);
4893 if (dstflag == -1 && PyErr_Occurred())
4894 return NULL;
4895
4896 if (none)
4897 dstflag = -1;
4898 else if (dstflag != 0)
4899 dstflag = 1;
4900
4901 }
4902 return build_struct_time(GET_YEAR(self),
4903 GET_MONTH(self),
4904 GET_DAY(self),
4905 DATE_GET_HOUR(self),
4906 DATE_GET_MINUTE(self),
4907 DATE_GET_SECOND(self),
4908 dstflag);
4909}
4910
4911static PyObject *
4912datetimetz_utctimetuple(PyDateTime_DateTimeTZ *self)
4913{
4914 int y = GET_YEAR(self);
4915 int m = GET_MONTH(self);
4916 int d = GET_DAY(self);
4917 int hh = DATE_GET_HOUR(self);
4918 int mm = DATE_GET_MINUTE(self);
4919 int ss = DATE_GET_SECOND(self);
4920 int us = 0; /* microseconds are ignored in a timetuple */
4921 int offset = 0;
4922
4923 if (self->tzinfo != Py_None) {
4924 int none;
4925
4926 offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4927 if (offset == -1 && PyErr_Occurred())
4928 return NULL;
4929 }
4930 /* Even if offset is 0, don't call timetuple() -- tm_isdst should be
4931 * 0 in a UTC timetuple regardless of what dst() says.
4932 */
4933 if (offset) {
4934 /* Subtract offset minutes & normalize. */
4935 int stat;
4936
4937 mm -= offset;
4938 stat = normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us);
4939 if (stat < 0) {
4940 /* At the edges, it's possible we overflowed
4941 * beyond MINYEAR or MAXYEAR.
4942 */
4943 if (PyErr_ExceptionMatches(PyExc_OverflowError))
4944 PyErr_Clear();
4945 else
4946 return NULL;
4947 }
4948 }
4949 return build_struct_time(y, m, d, hh, mm, ss, 0);
4950}
4951
4952static PyObject *
4953datetimetz_gettimetz(PyDateTime_DateTimeTZ *self)
4954{
4955 return new_timetz(DATE_GET_HOUR(self),
4956 DATE_GET_MINUTE(self),
4957 DATE_GET_SECOND(self),
4958 DATE_GET_MICROSECOND(self),
4959 self->tzinfo);
4960}
4961
4962/*
4963 * Pickle support. Quite a maze!
4964 */
4965
4966/* Let basestate be the state string returned by datetime_getstate.
4967 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4968 * So it's a tuple in any (non-error) case.
4969 */
4970static PyObject *
4971datetimetz_getstate(PyDateTime_DateTimeTZ *self)
4972{
4973 PyObject *basestate;
4974 PyObject *result = NULL;
4975
4976 basestate = datetime_getstate((PyDateTime_DateTime *)self);
4977 if (basestate != NULL) {
4978 if (self->tzinfo == Py_None)
4979 result = Py_BuildValue("(O)", basestate);
4980 else
4981 result = Py_BuildValue("OO", basestate, self->tzinfo);
4982 Py_DECREF(basestate);
4983 }
4984 return result;
4985}
4986
4987static PyObject *
4988datetimetz_setstate(PyDateTime_DateTimeTZ *self, PyObject *state)
4989{
4990 PyObject *temp;
4991 PyObject *basestate;
4992 PyObject *tzinfo = Py_None;
4993
4994 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
4995 &PyString_Type, &basestate,
4996 &tzinfo))
4997 return NULL;
4998 temp = datetime_setstate((PyDateTime_DateTime *)self, basestate);
4999 if (temp == NULL)
5000 return NULL;
5001 Py_DECREF(temp);
5002
5003 Py_INCREF(tzinfo);
5004 Py_XDECREF(self->tzinfo);
5005 self->tzinfo = tzinfo;
5006
5007 Py_INCREF(Py_None);
5008 return Py_None;
5009}
5010
5011static PyObject *
5012datetimetz_pickler(PyObject *module, PyDateTime_DateTimeTZ *datetimetz)
5013{
5014 PyObject *state;
5015 PyObject *result = NULL;
5016
5017 if (! PyDateTimeTZ_CheckExact(datetimetz)) {
5018 PyErr_Format(PyExc_TypeError,
5019 "bad type passed to datetimetz pickler: %s",
5020 datetimetz->ob_type->tp_name);
5021 return NULL;
5022 }
5023 state = datetimetz_getstate(datetimetz);
5024 if (state) {
5025 result = Py_BuildValue("O(O)",
5026 datetimetz_unpickler_object,
5027 state);
5028 Py_DECREF(state);
5029 }
5030 return result;
5031}
5032
5033static PyObject *
5034datetimetz_unpickler(PyObject *module, PyObject *arg)
5035{
5036 PyDateTime_DateTimeTZ *self;
5037
5038 self = PyObject_New(PyDateTime_DateTimeTZ, &PyDateTime_DateTimeTZType);
5039 if (self != NULL) {
5040 PyObject *res;
5041
5042 self->tzinfo = NULL;
5043 res = datetimetz_setstate(self, arg);
5044 if (res == NULL) {
5045 Py_DECREF(self);
5046 return NULL;
5047 }
5048 Py_DECREF(res);
5049 }
5050 return (PyObject *)self;
5051}
5052
5053
5054static PyMethodDef datetimetz_methods[] = {
5055 /* Class methods: */
5056 /* Inherited: combine(), utcnow(), utcfromtimestamp() */
5057
5058 {"now", (PyCFunction)datetimetz_now,
5059 METH_KEYWORDS | METH_CLASS,
5060 PyDoc_STR("[tzinfo] -> new datetimetz with local day and time.")},
5061
5062 {"fromtimestamp", (PyCFunction)datetimetz_fromtimestamp,
5063 METH_KEYWORDS | METH_CLASS,
5064 PyDoc_STR("timestamp[, tzinfo] -> local time from POSIX timestamp.")},
5065
5066 /* Instance methods: */
5067 /* Inherited: date(), time(), ctime(). */
5068 {"timetuple", (PyCFunction)datetimetz_timetuple, METH_NOARGS,
5069 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
5070
5071 {"utctimetuple", (PyCFunction)datetimetz_utctimetuple, METH_NOARGS,
5072 PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")},
5073
5074 {"timetz", (PyCFunction)datetimetz_gettimetz, METH_NOARGS,
5075 PyDoc_STR("Return timetz object with same hour, minute, second, "
5076 "microsecond, and tzinfo.")},
5077
5078 {"isoformat", (PyCFunction)datetimetz_isoformat, METH_KEYWORDS,
5079 PyDoc_STR("[sep] -> string in ISO 8601 format, "
5080 "YYYY-MM-DDTHH:MM:SS[.mmmmmm][+HH:MM].\n\n"
5081 "sep is used to separate the year from the time, and "
5082 "defaults to 'T'.")},
5083
5084 {"utcoffset", (PyCFunction)datetimetz_utcoffset, METH_NOARGS,
5085 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
5086
5087 {"tzname", (PyCFunction)datetimetz_tzname, METH_NOARGS,
5088 PyDoc_STR("Return self.tzinfo.tzname(self).")},
5089
5090 {"dst", (PyCFunction)datetimetz_dst, METH_NOARGS,
5091 PyDoc_STR("Return self.tzinfo.dst(self).")},
5092
Tim Peters12bf3392002-12-24 05:41:27 +00005093 {"replace", (PyCFunction)datetimetz_replace, METH_KEYWORDS,
5094 PyDoc_STR("Return datetimetz with new specified fields.")},
5095
Tim Peters80475bb2002-12-25 07:40:55 +00005096 {"astimezone", (PyCFunction)datetimetz_astimezone, METH_KEYWORDS,
5097 PyDoc_STR("tz -> convert to local time in new timezone tz\n")},
5098
Tim Peters2a799bf2002-12-16 20:18:38 +00005099 {"__setstate__", (PyCFunction)datetimetz_setstate, METH_O,
5100 PyDoc_STR("__setstate__(state)")},
5101
5102 {"__getstate__", (PyCFunction)datetimetz_getstate, METH_NOARGS,
5103 PyDoc_STR("__getstate__() -> state")},
5104 {NULL, NULL}
5105};
5106
5107static char datetimetz_doc[] =
5108PyDoc_STR("date/time type.");
5109
5110static PyNumberMethods datetimetz_as_number = {
5111 datetimetz_add, /* nb_add */
5112 datetimetz_subtract, /* nb_subtract */
5113 0, /* nb_multiply */
5114 0, /* nb_divide */
5115 0, /* nb_remainder */
5116 0, /* nb_divmod */
5117 0, /* nb_power */
5118 0, /* nb_negative */
5119 0, /* nb_positive */
5120 0, /* nb_absolute */
5121 0, /* nb_nonzero */
5122};
5123
5124statichere PyTypeObject PyDateTime_DateTimeTZType = {
5125 PyObject_HEAD_INIT(NULL)
5126 0, /* ob_size */
5127 "datetime.datetimetz", /* tp_name */
5128 sizeof(PyDateTime_DateTimeTZ), /* tp_basicsize */
5129 0, /* tp_itemsize */
5130 (destructor)datetimetz_dealloc, /* tp_dealloc */
5131 0, /* tp_print */
5132 0, /* tp_getattr */
5133 0, /* tp_setattr */
5134 0, /* tp_compare */
5135 (reprfunc)datetimetz_repr, /* tp_repr */
5136 &datetimetz_as_number, /* tp_as_number */
5137 0, /* tp_as_sequence */
5138 0, /* tp_as_mapping */
5139 0, /* tp_hash */
5140 0, /* tp_call */
5141 0, /* tp_str */
5142 PyObject_GenericGetAttr, /* tp_getattro */
5143 0, /* tp_setattro */
5144 0, /* tp_as_buffer */
5145 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
5146 Py_TPFLAGS_BASETYPE, /* tp_flags */
5147 datetimetz_doc, /* tp_doc */
5148 0, /* tp_traverse */
5149 0, /* tp_clear */
5150 0, /* tp_richcompare */
5151 0, /* tp_weaklistoffset */
5152 0, /* tp_iter */
5153 0, /* tp_iternext */
5154 datetimetz_methods, /* tp_methods */
5155 0, /* tp_members */
5156 datetimetz_getset, /* tp_getset */
5157 &PyDateTime_DateTimeType, /* tp_base */
5158 0, /* tp_dict */
5159 0, /* tp_descr_get */
5160 0, /* tp_descr_set */
5161 0, /* tp_dictoffset */
5162 0, /* tp_init */
5163 0, /* tp_alloc */
5164 datetimetz_new, /* tp_new */
5165 _PyObject_Del, /* tp_free */
5166};
5167
5168/* ---------------------------------------------------------------------------
5169 * Module methods and initialization.
5170 */
5171
5172static PyMethodDef module_methods[] = {
5173 /* Private functions for pickling support, registered with the
5174 * copy_reg module by the module init function.
5175 */
5176 {"_date_pickler", (PyCFunction)date_pickler, METH_O, NULL},
5177 {"_date_unpickler", (PyCFunction)date_unpickler, METH_O, NULL},
5178 {"_datetime_pickler", (PyCFunction)datetime_pickler, METH_O, NULL},
5179 {"_datetime_unpickler", (PyCFunction)datetime_unpickler,METH_O, NULL},
5180 {"_datetimetz_pickler", (PyCFunction)datetimetz_pickler,METH_O, NULL},
5181 {"_datetimetz_unpickler",(PyCFunction)datetimetz_unpickler,METH_O, NULL},
5182 {"_time_pickler", (PyCFunction)time_pickler, METH_O, NULL},
5183 {"_time_unpickler", (PyCFunction)time_unpickler, METH_O, NULL},
5184 {"_timetz_pickler", (PyCFunction)timetz_pickler, METH_O, NULL},
5185 {"_timetz_unpickler", (PyCFunction)timetz_unpickler, METH_O, NULL},
5186 {"_tzinfo_pickler", (PyCFunction)tzinfo_pickler, METH_O, NULL},
5187 {"_tzinfo_unpickler", (PyCFunction)tzinfo_unpickler, METH_NOARGS,
5188 NULL},
5189 {NULL, NULL}
5190};
5191
5192PyMODINIT_FUNC
5193initdatetime(void)
5194{
5195 PyObject *m; /* a module object */
5196 PyObject *d; /* its dict */
5197 PyObject *x;
5198
5199 /* Types that use __reduce__ for pickling need to set the following
5200 * magical attr in the type dict, with a true value.
5201 */
5202 PyObject *safepickle = PyString_FromString("__safe_for_unpickling__");
5203 if (safepickle == NULL)
5204 return;
5205
5206 m = Py_InitModule3("datetime", module_methods,
5207 "Fast implementation of the datetime type.");
5208
5209 if (PyType_Ready(&PyDateTime_DateType) < 0)
5210 return;
5211 if (PyType_Ready(&PyDateTime_DateTimeType) < 0)
5212 return;
5213 if (PyType_Ready(&PyDateTime_DeltaType) < 0)
5214 return;
5215 if (PyType_Ready(&PyDateTime_TimeType) < 0)
5216 return;
5217 if (PyType_Ready(&PyDateTime_TZInfoType) < 0)
5218 return;
5219 if (PyType_Ready(&PyDateTime_TimeTZType) < 0)
5220 return;
5221 if (PyType_Ready(&PyDateTime_DateTimeTZType) < 0)
5222 return;
5223
5224 /* Pickling support, via registering functions with copy_reg. */
5225 {
5226 PyObject *pickler;
5227 PyObject *copyreg = PyImport_ImportModule("copy_reg");
5228
5229 if (copyreg == NULL) return;
5230
5231 pickler = PyObject_GetAttrString(m, "_date_pickler");
5232 if (pickler == NULL) return;
5233 date_unpickler_object = PyObject_GetAttrString(m,
5234 "_date_unpickler");
5235 if (date_unpickler_object == NULL) return;
5236 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5237 &PyDateTime_DateType,
5238 pickler,
5239 date_unpickler_object);
5240 if (x == NULL) return;
5241 Py_DECREF(x);
5242 Py_DECREF(pickler);
5243
5244 pickler = PyObject_GetAttrString(m, "_datetime_pickler");
5245 if (pickler == NULL) return;
5246 datetime_unpickler_object = PyObject_GetAttrString(m,
5247 "_datetime_unpickler");
5248 if (datetime_unpickler_object == NULL) return;
5249 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5250 &PyDateTime_DateTimeType,
5251 pickler,
5252 datetime_unpickler_object);
5253 if (x == NULL) return;
5254 Py_DECREF(x);
5255 Py_DECREF(pickler);
5256
5257 pickler = PyObject_GetAttrString(m, "_time_pickler");
5258 if (pickler == NULL) return;
5259 time_unpickler_object = PyObject_GetAttrString(m,
5260 "_time_unpickler");
5261 if (time_unpickler_object == NULL) return;
5262 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5263 &PyDateTime_TimeType,
5264 pickler,
5265 time_unpickler_object);
5266 if (x == NULL) return;
5267 Py_DECREF(x);
5268 Py_DECREF(pickler);
5269
5270 pickler = PyObject_GetAttrString(m, "_timetz_pickler");
5271 if (pickler == NULL) return;
5272 timetz_unpickler_object = PyObject_GetAttrString(m,
5273 "_timetz_unpickler");
5274 if (timetz_unpickler_object == NULL) return;
5275 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5276 &PyDateTime_TimeTZType,
5277 pickler,
5278 timetz_unpickler_object);
5279 if (x == NULL) return;
5280 Py_DECREF(x);
5281 Py_DECREF(pickler);
5282
5283 pickler = PyObject_GetAttrString(m, "_tzinfo_pickler");
5284 if (pickler == NULL) return;
5285 tzinfo_unpickler_object = PyObject_GetAttrString(m,
5286 "_tzinfo_unpickler");
5287 if (tzinfo_unpickler_object == NULL) return;
5288 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5289 &PyDateTime_TZInfoType,
5290 pickler,
5291 tzinfo_unpickler_object);
5292 if (x== NULL) return;
5293 Py_DECREF(x);
5294 Py_DECREF(pickler);
5295
5296 pickler = PyObject_GetAttrString(m, "_datetimetz_pickler");
5297 if (pickler == NULL) return;
5298 datetimetz_unpickler_object = PyObject_GetAttrString(m,
5299 "_datetimetz_unpickler");
5300 if (datetimetz_unpickler_object == NULL) return;
5301 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
5302 &PyDateTime_DateTimeTZType,
5303 pickler,
5304 datetimetz_unpickler_object);
5305 if (x== NULL) return;
5306 Py_DECREF(x);
5307 Py_DECREF(pickler);
5308
5309 Py_DECREF(copyreg);
5310 }
5311
5312 /* timedelta values */
5313 d = PyDateTime_DeltaType.tp_dict;
5314
5315 if (PyDict_SetItem(d, safepickle, Py_True) < 0)
5316 return;
5317
5318 x = new_delta(0, 0, 1, 0);
5319 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5320 return;
5321 Py_DECREF(x);
5322
5323 x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0);
5324 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5325 return;
5326 Py_DECREF(x);
5327
5328 x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0);
5329 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5330 return;
5331 Py_DECREF(x);
5332
5333 /* date values */
5334 d = PyDateTime_DateType.tp_dict;
5335
5336 x = new_date(1, 1, 1);
5337 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5338 return;
5339 Py_DECREF(x);
5340
5341 x = new_date(MAXYEAR, 12, 31);
5342 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5343 return;
5344 Py_DECREF(x);
5345
5346 x = new_delta(1, 0, 0, 0);
5347 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5348 return;
5349 Py_DECREF(x);
5350
5351 /* datetime values */
5352 d = PyDateTime_DateTimeType.tp_dict;
5353
5354 x = new_datetime(1, 1, 1, 0, 0, 0, 0);
5355 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5356 return;
5357 Py_DECREF(x);
5358
5359 x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999);
5360 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5361 return;
5362 Py_DECREF(x);
5363
5364 x = new_delta(0, 0, 1, 0);
5365 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5366 return;
5367 Py_DECREF(x);
5368
5369 /* time values */
5370 d = PyDateTime_TimeType.tp_dict;
5371
5372 x = new_time(0, 0, 0, 0);
5373 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5374 return;
5375 Py_DECREF(x);
5376
5377 x = new_time(23, 59, 59, 999999);
5378 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5379 return;
5380 Py_DECREF(x);
5381
5382 x = new_delta(0, 0, 1, 0);
5383 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5384 return;
5385 Py_DECREF(x);
5386
5387 /* timetz values */
5388 d = PyDateTime_TimeTZType.tp_dict;
5389
5390 x = new_timetz(0, 0, 0, 0, Py_None);
5391 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5392 return;
5393 Py_DECREF(x);
5394
5395 x = new_timetz(23, 59, 59, 999999, Py_None);
5396 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5397 return;
5398 Py_DECREF(x);
5399
5400 x = new_delta(0, 0, 1, 0);
5401 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5402 return;
5403 Py_DECREF(x);
5404
5405 /* datetimetz values */
5406 d = PyDateTime_DateTimeTZType.tp_dict;
5407
5408 x = new_datetimetz(1, 1, 1, 0, 0, 0, 0, Py_None);
5409 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
5410 return;
5411 Py_DECREF(x);
5412
5413 x = new_datetimetz(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None);
5414 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
5415 return;
5416 Py_DECREF(x);
5417
5418 x = new_delta(0, 0, 1, 0);
5419 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
5420 return;
5421 Py_DECREF(x);
5422
5423 Py_DECREF(safepickle);
5424
5425 /* module initialization */
5426 PyModule_AddIntConstant(m, "MINYEAR", MINYEAR);
5427 PyModule_AddIntConstant(m, "MAXYEAR", MAXYEAR);
5428
5429 Py_INCREF(&PyDateTime_DateType);
5430 PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType);
5431
5432 Py_INCREF(&PyDateTime_DateTimeType);
5433 PyModule_AddObject(m, "datetime",
5434 (PyObject *) &PyDateTime_DateTimeType);
5435
5436 Py_INCREF(&PyDateTime_DeltaType);
5437 PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType);
5438
5439 Py_INCREF(&PyDateTime_TimeType);
5440 PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType);
5441
5442 Py_INCREF(&PyDateTime_TZInfoType);
5443 PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
5444
5445 Py_INCREF(&PyDateTime_TimeTZType);
5446 PyModule_AddObject(m, "timetz", (PyObject *) &PyDateTime_TimeTZType);
5447
5448 Py_INCREF(&PyDateTime_DateTimeTZType);
5449 PyModule_AddObject(m, "datetimetz",
5450 (PyObject *)&PyDateTime_DateTimeTZType);
5451
5452 /* A 4-year cycle has an extra leap day over what we'd get from
5453 * pasting together 4 single years.
5454 */
5455 assert(DI4Y == 4 * 365 + 1);
5456 assert(DI4Y == days_before_year(4+1));
5457
5458 /* Similarly, a 400-year cycle has an extra leap day over what we'd
5459 * get from pasting together 4 100-year cycles.
5460 */
5461 assert(DI400Y == 4 * DI100Y + 1);
5462 assert(DI400Y == days_before_year(400+1));
5463
5464 /* OTOH, a 100-year cycle has one fewer leap day than we'd get from
5465 * pasting together 25 4-year cycles.
5466 */
5467 assert(DI100Y == 25 * DI4Y - 1);
5468 assert(DI100Y == days_before_year(100+1));
5469
5470 us_per_us = PyInt_FromLong(1);
5471 us_per_ms = PyInt_FromLong(1000);
5472 us_per_second = PyInt_FromLong(1000000);
5473 us_per_minute = PyInt_FromLong(60000000);
5474 seconds_per_day = PyInt_FromLong(24 * 3600);
5475 if (us_per_us == NULL || us_per_ms == NULL || us_per_second == NULL ||
5476 us_per_minute == NULL || seconds_per_day == NULL)
5477 return;
5478
5479 /* The rest are too big for 32-bit ints, but even
5480 * us_per_week fits in 40 bits, so doubles should be exact.
5481 */
5482 us_per_hour = PyLong_FromDouble(3600000000.0);
5483 us_per_day = PyLong_FromDouble(86400000000.0);
5484 us_per_week = PyLong_FromDouble(604800000000.0);
5485 if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL)
5486 return;
5487}
Tim Petersf3615152003-01-01 21:51:37 +00005488
5489/* ---------------------------------------------------------------------------
5490Some time zone algebra. For a datetimetz x, let
5491 x.n = x stripped of its timezone -- its naive time.
5492 x.o = x.utcoffset(), and assuming that doesn't raise an exception or
5493 return None
5494 x.d = x.dst(), and assuming that doesn't raise an exception or
5495 return None
5496 x.s = x's standard offset, x.o - x.d
5497
5498Now some derived rules, where k is a duration (timedelta).
5499
55001. x.o = x.s + x.d
5501 This follows from the definition of x.s.
5502
Tim Petersc5dc4da2003-01-02 17:55:03 +000055032. If x and y have the same tzinfo member, x.s = y.s.
Tim Petersf3615152003-01-01 21:51:37 +00005504 This is actually a requirement, an assumption we need to make about
5505 sane tzinfo classes.
5506
55073. The naive UTC time corresponding to x is x.n - x.o.
5508 This is again a requirement for a sane tzinfo class.
5509
55104. (x+k).s = x.s
5511 This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
5512
Tim Petersc5dc4da2003-01-02 17:55:03 +000055135. (x+k).n = x.n + k
Tim Petersf3615152003-01-01 21:51:37 +00005514 Again follows from how arithmetic is defined.
5515
5516Now we can explain x.astimezone(tz). Let's assume it's an interesting case
5517(meaning that the various tzinfo methods exist, and don't blow up or return
5518None when called).
5519
5520The function wants to return a datetimetz y with timezone tz, equivalent to x.
5521
5522By #3, we want
5523
5524 y.n - y.o = x.n - x.o [1]
5525
5526The algorithm starts by attaching tz to x.n, and calling that y. So
5527x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
5528becomes true; in effect, we want to solve [2] for k:
5529
5530 (y+k).n - (y+k).o = x.n - x.o [2]
5531
5532By #1, this is the same as
5533
5534 (y+k).n - ((y+k).s + (y+k).d) = x.n - x.o [3]
5535
5536By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
5537Substituting that into [3],
5538
5539 x.n + k - (y+k).s - (y+k).d = x.n - x.o; the x.n terms cancel, leaving
5540 k - (y+k).s - (y+k).d = - x.o; rearranging,
5541 k = (y+k).s - x.o - (y+k).d; by #4, (y+k).s == y.s, so
5542 k = y.s - x.o - (y+k).d; then by #1, y.s = y.o - y.d, so
5543 k = y.o - y.d - x.o - (y+k).d
5544
5545On the RHS, (y+k).d can't be computed directly, but all the rest can be, and
5546we approximate k by ignoring the (y+k).d term at first. Note that k can't
5547be very large, since all offset-returning methods return a duration of
5548magnitude less than 24 hours. For that reason, if y is firmly in std time,
5549(y+k).d must be 0, so ignoring it has no consequence then.
5550
5551In any case, the new value is
5552
Tim Petersc5dc4da2003-01-02 17:55:03 +00005553 z = y + y.o - y.d - x.o [4]
Tim Petersf3615152003-01-01 21:51:37 +00005554
Tim Petersc5dc4da2003-01-02 17:55:03 +00005555It's helpful to step back at look at [4] from a higher level: rewrite it as
Tim Petersf3615152003-01-01 21:51:37 +00005556
Tim Petersc5dc4da2003-01-02 17:55:03 +00005557 z = (y - x.o) + (y.o - y.d)
5558
5559(y - x.o).n = [by #5] y.n - x.o = [since y.n=x.n] x.n - x.o = [by #3] x's
5560UTC equivalent time. So the y-x.o part essentially converts x to UTC. Then
5561the y.o-y.d part essentially converts x's UTC equivalent into tz's standard
5562time (y.o-y.d=y.s by #1).
5563
5564At this point, if
5565
5566 z.n - z.o = x.n - x.o [5]
5567
5568we have an equivalent time, and are almost done. The insecurity here is
Tim Petersf3615152003-01-01 21:51:37 +00005569at the start of daylight time. Picture US Eastern for concreteness. The wall
5570time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
5571sense then. A sensible Eastern tzinfo class will consider such a time to be
5572EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST on the
5573day DST starts. We want to return the 1:MM EST spelling because that's
5574the only spelling that makes sense on the local wall clock.
5575
Tim Petersc5dc4da2003-01-02 17:55:03 +00005576In fact, if [5] holds at this point, we do have the standard-time spelling,
5577but that takes a bit of proof. We first prove a stronger result. What's the
5578difference between the LHS and RHS of [5]? Let
Tim Petersf3615152003-01-01 21:51:37 +00005579
Tim Petersc5dc4da2003-01-02 17:55:03 +00005580 diff = (x.n - x.o) - (z.n - z.o) [6]
Tim Petersf3615152003-01-01 21:51:37 +00005581
Tim Petersc5dc4da2003-01-02 17:55:03 +00005582Now
5583 z.n = by [4]
5584 (y + y.o - y.d - x.o).n = by #5
5585 y.n + y.o - y.d - x.o = since y.n = x.n
5586 x.n + y.o - y.d - x.o = since y.o = y.s + y.d by #1
5587 x.n + (y.s + y.d) - y.d - x.o = cancelling the y.d terms
5588 x.n + y.s - x.o = since z and y are have the same tzinfo member,
5589 y.s = z.s by #2
5590 x.n + z.s - x.o
Tim Petersf3615152003-01-01 21:51:37 +00005591
Tim Petersc5dc4da2003-01-02 17:55:03 +00005592Plugging that back into [6] gives
Tim Petersf3615152003-01-01 21:51:37 +00005593
Tim Petersc5dc4da2003-01-02 17:55:03 +00005594 diff =
5595 (x.n - x.o) - ((x.n + z.s - x.o) - z.o) = expanding
5596 x.n - x.o - x.n - z.s + x.o + z.o = cancelling
5597 - z.s + z.o = by #2
5598 z.d
Tim Petersf3615152003-01-01 21:51:37 +00005599
Tim Petersc5dc4da2003-01-02 17:55:03 +00005600So diff = z.d.
Tim Petersf3615152003-01-01 21:51:37 +00005601
Tim Petersc5dc4da2003-01-02 17:55:03 +00005602If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
5603spelling we wanted in the endcase described above. We're done.
Tim Petersf3615152003-01-01 21:51:37 +00005604
Tim Petersc5dc4da2003-01-02 17:55:03 +00005605If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
5606add to z (in effect, z is in tz's standard time, and we need to shift the
5607offset into tz's daylight time).
Tim Petersf3615152003-01-01 21:51:37 +00005608
Tim Petersc5dc4da2003-01-02 17:55:03 +00005609Let
Tim Petersf3615152003-01-01 21:51:37 +00005610
Tim Petersc5dc4da2003-01-02 17:55:03 +00005611 z' = z + z.d = z + diff
Tim Petersc3bb26a2003-01-02 03:14:59 +00005612
5613we can again ask whether
5614
5615 z'.n - z'.o = x.n - x.o
5616
5617If so, we're done. If not, the tzinfo class is insane, or we're trying to
5618convert to the hour that can't be spelled in tz.
Tim Petersf3615152003-01-01 21:51:37 +00005619--------------------------------------------------------------------------- */