blob: 88a076b6677f3312965b5b8e93ad1adcdbc881c0 [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
Tim Petersa032d2e2003-01-11 00:15:54 +000078/* p is a pointer to a time or a datetime object; HASTZINFO(p) returns
79 * p->hastzinfo.
80 */
81#define HASTZINFO(p) (((_PyDateTime_BaseTZInfo *)(p))->hastzinfo)
82
Tim Peters2a799bf2002-12-16 20:18:38 +000083/* Forward declarations. */
84static PyTypeObject PyDateTime_DateType;
85static PyTypeObject PyDateTime_DateTimeType;
Tim Peters2a799bf2002-12-16 20:18:38 +000086static PyTypeObject PyDateTime_DeltaType;
87static PyTypeObject PyDateTime_TimeType;
88static PyTypeObject PyDateTime_TZInfoType;
Tim Peters2a799bf2002-12-16 20:18:38 +000089
90/* ---------------------------------------------------------------------------
91 * Math utilities.
92 */
93
94/* k = i+j overflows iff k differs in sign from both inputs,
95 * iff k^i has sign bit set and k^j has sign bit set,
96 * iff (k^i)&(k^j) has sign bit set.
97 */
98#define SIGNED_ADD_OVERFLOWED(RESULT, I, J) \
99 ((((RESULT) ^ (I)) & ((RESULT) ^ (J))) < 0)
100
101/* Compute Python divmod(x, y), returning the quotient and storing the
102 * remainder into *r. The quotient is the floor of x/y, and that's
103 * the real point of this. C will probably truncate instead (C99
104 * requires truncation; C89 left it implementation-defined).
105 * Simplification: we *require* that y > 0 here. That's appropriate
106 * for all the uses made of it. This simplifies the code and makes
107 * the overflow case impossible (divmod(LONG_MIN, -1) is the only
108 * overflow case).
109 */
110static int
111divmod(int x, int y, int *r)
112{
113 int quo;
114
115 assert(y > 0);
116 quo = x / y;
117 *r = x - quo * y;
118 if (*r < 0) {
119 --quo;
120 *r += y;
121 }
122 assert(0 <= *r && *r < y);
123 return quo;
124}
125
Tim Peters5d644dd2003-01-02 16:32:54 +0000126/* Round a double to the nearest long. |x| must be small enough to fit
127 * in a C long; this is not checked.
128 */
129static long
130round_to_long(double x)
131{
132 if (x >= 0.0)
133 x = floor(x + 0.5);
134 else
135 x = ceil(x - 0.5);
136 return (long)x;
137}
138
Tim Peters2a799bf2002-12-16 20:18:38 +0000139/* ---------------------------------------------------------------------------
140 * General calendrical helper functions
141 */
142
143/* For each month ordinal in 1..12, the number of days in that month,
144 * and the number of days before that month in the same year. These
145 * are correct for non-leap years only.
146 */
147static int _days_in_month[] = {
148 0, /* unused; this vector uses 1-based indexing */
149 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
150};
151
152static int _days_before_month[] = {
153 0, /* unused; this vector uses 1-based indexing */
154 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
155};
156
157/* year -> 1 if leap year, else 0. */
158static int
159is_leap(int year)
160{
161 /* Cast year to unsigned. The result is the same either way, but
162 * C can generate faster code for unsigned mod than for signed
163 * mod (especially for % 4 -- a good compiler should just grab
164 * the last 2 bits when the LHS is unsigned).
165 */
166 const unsigned int ayear = (unsigned int)year;
167 return ayear % 4 == 0 && (ayear % 100 != 0 || ayear % 400 == 0);
168}
169
170/* year, month -> number of days in that month in that year */
171static int
172days_in_month(int year, int month)
173{
174 assert(month >= 1);
175 assert(month <= 12);
176 if (month == 2 && is_leap(year))
177 return 29;
178 else
179 return _days_in_month[month];
180}
181
182/* year, month -> number of days in year preceeding first day of month */
183static int
184days_before_month(int year, int month)
185{
186 int days;
187
188 assert(month >= 1);
189 assert(month <= 12);
190 days = _days_before_month[month];
191 if (month > 2 && is_leap(year))
192 ++days;
193 return days;
194}
195
196/* year -> number of days before January 1st of year. Remember that we
197 * start with year 1, so days_before_year(1) == 0.
198 */
199static int
200days_before_year(int year)
201{
202 int y = year - 1;
203 /* This is incorrect if year <= 0; we really want the floor
204 * here. But so long as MINYEAR is 1, the smallest year this
205 * can see is 0 (this can happen in some normalization endcases),
206 * so we'll just special-case that.
207 */
208 assert (year >= 0);
209 if (y >= 0)
210 return y*365 + y/4 - y/100 + y/400;
211 else {
212 assert(y == -1);
213 return -366;
214 }
215}
216
217/* Number of days in 4, 100, and 400 year cycles. That these have
218 * the correct values is asserted in the module init function.
219 */
220#define DI4Y 1461 /* days_before_year(5); days in 4 years */
221#define DI100Y 36524 /* days_before_year(101); days in 100 years */
222#define DI400Y 146097 /* days_before_year(401); days in 400 years */
223
224/* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */
225static void
226ord_to_ymd(int ordinal, int *year, int *month, int *day)
227{
228 int n, n1, n4, n100, n400, leapyear, preceding;
229
230 /* ordinal is a 1-based index, starting at 1-Jan-1. The pattern of
231 * leap years repeats exactly every 400 years. The basic strategy is
232 * to find the closest 400-year boundary at or before ordinal, then
233 * work with the offset from that boundary to ordinal. Life is much
234 * clearer if we subtract 1 from ordinal first -- then the values
235 * of ordinal at 400-year boundaries are exactly those divisible
236 * by DI400Y:
237 *
238 * D M Y n n-1
239 * -- --- ---- ---------- ----------------
240 * 31 Dec -400 -DI400Y -DI400Y -1
241 * 1 Jan -399 -DI400Y +1 -DI400Y 400-year boundary
242 * ...
243 * 30 Dec 000 -1 -2
244 * 31 Dec 000 0 -1
245 * 1 Jan 001 1 0 400-year boundary
246 * 2 Jan 001 2 1
247 * 3 Jan 001 3 2
248 * ...
249 * 31 Dec 400 DI400Y DI400Y -1
250 * 1 Jan 401 DI400Y +1 DI400Y 400-year boundary
251 */
252 assert(ordinal >= 1);
253 --ordinal;
254 n400 = ordinal / DI400Y;
255 n = ordinal % DI400Y;
256 *year = n400 * 400 + 1;
257
258 /* Now n is the (non-negative) offset, in days, from January 1 of
259 * year, to the desired date. Now compute how many 100-year cycles
260 * precede n.
261 * Note that it's possible for n100 to equal 4! In that case 4 full
262 * 100-year cycles precede the desired day, which implies the
263 * desired day is December 31 at the end of a 400-year cycle.
264 */
265 n100 = n / DI100Y;
266 n = n % DI100Y;
267
268 /* Now compute how many 4-year cycles precede it. */
269 n4 = n / DI4Y;
270 n = n % DI4Y;
271
272 /* And now how many single years. Again n1 can be 4, and again
273 * meaning that the desired day is December 31 at the end of the
274 * 4-year cycle.
275 */
276 n1 = n / 365;
277 n = n % 365;
278
279 *year += n100 * 100 + n4 * 4 + n1;
280 if (n1 == 4 || n100 == 4) {
281 assert(n == 0);
282 *year -= 1;
283 *month = 12;
284 *day = 31;
285 return;
286 }
287
288 /* Now the year is correct, and n is the offset from January 1. We
289 * find the month via an estimate that's either exact or one too
290 * large.
291 */
292 leapyear = n1 == 3 && (n4 != 24 || n100 == 3);
293 assert(leapyear == is_leap(*year));
294 *month = (n + 50) >> 5;
295 preceding = (_days_before_month[*month] + (*month > 2 && leapyear));
296 if (preceding > n) {
297 /* estimate is too large */
298 *month -= 1;
299 preceding -= days_in_month(*year, *month);
300 }
301 n -= preceding;
302 assert(0 <= n);
303 assert(n < days_in_month(*year, *month));
304
305 *day = n + 1;
306}
307
308/* year, month, day -> ordinal, considering 01-Jan-0001 as day 1. */
309static int
310ymd_to_ord(int year, int month, int day)
311{
312 return days_before_year(year) + days_before_month(year, month) + day;
313}
314
315/* Day of week, where Monday==0, ..., Sunday==6. 1/1/1 was a Monday. */
316static int
317weekday(int year, int month, int day)
318{
319 return (ymd_to_ord(year, month, day) + 6) % 7;
320}
321
322/* Ordinal of the Monday starting week 1 of the ISO year. Week 1 is the
323 * first calendar week containing a Thursday.
324 */
325static int
326iso_week1_monday(int year)
327{
328 int first_day = ymd_to_ord(year, 1, 1); /* ord of 1/1 */
329 /* 0 if 1/1 is a Monday, 1 if a Tue, etc. */
330 int first_weekday = (first_day + 6) % 7;
331 /* ordinal of closest Monday at or before 1/1 */
332 int week1_monday = first_day - first_weekday;
333
334 if (first_weekday > 3) /* if 1/1 was Fri, Sat, Sun */
335 week1_monday += 7;
336 return week1_monday;
337}
338
339/* ---------------------------------------------------------------------------
340 * Range checkers.
341 */
342
343/* Check that -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS. If so, return 0.
344 * If not, raise OverflowError and return -1.
345 */
346static int
347check_delta_day_range(int days)
348{
349 if (-MAX_DELTA_DAYS <= days && days <= MAX_DELTA_DAYS)
350 return 0;
351 PyErr_Format(PyExc_OverflowError,
352 "days=%d; must have magnitude <= %d",
Guido van Rossumbd43e912002-12-16 20:34:55 +0000353 days, MAX_DELTA_DAYS);
Tim Peters2a799bf2002-12-16 20:18:38 +0000354 return -1;
355}
356
357/* Check that date arguments are in range. Return 0 if they are. If they
358 * aren't, raise ValueError and return -1.
359 */
360static int
361check_date_args(int year, int month, int day)
362{
363
364 if (year < MINYEAR || year > MAXYEAR) {
365 PyErr_SetString(PyExc_ValueError,
366 "year is out of range");
367 return -1;
368 }
369 if (month < 1 || month > 12) {
370 PyErr_SetString(PyExc_ValueError,
371 "month must be in 1..12");
372 return -1;
373 }
374 if (day < 1 || day > days_in_month(year, month)) {
375 PyErr_SetString(PyExc_ValueError,
376 "day is out of range for month");
377 return -1;
378 }
379 return 0;
380}
381
382/* Check that time arguments are in range. Return 0 if they are. If they
383 * aren't, raise ValueError and return -1.
384 */
385static int
386check_time_args(int h, int m, int s, int us)
387{
388 if (h < 0 || h > 23) {
389 PyErr_SetString(PyExc_ValueError,
390 "hour must be in 0..23");
391 return -1;
392 }
393 if (m < 0 || m > 59) {
394 PyErr_SetString(PyExc_ValueError,
395 "minute must be in 0..59");
396 return -1;
397 }
398 if (s < 0 || s > 59) {
399 PyErr_SetString(PyExc_ValueError,
400 "second must be in 0..59");
401 return -1;
402 }
403 if (us < 0 || us > 999999) {
404 PyErr_SetString(PyExc_ValueError,
405 "microsecond must be in 0..999999");
406 return -1;
407 }
408 return 0;
409}
410
411/* ---------------------------------------------------------------------------
412 * Normalization utilities.
413 */
414
415/* One step of a mixed-radix conversion. A "hi" unit is equivalent to
416 * factor "lo" units. factor must be > 0. If *lo is less than 0, or
417 * at least factor, enough of *lo is converted into "hi" units so that
418 * 0 <= *lo < factor. The input values must be such that int overflow
419 * is impossible.
420 */
421static void
422normalize_pair(int *hi, int *lo, int factor)
423{
424 assert(factor > 0);
425 assert(lo != hi);
426 if (*lo < 0 || *lo >= factor) {
427 const int num_hi = divmod(*lo, factor, lo);
428 const int new_hi = *hi + num_hi;
429 assert(! SIGNED_ADD_OVERFLOWED(new_hi, *hi, num_hi));
430 *hi = new_hi;
431 }
432 assert(0 <= *lo && *lo < factor);
433}
434
435/* Fiddle days (d), seconds (s), and microseconds (us) so that
436 * 0 <= *s < 24*3600
437 * 0 <= *us < 1000000
438 * The input values must be such that the internals don't overflow.
439 * The way this routine is used, we don't get close.
440 */
441static void
442normalize_d_s_us(int *d, int *s, int *us)
443{
444 if (*us < 0 || *us >= 1000000) {
445 normalize_pair(s, us, 1000000);
446 /* |s| can't be bigger than about
447 * |original s| + |original us|/1000000 now.
448 */
449
450 }
451 if (*s < 0 || *s >= 24*3600) {
452 normalize_pair(d, s, 24*3600);
453 /* |d| can't be bigger than about
454 * |original d| +
455 * (|original s| + |original us|/1000000) / (24*3600) now.
456 */
457 }
458 assert(0 <= *s && *s < 24*3600);
459 assert(0 <= *us && *us < 1000000);
460}
461
462/* Fiddle years (y), months (m), and days (d) so that
463 * 1 <= *m <= 12
464 * 1 <= *d <= days_in_month(*y, *m)
465 * The input values must be such that the internals don't overflow.
466 * The way this routine is used, we don't get close.
467 */
468static void
469normalize_y_m_d(int *y, int *m, int *d)
470{
471 int dim; /* # of days in month */
472
473 /* This gets muddy: the proper range for day can't be determined
474 * without knowing the correct month and year, but if day is, e.g.,
475 * plus or minus a million, the current month and year values make
476 * no sense (and may also be out of bounds themselves).
477 * Saying 12 months == 1 year should be non-controversial.
478 */
479 if (*m < 1 || *m > 12) {
480 --*m;
481 normalize_pair(y, m, 12);
482 ++*m;
483 /* |y| can't be bigger than about
484 * |original y| + |original m|/12 now.
485 */
486 }
487 assert(1 <= *m && *m <= 12);
488
489 /* Now only day can be out of bounds (year may also be out of bounds
490 * for a datetime object, but we don't care about that here).
491 * If day is out of bounds, what to do is arguable, but at least the
492 * method here is principled and explainable.
493 */
494 dim = days_in_month(*y, *m);
495 if (*d < 1 || *d > dim) {
496 /* Move day-1 days from the first of the month. First try to
497 * get off cheap if we're only one day out of range
498 * (adjustments for timezone alone can't be worse than that).
499 */
500 if (*d == 0) {
501 --*m;
502 if (*m > 0)
503 *d = days_in_month(*y, *m);
504 else {
505 --*y;
506 *m = 12;
507 *d = 31;
508 }
509 }
510 else if (*d == dim + 1) {
511 /* move forward a day */
512 ++*m;
513 *d = 1;
514 if (*m > 12) {
515 *m = 1;
516 ++*y;
517 }
518 }
519 else {
520 int ordinal = ymd_to_ord(*y, *m, 1) +
521 *d - 1;
522 ord_to_ymd(ordinal, y, m, d);
523 }
524 }
525 assert(*m > 0);
526 assert(*d > 0);
527}
528
529/* Fiddle out-of-bounds months and days so that the result makes some kind
530 * of sense. The parameters are both inputs and outputs. Returns < 0 on
531 * failure, where failure means the adjusted year is out of bounds.
532 */
533static int
534normalize_date(int *year, int *month, int *day)
535{
536 int result;
537
538 normalize_y_m_d(year, month, day);
539 if (MINYEAR <= *year && *year <= MAXYEAR)
540 result = 0;
541 else {
542 PyErr_SetString(PyExc_OverflowError,
543 "date value out of range");
544 result = -1;
545 }
546 return result;
547}
548
549/* Force all the datetime fields into range. The parameters are both
550 * inputs and outputs. Returns < 0 on error.
551 */
552static int
553normalize_datetime(int *year, int *month, int *day,
554 int *hour, int *minute, int *second,
555 int *microsecond)
556{
557 normalize_pair(second, microsecond, 1000000);
558 normalize_pair(minute, second, 60);
559 normalize_pair(hour, minute, 60);
560 normalize_pair(day, hour, 24);
561 return normalize_date(year, month, day);
562}
563
564/* ---------------------------------------------------------------------------
565 * tzinfo helpers.
566 */
567
Tim Peters855fe882002-12-22 03:43:39 +0000568/* Ensure that p is None or of a tzinfo subclass. Return 0 if OK; if not
569 * raise TypeError and return -1.
570 */
571static int
572check_tzinfo_subclass(PyObject *p)
573{
574 if (p == Py_None || PyTZInfo_Check(p))
575 return 0;
576 PyErr_Format(PyExc_TypeError,
577 "tzinfo argument must be None or of a tzinfo subclass, "
578 "not type '%s'",
579 p->ob_type->tp_name);
580 return -1;
581}
582
Tim Petersbad8ff02002-12-30 20:52:32 +0000583/* Return tzinfo.methname(tzinfoarg), without any checking of results.
Tim Peters855fe882002-12-22 03:43:39 +0000584 * If tzinfo is None, returns None.
585 */
586static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000587call_tzinfo_method(PyObject *tzinfo, char *methname, PyObject *tzinfoarg)
Tim Peters855fe882002-12-22 03:43:39 +0000588{
589 PyObject *result;
590
Tim Petersbad8ff02002-12-30 20:52:32 +0000591 assert(tzinfo && methname && tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000592 assert(check_tzinfo_subclass(tzinfo) >= 0);
593 if (tzinfo == Py_None) {
594 result = Py_None;
595 Py_INCREF(result);
596 }
597 else
Tim Petersbad8ff02002-12-30 20:52:32 +0000598 result = PyObject_CallMethod(tzinfo, methname, "O", tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000599 return result;
600}
601
Tim Peters2a799bf2002-12-16 20:18:38 +0000602/* If self has a tzinfo member, return a BORROWED reference to it. Else
603 * return NULL, which is NOT AN ERROR. There are no error returns here,
604 * and the caller must not decref the result.
605 */
606static PyObject *
607get_tzinfo_member(PyObject *self)
608{
609 PyObject *tzinfo = NULL;
610
Tim Petersa9bc1682003-01-11 03:39:11 +0000611 if (PyDateTime_Check(self) && HASTZINFO(self))
612 tzinfo = ((PyDateTime_DateTime *)self)->tzinfo;
Tim Petersa032d2e2003-01-11 00:15:54 +0000613 else if (PyTime_Check(self) && HASTZINFO(self))
Tim Peters37f39822003-01-10 03:49:02 +0000614 tzinfo = ((PyDateTime_Time *)self)->tzinfo;
Tim Peters2a799bf2002-12-16 20:18:38 +0000615
616 return tzinfo;
617}
618
Tim Petersbad8ff02002-12-30 20:52:32 +0000619/* Call getattr(tzinfo, name)(tzinfoarg), and extract an int from the
Tim Peters2a799bf2002-12-16 20:18:38 +0000620 * result. tzinfo must be an instance of the tzinfo class. If the method
621 * returns None, this returns 0 and sets *none to 1. If the method doesn't
Tim Peters397301e2003-01-02 21:28:08 +0000622 * return None or timedelta, TypeError is raised and this returns -1. If it
623 * returnsa timedelta and the value is out of range or isn't a whole number
624 * of minutes, ValueError is raised and this returns -1.
Tim Peters2a799bf2002-12-16 20:18:38 +0000625 * Else *none is set to 0 and the integer method result is returned.
626 */
627static int
628call_utc_tzinfo_method(PyObject *tzinfo, char *name, PyObject *tzinfoarg,
629 int *none)
630{
631 PyObject *u;
Tim Peters397301e2003-01-02 21:28:08 +0000632 int result = -1;
Tim Peters2a799bf2002-12-16 20:18:38 +0000633
634 assert(tzinfo != NULL);
635 assert(PyTZInfo_Check(tzinfo));
636 assert(tzinfoarg != NULL);
637
638 *none = 0;
Tim Petersbad8ff02002-12-30 20:52:32 +0000639 u = call_tzinfo_method(tzinfo, name, tzinfoarg);
Tim Peters2a799bf2002-12-16 20:18:38 +0000640 if (u == NULL)
641 return -1;
642
Tim Peters27362852002-12-23 16:17:39 +0000643 else if (u == Py_None) {
Tim Peters2a799bf2002-12-16 20:18:38 +0000644 result = 0;
645 *none = 1;
Tim Peters2a799bf2002-12-16 20:18:38 +0000646 }
Tim Peters855fe882002-12-22 03:43:39 +0000647 else if (PyDelta_Check(u)) {
648 const int days = GET_TD_DAYS(u);
649 if (days < -1 || days > 0)
650 result = 24*60; /* trigger ValueError below */
651 else {
652 /* next line can't overflow because we know days
653 * is -1 or 0 now
654 */
655 int ss = days * 24 * 3600 + GET_TD_SECONDS(u);
656 result = divmod(ss, 60, &ss);
657 if (ss || GET_TD_MICROSECONDS(u)) {
658 PyErr_Format(PyExc_ValueError,
659 "tzinfo.%s() must return a "
660 "whole number of minutes",
661 name);
662 result = -1;
Tim Peters855fe882002-12-22 03:43:39 +0000663 }
664 }
665 }
Tim Peters2a799bf2002-12-16 20:18:38 +0000666 else {
667 PyErr_Format(PyExc_TypeError,
Tim Peters397301e2003-01-02 21:28:08 +0000668 "tzinfo.%s() must return None or "
Tim Peters855fe882002-12-22 03:43:39 +0000669 "timedelta, not '%s'",
670 name, u->ob_type->tp_name);
Tim Peters2a799bf2002-12-16 20:18:38 +0000671 }
672
Tim Peters2a799bf2002-12-16 20:18:38 +0000673 Py_DECREF(u);
674 if (result < -1439 || result > 1439) {
675 PyErr_Format(PyExc_ValueError,
Neal Norwitz506a2242003-01-04 01:02:25 +0000676 "tzinfo.%s() returned %d; must be in "
Tim Peters2a799bf2002-12-16 20:18:38 +0000677 "-1439 .. 1439",
678 name, result);
679 result = -1;
680 }
Tim Peters397301e2003-01-02 21:28:08 +0000681 return result;
Tim Peters2a799bf2002-12-16 20:18:38 +0000682}
683
684/* Call tzinfo.utcoffset(tzinfoarg), and extract an integer from the
685 * result. tzinfo must be an instance of the tzinfo class. If utcoffset()
686 * returns None, call_utcoffset returns 0 and sets *none to 1. If uctoffset()
Tim Peters397301e2003-01-02 21:28:08 +0000687 * doesn't return None or timedelta, TypeError is raised and this returns -1.
688 * If utcoffset() returns an invalid timedelta (out of range, or not a whole
689 * # of minutes), ValueError is raised and this returns -1. Else *none is
690 * set to 0 and the offset is returned (as int # of minutes east of UTC).
Tim Peters2a799bf2002-12-16 20:18:38 +0000691 */
692static int
693call_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
694{
695 return call_utc_tzinfo_method(tzinfo, "utcoffset", tzinfoarg, none);
696}
697
Tim Peters855fe882002-12-22 03:43:39 +0000698static PyObject *new_delta(int d, int sec, int usec, int normalize);
699
Tim Petersbad8ff02002-12-30 20:52:32 +0000700/* Call tzinfo.name(tzinfoarg), and return the offset as a timedelta or None.
701 */
Tim Peters855fe882002-12-22 03:43:39 +0000702static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000703offset_as_timedelta(PyObject *tzinfo, char *name, PyObject *tzinfoarg) {
Tim Peters855fe882002-12-22 03:43:39 +0000704 PyObject *result;
705
Tim Petersbad8ff02002-12-30 20:52:32 +0000706 assert(tzinfo && name && tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000707 if (tzinfo == Py_None) {
708 result = Py_None;
709 Py_INCREF(result);
710 }
711 else {
712 int none;
Tim Petersbad8ff02002-12-30 20:52:32 +0000713 int offset = call_utc_tzinfo_method(tzinfo, name, tzinfoarg,
714 &none);
Tim Peters855fe882002-12-22 03:43:39 +0000715 if (offset < 0 && PyErr_Occurred())
716 return NULL;
717 if (none) {
718 result = Py_None;
719 Py_INCREF(result);
720 }
721 else
722 result = new_delta(0, offset * 60, 0, 1);
723 }
724 return result;
725}
726
Tim Peters2a799bf2002-12-16 20:18:38 +0000727/* Call tzinfo.dst(tzinfoarg), and extract an integer from the
728 * result. tzinfo must be an instance of the tzinfo class. If dst()
729 * returns None, call_dst returns 0 and sets *none to 1. If dst()
Tim Peters397301e2003-01-02 21:28:08 +0000730 & doesn't return None or timedelta, TypeError is raised and this
731 * returns -1. If dst() returns an invalid timedelta for for a UTC offset,
732 * ValueError is raised and this returns -1. Else *none is set to 0 and
733 * the offset is returned (as an int # of minutes east of UTC).
Tim Peters2a799bf2002-12-16 20:18:38 +0000734 */
735static int
736call_dst(PyObject *tzinfo, PyObject *tzinfoarg, int *none)
737{
738 return call_utc_tzinfo_method(tzinfo, "dst", tzinfoarg, none);
739}
740
Tim Petersbad8ff02002-12-30 20:52:32 +0000741/* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be
Tim Peters855fe882002-12-22 03:43:39 +0000742 * an instance of the tzinfo class or None. If tzinfo isn't None, and
Tim Petersbad8ff02002-12-30 20:52:32 +0000743 * tzname() doesn't return None or a string, TypeError is raised and this
Tim Peters855fe882002-12-22 03:43:39 +0000744 * returns NULL.
Tim Peters2a799bf2002-12-16 20:18:38 +0000745 */
746static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000747call_tzname(PyObject *tzinfo, PyObject *tzinfoarg)
Tim Peters2a799bf2002-12-16 20:18:38 +0000748{
749 PyObject *result;
750
751 assert(tzinfo != NULL);
Tim Peters855fe882002-12-22 03:43:39 +0000752 assert(check_tzinfo_subclass(tzinfo) >= 0);
Tim Petersbad8ff02002-12-30 20:52:32 +0000753 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +0000754
Tim Peters855fe882002-12-22 03:43:39 +0000755 if (tzinfo == Py_None) {
756 result = Py_None;
757 Py_INCREF(result);
758 }
759 else
Tim Petersbad8ff02002-12-30 20:52:32 +0000760 result = PyObject_CallMethod(tzinfo, "tzname", "O", tzinfoarg);
Tim Peters855fe882002-12-22 03:43:39 +0000761
762 if (result != NULL && result != Py_None && ! PyString_Check(result)) {
763 PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must "
Tim Peters2a799bf2002-12-16 20:18:38 +0000764 "return None or a string, not '%s'",
765 result->ob_type->tp_name);
766 Py_DECREF(result);
767 result = NULL;
768 }
769 return result;
770}
771
772typedef enum {
773 /* an exception has been set; the caller should pass it on */
774 OFFSET_ERROR,
775
Tim Petersa9bc1682003-01-11 03:39:11 +0000776 /* type isn't date, datetime, or time subclass */
Tim Peters2a799bf2002-12-16 20:18:38 +0000777 OFFSET_UNKNOWN,
778
779 /* date,
Tim Petersa9bc1682003-01-11 03:39:11 +0000780 * datetime with !hastzinfo
781 * datetime with None tzinfo,
782 * datetime where utcoffset() returns None
Tim Peters37f39822003-01-10 03:49:02 +0000783 * time with !hastzinfo
784 * time with None tzinfo,
785 * time where utcoffset() returns None
Tim Peters2a799bf2002-12-16 20:18:38 +0000786 */
787 OFFSET_NAIVE,
788
Tim Petersa9bc1682003-01-11 03:39:11 +0000789 /* time or datetime where utcoffset() doesn't return None */
Tim Peters2a799bf2002-12-16 20:18:38 +0000790 OFFSET_AWARE,
791} naivety;
792
Tim Peters14b69412002-12-22 18:10:22 +0000793/* Classify an object as to whether it's naive or offset-aware. See
Tim Peters2a799bf2002-12-16 20:18:38 +0000794 * the "naivety" typedef for details. If the type is aware, *offset is set
795 * to minutes east of UTC (as returned by the tzinfo.utcoffset() method).
Tim Peters14b69412002-12-22 18:10:22 +0000796 * If the type is offset-naive (or unknown, or error), *offset is set to 0.
Tim Peterse39a80c2002-12-30 21:28:52 +0000797 * tzinfoarg is the argument to pass to the tzinfo.utcoffset() method.
Tim Peters2a799bf2002-12-16 20:18:38 +0000798 */
799static naivety
Tim Peterse39a80c2002-12-30 21:28:52 +0000800classify_utcoffset(PyObject *op, PyObject *tzinfoarg, int *offset)
Tim Peters2a799bf2002-12-16 20:18:38 +0000801{
802 int none;
803 PyObject *tzinfo;
804
Tim Peterse39a80c2002-12-30 21:28:52 +0000805 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +0000806 *offset = 0;
Tim Peters14b69412002-12-22 18:10:22 +0000807 tzinfo = get_tzinfo_member(op); /* NULL means no tzinfo, not error */
Tim Peters2a799bf2002-12-16 20:18:38 +0000808 if (tzinfo == Py_None)
809 return OFFSET_NAIVE;
Tim Peters14b69412002-12-22 18:10:22 +0000810 if (tzinfo == NULL) {
811 /* note that a datetime passes the PyDate_Check test */
812 return (PyTime_Check(op) || PyDate_Check(op)) ?
813 OFFSET_NAIVE : OFFSET_UNKNOWN;
814 }
Tim Peterse39a80c2002-12-30 21:28:52 +0000815 *offset = call_utcoffset(tzinfo, tzinfoarg, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +0000816 if (*offset == -1 && PyErr_Occurred())
817 return OFFSET_ERROR;
818 return none ? OFFSET_NAIVE : OFFSET_AWARE;
819}
820
Tim Peters00237032002-12-27 02:21:51 +0000821/* Classify two objects as to whether they're naive or offset-aware.
822 * This isn't quite the same as calling classify_utcoffset() twice: for
823 * binary operations (comparison and subtraction), we generally want to
824 * ignore the tzinfo members if they're identical. This is by design,
825 * so that results match "naive" expectations when mixing objects from a
826 * single timezone. So in that case, this sets both offsets to 0 and
827 * both naiveties to OFFSET_NAIVE.
828 * The function returns 0 if everything's OK, and -1 on error.
829 */
830static int
831classify_two_utcoffsets(PyObject *o1, int *offset1, naivety *n1,
Tim Peterse39a80c2002-12-30 21:28:52 +0000832 PyObject *tzinfoarg1,
833 PyObject *o2, int *offset2, naivety *n2,
834 PyObject *tzinfoarg2)
Tim Peters00237032002-12-27 02:21:51 +0000835{
836 if (get_tzinfo_member(o1) == get_tzinfo_member(o2)) {
837 *offset1 = *offset2 = 0;
838 *n1 = *n2 = OFFSET_NAIVE;
839 }
840 else {
Tim Peterse39a80c2002-12-30 21:28:52 +0000841 *n1 = classify_utcoffset(o1, tzinfoarg1, offset1);
Tim Peters00237032002-12-27 02:21:51 +0000842 if (*n1 == OFFSET_ERROR)
843 return -1;
Tim Peterse39a80c2002-12-30 21:28:52 +0000844 *n2 = classify_utcoffset(o2, tzinfoarg2, offset2);
Tim Peters00237032002-12-27 02:21:51 +0000845 if (*n2 == OFFSET_ERROR)
846 return -1;
847 }
848 return 0;
849}
850
Tim Peters2a799bf2002-12-16 20:18:38 +0000851/* repr is like "someclass(arg1, arg2)". If tzinfo isn't None,
852 * stuff
853 * ", tzinfo=" + repr(tzinfo)
854 * before the closing ")".
855 */
856static PyObject *
857append_keyword_tzinfo(PyObject *repr, PyObject *tzinfo)
858{
859 PyObject *temp;
860
861 assert(PyString_Check(repr));
862 assert(tzinfo);
863 if (tzinfo == Py_None)
864 return repr;
865 /* Get rid of the trailing ')'. */
866 assert(PyString_AsString(repr)[PyString_Size(repr)-1] == ')');
867 temp = PyString_FromStringAndSize(PyString_AsString(repr),
868 PyString_Size(repr) - 1);
869 Py_DECREF(repr);
870 if (temp == NULL)
871 return NULL;
872 repr = temp;
873
874 /* Append ", tzinfo=". */
875 PyString_ConcatAndDel(&repr, PyString_FromString(", tzinfo="));
876
877 /* Append repr(tzinfo). */
878 PyString_ConcatAndDel(&repr, PyObject_Repr(tzinfo));
879
880 /* Add a closing paren. */
881 PyString_ConcatAndDel(&repr, PyString_FromString(")"));
882 return repr;
883}
884
885/* ---------------------------------------------------------------------------
886 * String format helpers.
887 */
888
889static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +0000890format_ctime(PyDateTime_Date *date, int hours, int minutes, int seconds)
Tim Peters2a799bf2002-12-16 20:18:38 +0000891{
892 static char *DayNames[] = {
893 "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
894 };
895 static char *MonthNames[] = {
896 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
897 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
898 };
899
900 char buffer[128];
901 int wday = weekday(GET_YEAR(date), GET_MONTH(date), GET_DAY(date));
902
903 PyOS_snprintf(buffer, sizeof(buffer), "%s %s %2d %02d:%02d:%02d %04d",
904 DayNames[wday], MonthNames[GET_MONTH(date) - 1],
905 GET_DAY(date), hours, minutes, seconds,
906 GET_YEAR(date));
907 return PyString_FromString(buffer);
908}
909
910/* Add an hours & minutes UTC offset string to buf. buf has no more than
911 * buflen bytes remaining. The UTC offset is gotten by calling
912 * tzinfo.uctoffset(tzinfoarg). If that returns None, \0 is stored into
913 * *buf, and that's all. Else the returned value is checked for sanity (an
914 * integer in range), and if that's OK it's converted to an hours & minutes
915 * string of the form
916 * sign HH sep MM
917 * Returns 0 if everything is OK. If the return value from utcoffset() is
918 * bogus, an appropriate exception is set and -1 is returned.
919 */
920static int
Tim Peters328fff72002-12-20 01:31:27 +0000921format_utcoffset(char *buf, size_t buflen, const char *sep,
Tim Peters2a799bf2002-12-16 20:18:38 +0000922 PyObject *tzinfo, PyObject *tzinfoarg)
923{
924 int offset;
925 int hours;
926 int minutes;
927 char sign;
928 int none;
929
930 offset = call_utcoffset(tzinfo, tzinfoarg, &none);
931 if (offset == -1 && PyErr_Occurred())
932 return -1;
933 if (none) {
934 *buf = '\0';
935 return 0;
936 }
937 sign = '+';
938 if (offset < 0) {
939 sign = '-';
940 offset = - offset;
941 }
942 hours = divmod(offset, 60, &minutes);
943 PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes);
944 return 0;
945}
946
947/* I sure don't want to reproduce the strftime code from the time module,
948 * so this imports the module and calls it. All the hair is due to
949 * giving special meanings to the %z and %Z format codes via a preprocessing
950 * step on the format string.
Tim Petersbad8ff02002-12-30 20:52:32 +0000951 * tzinfoarg is the argument to pass to the object's tzinfo method, if
952 * needed.
Tim Peters2a799bf2002-12-16 20:18:38 +0000953 */
954static PyObject *
Tim Petersbad8ff02002-12-30 20:52:32 +0000955wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple,
956 PyObject *tzinfoarg)
Tim Peters2a799bf2002-12-16 20:18:38 +0000957{
958 PyObject *result = NULL; /* guilty until proved innocent */
959
960 PyObject *zreplacement = NULL; /* py string, replacement for %z */
961 PyObject *Zreplacement = NULL; /* py string, replacement for %Z */
962
963 char *pin; /* pointer to next char in input format */
964 char ch; /* next char in input format */
965
966 PyObject *newfmt = NULL; /* py string, the output format */
967 char *pnew; /* pointer to available byte in output format */
968 char totalnew; /* number bytes total in output format buffer,
969 exclusive of trailing \0 */
970 char usednew; /* number bytes used so far in output format buffer */
971
972 char *ptoappend; /* pointer to string to append to output buffer */
973 int ntoappend; /* # of bytes to append to output buffer */
974
Tim Peters2a799bf2002-12-16 20:18:38 +0000975 assert(object && format && timetuple);
976 assert(PyString_Check(format));
977
Tim Petersd6844152002-12-22 20:58:42 +0000978 /* Give up if the year is before 1900.
979 * Python strftime() plays games with the year, and different
980 * games depending on whether envar PYTHON2K is set. This makes
981 * years before 1900 a nightmare, even if the platform strftime
982 * supports them (and not all do).
983 * We could get a lot farther here by avoiding Python's strftime
984 * wrapper and calling the C strftime() directly, but that isn't
985 * an option in the Python implementation of this module.
986 */
987 {
988 long year;
989 PyObject *pyyear = PySequence_GetItem(timetuple, 0);
990 if (pyyear == NULL) return NULL;
991 assert(PyInt_Check(pyyear));
992 year = PyInt_AsLong(pyyear);
993 Py_DECREF(pyyear);
994 if (year < 1900) {
995 PyErr_Format(PyExc_ValueError, "year=%ld is before "
996 "1900; the datetime strftime() "
997 "methods require year >= 1900",
998 year);
999 return NULL;
1000 }
1001 }
1002
Tim Peters2a799bf2002-12-16 20:18:38 +00001003 /* Scan the input format, looking for %z and %Z escapes, building
Tim Peters328fff72002-12-20 01:31:27 +00001004 * a new format. Since computing the replacements for those codes
1005 * is expensive, don't unless they're actually used.
Tim Peters2a799bf2002-12-16 20:18:38 +00001006 */
1007 totalnew = PyString_Size(format); /* realistic if no %z/%Z */
1008 newfmt = PyString_FromStringAndSize(NULL, totalnew);
1009 if (newfmt == NULL) goto Done;
1010 pnew = PyString_AsString(newfmt);
1011 usednew = 0;
1012
1013 pin = PyString_AsString(format);
1014 while ((ch = *pin++) != '\0') {
1015 if (ch != '%') {
Tim Peters328fff72002-12-20 01:31:27 +00001016 ptoappend = pin - 1;
Tim Peters2a799bf2002-12-16 20:18:38 +00001017 ntoappend = 1;
1018 }
1019 else if ((ch = *pin++) == '\0') {
1020 /* There's a lone trailing %; doesn't make sense. */
1021 PyErr_SetString(PyExc_ValueError, "strftime format "
1022 "ends with raw %");
1023 goto Done;
1024 }
1025 /* A % has been seen and ch is the character after it. */
1026 else if (ch == 'z') {
1027 if (zreplacement == NULL) {
1028 /* format utcoffset */
Tim Peters328fff72002-12-20 01:31:27 +00001029 char buf[100];
Tim Peters2a799bf2002-12-16 20:18:38 +00001030 PyObject *tzinfo = get_tzinfo_member(object);
1031 zreplacement = PyString_FromString("");
1032 if (zreplacement == NULL) goto Done;
1033 if (tzinfo != Py_None && tzinfo != NULL) {
Tim Petersbad8ff02002-12-30 20:52:32 +00001034 assert(tzinfoarg != NULL);
Tim Peters2a799bf2002-12-16 20:18:38 +00001035 if (format_utcoffset(buf,
Tim Peters328fff72002-12-20 01:31:27 +00001036 sizeof(buf),
Tim Peters2a799bf2002-12-16 20:18:38 +00001037 "",
1038 tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00001039 tzinfoarg) < 0)
Tim Peters2a799bf2002-12-16 20:18:38 +00001040 goto Done;
1041 Py_DECREF(zreplacement);
1042 zreplacement = PyString_FromString(buf);
1043 if (zreplacement == NULL) goto Done;
1044 }
1045 }
1046 assert(zreplacement != NULL);
1047 ptoappend = PyString_AsString(zreplacement);
1048 ntoappend = PyString_Size(zreplacement);
1049 }
1050 else if (ch == 'Z') {
1051 /* format tzname */
1052 if (Zreplacement == NULL) {
1053 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 PyObject *temp;
1058 assert(tzinfoarg != NULL);
1059 temp = call_tzname(tzinfo, tzinfoarg);
Tim Peters2a799bf2002-12-16 20:18:38 +00001060 if (temp == NULL) goto Done;
1061 if (temp != Py_None) {
1062 assert(PyString_Check(temp));
1063 /* Since the tzname is getting
1064 * stuffed into the format, we
1065 * have to double any % signs
1066 * so that strftime doesn't
1067 * treat them as format codes.
1068 */
1069 Py_DECREF(Zreplacement);
1070 Zreplacement = PyObject_CallMethod(
1071 temp, "replace",
1072 "ss", "%", "%%");
1073 Py_DECREF(temp);
1074 if (Zreplacement == NULL)
1075 goto Done;
1076 }
1077 else
1078 Py_DECREF(temp);
1079 }
1080 }
1081 assert(Zreplacement != NULL);
1082 ptoappend = PyString_AsString(Zreplacement);
1083 ntoappend = PyString_Size(Zreplacement);
1084 }
1085 else {
Tim Peters328fff72002-12-20 01:31:27 +00001086 /* percent followed by neither z nor Z */
1087 ptoappend = pin - 2;
Tim Peters2a799bf2002-12-16 20:18:38 +00001088 ntoappend = 2;
1089 }
1090
1091 /* Append the ntoappend chars starting at ptoappend to
1092 * the new format.
1093 */
1094 assert(ntoappend >= 0);
1095 if (ntoappend == 0)
1096 continue;
1097 while (usednew + ntoappend > totalnew) {
1098 int bigger = totalnew << 1;
1099 if ((bigger >> 1) != totalnew) { /* overflow */
1100 PyErr_NoMemory();
1101 goto Done;
1102 }
1103 if (_PyString_Resize(&newfmt, bigger) < 0)
1104 goto Done;
1105 totalnew = bigger;
1106 pnew = PyString_AsString(newfmt) + usednew;
1107 }
1108 memcpy(pnew, ptoappend, ntoappend);
1109 pnew += ntoappend;
1110 usednew += ntoappend;
1111 assert(usednew <= totalnew);
1112 } /* end while() */
1113
1114 if (_PyString_Resize(&newfmt, usednew) < 0)
1115 goto Done;
1116 {
1117 PyObject *time = PyImport_ImportModule("time");
1118 if (time == NULL)
1119 goto Done;
1120 result = PyObject_CallMethod(time, "strftime", "OO",
1121 newfmt, timetuple);
1122 Py_DECREF(time);
1123 }
1124 Done:
1125 Py_XDECREF(zreplacement);
1126 Py_XDECREF(Zreplacement);
1127 Py_XDECREF(newfmt);
1128 return result;
1129}
1130
1131static char *
1132isoformat_date(PyDateTime_Date *dt, char buffer[], int bufflen)
1133{
1134 int x;
1135 x = PyOS_snprintf(buffer, bufflen,
1136 "%04d-%02d-%02d",
1137 GET_YEAR(dt), GET_MONTH(dt), GET_DAY(dt));
1138 return buffer + x;
1139}
1140
1141static void
1142isoformat_time(PyDateTime_DateTime *dt, char buffer[], int bufflen)
1143{
1144 int us = DATE_GET_MICROSECOND(dt);
1145
1146 PyOS_snprintf(buffer, bufflen,
1147 "%02d:%02d:%02d", /* 8 characters */
1148 DATE_GET_HOUR(dt),
1149 DATE_GET_MINUTE(dt),
1150 DATE_GET_SECOND(dt));
1151 if (us)
1152 PyOS_snprintf(buffer + 8, bufflen - 8, ".%06d", us);
1153}
1154
1155/* ---------------------------------------------------------------------------
1156 * Wrap functions from the time module. These aren't directly available
1157 * from C. Perhaps they should be.
1158 */
1159
1160/* Call time.time() and return its result (a Python float). */
1161static PyObject *
Guido van Rossumbd43e912002-12-16 20:34:55 +00001162time_time(void)
Tim Peters2a799bf2002-12-16 20:18:38 +00001163{
1164 PyObject *result = NULL;
1165 PyObject *time = PyImport_ImportModule("time");
1166
1167 if (time != NULL) {
1168 result = PyObject_CallMethod(time, "time", "()");
1169 Py_DECREF(time);
1170 }
1171 return result;
1172}
1173
1174/* Build a time.struct_time. The weekday and day number are automatically
1175 * computed from the y,m,d args.
1176 */
1177static PyObject *
1178build_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag)
1179{
1180 PyObject *time;
1181 PyObject *result = NULL;
1182
1183 time = PyImport_ImportModule("time");
1184 if (time != NULL) {
1185 result = PyObject_CallMethod(time, "struct_time",
1186 "((iiiiiiiii))",
1187 y, m, d,
1188 hh, mm, ss,
1189 weekday(y, m, d),
1190 days_before_month(y, m) + d,
1191 dstflag);
1192 Py_DECREF(time);
1193 }
1194 return result;
1195}
1196
1197/* ---------------------------------------------------------------------------
1198 * Miscellaneous helpers.
1199 */
1200
1201/* For obscure reasons, we need to use tp_richcompare instead of tp_compare.
1202 * The comparisons here all most naturally compute a cmp()-like result.
1203 * This little helper turns that into a bool result for rich comparisons.
1204 */
1205static PyObject *
1206diff_to_bool(int diff, int op)
1207{
1208 PyObject *result;
1209 int istrue;
1210
1211 switch (op) {
1212 case Py_EQ: istrue = diff == 0; break;
1213 case Py_NE: istrue = diff != 0; break;
1214 case Py_LE: istrue = diff <= 0; break;
1215 case Py_GE: istrue = diff >= 0; break;
1216 case Py_LT: istrue = diff < 0; break;
1217 case Py_GT: istrue = diff > 0; break;
1218 default:
1219 assert(! "op unknown");
1220 istrue = 0; /* To shut up compiler */
1221 }
1222 result = istrue ? Py_True : Py_False;
1223 Py_INCREF(result);
1224 return result;
1225}
1226
Tim Peters07534a62003-02-07 22:50:28 +00001227/* Raises a "can't compare" TypeError and returns NULL. */
1228static PyObject *
1229cmperror(PyObject *a, PyObject *b)
1230{
1231 PyErr_Format(PyExc_TypeError,
1232 "can't compare %s to %s",
1233 a->ob_type->tp_name, b->ob_type->tp_name);
1234 return NULL;
1235}
1236
Tim Peters2a799bf2002-12-16 20:18:38 +00001237/* ---------------------------------------------------------------------------
Tim Peters70533e22003-02-01 04:40:04 +00001238 * Basic object allocation. These allocate Python objects of the right
1239 * size and type, and do the Python object-initialization bit. If there's
1240 * not enough memory, they return NULL after setting MemoryError. All
1241 * data members remain uninitialized trash.
1242 */
1243static PyDateTime_Time *
1244alloc_time(int aware)
1245{
1246 PyDateTime_Time *self;
1247
1248 self = (PyDateTime_Time *)
1249 PyObject_MALLOC(aware ?
1250 sizeof(PyDateTime_Time) :
1251 sizeof(_PyDateTime_BaseTime));
1252 if (self == NULL)
1253 return (PyDateTime_Time *)PyErr_NoMemory();
1254 PyObject_INIT(self, &PyDateTime_TimeType);
1255 return self;
1256}
1257
1258static PyDateTime_DateTime *
1259alloc_datetime(int aware)
1260{
1261 PyDateTime_DateTime *self;
1262
1263 self = (PyDateTime_DateTime *)
1264 PyObject_MALLOC(aware ?
1265 sizeof(PyDateTime_DateTime) :
1266 sizeof(_PyDateTime_BaseDateTime));
1267 if (self == NULL)
1268 return (PyDateTime_DateTime *)PyErr_NoMemory();
1269 PyObject_INIT(self, &PyDateTime_DateTimeType);
1270 return self;
1271}
1272
1273/* ---------------------------------------------------------------------------
Tim Peters2a799bf2002-12-16 20:18:38 +00001274 * Helpers for setting object fields. These work on pointers to the
1275 * appropriate base class.
1276 */
1277
Tim Petersa9bc1682003-01-11 03:39:11 +00001278/* For date and datetime. */
Tim Peters2a799bf2002-12-16 20:18:38 +00001279static void
1280set_date_fields(PyDateTime_Date *self, int y, int m, int d)
1281{
1282 self->hashcode = -1;
1283 SET_YEAR(self, y);
1284 SET_MONTH(self, m);
1285 SET_DAY(self, d);
1286}
1287
Tim Peters2a799bf2002-12-16 20:18:38 +00001288/* ---------------------------------------------------------------------------
1289 * Create various objects, mostly without range checking.
1290 */
1291
1292/* Create a date instance with no range checking. */
1293static PyObject *
Guido van Rossum8b7a9a32003-04-14 22:01:58 +00001294new_date_ex(int year, int month, int day, PyTypeObject *type)
Tim Peters2a799bf2002-12-16 20:18:38 +00001295{
1296 PyDateTime_Date *self;
1297
Guido van Rossum8b7a9a32003-04-14 22:01:58 +00001298 self = (PyDateTime_Date *) (type->tp_alloc(type, 0));
Tim Peters2a799bf2002-12-16 20:18:38 +00001299 if (self != NULL)
1300 set_date_fields(self, year, month, day);
1301 return (PyObject *) self;
1302}
1303
Guido van Rossum8b7a9a32003-04-14 22:01:58 +00001304#define new_date(year, month, day) \
1305 (new_date_ex(year, month, day, &PyDateTime_DateType))
1306
Tim Peters2a799bf2002-12-16 20:18:38 +00001307/* Create a datetime instance with no range checking. */
1308static PyObject *
1309new_datetime(int year, int month, int day, int hour, int minute,
Tim Petersa9bc1682003-01-11 03:39:11 +00001310 int second, int usecond, PyObject *tzinfo)
Tim Peters2a799bf2002-12-16 20:18:38 +00001311{
1312 PyDateTime_DateTime *self;
Tim Petersa9bc1682003-01-11 03:39:11 +00001313 char aware = tzinfo != Py_None;
Tim Peters2a799bf2002-12-16 20:18:38 +00001314
Tim Peters70533e22003-02-01 04:40:04 +00001315 self = alloc_datetime(aware);
1316 if (self != NULL) {
1317 self->hastzinfo = aware;
1318 set_date_fields((PyDateTime_Date *)self, year, month, day);
1319 DATE_SET_HOUR(self, hour);
1320 DATE_SET_MINUTE(self, minute);
1321 DATE_SET_SECOND(self, second);
1322 DATE_SET_MICROSECOND(self, usecond);
1323 if (aware) {
1324 Py_INCREF(tzinfo);
1325 self->tzinfo = tzinfo;
1326 }
Tim Peters2a799bf2002-12-16 20:18:38 +00001327 }
Tim Peters70533e22003-02-01 04:40:04 +00001328 return (PyObject *)self;
Tim Peters2a799bf2002-12-16 20:18:38 +00001329}
1330
1331/* Create a time instance with no range checking. */
1332static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00001333new_time(int hour, int minute, int second, int usecond, PyObject *tzinfo)
Tim Peters2a799bf2002-12-16 20:18:38 +00001334{
1335 PyDateTime_Time *self;
Tim Peters37f39822003-01-10 03:49:02 +00001336 char aware = tzinfo != Py_None;
Tim Peters2a799bf2002-12-16 20:18:38 +00001337
Tim Peters70533e22003-02-01 04:40:04 +00001338 self = alloc_time(aware);
1339 if (self != NULL) {
1340 self->hastzinfo = aware;
1341 self->hashcode = -1;
1342 TIME_SET_HOUR(self, hour);
1343 TIME_SET_MINUTE(self, minute);
1344 TIME_SET_SECOND(self, second);
1345 TIME_SET_MICROSECOND(self, usecond);
1346 if (aware) {
1347 Py_INCREF(tzinfo);
1348 self->tzinfo = tzinfo;
1349 }
Tim Peters2a799bf2002-12-16 20:18:38 +00001350 }
Tim Peters70533e22003-02-01 04:40:04 +00001351 return (PyObject *)self;
Tim Peters2a799bf2002-12-16 20:18:38 +00001352}
1353
1354/* Create a timedelta instance. Normalize the members iff normalize is
1355 * true. Passing false is a speed optimization, if you know for sure
1356 * that seconds and microseconds are already in their proper ranges. In any
1357 * case, raises OverflowError and returns NULL if the normalized days is out
1358 * of range).
1359 */
1360static PyObject *
1361new_delta(int days, int seconds, int microseconds, int normalize)
1362{
1363 PyDateTime_Delta *self;
1364
1365 if (normalize)
1366 normalize_d_s_us(&days, &seconds, &microseconds);
1367 assert(0 <= seconds && seconds < 24*3600);
1368 assert(0 <= microseconds && microseconds < 1000000);
1369
1370 if (check_delta_day_range(days) < 0)
1371 return NULL;
1372
1373 self = PyObject_New(PyDateTime_Delta, &PyDateTime_DeltaType);
1374 if (self != NULL) {
1375 self->hashcode = -1;
1376 SET_TD_DAYS(self, days);
1377 SET_TD_SECONDS(self, seconds);
1378 SET_TD_MICROSECONDS(self, microseconds);
1379 }
1380 return (PyObject *) self;
1381}
1382
1383
1384/* ---------------------------------------------------------------------------
1385 * Cached Python objects; these are set by the module init function.
1386 */
1387
1388/* Conversion factors. */
1389static PyObject *us_per_us = NULL; /* 1 */
1390static PyObject *us_per_ms = NULL; /* 1000 */
1391static PyObject *us_per_second = NULL; /* 1000000 */
1392static PyObject *us_per_minute = NULL; /* 1e6 * 60 as Python int */
1393static PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python long */
1394static PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python long */
1395static PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python long */
1396static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */
1397
Tim Peters2a799bf2002-12-16 20:18:38 +00001398/* ---------------------------------------------------------------------------
1399 * Class implementations.
1400 */
1401
1402/*
1403 * PyDateTime_Delta implementation.
1404 */
1405
1406/* Convert a timedelta to a number of us,
1407 * (24*3600*self.days + self.seconds)*1000000 + self.microseconds
1408 * as a Python int or long.
1409 * Doing mixed-radix arithmetic by hand instead is excruciating in C,
1410 * due to ubiquitous overflow possibilities.
1411 */
1412static PyObject *
1413delta_to_microseconds(PyDateTime_Delta *self)
1414{
1415 PyObject *x1 = NULL;
1416 PyObject *x2 = NULL;
1417 PyObject *x3 = NULL;
1418 PyObject *result = NULL;
1419
1420 x1 = PyInt_FromLong(GET_TD_DAYS(self));
1421 if (x1 == NULL)
1422 goto Done;
1423 x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */
1424 if (x2 == NULL)
1425 goto Done;
1426 Py_DECREF(x1);
1427 x1 = NULL;
1428
1429 /* x2 has days in seconds */
1430 x1 = PyInt_FromLong(GET_TD_SECONDS(self)); /* seconds */
1431 if (x1 == NULL)
1432 goto Done;
1433 x3 = PyNumber_Add(x1, x2); /* days and seconds in seconds */
1434 if (x3 == NULL)
1435 goto Done;
1436 Py_DECREF(x1);
1437 Py_DECREF(x2);
1438 x1 = x2 = NULL;
1439
1440 /* x3 has days+seconds in seconds */
1441 x1 = PyNumber_Multiply(x3, us_per_second); /* us */
1442 if (x1 == NULL)
1443 goto Done;
1444 Py_DECREF(x3);
1445 x3 = NULL;
1446
1447 /* x1 has days+seconds in us */
1448 x2 = PyInt_FromLong(GET_TD_MICROSECONDS(self));
1449 if (x2 == NULL)
1450 goto Done;
1451 result = PyNumber_Add(x1, x2);
1452
1453Done:
1454 Py_XDECREF(x1);
1455 Py_XDECREF(x2);
1456 Py_XDECREF(x3);
1457 return result;
1458}
1459
1460/* Convert a number of us (as a Python int or long) to a timedelta.
1461 */
1462static PyObject *
1463microseconds_to_delta(PyObject *pyus)
1464{
1465 int us;
1466 int s;
1467 int d;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001468 long temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001469
1470 PyObject *tuple = NULL;
1471 PyObject *num = NULL;
1472 PyObject *result = NULL;
1473
1474 tuple = PyNumber_Divmod(pyus, us_per_second);
1475 if (tuple == NULL)
1476 goto Done;
1477
1478 num = PyTuple_GetItem(tuple, 1); /* us */
1479 if (num == NULL)
1480 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001481 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001482 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001483 if (temp == -1 && PyErr_Occurred())
1484 goto Done;
1485 assert(0 <= temp && temp < 1000000);
1486 us = (int)temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001487 if (us < 0) {
1488 /* The divisor was positive, so this must be an error. */
1489 assert(PyErr_Occurred());
1490 goto Done;
1491 }
1492
1493 num = PyTuple_GetItem(tuple, 0); /* leftover seconds */
1494 if (num == NULL)
1495 goto Done;
1496 Py_INCREF(num);
1497 Py_DECREF(tuple);
1498
1499 tuple = PyNumber_Divmod(num, seconds_per_day);
1500 if (tuple == NULL)
1501 goto Done;
1502 Py_DECREF(num);
1503
1504 num = PyTuple_GetItem(tuple, 1); /* seconds */
1505 if (num == NULL)
1506 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001507 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001508 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001509 if (temp == -1 && PyErr_Occurred())
1510 goto Done;
1511 assert(0 <= temp && temp < 24*3600);
1512 s = (int)temp;
1513
Tim Peters2a799bf2002-12-16 20:18:38 +00001514 if (s < 0) {
1515 /* The divisor was positive, so this must be an error. */
1516 assert(PyErr_Occurred());
1517 goto Done;
1518 }
1519
1520 num = PyTuple_GetItem(tuple, 0); /* leftover days */
1521 if (num == NULL)
1522 goto Done;
1523 Py_INCREF(num);
Tim Peters0b0f41c2002-12-19 01:44:38 +00001524 temp = PyLong_AsLong(num);
1525 if (temp == -1 && PyErr_Occurred())
Tim Peters2a799bf2002-12-16 20:18:38 +00001526 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001527 d = (int)temp;
1528 if ((long)d != temp) {
1529 PyErr_SetString(PyExc_OverflowError, "normalized days too "
1530 "large to fit in a C int");
1531 goto Done;
1532 }
Tim Peters2a799bf2002-12-16 20:18:38 +00001533 result = new_delta(d, s, us, 0);
1534
1535Done:
1536 Py_XDECREF(tuple);
1537 Py_XDECREF(num);
1538 return result;
1539}
1540
1541static PyObject *
1542multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
1543{
1544 PyObject *pyus_in;
1545 PyObject *pyus_out;
1546 PyObject *result;
1547
1548 pyus_in = delta_to_microseconds(delta);
1549 if (pyus_in == NULL)
1550 return NULL;
1551
1552 pyus_out = PyNumber_Multiply(pyus_in, intobj);
1553 Py_DECREF(pyus_in);
1554 if (pyus_out == NULL)
1555 return NULL;
1556
1557 result = microseconds_to_delta(pyus_out);
1558 Py_DECREF(pyus_out);
1559 return result;
1560}
1561
1562static PyObject *
1563divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj)
1564{
1565 PyObject *pyus_in;
1566 PyObject *pyus_out;
1567 PyObject *result;
1568
1569 pyus_in = delta_to_microseconds(delta);
1570 if (pyus_in == NULL)
1571 return NULL;
1572
1573 pyus_out = PyNumber_FloorDivide(pyus_in, intobj);
1574 Py_DECREF(pyus_in);
1575 if (pyus_out == NULL)
1576 return NULL;
1577
1578 result = microseconds_to_delta(pyus_out);
1579 Py_DECREF(pyus_out);
1580 return result;
1581}
1582
1583static PyObject *
1584delta_add(PyObject *left, PyObject *right)
1585{
1586 PyObject *result = Py_NotImplemented;
1587
1588 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1589 /* delta + delta */
1590 /* The C-level additions can't overflow because of the
1591 * invariant bounds.
1592 */
1593 int days = GET_TD_DAYS(left) + GET_TD_DAYS(right);
1594 int seconds = GET_TD_SECONDS(left) + GET_TD_SECONDS(right);
1595 int microseconds = GET_TD_MICROSECONDS(left) +
1596 GET_TD_MICROSECONDS(right);
1597 result = new_delta(days, seconds, microseconds, 1);
1598 }
1599
1600 if (result == Py_NotImplemented)
1601 Py_INCREF(result);
1602 return result;
1603}
1604
1605static PyObject *
1606delta_negative(PyDateTime_Delta *self)
1607{
1608 return new_delta(-GET_TD_DAYS(self),
1609 -GET_TD_SECONDS(self),
1610 -GET_TD_MICROSECONDS(self),
1611 1);
1612}
1613
1614static PyObject *
1615delta_positive(PyDateTime_Delta *self)
1616{
1617 /* Could optimize this (by returning self) if this isn't a
1618 * subclass -- but who uses unary + ? Approximately nobody.
1619 */
1620 return new_delta(GET_TD_DAYS(self),
1621 GET_TD_SECONDS(self),
1622 GET_TD_MICROSECONDS(self),
1623 0);
1624}
1625
1626static PyObject *
1627delta_abs(PyDateTime_Delta *self)
1628{
1629 PyObject *result;
1630
1631 assert(GET_TD_MICROSECONDS(self) >= 0);
1632 assert(GET_TD_SECONDS(self) >= 0);
1633
1634 if (GET_TD_DAYS(self) < 0)
1635 result = delta_negative(self);
1636 else
1637 result = delta_positive(self);
1638
1639 return result;
1640}
1641
1642static PyObject *
1643delta_subtract(PyObject *left, PyObject *right)
1644{
1645 PyObject *result = Py_NotImplemented;
1646
1647 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1648 /* delta - delta */
1649 PyObject *minus_right = PyNumber_Negative(right);
1650 if (minus_right) {
1651 result = delta_add(left, minus_right);
1652 Py_DECREF(minus_right);
1653 }
1654 else
1655 result = NULL;
1656 }
1657
1658 if (result == Py_NotImplemented)
1659 Py_INCREF(result);
1660 return result;
1661}
1662
1663/* This is more natural as a tp_compare, but doesn't work then: for whatever
1664 * reason, Python's try_3way_compare ignores tp_compare unless
1665 * PyInstance_Check returns true, but these aren't old-style classes.
1666 */
1667static PyObject *
1668delta_richcompare(PyDateTime_Delta *self, PyObject *other, int op)
1669{
Tim Peters07534a62003-02-07 22:50:28 +00001670 int diff = 42; /* nonsense */
Tim Peters2a799bf2002-12-16 20:18:38 +00001671
Tim Petersaa7d8492003-02-08 03:28:59 +00001672 if (PyDelta_Check(other)) {
Tim Peters07534a62003-02-07 22:50:28 +00001673 diff = GET_TD_DAYS(self) - GET_TD_DAYS(other);
1674 if (diff == 0) {
1675 diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other);
1676 if (diff == 0)
1677 diff = GET_TD_MICROSECONDS(self) -
1678 GET_TD_MICROSECONDS(other);
1679 }
Tim Peters2a799bf2002-12-16 20:18:38 +00001680 }
Tim Peters07534a62003-02-07 22:50:28 +00001681 else if (op == Py_EQ || op == Py_NE)
1682 diff = 1; /* any non-zero value will do */
1683
1684 else /* stop this from falling back to address comparison */
1685 return cmperror((PyObject *)self, other);
1686
Tim Peters2a799bf2002-12-16 20:18:38 +00001687 return diff_to_bool(diff, op);
1688}
1689
1690static PyObject *delta_getstate(PyDateTime_Delta *self);
1691
1692static long
1693delta_hash(PyDateTime_Delta *self)
1694{
1695 if (self->hashcode == -1) {
1696 PyObject *temp = delta_getstate(self);
1697 if (temp != NULL) {
1698 self->hashcode = PyObject_Hash(temp);
1699 Py_DECREF(temp);
1700 }
1701 }
1702 return self->hashcode;
1703}
1704
1705static PyObject *
1706delta_multiply(PyObject *left, PyObject *right)
1707{
1708 PyObject *result = Py_NotImplemented;
1709
1710 if (PyDelta_Check(left)) {
1711 /* delta * ??? */
1712 if (PyInt_Check(right) || PyLong_Check(right))
1713 result = multiply_int_timedelta(right,
1714 (PyDateTime_Delta *) left);
1715 }
1716 else if (PyInt_Check(left) || PyLong_Check(left))
1717 result = multiply_int_timedelta(left,
1718 (PyDateTime_Delta *) right);
1719
1720 if (result == Py_NotImplemented)
1721 Py_INCREF(result);
1722 return result;
1723}
1724
1725static PyObject *
1726delta_divide(PyObject *left, PyObject *right)
1727{
1728 PyObject *result = Py_NotImplemented;
1729
1730 if (PyDelta_Check(left)) {
1731 /* delta * ??? */
1732 if (PyInt_Check(right) || PyLong_Check(right))
1733 result = divide_timedelta_int(
1734 (PyDateTime_Delta *)left,
1735 right);
1736 }
1737
1738 if (result == Py_NotImplemented)
1739 Py_INCREF(result);
1740 return result;
1741}
1742
1743/* Fold in the value of the tag ("seconds", "weeks", etc) component of a
1744 * timedelta constructor. sofar is the # of microseconds accounted for
1745 * so far, and there are factor microseconds per current unit, the number
1746 * of which is given by num. num * factor is added to sofar in a
1747 * numerically careful way, and that's the result. Any fractional
1748 * microseconds left over (this can happen if num is a float type) are
1749 * added into *leftover.
1750 * Note that there are many ways this can give an error (NULL) return.
1751 */
1752static PyObject *
1753accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
1754 double *leftover)
1755{
1756 PyObject *prod;
1757 PyObject *sum;
1758
1759 assert(num != NULL);
1760
1761 if (PyInt_Check(num) || PyLong_Check(num)) {
1762 prod = PyNumber_Multiply(num, factor);
1763 if (prod == NULL)
1764 return NULL;
1765 sum = PyNumber_Add(sofar, prod);
1766 Py_DECREF(prod);
1767 return sum;
1768 }
1769
1770 if (PyFloat_Check(num)) {
1771 double dnum;
1772 double fracpart;
1773 double intpart;
1774 PyObject *x;
1775 PyObject *y;
1776
1777 /* The Plan: decompose num into an integer part and a
1778 * fractional part, num = intpart + fracpart.
1779 * Then num * factor ==
1780 * intpart * factor + fracpart * factor
1781 * and the LHS can be computed exactly in long arithmetic.
1782 * The RHS is again broken into an int part and frac part.
1783 * and the frac part is added into *leftover.
1784 */
1785 dnum = PyFloat_AsDouble(num);
1786 if (dnum == -1.0 && PyErr_Occurred())
1787 return NULL;
1788 fracpart = modf(dnum, &intpart);
1789 x = PyLong_FromDouble(intpart);
1790 if (x == NULL)
1791 return NULL;
1792
1793 prod = PyNumber_Multiply(x, factor);
1794 Py_DECREF(x);
1795 if (prod == NULL)
1796 return NULL;
1797
1798 sum = PyNumber_Add(sofar, prod);
1799 Py_DECREF(prod);
1800 if (sum == NULL)
1801 return NULL;
1802
1803 if (fracpart == 0.0)
1804 return sum;
1805 /* So far we've lost no information. Dealing with the
1806 * fractional part requires float arithmetic, and may
1807 * lose a little info.
1808 */
1809 assert(PyInt_Check(factor) || PyLong_Check(factor));
1810 if (PyInt_Check(factor))
1811 dnum = (double)PyInt_AsLong(factor);
1812 else
1813 dnum = PyLong_AsDouble(factor);
1814
1815 dnum *= fracpart;
1816 fracpart = modf(dnum, &intpart);
1817 x = PyLong_FromDouble(intpart);
1818 if (x == NULL) {
1819 Py_DECREF(sum);
1820 return NULL;
1821 }
1822
1823 y = PyNumber_Add(sum, x);
1824 Py_DECREF(sum);
1825 Py_DECREF(x);
1826 *leftover += fracpart;
1827 return y;
1828 }
1829
1830 PyErr_Format(PyExc_TypeError,
1831 "unsupported type for timedelta %s component: %s",
1832 tag, num->ob_type->tp_name);
1833 return NULL;
1834}
1835
1836static PyObject *
1837delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1838{
1839 PyObject *self = NULL;
1840
1841 /* Argument objects. */
1842 PyObject *day = NULL;
1843 PyObject *second = NULL;
1844 PyObject *us = NULL;
1845 PyObject *ms = NULL;
1846 PyObject *minute = NULL;
1847 PyObject *hour = NULL;
1848 PyObject *week = NULL;
1849
1850 PyObject *x = NULL; /* running sum of microseconds */
1851 PyObject *y = NULL; /* temp sum of microseconds */
1852 double leftover_us = 0.0;
1853
1854 static char *keywords[] = {
1855 "days", "seconds", "microseconds", "milliseconds",
1856 "minutes", "hours", "weeks", NULL
1857 };
1858
1859 if (PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOO:__new__",
1860 keywords,
1861 &day, &second, &us,
1862 &ms, &minute, &hour, &week) == 0)
1863 goto Done;
1864
1865 x = PyInt_FromLong(0);
1866 if (x == NULL)
1867 goto Done;
1868
1869#define CLEANUP \
1870 Py_DECREF(x); \
1871 x = y; \
1872 if (x == NULL) \
1873 goto Done
1874
1875 if (us) {
1876 y = accum("microseconds", x, us, us_per_us, &leftover_us);
1877 CLEANUP;
1878 }
1879 if (ms) {
1880 y = accum("milliseconds", x, ms, us_per_ms, &leftover_us);
1881 CLEANUP;
1882 }
1883 if (second) {
1884 y = accum("seconds", x, second, us_per_second, &leftover_us);
1885 CLEANUP;
1886 }
1887 if (minute) {
1888 y = accum("minutes", x, minute, us_per_minute, &leftover_us);
1889 CLEANUP;
1890 }
1891 if (hour) {
1892 y = accum("hours", x, hour, us_per_hour, &leftover_us);
1893 CLEANUP;
1894 }
1895 if (day) {
1896 y = accum("days", x, day, us_per_day, &leftover_us);
1897 CLEANUP;
1898 }
1899 if (week) {
1900 y = accum("weeks", x, week, us_per_week, &leftover_us);
1901 CLEANUP;
1902 }
1903 if (leftover_us) {
1904 /* Round to nearest whole # of us, and add into x. */
Tim Peters5d644dd2003-01-02 16:32:54 +00001905 PyObject *temp = PyLong_FromLong(round_to_long(leftover_us));
Tim Peters2a799bf2002-12-16 20:18:38 +00001906 if (temp == NULL) {
1907 Py_DECREF(x);
1908 goto Done;
1909 }
1910 y = PyNumber_Add(x, temp);
1911 Py_DECREF(temp);
1912 CLEANUP;
1913 }
1914
1915 self = microseconds_to_delta(x);
1916 Py_DECREF(x);
1917Done:
1918 return self;
1919
1920#undef CLEANUP
1921}
1922
1923static int
1924delta_nonzero(PyDateTime_Delta *self)
1925{
1926 return (GET_TD_DAYS(self) != 0
1927 || GET_TD_SECONDS(self) != 0
1928 || GET_TD_MICROSECONDS(self) != 0);
1929}
1930
1931static PyObject *
1932delta_repr(PyDateTime_Delta *self)
1933{
1934 if (GET_TD_MICROSECONDS(self) != 0)
1935 return PyString_FromFormat("%s(%d, %d, %d)",
1936 self->ob_type->tp_name,
1937 GET_TD_DAYS(self),
1938 GET_TD_SECONDS(self),
1939 GET_TD_MICROSECONDS(self));
1940 if (GET_TD_SECONDS(self) != 0)
1941 return PyString_FromFormat("%s(%d, %d)",
1942 self->ob_type->tp_name,
1943 GET_TD_DAYS(self),
1944 GET_TD_SECONDS(self));
1945
1946 return PyString_FromFormat("%s(%d)",
1947 self->ob_type->tp_name,
1948 GET_TD_DAYS(self));
1949}
1950
1951static PyObject *
1952delta_str(PyDateTime_Delta *self)
1953{
1954 int days = GET_TD_DAYS(self);
1955 int seconds = GET_TD_SECONDS(self);
1956 int us = GET_TD_MICROSECONDS(self);
1957 int hours;
1958 int minutes;
Tim Petersba873472002-12-18 20:19:21 +00001959 char buf[100];
1960 char *pbuf = buf;
1961 size_t buflen = sizeof(buf);
1962 int n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001963
1964 minutes = divmod(seconds, 60, &seconds);
1965 hours = divmod(minutes, 60, &minutes);
1966
1967 if (days) {
Tim Petersba873472002-12-18 20:19:21 +00001968 n = PyOS_snprintf(pbuf, buflen, "%d day%s, ", days,
1969 (days == 1 || days == -1) ? "" : "s");
1970 if (n < 0 || (size_t)n >= buflen)
1971 goto Fail;
1972 pbuf += n;
1973 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001974 }
1975
Tim Petersba873472002-12-18 20:19:21 +00001976 n = PyOS_snprintf(pbuf, buflen, "%d:%02d:%02d",
1977 hours, minutes, seconds);
1978 if (n < 0 || (size_t)n >= buflen)
1979 goto Fail;
1980 pbuf += n;
1981 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001982
1983 if (us) {
Tim Petersba873472002-12-18 20:19:21 +00001984 n = PyOS_snprintf(pbuf, buflen, ".%06d", us);
1985 if (n < 0 || (size_t)n >= buflen)
1986 goto Fail;
1987 pbuf += n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001988 }
1989
Tim Petersba873472002-12-18 20:19:21 +00001990 return PyString_FromStringAndSize(buf, pbuf - buf);
1991
1992 Fail:
1993 PyErr_SetString(PyExc_SystemError, "goofy result from PyOS_snprintf");
1994 return NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00001995}
1996
Tim Peters371935f2003-02-01 01:52:50 +00001997/* Pickle support, a simple use of __reduce__. */
1998
Tim Petersb57f8f02003-02-01 02:54:15 +00001999/* __getstate__ isn't exposed */
Tim Peters2a799bf2002-12-16 20:18:38 +00002000static PyObject *
2001delta_getstate(PyDateTime_Delta *self)
2002{
2003 return Py_BuildValue("iii", GET_TD_DAYS(self),
2004 GET_TD_SECONDS(self),
2005 GET_TD_MICROSECONDS(self));
2006}
2007
Tim Peters2a799bf2002-12-16 20:18:38 +00002008static PyObject *
2009delta_reduce(PyDateTime_Delta* self)
2010{
Tim Peters8a60c222003-02-01 01:47:29 +00002011 return Py_BuildValue("ON", self->ob_type, delta_getstate(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00002012}
2013
2014#define OFFSET(field) offsetof(PyDateTime_Delta, field)
2015
2016static PyMemberDef delta_members[] = {
Guido van Rossum177e41a2003-01-30 22:06:23 +00002017
Neal Norwitzdfb80862002-12-19 02:30:56 +00002018 {"days", T_INT, OFFSET(days), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002019 PyDoc_STR("Number of days.")},
2020
Neal Norwitzdfb80862002-12-19 02:30:56 +00002021 {"seconds", T_INT, OFFSET(seconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002022 PyDoc_STR("Number of seconds (>= 0 and less than 1 day).")},
2023
Neal Norwitzdfb80862002-12-19 02:30:56 +00002024 {"microseconds", T_INT, OFFSET(microseconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002025 PyDoc_STR("Number of microseconds (>= 0 and less than 1 second).")},
2026 {NULL}
2027};
2028
2029static PyMethodDef delta_methods[] = {
Guido van Rossum177e41a2003-01-30 22:06:23 +00002030 {"__reduce__", (PyCFunction)delta_reduce, METH_NOARGS,
2031 PyDoc_STR("__reduce__() -> (cls, state)")},
2032
Tim Peters2a799bf2002-12-16 20:18:38 +00002033 {NULL, NULL},
2034};
2035
2036static char delta_doc[] =
2037PyDoc_STR("Difference between two datetime values.");
2038
2039static PyNumberMethods delta_as_number = {
2040 delta_add, /* nb_add */
2041 delta_subtract, /* nb_subtract */
2042 delta_multiply, /* nb_multiply */
2043 delta_divide, /* nb_divide */
2044 0, /* nb_remainder */
2045 0, /* nb_divmod */
2046 0, /* nb_power */
2047 (unaryfunc)delta_negative, /* nb_negative */
2048 (unaryfunc)delta_positive, /* nb_positive */
2049 (unaryfunc)delta_abs, /* nb_absolute */
2050 (inquiry)delta_nonzero, /* nb_nonzero */
2051 0, /*nb_invert*/
2052 0, /*nb_lshift*/
2053 0, /*nb_rshift*/
2054 0, /*nb_and*/
2055 0, /*nb_xor*/
2056 0, /*nb_or*/
2057 0, /*nb_coerce*/
2058 0, /*nb_int*/
2059 0, /*nb_long*/
2060 0, /*nb_float*/
2061 0, /*nb_oct*/
2062 0, /*nb_hex*/
2063 0, /*nb_inplace_add*/
2064 0, /*nb_inplace_subtract*/
2065 0, /*nb_inplace_multiply*/
2066 0, /*nb_inplace_divide*/
2067 0, /*nb_inplace_remainder*/
2068 0, /*nb_inplace_power*/
2069 0, /*nb_inplace_lshift*/
2070 0, /*nb_inplace_rshift*/
2071 0, /*nb_inplace_and*/
2072 0, /*nb_inplace_xor*/
2073 0, /*nb_inplace_or*/
2074 delta_divide, /* nb_floor_divide */
2075 0, /* nb_true_divide */
2076 0, /* nb_inplace_floor_divide */
2077 0, /* nb_inplace_true_divide */
2078};
2079
2080static PyTypeObject PyDateTime_DeltaType = {
2081 PyObject_HEAD_INIT(NULL)
2082 0, /* ob_size */
2083 "datetime.timedelta", /* tp_name */
2084 sizeof(PyDateTime_Delta), /* tp_basicsize */
2085 0, /* tp_itemsize */
2086 0, /* tp_dealloc */
2087 0, /* tp_print */
2088 0, /* tp_getattr */
2089 0, /* tp_setattr */
2090 0, /* tp_compare */
2091 (reprfunc)delta_repr, /* tp_repr */
2092 &delta_as_number, /* tp_as_number */
2093 0, /* tp_as_sequence */
2094 0, /* tp_as_mapping */
2095 (hashfunc)delta_hash, /* tp_hash */
2096 0, /* tp_call */
2097 (reprfunc)delta_str, /* tp_str */
2098 PyObject_GenericGetAttr, /* tp_getattro */
2099 0, /* tp_setattro */
2100 0, /* tp_as_buffer */
2101 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
2102 delta_doc, /* tp_doc */
2103 0, /* tp_traverse */
2104 0, /* tp_clear */
2105 (richcmpfunc)delta_richcompare, /* tp_richcompare */
2106 0, /* tp_weaklistoffset */
2107 0, /* tp_iter */
2108 0, /* tp_iternext */
2109 delta_methods, /* tp_methods */
2110 delta_members, /* tp_members */
2111 0, /* tp_getset */
2112 0, /* tp_base */
2113 0, /* tp_dict */
2114 0, /* tp_descr_get */
2115 0, /* tp_descr_set */
2116 0, /* tp_dictoffset */
2117 0, /* tp_init */
2118 0, /* tp_alloc */
2119 delta_new, /* tp_new */
2120 _PyObject_Del, /* tp_free */
2121};
2122
2123/*
2124 * PyDateTime_Date implementation.
2125 */
2126
2127/* Accessor properties. */
2128
2129static PyObject *
2130date_year(PyDateTime_Date *self, void *unused)
2131{
2132 return PyInt_FromLong(GET_YEAR(self));
2133}
2134
2135static PyObject *
2136date_month(PyDateTime_Date *self, void *unused)
2137{
2138 return PyInt_FromLong(GET_MONTH(self));
2139}
2140
2141static PyObject *
2142date_day(PyDateTime_Date *self, void *unused)
2143{
2144 return PyInt_FromLong(GET_DAY(self));
2145}
2146
2147static PyGetSetDef date_getset[] = {
2148 {"year", (getter)date_year},
2149 {"month", (getter)date_month},
2150 {"day", (getter)date_day},
2151 {NULL}
2152};
2153
2154/* Constructors. */
2155
Tim Peters12bf3392002-12-24 05:41:27 +00002156static char *date_kws[] = {"year", "month", "day", NULL};
2157
Tim Peters2a799bf2002-12-16 20:18:38 +00002158static PyObject *
2159date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2160{
2161 PyObject *self = NULL;
Tim Peters70533e22003-02-01 04:40:04 +00002162 PyObject *state;
Tim Peters2a799bf2002-12-16 20:18:38 +00002163 int year;
2164 int month;
2165 int day;
2166
Guido van Rossum177e41a2003-01-30 22:06:23 +00002167 /* Check for invocation from pickle with __getstate__ state */
2168 if (PyTuple_GET_SIZE(args) == 1 &&
Tim Peters70533e22003-02-01 04:40:04 +00002169 PyString_Check(state = PyTuple_GET_ITEM(args, 0)) &&
2170 PyString_GET_SIZE(state) == _PyDateTime_DATE_DATASIZE)
Guido van Rossum177e41a2003-01-30 22:06:23 +00002171 {
Tim Peters70533e22003-02-01 04:40:04 +00002172 PyDateTime_Date *me;
2173
Guido van Rossum8b7a9a32003-04-14 22:01:58 +00002174 me = PyObject_New(PyDateTime_Date, type);
Tim Peters70533e22003-02-01 04:40:04 +00002175 if (me != NULL) {
2176 char *pdata = PyString_AS_STRING(state);
2177 memcpy(me->data, pdata, _PyDateTime_DATE_DATASIZE);
2178 me->hashcode = -1;
Guido van Rossum177e41a2003-01-30 22:06:23 +00002179 }
Tim Peters70533e22003-02-01 04:40:04 +00002180 return (PyObject *)me;
Guido van Rossum177e41a2003-01-30 22:06:23 +00002181 }
2182
Tim Peters12bf3392002-12-24 05:41:27 +00002183 if (PyArg_ParseTupleAndKeywords(args, kw, "iii", date_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002184 &year, &month, &day)) {
2185 if (check_date_args(year, month, day) < 0)
2186 return NULL;
Guido van Rossum8b7a9a32003-04-14 22:01:58 +00002187 self = new_date_ex(year, month, day, type);
Tim Peters2a799bf2002-12-16 20:18:38 +00002188 }
2189 return self;
2190}
2191
2192/* Return new date from localtime(t). */
2193static PyObject *
2194date_local_from_time_t(PyObject *cls, time_t t)
2195{
2196 struct tm *tm;
2197 PyObject *result = NULL;
2198
2199 tm = localtime(&t);
2200 if (tm)
2201 result = PyObject_CallFunction(cls, "iii",
2202 tm->tm_year + 1900,
2203 tm->tm_mon + 1,
2204 tm->tm_mday);
2205 else
2206 PyErr_SetString(PyExc_ValueError,
2207 "timestamp out of range for "
2208 "platform localtime() function");
2209 return result;
2210}
2211
2212/* Return new date from current time.
2213 * We say this is equivalent to fromtimestamp(time.time()), and the
2214 * only way to be sure of that is to *call* time.time(). That's not
2215 * generally the same as calling C's time.
2216 */
2217static PyObject *
2218date_today(PyObject *cls, PyObject *dummy)
2219{
2220 PyObject *time;
2221 PyObject *result;
2222
2223 time = time_time();
2224 if (time == NULL)
2225 return NULL;
2226
2227 /* Note well: today() is a class method, so this may not call
2228 * date.fromtimestamp. For example, it may call
2229 * datetime.fromtimestamp. That's why we need all the accuracy
2230 * time.time() delivers; if someone were gonzo about optimization,
2231 * date.today() could get away with plain C time().
2232 */
2233 result = PyObject_CallMethod(cls, "fromtimestamp", "O", time);
2234 Py_DECREF(time);
2235 return result;
2236}
2237
2238/* Return new date from given timestamp (Python timestamp -- a double). */
2239static PyObject *
2240date_fromtimestamp(PyObject *cls, PyObject *args)
2241{
2242 double timestamp;
2243 PyObject *result = NULL;
2244
2245 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2246 result = date_local_from_time_t(cls, (time_t)timestamp);
2247 return result;
2248}
2249
2250/* Return new date from proleptic Gregorian ordinal. Raises ValueError if
2251 * the ordinal is out of range.
2252 */
2253static PyObject *
2254date_fromordinal(PyObject *cls, PyObject *args)
2255{
2256 PyObject *result = NULL;
2257 int ordinal;
2258
2259 if (PyArg_ParseTuple(args, "i:fromordinal", &ordinal)) {
2260 int year;
2261 int month;
2262 int day;
2263
2264 if (ordinal < 1)
2265 PyErr_SetString(PyExc_ValueError, "ordinal must be "
2266 ">= 1");
2267 else {
2268 ord_to_ymd(ordinal, &year, &month, &day);
2269 result = PyObject_CallFunction(cls, "iii",
2270 year, month, day);
2271 }
2272 }
2273 return result;
2274}
2275
2276/*
2277 * Date arithmetic.
2278 */
2279
2280/* date + timedelta -> date. If arg negate is true, subtract the timedelta
2281 * instead.
2282 */
2283static PyObject *
2284add_date_timedelta(PyDateTime_Date *date, PyDateTime_Delta *delta, int negate)
2285{
2286 PyObject *result = NULL;
2287 int year = GET_YEAR(date);
2288 int month = GET_MONTH(date);
2289 int deltadays = GET_TD_DAYS(delta);
2290 /* C-level overflow is impossible because |deltadays| < 1e9. */
2291 int day = GET_DAY(date) + (negate ? -deltadays : deltadays);
2292
2293 if (normalize_date(&year, &month, &day) >= 0)
2294 result = new_date(year, month, day);
2295 return result;
2296}
2297
2298static PyObject *
2299date_add(PyObject *left, PyObject *right)
2300{
2301 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2302 Py_INCREF(Py_NotImplemented);
2303 return Py_NotImplemented;
2304 }
Tim Petersaa7d8492003-02-08 03:28:59 +00002305 if (PyDate_Check(left)) {
Tim Peters2a799bf2002-12-16 20:18:38 +00002306 /* date + ??? */
2307 if (PyDelta_Check(right))
2308 /* date + delta */
2309 return add_date_timedelta((PyDateTime_Date *) left,
2310 (PyDateTime_Delta *) right,
2311 0);
2312 }
2313 else {
2314 /* ??? + date
2315 * 'right' must be one of us, or we wouldn't have been called
2316 */
2317 if (PyDelta_Check(left))
2318 /* delta + date */
2319 return add_date_timedelta((PyDateTime_Date *) right,
2320 (PyDateTime_Delta *) left,
2321 0);
2322 }
2323 Py_INCREF(Py_NotImplemented);
2324 return Py_NotImplemented;
2325}
2326
2327static PyObject *
2328date_subtract(PyObject *left, PyObject *right)
2329{
2330 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2331 Py_INCREF(Py_NotImplemented);
2332 return Py_NotImplemented;
2333 }
Tim Petersaa7d8492003-02-08 03:28:59 +00002334 if (PyDate_Check(left)) {
2335 if (PyDate_Check(right)) {
Tim Peters2a799bf2002-12-16 20:18:38 +00002336 /* date - date */
2337 int left_ord = ymd_to_ord(GET_YEAR(left),
2338 GET_MONTH(left),
2339 GET_DAY(left));
2340 int right_ord = ymd_to_ord(GET_YEAR(right),
2341 GET_MONTH(right),
2342 GET_DAY(right));
2343 return new_delta(left_ord - right_ord, 0, 0, 0);
2344 }
2345 if (PyDelta_Check(right)) {
2346 /* date - delta */
2347 return add_date_timedelta((PyDateTime_Date *) left,
2348 (PyDateTime_Delta *) right,
2349 1);
2350 }
2351 }
2352 Py_INCREF(Py_NotImplemented);
2353 return Py_NotImplemented;
2354}
2355
2356
2357/* Various ways to turn a date into a string. */
2358
2359static PyObject *
2360date_repr(PyDateTime_Date *self)
2361{
2362 char buffer[1028];
2363 char *typename;
2364
2365 typename = self->ob_type->tp_name;
2366 PyOS_snprintf(buffer, sizeof(buffer), "%s(%d, %d, %d)",
2367 typename,
2368 GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2369
2370 return PyString_FromString(buffer);
2371}
2372
2373static PyObject *
2374date_isoformat(PyDateTime_Date *self)
2375{
2376 char buffer[128];
2377
2378 isoformat_date(self, buffer, sizeof(buffer));
2379 return PyString_FromString(buffer);
2380}
2381
2382/* str() calls the appropriate isofomat() method. */
2383static PyObject *
2384date_str(PyDateTime_Date *self)
2385{
2386 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
2387}
2388
2389
2390static PyObject *
2391date_ctime(PyDateTime_Date *self)
2392{
2393 return format_ctime(self, 0, 0, 0);
2394}
2395
2396static PyObject *
2397date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2398{
2399 /* This method can be inherited, and needs to call the
2400 * timetuple() method appropriate to self's class.
2401 */
2402 PyObject *result;
2403 PyObject *format;
2404 PyObject *tuple;
2405 static char *keywords[] = {"format", NULL};
2406
2407 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
2408 &PyString_Type, &format))
2409 return NULL;
2410
2411 tuple = PyObject_CallMethod((PyObject *)self, "timetuple", "()");
2412 if (tuple == NULL)
2413 return NULL;
Tim Petersbad8ff02002-12-30 20:52:32 +00002414 result = wrap_strftime((PyObject *)self, format, tuple,
2415 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00002416 Py_DECREF(tuple);
2417 return result;
2418}
2419
2420/* ISO methods. */
2421
2422static PyObject *
2423date_isoweekday(PyDateTime_Date *self)
2424{
2425 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2426
2427 return PyInt_FromLong(dow + 1);
2428}
2429
2430static PyObject *
2431date_isocalendar(PyDateTime_Date *self)
2432{
2433 int year = GET_YEAR(self);
2434 int week1_monday = iso_week1_monday(year);
2435 int today = ymd_to_ord(year, GET_MONTH(self), GET_DAY(self));
2436 int week;
2437 int day;
2438
2439 week = divmod(today - week1_monday, 7, &day);
2440 if (week < 0) {
2441 --year;
2442 week1_monday = iso_week1_monday(year);
2443 week = divmod(today - week1_monday, 7, &day);
2444 }
2445 else if (week >= 52 && today >= iso_week1_monday(year + 1)) {
2446 ++year;
2447 week = 0;
2448 }
2449 return Py_BuildValue("iii", year, week + 1, day + 1);
2450}
2451
2452/* Miscellaneous methods. */
2453
2454/* This is more natural as a tp_compare, but doesn't work then: for whatever
2455 * reason, Python's try_3way_compare ignores tp_compare unless
2456 * PyInstance_Check returns true, but these aren't old-style classes.
2457 */
2458static PyObject *
2459date_richcompare(PyDateTime_Date *self, PyObject *other, int op)
2460{
Tim Peters07534a62003-02-07 22:50:28 +00002461 int diff = 42; /* nonsense */
Tim Peters2a799bf2002-12-16 20:18:38 +00002462
Tim Peters07534a62003-02-07 22:50:28 +00002463 if (PyDate_Check(other))
2464 diff = memcmp(self->data, ((PyDateTime_Date *)other)->data,
2465 _PyDateTime_DATE_DATASIZE);
2466
2467 else if (PyObject_HasAttrString(other, "timetuple")) {
2468 /* A hook for other kinds of date objects. */
2469 Py_INCREF(Py_NotImplemented);
2470 return Py_NotImplemented;
Tim Peters2a799bf2002-12-16 20:18:38 +00002471 }
Tim Peters07534a62003-02-07 22:50:28 +00002472 else if (op == Py_EQ || op == Py_NE)
2473 diff = 1; /* any non-zero value will do */
2474
2475 else /* stop this from falling back to address comparison */
2476 return cmperror((PyObject *)self, other);
2477
Tim Peters2a799bf2002-12-16 20:18:38 +00002478 return diff_to_bool(diff, op);
2479}
2480
2481static PyObject *
2482date_timetuple(PyDateTime_Date *self)
2483{
2484 return build_struct_time(GET_YEAR(self),
2485 GET_MONTH(self),
2486 GET_DAY(self),
2487 0, 0, 0, -1);
2488}
2489
Tim Peters12bf3392002-12-24 05:41:27 +00002490static PyObject *
2491date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2492{
2493 PyObject *clone;
2494 PyObject *tuple;
2495 int year = GET_YEAR(self);
2496 int month = GET_MONTH(self);
2497 int day = GET_DAY(self);
2498
2499 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iii:replace", date_kws,
2500 &year, &month, &day))
2501 return NULL;
2502 tuple = Py_BuildValue("iii", year, month, day);
2503 if (tuple == NULL)
2504 return NULL;
2505 clone = date_new(self->ob_type, tuple, NULL);
2506 Py_DECREF(tuple);
2507 return clone;
2508}
2509
Tim Peters2a799bf2002-12-16 20:18:38 +00002510static PyObject *date_getstate(PyDateTime_Date *self);
2511
2512static long
2513date_hash(PyDateTime_Date *self)
2514{
2515 if (self->hashcode == -1) {
2516 PyObject *temp = date_getstate(self);
2517 if (temp != NULL) {
2518 self->hashcode = PyObject_Hash(temp);
2519 Py_DECREF(temp);
2520 }
2521 }
2522 return self->hashcode;
2523}
2524
2525static PyObject *
2526date_toordinal(PyDateTime_Date *self)
2527{
2528 return PyInt_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self),
2529 GET_DAY(self)));
2530}
2531
2532static PyObject *
2533date_weekday(PyDateTime_Date *self)
2534{
2535 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2536
2537 return PyInt_FromLong(dow);
2538}
2539
Tim Peters371935f2003-02-01 01:52:50 +00002540/* Pickle support, a simple use of __reduce__. */
Tim Peters2a799bf2002-12-16 20:18:38 +00002541
Tim Petersb57f8f02003-02-01 02:54:15 +00002542/* __getstate__ isn't exposed */
Tim Peters2a799bf2002-12-16 20:18:38 +00002543static PyObject *
2544date_getstate(PyDateTime_Date *self)
2545{
Guido van Rossum177e41a2003-01-30 22:06:23 +00002546 return Py_BuildValue(
2547 "(N)",
2548 PyString_FromStringAndSize((char *)self->data,
2549 _PyDateTime_DATE_DATASIZE));
Tim Peters2a799bf2002-12-16 20:18:38 +00002550}
2551
2552static PyObject *
Guido van Rossum177e41a2003-01-30 22:06:23 +00002553date_reduce(PyDateTime_Date *self, PyObject *arg)
Tim Peters2a799bf2002-12-16 20:18:38 +00002554{
Guido van Rossum177e41a2003-01-30 22:06:23 +00002555 return Py_BuildValue("(ON)", self->ob_type, date_getstate(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00002556}
2557
2558static PyMethodDef date_methods[] = {
Guido van Rossum177e41a2003-01-30 22:06:23 +00002559
Tim Peters2a799bf2002-12-16 20:18:38 +00002560 /* Class methods: */
Guido van Rossum177e41a2003-01-30 22:06:23 +00002561
Tim Peters2a799bf2002-12-16 20:18:38 +00002562 {"fromtimestamp", (PyCFunction)date_fromtimestamp, METH_VARARGS |
2563 METH_CLASS,
2564 PyDoc_STR("timestamp -> local date from a POSIX timestamp (like "
2565 "time.time()).")},
2566
2567 {"fromordinal", (PyCFunction)date_fromordinal, METH_VARARGS |
2568 METH_CLASS,
2569 PyDoc_STR("int -> date corresponding to a proleptic Gregorian "
2570 "ordinal.")},
2571
2572 {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS,
2573 PyDoc_STR("Current date or datetime: same as "
2574 "self.__class__.fromtimestamp(time.time()).")},
2575
2576 /* Instance methods: */
2577
2578 {"ctime", (PyCFunction)date_ctime, METH_NOARGS,
2579 PyDoc_STR("Return ctime() style string.")},
2580
2581 {"strftime", (PyCFunction)date_strftime, METH_KEYWORDS,
2582 PyDoc_STR("format -> strftime() style string.")},
2583
2584 {"timetuple", (PyCFunction)date_timetuple, METH_NOARGS,
2585 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
2586
2587 {"isocalendar", (PyCFunction)date_isocalendar, METH_NOARGS,
2588 PyDoc_STR("Return a 3-tuple containing ISO year, week number, and "
2589 "weekday.")},
2590
2591 {"isoformat", (PyCFunction)date_isoformat, METH_NOARGS,
2592 PyDoc_STR("Return string in ISO 8601 format, YYYY-MM-DD.")},
2593
2594 {"isoweekday", (PyCFunction)date_isoweekday, METH_NOARGS,
2595 PyDoc_STR("Return the day of the week represented by the date.\n"
2596 "Monday == 1 ... Sunday == 7")},
2597
2598 {"toordinal", (PyCFunction)date_toordinal, METH_NOARGS,
2599 PyDoc_STR("Return proleptic Gregorian ordinal. January 1 of year "
2600 "1 is day 1.")},
2601
2602 {"weekday", (PyCFunction)date_weekday, METH_NOARGS,
2603 PyDoc_STR("Return the day of the week represented by the date.\n"
2604 "Monday == 0 ... Sunday == 6")},
2605
Tim Peters12bf3392002-12-24 05:41:27 +00002606 {"replace", (PyCFunction)date_replace, METH_KEYWORDS,
2607 PyDoc_STR("Return date with new specified fields.")},
2608
Guido van Rossum177e41a2003-01-30 22:06:23 +00002609 {"__reduce__", (PyCFunction)date_reduce, METH_NOARGS,
2610 PyDoc_STR("__reduce__() -> (cls, state)")},
2611
Tim Peters2a799bf2002-12-16 20:18:38 +00002612 {NULL, NULL}
2613};
2614
2615static char date_doc[] =
2616PyDoc_STR("Basic date type.");
2617
2618static PyNumberMethods date_as_number = {
2619 date_add, /* nb_add */
2620 date_subtract, /* nb_subtract */
2621 0, /* nb_multiply */
2622 0, /* nb_divide */
2623 0, /* nb_remainder */
2624 0, /* nb_divmod */
2625 0, /* nb_power */
2626 0, /* nb_negative */
2627 0, /* nb_positive */
2628 0, /* nb_absolute */
2629 0, /* nb_nonzero */
2630};
2631
2632static PyTypeObject PyDateTime_DateType = {
2633 PyObject_HEAD_INIT(NULL)
2634 0, /* ob_size */
2635 "datetime.date", /* tp_name */
2636 sizeof(PyDateTime_Date), /* tp_basicsize */
2637 0, /* tp_itemsize */
Guido van Rossum8b7a9a32003-04-14 22:01:58 +00002638 0, /* tp_dealloc */
Tim Peters2a799bf2002-12-16 20:18:38 +00002639 0, /* tp_print */
2640 0, /* tp_getattr */
2641 0, /* tp_setattr */
2642 0, /* tp_compare */
2643 (reprfunc)date_repr, /* tp_repr */
2644 &date_as_number, /* tp_as_number */
2645 0, /* tp_as_sequence */
2646 0, /* tp_as_mapping */
2647 (hashfunc)date_hash, /* tp_hash */
2648 0, /* tp_call */
2649 (reprfunc)date_str, /* tp_str */
2650 PyObject_GenericGetAttr, /* tp_getattro */
2651 0, /* tp_setattro */
2652 0, /* tp_as_buffer */
2653 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
2654 Py_TPFLAGS_BASETYPE, /* tp_flags */
2655 date_doc, /* tp_doc */
2656 0, /* tp_traverse */
2657 0, /* tp_clear */
2658 (richcmpfunc)date_richcompare, /* tp_richcompare */
2659 0, /* tp_weaklistoffset */
2660 0, /* tp_iter */
2661 0, /* tp_iternext */
2662 date_methods, /* tp_methods */
2663 0, /* tp_members */
2664 date_getset, /* tp_getset */
2665 0, /* tp_base */
2666 0, /* tp_dict */
2667 0, /* tp_descr_get */
2668 0, /* tp_descr_set */
2669 0, /* tp_dictoffset */
2670 0, /* tp_init */
2671 0, /* tp_alloc */
2672 date_new, /* tp_new */
2673 _PyObject_Del, /* tp_free */
2674};
2675
2676/*
Tim Peters2a799bf2002-12-16 20:18:38 +00002677 * PyDateTime_TZInfo implementation.
2678 */
2679
2680/* This is a pure abstract base class, so doesn't do anything beyond
2681 * raising NotImplemented exceptions. Real tzinfo classes need
2682 * to derive from this. This is mostly for clarity, and for efficiency in
Tim Petersa9bc1682003-01-11 03:39:11 +00002683 * datetime and time constructors (their tzinfo arguments need to
Tim Peters2a799bf2002-12-16 20:18:38 +00002684 * be subclasses of this tzinfo class, which is easy and quick to check).
2685 *
2686 * Note: For reasons having to do with pickling of subclasses, we have
2687 * to allow tzinfo objects to be instantiated. This wasn't an issue
2688 * in the Python implementation (__init__() could raise NotImplementedError
2689 * there without ill effect), but doing so in the C implementation hit a
2690 * brick wall.
2691 */
2692
2693static PyObject *
2694tzinfo_nogo(const char* methodname)
2695{
2696 PyErr_Format(PyExc_NotImplementedError,
2697 "a tzinfo subclass must implement %s()",
2698 methodname);
2699 return NULL;
2700}
2701
2702/* Methods. A subclass must implement these. */
2703
Tim Peters52dcce22003-01-23 16:36:11 +00002704static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00002705tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt)
2706{
2707 return tzinfo_nogo("tzname");
2708}
2709
Tim Peters52dcce22003-01-23 16:36:11 +00002710static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00002711tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt)
2712{
2713 return tzinfo_nogo("utcoffset");
2714}
2715
Tim Peters52dcce22003-01-23 16:36:11 +00002716static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00002717tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
2718{
2719 return tzinfo_nogo("dst");
2720}
2721
Tim Peters52dcce22003-01-23 16:36:11 +00002722static PyObject *
2723tzinfo_fromutc(PyDateTime_TZInfo *self, PyDateTime_DateTime *dt)
2724{
2725 int y, m, d, hh, mm, ss, us;
2726
2727 PyObject *result;
2728 int off, dst;
2729 int none;
2730 int delta;
2731
2732 if (! PyDateTime_Check(dt)) {
2733 PyErr_SetString(PyExc_TypeError,
2734 "fromutc: argument must be a datetime");
2735 return NULL;
2736 }
2737 if (! HASTZINFO(dt) || dt->tzinfo != (PyObject *)self) {
2738 PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo "
2739 "is not self");
2740 return NULL;
2741 }
2742
2743 off = call_utcoffset(dt->tzinfo, (PyObject *)dt, &none);
2744 if (off == -1 && PyErr_Occurred())
2745 return NULL;
2746 if (none) {
2747 PyErr_SetString(PyExc_ValueError, "fromutc: non-None "
2748 "utcoffset() result required");
2749 return NULL;
2750 }
2751
2752 dst = call_dst(dt->tzinfo, (PyObject *)dt, &none);
2753 if (dst == -1 && PyErr_Occurred())
2754 return NULL;
2755 if (none) {
2756 PyErr_SetString(PyExc_ValueError, "fromutc: non-None "
2757 "dst() result required");
2758 return NULL;
2759 }
2760
2761 y = GET_YEAR(dt);
2762 m = GET_MONTH(dt);
2763 d = GET_DAY(dt);
2764 hh = DATE_GET_HOUR(dt);
2765 mm = DATE_GET_MINUTE(dt);
2766 ss = DATE_GET_SECOND(dt);
2767 us = DATE_GET_MICROSECOND(dt);
2768
2769 delta = off - dst;
2770 mm += delta;
2771 if ((mm < 0 || mm >= 60) &&
2772 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Petersb1049e82003-01-23 17:20:36 +00002773 return NULL;
Tim Peters52dcce22003-01-23 16:36:11 +00002774 result = new_datetime(y, m, d, hh, mm, ss, us, dt->tzinfo);
2775 if (result == NULL)
2776 return result;
2777
2778 dst = call_dst(dt->tzinfo, result, &none);
2779 if (dst == -1 && PyErr_Occurred())
2780 goto Fail;
2781 if (none)
2782 goto Inconsistent;
2783 if (dst == 0)
2784 return result;
2785
2786 mm += dst;
2787 if ((mm < 0 || mm >= 60) &&
2788 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
2789 goto Fail;
2790 Py_DECREF(result);
2791 result = new_datetime(y, m, d, hh, mm, ss, us, dt->tzinfo);
2792 return result;
2793
2794Inconsistent:
2795 PyErr_SetString(PyExc_ValueError, "fromutc: tz.dst() gave"
2796 "inconsistent results; cannot convert");
2797
2798 /* fall thru to failure */
2799Fail:
2800 Py_DECREF(result);
2801 return NULL;
2802}
2803
Tim Peters2a799bf2002-12-16 20:18:38 +00002804/*
2805 * Pickle support. This is solely so that tzinfo subclasses can use
Guido van Rossum177e41a2003-01-30 22:06:23 +00002806 * pickling -- tzinfo itself is supposed to be uninstantiable.
Tim Peters2a799bf2002-12-16 20:18:38 +00002807 */
2808
Guido van Rossum177e41a2003-01-30 22:06:23 +00002809static PyObject *
2810tzinfo_reduce(PyObject *self)
2811{
2812 PyObject *args, *state, *tmp;
2813 PyObject *getinitargs, *getstate;
Tim Peters2a799bf2002-12-16 20:18:38 +00002814
Guido van Rossum177e41a2003-01-30 22:06:23 +00002815 tmp = PyTuple_New(0);
2816 if (tmp == NULL)
2817 return NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00002818
Guido van Rossum177e41a2003-01-30 22:06:23 +00002819 getinitargs = PyObject_GetAttrString(self, "__getinitargs__");
2820 if (getinitargs != NULL) {
2821 args = PyObject_CallObject(getinitargs, tmp);
2822 Py_DECREF(getinitargs);
2823 if (args == NULL) {
2824 Py_DECREF(tmp);
2825 return NULL;
2826 }
2827 }
2828 else {
2829 PyErr_Clear();
2830 args = tmp;
2831 Py_INCREF(args);
2832 }
2833
2834 getstate = PyObject_GetAttrString(self, "__getstate__");
2835 if (getstate != NULL) {
2836 state = PyObject_CallObject(getstate, tmp);
2837 Py_DECREF(getstate);
2838 if (state == NULL) {
2839 Py_DECREF(args);
2840 Py_DECREF(tmp);
2841 return NULL;
2842 }
2843 }
2844 else {
2845 PyObject **dictptr;
2846 PyErr_Clear();
2847 state = Py_None;
2848 dictptr = _PyObject_GetDictPtr(self);
2849 if (dictptr && *dictptr && PyDict_Size(*dictptr))
2850 state = *dictptr;
2851 Py_INCREF(state);
2852 }
2853
2854 Py_DECREF(tmp);
2855
2856 if (state == Py_None) {
2857 Py_DECREF(state);
2858 return Py_BuildValue("(ON)", self->ob_type, args);
2859 }
2860 else
2861 return Py_BuildValue("(ONN)", self->ob_type, args, state);
2862}
Tim Peters2a799bf2002-12-16 20:18:38 +00002863
2864static PyMethodDef tzinfo_methods[] = {
Guido van Rossum177e41a2003-01-30 22:06:23 +00002865
Tim Peters2a799bf2002-12-16 20:18:38 +00002866 {"tzname", (PyCFunction)tzinfo_tzname, METH_O,
2867 PyDoc_STR("datetime -> string name of time zone.")},
2868
2869 {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
2870 PyDoc_STR("datetime -> minutes east of UTC (negative for "
2871 "west of UTC).")},
2872
2873 {"dst", (PyCFunction)tzinfo_dst, METH_O,
2874 PyDoc_STR("datetime -> DST offset in minutes east of UTC.")},
2875
Tim Peters52dcce22003-01-23 16:36:11 +00002876 {"fromutc", (PyCFunction)tzinfo_fromutc, METH_O,
2877 PyDoc_STR("datetime in UTC -> datetime in local time.")},
2878
Guido van Rossum177e41a2003-01-30 22:06:23 +00002879 {"__reduce__", (PyCFunction)tzinfo_reduce, METH_NOARGS,
2880 PyDoc_STR("-> (cls, state)")},
2881
Tim Peters2a799bf2002-12-16 20:18:38 +00002882 {NULL, NULL}
2883};
2884
2885static char tzinfo_doc[] =
2886PyDoc_STR("Abstract base class for time zone info objects.");
2887
Neal Norwitzce3d34d2003-02-04 20:45:17 +00002888statichere PyTypeObject PyDateTime_TZInfoType = {
Tim Peters2a799bf2002-12-16 20:18:38 +00002889 PyObject_HEAD_INIT(NULL)
2890 0, /* ob_size */
2891 "datetime.tzinfo", /* tp_name */
2892 sizeof(PyDateTime_TZInfo), /* tp_basicsize */
2893 0, /* tp_itemsize */
2894 0, /* tp_dealloc */
2895 0, /* tp_print */
2896 0, /* tp_getattr */
2897 0, /* tp_setattr */
2898 0, /* tp_compare */
2899 0, /* tp_repr */
2900 0, /* tp_as_number */
2901 0, /* tp_as_sequence */
2902 0, /* tp_as_mapping */
2903 0, /* tp_hash */
2904 0, /* tp_call */
2905 0, /* tp_str */
2906 PyObject_GenericGetAttr, /* tp_getattro */
2907 0, /* tp_setattro */
2908 0, /* tp_as_buffer */
2909 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
2910 Py_TPFLAGS_BASETYPE, /* tp_flags */
2911 tzinfo_doc, /* tp_doc */
2912 0, /* tp_traverse */
2913 0, /* tp_clear */
2914 0, /* tp_richcompare */
2915 0, /* tp_weaklistoffset */
2916 0, /* tp_iter */
2917 0, /* tp_iternext */
2918 tzinfo_methods, /* tp_methods */
2919 0, /* tp_members */
2920 0, /* tp_getset */
2921 0, /* tp_base */
2922 0, /* tp_dict */
2923 0, /* tp_descr_get */
2924 0, /* tp_descr_set */
2925 0, /* tp_dictoffset */
2926 0, /* tp_init */
2927 0, /* tp_alloc */
2928 PyType_GenericNew, /* tp_new */
2929 0, /* tp_free */
2930};
2931
2932/*
Tim Peters37f39822003-01-10 03:49:02 +00002933 * PyDateTime_Time implementation.
Tim Peters2a799bf2002-12-16 20:18:38 +00002934 */
2935
Tim Peters37f39822003-01-10 03:49:02 +00002936/* Accessor properties.
Tim Peters2a799bf2002-12-16 20:18:38 +00002937 */
2938
2939static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00002940time_hour(PyDateTime_Time *self, void *unused)
Tim Peters2a799bf2002-12-16 20:18:38 +00002941{
Tim Peters37f39822003-01-10 03:49:02 +00002942 return PyInt_FromLong(TIME_GET_HOUR(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00002943}
2944
Tim Peters37f39822003-01-10 03:49:02 +00002945static PyObject *
2946time_minute(PyDateTime_Time *self, void *unused)
2947{
2948 return PyInt_FromLong(TIME_GET_MINUTE(self));
2949}
2950
2951/* The name time_second conflicted with some platform header file. */
2952static PyObject *
2953py_time_second(PyDateTime_Time *self, void *unused)
2954{
2955 return PyInt_FromLong(TIME_GET_SECOND(self));
2956}
2957
2958static PyObject *
2959time_microsecond(PyDateTime_Time *self, void *unused)
2960{
2961 return PyInt_FromLong(TIME_GET_MICROSECOND(self));
2962}
2963
2964static PyObject *
2965time_tzinfo(PyDateTime_Time *self, void *unused)
2966{
Tim Petersa032d2e2003-01-11 00:15:54 +00002967 PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
Tim Peters37f39822003-01-10 03:49:02 +00002968 Py_INCREF(result);
2969 return result;
2970}
2971
2972static PyGetSetDef time_getset[] = {
2973 {"hour", (getter)time_hour},
2974 {"minute", (getter)time_minute},
2975 {"second", (getter)py_time_second},
2976 {"microsecond", (getter)time_microsecond},
2977 {"tzinfo", (getter)time_tzinfo},
Tim Peters2a799bf2002-12-16 20:18:38 +00002978 {NULL}
2979};
2980
2981/*
2982 * Constructors.
2983 */
2984
Tim Peters37f39822003-01-10 03:49:02 +00002985static char *time_kws[] = {"hour", "minute", "second", "microsecond",
2986 "tzinfo", NULL};
Tim Peters12bf3392002-12-24 05:41:27 +00002987
Tim Peters2a799bf2002-12-16 20:18:38 +00002988static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00002989time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00002990{
2991 PyObject *self = NULL;
Tim Peters70533e22003-02-01 04:40:04 +00002992 PyObject *state;
Tim Peters2a799bf2002-12-16 20:18:38 +00002993 int hour = 0;
2994 int minute = 0;
2995 int second = 0;
2996 int usecond = 0;
2997 PyObject *tzinfo = Py_None;
2998
Guido van Rossum177e41a2003-01-30 22:06:23 +00002999 /* Check for invocation from pickle with __getstate__ state */
3000 if (PyTuple_GET_SIZE(args) >= 1 &&
3001 PyTuple_GET_SIZE(args) <= 2 &&
Tim Peters70533e22003-02-01 04:40:04 +00003002 PyString_Check(state = PyTuple_GET_ITEM(args, 0)) &&
3003 PyString_GET_SIZE(state) == _PyDateTime_TIME_DATASIZE)
Guido van Rossum177e41a2003-01-30 22:06:23 +00003004 {
Tim Peters70533e22003-02-01 04:40:04 +00003005 PyDateTime_Time *me;
3006 char aware;
3007
3008 if (PyTuple_GET_SIZE(args) == 2) {
Guido van Rossum177e41a2003-01-30 22:06:23 +00003009 tzinfo = PyTuple_GET_ITEM(args, 1);
Tim Peters70533e22003-02-01 04:40:04 +00003010 if (check_tzinfo_subclass(tzinfo) < 0) {
3011 PyErr_SetString(PyExc_TypeError, "bad "
3012 "tzinfo state arg");
3013 return NULL;
Guido van Rossum177e41a2003-01-30 22:06:23 +00003014 }
3015 }
Tim Peters70533e22003-02-01 04:40:04 +00003016 aware = (char)(tzinfo != Py_None);
3017 me = alloc_time(aware);
3018 if (me != NULL) {
3019 char *pdata = PyString_AS_STRING(state);
3020
3021 memcpy(me->data, pdata, _PyDateTime_TIME_DATASIZE);
3022 me->hashcode = -1;
3023 me->hastzinfo = aware;
3024 if (aware) {
3025 Py_INCREF(tzinfo);
3026 me->tzinfo = tzinfo;
3027 }
3028 }
3029 return (PyObject *)me;
Guido van Rossum177e41a2003-01-30 22:06:23 +00003030 }
3031
Tim Peters37f39822003-01-10 03:49:02 +00003032 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", time_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00003033 &hour, &minute, &second, &usecond,
3034 &tzinfo)) {
3035 if (check_time_args(hour, minute, second, usecond) < 0)
3036 return NULL;
3037 if (check_tzinfo_subclass(tzinfo) < 0)
3038 return NULL;
Tim Peters37f39822003-01-10 03:49:02 +00003039 self = new_time(hour, minute, second, usecond, tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00003040 }
3041 return self;
3042}
3043
3044/*
3045 * Destructor.
3046 */
3047
3048static void
Tim Peters37f39822003-01-10 03:49:02 +00003049time_dealloc(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003050{
Tim Petersa032d2e2003-01-11 00:15:54 +00003051 if (HASTZINFO(self)) {
Tim Peters37f39822003-01-10 03:49:02 +00003052 Py_XDECREF(self->tzinfo);
Neal Norwitz8e914d92003-01-10 15:29:16 +00003053 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003054 self->ob_type->tp_free((PyObject *)self);
3055}
3056
3057/*
Tim Peters855fe882002-12-22 03:43:39 +00003058 * Indirect access to tzinfo methods.
Tim Peters2a799bf2002-12-16 20:18:38 +00003059 */
3060
Tim Peters2a799bf2002-12-16 20:18:38 +00003061/* These are all METH_NOARGS, so don't need to check the arglist. */
3062static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003063time_utcoffset(PyDateTime_Time *self, PyObject *unused) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003064 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
Tim Peters37f39822003-01-10 03:49:02 +00003065 "utcoffset", Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003066}
3067
3068static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003069time_dst(PyDateTime_Time *self, PyObject *unused) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003070 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
Tim Peters37f39822003-01-10 03:49:02 +00003071 "dst", Py_None);
Tim Peters855fe882002-12-22 03:43:39 +00003072}
3073
3074static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003075time_tzname(PyDateTime_Time *self, PyObject *unused) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003076 return call_tzname(HASTZINFO(self) ? self->tzinfo : Py_None,
Tim Peters37f39822003-01-10 03:49:02 +00003077 Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003078}
3079
3080/*
Tim Peters37f39822003-01-10 03:49:02 +00003081 * Various ways to turn a time into a string.
Tim Peters2a799bf2002-12-16 20:18:38 +00003082 */
3083
3084static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003085time_repr(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003086{
Tim Peters37f39822003-01-10 03:49:02 +00003087 char buffer[100];
3088 char *typename = self->ob_type->tp_name;
3089 int h = TIME_GET_HOUR(self);
3090 int m = TIME_GET_MINUTE(self);
3091 int s = TIME_GET_SECOND(self);
3092 int us = TIME_GET_MICROSECOND(self);
3093 PyObject *result = NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00003094
Tim Peters37f39822003-01-10 03:49:02 +00003095 if (us)
3096 PyOS_snprintf(buffer, sizeof(buffer),
3097 "%s(%d, %d, %d, %d)", typename, h, m, s, us);
3098 else if (s)
3099 PyOS_snprintf(buffer, sizeof(buffer),
3100 "%s(%d, %d, %d)", typename, h, m, s);
3101 else
3102 PyOS_snprintf(buffer, sizeof(buffer),
3103 "%s(%d, %d)", typename, h, m);
3104 result = PyString_FromString(buffer);
Tim Petersa032d2e2003-01-11 00:15:54 +00003105 if (result != NULL && HASTZINFO(self))
Tim Peters37f39822003-01-10 03:49:02 +00003106 result = append_keyword_tzinfo(result, self->tzinfo);
3107 return result;
Tim Peters2a799bf2002-12-16 20:18:38 +00003108}
3109
Tim Peters37f39822003-01-10 03:49:02 +00003110static PyObject *
3111time_str(PyDateTime_Time *self)
3112{
3113 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
3114}
Tim Peters2a799bf2002-12-16 20:18:38 +00003115
3116static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003117time_isoformat(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003118{
3119 char buf[100];
Tim Peters37f39822003-01-10 03:49:02 +00003120 PyObject *result;
3121 /* Reuse the time format code from the datetime type. */
3122 PyDateTime_DateTime datetime;
3123 PyDateTime_DateTime *pdatetime = &datetime;
Tim Peters2a799bf2002-12-16 20:18:38 +00003124
Tim Peters37f39822003-01-10 03:49:02 +00003125 /* Copy over just the time bytes. */
3126 memcpy(pdatetime->data + _PyDateTime_DATE_DATASIZE,
3127 self->data,
3128 _PyDateTime_TIME_DATASIZE);
3129
3130 isoformat_time(pdatetime, buf, sizeof(buf));
3131 result = PyString_FromString(buf);
Tim Petersa032d2e2003-01-11 00:15:54 +00003132 if (result == NULL || ! HASTZINFO(self) || self->tzinfo == Py_None)
Tim Peters2a799bf2002-12-16 20:18:38 +00003133 return result;
3134
3135 /* We need to append the UTC offset. */
3136 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00003137 Py_None) < 0) {
Tim Peters2a799bf2002-12-16 20:18:38 +00003138 Py_DECREF(result);
3139 return NULL;
3140 }
3141 PyString_ConcatAndDel(&result, PyString_FromString(buf));
3142 return result;
3143}
3144
Tim Peters37f39822003-01-10 03:49:02 +00003145static PyObject *
3146time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3147{
3148 PyObject *result;
3149 PyObject *format;
3150 PyObject *tuple;
3151 static char *keywords[] = {"format", NULL};
3152
3153 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
3154 &PyString_Type, &format))
3155 return NULL;
3156
3157 /* Python's strftime does insane things with the year part of the
3158 * timetuple. The year is forced to (the otherwise nonsensical)
3159 * 1900 to worm around that.
3160 */
3161 tuple = Py_BuildValue("iiiiiiiii",
3162 1900, 0, 0, /* year, month, day */
3163 TIME_GET_HOUR(self),
3164 TIME_GET_MINUTE(self),
3165 TIME_GET_SECOND(self),
3166 0, 0, -1); /* weekday, daynum, dst */
3167 if (tuple == NULL)
3168 return NULL;
3169 assert(PyTuple_Size(tuple) == 9);
3170 result = wrap_strftime((PyObject *)self, format, tuple, Py_None);
3171 Py_DECREF(tuple);
3172 return result;
3173}
Tim Peters2a799bf2002-12-16 20:18:38 +00003174
3175/*
3176 * Miscellaneous methods.
3177 */
3178
Tim Peters37f39822003-01-10 03:49:02 +00003179/* This is more natural as a tp_compare, but doesn't work then: for whatever
3180 * reason, Python's try_3way_compare ignores tp_compare unless
3181 * PyInstance_Check returns true, but these aren't old-style classes.
3182 */
3183static PyObject *
3184time_richcompare(PyDateTime_Time *self, PyObject *other, int op)
3185{
3186 int diff;
3187 naivety n1, n2;
3188 int offset1, offset2;
3189
3190 if (! PyTime_Check(other)) {
Tim Peters07534a62003-02-07 22:50:28 +00003191 if (op == Py_EQ || op == Py_NE) {
3192 PyObject *result = op == Py_EQ ? Py_False : Py_True;
3193 Py_INCREF(result);
3194 return result;
3195 }
Tim Peters37f39822003-01-10 03:49:02 +00003196 /* Stop this from falling back to address comparison. */
Tim Peters07534a62003-02-07 22:50:28 +00003197 return cmperror((PyObject *)self, other);
Tim Peters37f39822003-01-10 03:49:02 +00003198 }
3199 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1, Py_None,
3200 other, &offset2, &n2, Py_None) < 0)
3201 return NULL;
3202 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
3203 /* If they're both naive, or both aware and have the same offsets,
3204 * we get off cheap. Note that if they're both naive, offset1 ==
3205 * offset2 == 0 at this point.
3206 */
3207 if (n1 == n2 && offset1 == offset2) {
3208 diff = memcmp(self->data, ((PyDateTime_Time *)other)->data,
3209 _PyDateTime_TIME_DATASIZE);
3210 return diff_to_bool(diff, op);
3211 }
3212
3213 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3214 assert(offset1 != offset2); /* else last "if" handled it */
3215 /* Convert everything except microseconds to seconds. These
3216 * can't overflow (no more than the # of seconds in 2 days).
3217 */
3218 offset1 = TIME_GET_HOUR(self) * 3600 +
3219 (TIME_GET_MINUTE(self) - offset1) * 60 +
3220 TIME_GET_SECOND(self);
3221 offset2 = TIME_GET_HOUR(other) * 3600 +
3222 (TIME_GET_MINUTE(other) - offset2) * 60 +
3223 TIME_GET_SECOND(other);
3224 diff = offset1 - offset2;
3225 if (diff == 0)
3226 diff = TIME_GET_MICROSECOND(self) -
3227 TIME_GET_MICROSECOND(other);
3228 return diff_to_bool(diff, op);
3229 }
3230
3231 assert(n1 != n2);
3232 PyErr_SetString(PyExc_TypeError,
3233 "can't compare offset-naive and "
3234 "offset-aware times");
3235 return NULL;
3236}
3237
3238static long
3239time_hash(PyDateTime_Time *self)
3240{
3241 if (self->hashcode == -1) {
3242 naivety n;
3243 int offset;
3244 PyObject *temp;
3245
3246 n = classify_utcoffset((PyObject *)self, Py_None, &offset);
3247 assert(n != OFFSET_UNKNOWN);
3248 if (n == OFFSET_ERROR)
3249 return -1;
3250
3251 /* Reduce this to a hash of another object. */
3252 if (offset == 0)
3253 temp = PyString_FromStringAndSize((char *)self->data,
3254 _PyDateTime_TIME_DATASIZE);
3255 else {
3256 int hour;
3257 int minute;
3258
3259 assert(n == OFFSET_AWARE);
Tim Petersa032d2e2003-01-11 00:15:54 +00003260 assert(HASTZINFO(self));
Tim Peters37f39822003-01-10 03:49:02 +00003261 hour = divmod(TIME_GET_HOUR(self) * 60 +
3262 TIME_GET_MINUTE(self) - offset,
3263 60,
3264 &minute);
3265 if (0 <= hour && hour < 24)
3266 temp = new_time(hour, minute,
3267 TIME_GET_SECOND(self),
3268 TIME_GET_MICROSECOND(self),
3269 Py_None);
3270 else
3271 temp = Py_BuildValue("iiii",
3272 hour, minute,
3273 TIME_GET_SECOND(self),
3274 TIME_GET_MICROSECOND(self));
3275 }
3276 if (temp != NULL) {
3277 self->hashcode = PyObject_Hash(temp);
3278 Py_DECREF(temp);
3279 }
3280 }
3281 return self->hashcode;
3282}
Tim Peters2a799bf2002-12-16 20:18:38 +00003283
Tim Peters12bf3392002-12-24 05:41:27 +00003284static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003285time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
Tim Peters12bf3392002-12-24 05:41:27 +00003286{
3287 PyObject *clone;
3288 PyObject *tuple;
3289 int hh = TIME_GET_HOUR(self);
3290 int mm = TIME_GET_MINUTE(self);
3291 int ss = TIME_GET_SECOND(self);
3292 int us = TIME_GET_MICROSECOND(self);
Tim Petersa032d2e2003-01-11 00:15:54 +00003293 PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
Tim Peters12bf3392002-12-24 05:41:27 +00003294
3295 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
Tim Peters37f39822003-01-10 03:49:02 +00003296 time_kws,
Tim Peters12bf3392002-12-24 05:41:27 +00003297 &hh, &mm, &ss, &us, &tzinfo))
3298 return NULL;
3299 tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
3300 if (tuple == NULL)
3301 return NULL;
Tim Peters37f39822003-01-10 03:49:02 +00003302 clone = time_new(self->ob_type, tuple, NULL);
Tim Peters12bf3392002-12-24 05:41:27 +00003303 Py_DECREF(tuple);
3304 return clone;
3305}
3306
Tim Peters2a799bf2002-12-16 20:18:38 +00003307static int
Tim Peters37f39822003-01-10 03:49:02 +00003308time_nonzero(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003309{
3310 int offset;
3311 int none;
3312
3313 if (TIME_GET_SECOND(self) || TIME_GET_MICROSECOND(self)) {
3314 /* Since utcoffset is in whole minutes, nothing can
3315 * alter the conclusion that this is nonzero.
3316 */
3317 return 1;
3318 }
3319 offset = 0;
Tim Petersa032d2e2003-01-11 00:15:54 +00003320 if (HASTZINFO(self) && self->tzinfo != Py_None) {
Tim Petersbad8ff02002-12-30 20:52:32 +00003321 offset = call_utcoffset(self->tzinfo, Py_None, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +00003322 if (offset == -1 && PyErr_Occurred())
3323 return -1;
3324 }
3325 return (TIME_GET_MINUTE(self) - offset + TIME_GET_HOUR(self)*60) != 0;
3326}
3327
Tim Peters371935f2003-02-01 01:52:50 +00003328/* Pickle support, a simple use of __reduce__. */
Tim Peters2a799bf2002-12-16 20:18:38 +00003329
Tim Peters33e0f382003-01-10 02:05:14 +00003330/* Let basestate be the non-tzinfo data string.
Tim Peters2a799bf2002-12-16 20:18:38 +00003331 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
3332 * So it's a tuple in any (non-error) case.
Tim Petersb57f8f02003-02-01 02:54:15 +00003333 * __getstate__ isn't exposed.
Tim Peters2a799bf2002-12-16 20:18:38 +00003334 */
3335static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003336time_getstate(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003337{
3338 PyObject *basestate;
3339 PyObject *result = NULL;
3340
Tim Peters33e0f382003-01-10 02:05:14 +00003341 basestate = PyString_FromStringAndSize((char *)self->data,
3342 _PyDateTime_TIME_DATASIZE);
Tim Peters2a799bf2002-12-16 20:18:38 +00003343 if (basestate != NULL) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003344 if (! HASTZINFO(self) || self->tzinfo == Py_None)
Tim Peters2a799bf2002-12-16 20:18:38 +00003345 result = Py_BuildValue("(O)", basestate);
3346 else
3347 result = Py_BuildValue("OO", basestate, self->tzinfo);
3348 Py_DECREF(basestate);
3349 }
3350 return result;
3351}
3352
3353static PyObject *
Guido van Rossum177e41a2003-01-30 22:06:23 +00003354time_reduce(PyDateTime_Time *self, PyObject *arg)
Tim Peters2a799bf2002-12-16 20:18:38 +00003355{
Guido van Rossum177e41a2003-01-30 22:06:23 +00003356 return Py_BuildValue("(ON)", self->ob_type, time_getstate(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00003357}
3358
Tim Peters37f39822003-01-10 03:49:02 +00003359static PyMethodDef time_methods[] = {
Guido van Rossum177e41a2003-01-30 22:06:23 +00003360
Tim Peters37f39822003-01-10 03:49:02 +00003361 {"isoformat", (PyCFunction)time_isoformat, METH_KEYWORDS,
Tim Peters2a799bf2002-12-16 20:18:38 +00003362 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]"
3363 "[+HH:MM].")},
3364
Tim Peters37f39822003-01-10 03:49:02 +00003365 {"strftime", (PyCFunction)time_strftime, METH_KEYWORDS,
3366 PyDoc_STR("format -> strftime() style string.")},
3367
3368 {"utcoffset", (PyCFunction)time_utcoffset, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00003369 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
3370
Tim Peters37f39822003-01-10 03:49:02 +00003371 {"tzname", (PyCFunction)time_tzname, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00003372 PyDoc_STR("Return self.tzinfo.tzname(self).")},
3373
Tim Peters37f39822003-01-10 03:49:02 +00003374 {"dst", (PyCFunction)time_dst, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00003375 PyDoc_STR("Return self.tzinfo.dst(self).")},
3376
Tim Peters37f39822003-01-10 03:49:02 +00003377 {"replace", (PyCFunction)time_replace, METH_KEYWORDS,
3378 PyDoc_STR("Return time with new specified fields.")},
Tim Peters12bf3392002-12-24 05:41:27 +00003379
Guido van Rossum177e41a2003-01-30 22:06:23 +00003380 {"__reduce__", (PyCFunction)time_reduce, METH_NOARGS,
3381 PyDoc_STR("__reduce__() -> (cls, state)")},
3382
Tim Peters2a799bf2002-12-16 20:18:38 +00003383 {NULL, NULL}
Tim Peters2a799bf2002-12-16 20:18:38 +00003384};
3385
Tim Peters37f39822003-01-10 03:49:02 +00003386static char time_doc[] =
Tim Peters2a799bf2002-12-16 20:18:38 +00003387PyDoc_STR("Time type.");
3388
Tim Peters37f39822003-01-10 03:49:02 +00003389static PyNumberMethods time_as_number = {
Tim Peters2a799bf2002-12-16 20:18:38 +00003390 0, /* nb_add */
3391 0, /* nb_subtract */
3392 0, /* nb_multiply */
3393 0, /* nb_divide */
3394 0, /* nb_remainder */
3395 0, /* nb_divmod */
3396 0, /* nb_power */
3397 0, /* nb_negative */
3398 0, /* nb_positive */
3399 0, /* nb_absolute */
Tim Peters37f39822003-01-10 03:49:02 +00003400 (inquiry)time_nonzero, /* nb_nonzero */
Tim Peters2a799bf2002-12-16 20:18:38 +00003401};
3402
Tim Peters37f39822003-01-10 03:49:02 +00003403statichere PyTypeObject PyDateTime_TimeType = {
Tim Peters2a799bf2002-12-16 20:18:38 +00003404 PyObject_HEAD_INIT(NULL)
3405 0, /* ob_size */
Tim Peters0bf60bd2003-01-08 20:40:01 +00003406 "datetime.time", /* tp_name */
Tim Peters37f39822003-01-10 03:49:02 +00003407 sizeof(PyDateTime_Time), /* tp_basicsize */
Tim Peters2a799bf2002-12-16 20:18:38 +00003408 0, /* tp_itemsize */
Tim Peters37f39822003-01-10 03:49:02 +00003409 (destructor)time_dealloc, /* tp_dealloc */
Tim Peters2a799bf2002-12-16 20:18:38 +00003410 0, /* tp_print */
3411 0, /* tp_getattr */
3412 0, /* tp_setattr */
3413 0, /* tp_compare */
Tim Peters37f39822003-01-10 03:49:02 +00003414 (reprfunc)time_repr, /* tp_repr */
3415 &time_as_number, /* tp_as_number */
Tim Peters2a799bf2002-12-16 20:18:38 +00003416 0, /* tp_as_sequence */
3417 0, /* tp_as_mapping */
Tim Peters37f39822003-01-10 03:49:02 +00003418 (hashfunc)time_hash, /* tp_hash */
Tim Peters2a799bf2002-12-16 20:18:38 +00003419 0, /* tp_call */
Tim Peters37f39822003-01-10 03:49:02 +00003420 (reprfunc)time_str, /* tp_str */
Tim Peters2a799bf2002-12-16 20:18:38 +00003421 PyObject_GenericGetAttr, /* tp_getattro */
3422 0, /* tp_setattro */
3423 0, /* tp_as_buffer */
3424 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3425 Py_TPFLAGS_BASETYPE, /* tp_flags */
Tim Peters37f39822003-01-10 03:49:02 +00003426 time_doc, /* tp_doc */
Tim Peters2a799bf2002-12-16 20:18:38 +00003427 0, /* tp_traverse */
3428 0, /* tp_clear */
Tim Peters37f39822003-01-10 03:49:02 +00003429 (richcmpfunc)time_richcompare, /* tp_richcompare */
Tim Peters2a799bf2002-12-16 20:18:38 +00003430 0, /* tp_weaklistoffset */
3431 0, /* tp_iter */
3432 0, /* tp_iternext */
Tim Peters37f39822003-01-10 03:49:02 +00003433 time_methods, /* tp_methods */
Tim Peters2a799bf2002-12-16 20:18:38 +00003434 0, /* tp_members */
Tim Peters37f39822003-01-10 03:49:02 +00003435 time_getset, /* tp_getset */
3436 0, /* tp_base */
Tim Peters2a799bf2002-12-16 20:18:38 +00003437 0, /* tp_dict */
3438 0, /* tp_descr_get */
3439 0, /* tp_descr_set */
3440 0, /* tp_dictoffset */
3441 0, /* tp_init */
3442 0, /* tp_alloc */
Tim Peters37f39822003-01-10 03:49:02 +00003443 time_new, /* tp_new */
Tim Peters2a799bf2002-12-16 20:18:38 +00003444 _PyObject_Del, /* tp_free */
3445};
3446
3447/*
Tim Petersa9bc1682003-01-11 03:39:11 +00003448 * PyDateTime_DateTime implementation.
Tim Peters2a799bf2002-12-16 20:18:38 +00003449 */
3450
Tim Petersa9bc1682003-01-11 03:39:11 +00003451/* Accessor properties. Properties for day, month, and year are inherited
3452 * from date.
Tim Peters2a799bf2002-12-16 20:18:38 +00003453 */
3454
3455static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003456datetime_hour(PyDateTime_DateTime *self, void *unused)
Tim Peters2a799bf2002-12-16 20:18:38 +00003457{
Tim Petersa9bc1682003-01-11 03:39:11 +00003458 return PyInt_FromLong(DATE_GET_HOUR(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00003459}
3460
Tim Petersa9bc1682003-01-11 03:39:11 +00003461static PyObject *
3462datetime_minute(PyDateTime_DateTime *self, void *unused)
3463{
3464 return PyInt_FromLong(DATE_GET_MINUTE(self));
3465}
3466
3467static PyObject *
3468datetime_second(PyDateTime_DateTime *self, void *unused)
3469{
3470 return PyInt_FromLong(DATE_GET_SECOND(self));
3471}
3472
3473static PyObject *
3474datetime_microsecond(PyDateTime_DateTime *self, void *unused)
3475{
3476 return PyInt_FromLong(DATE_GET_MICROSECOND(self));
3477}
3478
3479static PyObject *
3480datetime_tzinfo(PyDateTime_DateTime *self, void *unused)
3481{
3482 PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
3483 Py_INCREF(result);
3484 return result;
3485}
3486
3487static PyGetSetDef datetime_getset[] = {
3488 {"hour", (getter)datetime_hour},
3489 {"minute", (getter)datetime_minute},
3490 {"second", (getter)datetime_second},
3491 {"microsecond", (getter)datetime_microsecond},
3492 {"tzinfo", (getter)datetime_tzinfo},
Tim Peters2a799bf2002-12-16 20:18:38 +00003493 {NULL}
3494};
3495
3496/*
3497 * Constructors.
Tim Peters2a799bf2002-12-16 20:18:38 +00003498 */
3499
Tim Petersa9bc1682003-01-11 03:39:11 +00003500static char *datetime_kws[] = {
Tim Peters12bf3392002-12-24 05:41:27 +00003501 "year", "month", "day", "hour", "minute", "second",
3502 "microsecond", "tzinfo", NULL
3503};
3504
Tim Peters2a799bf2002-12-16 20:18:38 +00003505static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003506datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003507{
3508 PyObject *self = NULL;
Tim Peters70533e22003-02-01 04:40:04 +00003509 PyObject *state;
Tim Peters2a799bf2002-12-16 20:18:38 +00003510 int year;
3511 int month;
3512 int day;
3513 int hour = 0;
3514 int minute = 0;
3515 int second = 0;
3516 int usecond = 0;
3517 PyObject *tzinfo = Py_None;
3518
Guido van Rossum177e41a2003-01-30 22:06:23 +00003519 /* Check for invocation from pickle with __getstate__ state */
3520 if (PyTuple_GET_SIZE(args) >= 1 &&
3521 PyTuple_GET_SIZE(args) <= 2 &&
Tim Peters70533e22003-02-01 04:40:04 +00003522 PyString_Check(state = PyTuple_GET_ITEM(args, 0)) &&
3523 PyString_GET_SIZE(state) == _PyDateTime_DATETIME_DATASIZE)
Guido van Rossum177e41a2003-01-30 22:06:23 +00003524 {
Tim Peters70533e22003-02-01 04:40:04 +00003525 PyDateTime_DateTime *me;
3526 char aware;
3527
3528 if (PyTuple_GET_SIZE(args) == 2) {
Guido van Rossum177e41a2003-01-30 22:06:23 +00003529 tzinfo = PyTuple_GET_ITEM(args, 1);
Tim Peters70533e22003-02-01 04:40:04 +00003530 if (check_tzinfo_subclass(tzinfo) < 0) {
3531 PyErr_SetString(PyExc_TypeError, "bad "
3532 "tzinfo state arg");
3533 return NULL;
Guido van Rossum177e41a2003-01-30 22:06:23 +00003534 }
3535 }
Tim Peters70533e22003-02-01 04:40:04 +00003536 aware = (char)(tzinfo != Py_None);
3537 me = alloc_datetime(aware);
3538 if (me != NULL) {
3539 char *pdata = PyString_AS_STRING(state);
3540
3541 memcpy(me->data, pdata, _PyDateTime_DATETIME_DATASIZE);
3542 me->hashcode = -1;
3543 me->hastzinfo = aware;
3544 if (aware) {
3545 Py_INCREF(tzinfo);
3546 me->tzinfo = tzinfo;
3547 }
3548 }
3549 return (PyObject *)me;
Guido van Rossum177e41a2003-01-30 22:06:23 +00003550 }
3551
Tim Petersa9bc1682003-01-11 03:39:11 +00003552 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO", datetime_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00003553 &year, &month, &day, &hour, &minute,
3554 &second, &usecond, &tzinfo)) {
3555 if (check_date_args(year, month, day) < 0)
3556 return NULL;
3557 if (check_time_args(hour, minute, second, usecond) < 0)
3558 return NULL;
3559 if (check_tzinfo_subclass(tzinfo) < 0)
3560 return NULL;
Tim Petersa9bc1682003-01-11 03:39:11 +00003561 self = new_datetime(year, month, day,
3562 hour, minute, second, usecond,
3563 tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00003564 }
3565 return self;
3566}
3567
Tim Petersa9bc1682003-01-11 03:39:11 +00003568/* TM_FUNC is the shared type of localtime() and gmtime(). */
3569typedef struct tm *(*TM_FUNC)(const time_t *timer);
3570
3571/* Internal helper.
3572 * Build datetime from a time_t and a distinct count of microseconds.
3573 * Pass localtime or gmtime for f, to control the interpretation of timet.
3574 */
3575static PyObject *
3576datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us,
3577 PyObject *tzinfo)
3578{
3579 struct tm *tm;
3580 PyObject *result = NULL;
3581
3582 tm = f(&timet);
3583 if (tm) {
3584 /* The platform localtime/gmtime may insert leap seconds,
3585 * indicated by tm->tm_sec > 59. We don't care about them,
3586 * except to the extent that passing them on to the datetime
3587 * constructor would raise ValueError for a reason that
3588 * made no sense to the user.
3589 */
3590 if (tm->tm_sec > 59)
3591 tm->tm_sec = 59;
3592 result = PyObject_CallFunction(cls, "iiiiiiiO",
3593 tm->tm_year + 1900,
3594 tm->tm_mon + 1,
3595 tm->tm_mday,
3596 tm->tm_hour,
3597 tm->tm_min,
3598 tm->tm_sec,
3599 us,
3600 tzinfo);
3601 }
3602 else
3603 PyErr_SetString(PyExc_ValueError,
3604 "timestamp out of range for "
3605 "platform localtime()/gmtime() function");
3606 return result;
3607}
3608
3609/* Internal helper.
3610 * Build datetime from a Python timestamp. Pass localtime or gmtime for f,
3611 * to control the interpretation of the timestamp. Since a double doesn't
3612 * have enough bits to cover a datetime's full range of precision, it's
3613 * better to call datetime_from_timet_and_us provided you have a way
3614 * to get that much precision (e.g., C time() isn't good enough).
3615 */
3616static PyObject *
3617datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp,
3618 PyObject *tzinfo)
3619{
3620 time_t timet = (time_t)timestamp;
3621 double fraction = timestamp - (double)timet;
3622 int us = (int)round_to_long(fraction * 1e6);
3623
3624 return datetime_from_timet_and_us(cls, f, timet, us, tzinfo);
3625}
3626
3627/* Internal helper.
3628 * Build most accurate possible datetime for current time. Pass localtime or
3629 * gmtime for f as appropriate.
3630 */
3631static PyObject *
3632datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
3633{
3634#ifdef HAVE_GETTIMEOFDAY
3635 struct timeval t;
3636
3637#ifdef GETTIMEOFDAY_NO_TZ
3638 gettimeofday(&t);
3639#else
3640 gettimeofday(&t, (struct timezone *)NULL);
3641#endif
3642 return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec,
3643 tzinfo);
3644
3645#else /* ! HAVE_GETTIMEOFDAY */
3646 /* No flavor of gettimeofday exists on this platform. Python's
3647 * time.time() does a lot of other platform tricks to get the
3648 * best time it can on the platform, and we're not going to do
3649 * better than that (if we could, the better code would belong
3650 * in time.time()!) We're limited by the precision of a double,
3651 * though.
3652 */
3653 PyObject *time;
3654 double dtime;
3655
3656 time = time_time();
3657 if (time == NULL)
3658 return NULL;
3659 dtime = PyFloat_AsDouble(time);
3660 Py_DECREF(time);
3661 if (dtime == -1.0 && PyErr_Occurred())
3662 return NULL;
3663 return datetime_from_timestamp(cls, f, dtime, tzinfo);
3664#endif /* ! HAVE_GETTIMEOFDAY */
3665}
3666
Tim Peters2a799bf2002-12-16 20:18:38 +00003667/* Return best possible local time -- this isn't constrained by the
3668 * precision of a timestamp.
3669 */
3670static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003671datetime_now(PyObject *cls, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003672{
Tim Peters10cadce2003-01-23 19:58:02 +00003673 PyObject *self;
Tim Peters2a799bf2002-12-16 20:18:38 +00003674 PyObject *tzinfo = Py_None;
Tim Peters10cadce2003-01-23 19:58:02 +00003675 static char *keywords[] = {"tz", NULL};
Tim Peters2a799bf2002-12-16 20:18:38 +00003676
Tim Peters10cadce2003-01-23 19:58:02 +00003677 if (! PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords,
3678 &tzinfo))
3679 return NULL;
3680 if (check_tzinfo_subclass(tzinfo) < 0)
3681 return NULL;
3682
3683 self = datetime_best_possible(cls,
3684 tzinfo == Py_None ? localtime : gmtime,
3685 tzinfo);
3686 if (self != NULL && tzinfo != Py_None) {
3687 /* Convert UTC to tzinfo's zone. */
3688 PyObject *temp = self;
Tim Peters2a44a8d2003-01-23 20:53:10 +00003689 self = PyObject_CallMethod(tzinfo, "fromutc", "O", self);
Tim Peters10cadce2003-01-23 19:58:02 +00003690 Py_DECREF(temp);
Tim Peters2a799bf2002-12-16 20:18:38 +00003691 }
3692 return self;
3693}
3694
Tim Petersa9bc1682003-01-11 03:39:11 +00003695/* Return best possible UTC time -- this isn't constrained by the
3696 * precision of a timestamp.
3697 */
3698static PyObject *
3699datetime_utcnow(PyObject *cls, PyObject *dummy)
3700{
3701 return datetime_best_possible(cls, gmtime, Py_None);
3702}
3703
Tim Peters2a799bf2002-12-16 20:18:38 +00003704/* Return new local datetime from timestamp (Python timestamp -- a double). */
3705static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003706datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003707{
Tim Peters2a44a8d2003-01-23 20:53:10 +00003708 PyObject *self;
Tim Peters2a799bf2002-12-16 20:18:38 +00003709 double timestamp;
3710 PyObject *tzinfo = Py_None;
Tim Peters2a44a8d2003-01-23 20:53:10 +00003711 static char *keywords[] = {"timestamp", "tz", NULL};
Tim Peters2a799bf2002-12-16 20:18:38 +00003712
Tim Peters2a44a8d2003-01-23 20:53:10 +00003713 if (! PyArg_ParseTupleAndKeywords(args, kw, "d|O:fromtimestamp",
3714 keywords, &timestamp, &tzinfo))
3715 return NULL;
3716 if (check_tzinfo_subclass(tzinfo) < 0)
3717 return NULL;
3718
3719 self = datetime_from_timestamp(cls,
3720 tzinfo == Py_None ? localtime : gmtime,
3721 timestamp,
3722 tzinfo);
3723 if (self != NULL && tzinfo != Py_None) {
3724 /* Convert UTC to tzinfo's zone. */
3725 PyObject *temp = self;
3726 self = PyObject_CallMethod(tzinfo, "fromutc", "O", self);
3727 Py_DECREF(temp);
Tim Peters2a799bf2002-12-16 20:18:38 +00003728 }
3729 return self;
3730}
3731
Tim Petersa9bc1682003-01-11 03:39:11 +00003732/* Return new UTC datetime from timestamp (Python timestamp -- a double). */
3733static PyObject *
3734datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
3735{
3736 double timestamp;
3737 PyObject *result = NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00003738
Tim Petersa9bc1682003-01-11 03:39:11 +00003739 if (PyArg_ParseTuple(args, "d:utcfromtimestamp", &timestamp))
3740 result = datetime_from_timestamp(cls, gmtime, timestamp,
3741 Py_None);
3742 return result;
3743}
3744
3745/* Return new datetime from date/datetime and time arguments. */
3746static PyObject *
3747datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
3748{
3749 static char *keywords[] = {"date", "time", NULL};
3750 PyObject *date;
3751 PyObject *time;
3752 PyObject *result = NULL;
3753
3754 if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!:combine", keywords,
3755 &PyDateTime_DateType, &date,
3756 &PyDateTime_TimeType, &time)) {
3757 PyObject *tzinfo = Py_None;
3758
3759 if (HASTZINFO(time))
3760 tzinfo = ((PyDateTime_Time *)time)->tzinfo;
3761 result = PyObject_CallFunction(cls, "iiiiiiiO",
3762 GET_YEAR(date),
3763 GET_MONTH(date),
3764 GET_DAY(date),
3765 TIME_GET_HOUR(time),
3766 TIME_GET_MINUTE(time),
3767 TIME_GET_SECOND(time),
3768 TIME_GET_MICROSECOND(time),
3769 tzinfo);
3770 }
3771 return result;
3772}
Tim Peters2a799bf2002-12-16 20:18:38 +00003773
3774/*
3775 * Destructor.
3776 */
3777
3778static void
Tim Petersa9bc1682003-01-11 03:39:11 +00003779datetime_dealloc(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003780{
Tim Petersa9bc1682003-01-11 03:39:11 +00003781 if (HASTZINFO(self)) {
3782 Py_XDECREF(self->tzinfo);
3783 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003784 self->ob_type->tp_free((PyObject *)self);
3785}
3786
3787/*
3788 * Indirect access to tzinfo methods.
3789 */
3790
Tim Peters2a799bf2002-12-16 20:18:38 +00003791/* These are all METH_NOARGS, so don't need to check the arglist. */
3792static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003793datetime_utcoffset(PyDateTime_DateTime *self, PyObject *unused) {
3794 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
3795 "utcoffset", (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00003796}
3797
3798static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003799datetime_dst(PyDateTime_DateTime *self, PyObject *unused) {
3800 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
3801 "dst", (PyObject *)self);
Tim Peters855fe882002-12-22 03:43:39 +00003802}
3803
3804static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003805datetime_tzname(PyDateTime_DateTime *self, PyObject *unused) {
3806 return call_tzname(HASTZINFO(self) ? self->tzinfo : Py_None,
3807 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00003808}
3809
3810/*
Tim Petersa9bc1682003-01-11 03:39:11 +00003811 * datetime arithmetic.
Tim Peters2a799bf2002-12-16 20:18:38 +00003812 */
3813
Tim Petersa9bc1682003-01-11 03:39:11 +00003814/* factor must be 1 (to add) or -1 (to subtract). The result inherits
3815 * the tzinfo state of date.
Tim Peters2a799bf2002-12-16 20:18:38 +00003816 */
3817static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003818add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta,
3819 int factor)
Tim Peters2a799bf2002-12-16 20:18:38 +00003820{
Tim Petersa9bc1682003-01-11 03:39:11 +00003821 /* Note that the C-level additions can't overflow, because of
3822 * invariant bounds on the member values.
3823 */
3824 int year = GET_YEAR(date);
3825 int month = GET_MONTH(date);
3826 int day = GET_DAY(date) + GET_TD_DAYS(delta) * factor;
3827 int hour = DATE_GET_HOUR(date);
3828 int minute = DATE_GET_MINUTE(date);
3829 int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta) * factor;
3830 int microsecond = DATE_GET_MICROSECOND(date) +
3831 GET_TD_MICROSECONDS(delta) * factor;
Tim Peters2a799bf2002-12-16 20:18:38 +00003832
Tim Petersa9bc1682003-01-11 03:39:11 +00003833 assert(factor == 1 || factor == -1);
3834 if (normalize_datetime(&year, &month, &day,
3835 &hour, &minute, &second, &microsecond) < 0)
3836 return NULL;
3837 else
3838 return new_datetime(year, month, day,
3839 hour, minute, second, microsecond,
3840 HASTZINFO(date) ? date->tzinfo : Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003841}
3842
3843static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003844datetime_add(PyObject *left, PyObject *right)
Tim Peters2a799bf2002-12-16 20:18:38 +00003845{
Tim Petersa9bc1682003-01-11 03:39:11 +00003846 if (PyDateTime_Check(left)) {
3847 /* datetime + ??? */
3848 if (PyDelta_Check(right))
3849 /* datetime + delta */
3850 return add_datetime_timedelta(
3851 (PyDateTime_DateTime *)left,
3852 (PyDateTime_Delta *)right,
3853 1);
3854 }
3855 else if (PyDelta_Check(left)) {
3856 /* delta + datetime */
3857 return add_datetime_timedelta((PyDateTime_DateTime *) right,
3858 (PyDateTime_Delta *) left,
3859 1);
3860 }
3861 Py_INCREF(Py_NotImplemented);
3862 return Py_NotImplemented;
Tim Peters2a799bf2002-12-16 20:18:38 +00003863}
3864
3865static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003866datetime_subtract(PyObject *left, PyObject *right)
Tim Peters2a799bf2002-12-16 20:18:38 +00003867{
3868 PyObject *result = Py_NotImplemented;
3869
3870 if (PyDateTime_Check(left)) {
3871 /* datetime - ??? */
3872 if (PyDateTime_Check(right)) {
3873 /* datetime - datetime */
3874 naivety n1, n2;
3875 int offset1, offset2;
Tim Petersa9bc1682003-01-11 03:39:11 +00003876 int delta_d, delta_s, delta_us;
Tim Peters2a799bf2002-12-16 20:18:38 +00003877
Tim Peterse39a80c2002-12-30 21:28:52 +00003878 if (classify_two_utcoffsets(left, &offset1, &n1, left,
3879 right, &offset2, &n2,
3880 right) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003881 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003882 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00003883 if (n1 != n2) {
3884 PyErr_SetString(PyExc_TypeError,
3885 "can't subtract offset-naive and "
3886 "offset-aware datetimes");
3887 return NULL;
3888 }
Tim Petersa9bc1682003-01-11 03:39:11 +00003889 delta_d = ymd_to_ord(GET_YEAR(left),
3890 GET_MONTH(left),
3891 GET_DAY(left)) -
3892 ymd_to_ord(GET_YEAR(right),
3893 GET_MONTH(right),
3894 GET_DAY(right));
3895 /* These can't overflow, since the values are
3896 * normalized. At most this gives the number of
3897 * seconds in one day.
3898 */
3899 delta_s = (DATE_GET_HOUR(left) -
3900 DATE_GET_HOUR(right)) * 3600 +
3901 (DATE_GET_MINUTE(left) -
3902 DATE_GET_MINUTE(right)) * 60 +
3903 (DATE_GET_SECOND(left) -
3904 DATE_GET_SECOND(right));
3905 delta_us = DATE_GET_MICROSECOND(left) -
3906 DATE_GET_MICROSECOND(right);
Tim Peters2a799bf2002-12-16 20:18:38 +00003907 /* (left - offset1) - (right - offset2) =
3908 * (left - right) + (offset2 - offset1)
3909 */
Tim Petersa9bc1682003-01-11 03:39:11 +00003910 delta_s += (offset2 - offset1) * 60;
3911 result = new_delta(delta_d, delta_s, delta_us, 1);
Tim Peters2a799bf2002-12-16 20:18:38 +00003912 }
3913 else if (PyDelta_Check(right)) {
Tim Petersa9bc1682003-01-11 03:39:11 +00003914 /* datetime - delta */
3915 result = add_datetime_timedelta(
Tim Peters2a799bf2002-12-16 20:18:38 +00003916 (PyDateTime_DateTime *)left,
Tim Petersa9bc1682003-01-11 03:39:11 +00003917 (PyDateTime_Delta *)right,
3918 -1);
Tim Peters2a799bf2002-12-16 20:18:38 +00003919 }
3920 }
3921
3922 if (result == Py_NotImplemented)
3923 Py_INCREF(result);
3924 return result;
3925}
3926
3927/* Various ways to turn a datetime into a string. */
3928
3929static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003930datetime_repr(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003931{
Tim Petersa9bc1682003-01-11 03:39:11 +00003932 char buffer[1000];
3933 char *typename = self->ob_type->tp_name;
3934 PyObject *baserepr;
Tim Peters2a799bf2002-12-16 20:18:38 +00003935
Tim Petersa9bc1682003-01-11 03:39:11 +00003936 if (DATE_GET_MICROSECOND(self)) {
3937 PyOS_snprintf(buffer, sizeof(buffer),
3938 "%s(%d, %d, %d, %d, %d, %d, %d)",
3939 typename,
3940 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3941 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3942 DATE_GET_SECOND(self),
3943 DATE_GET_MICROSECOND(self));
3944 }
3945 else if (DATE_GET_SECOND(self)) {
3946 PyOS_snprintf(buffer, sizeof(buffer),
3947 "%s(%d, %d, %d, %d, %d, %d)",
3948 typename,
3949 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3950 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3951 DATE_GET_SECOND(self));
3952 }
3953 else {
3954 PyOS_snprintf(buffer, sizeof(buffer),
3955 "%s(%d, %d, %d, %d, %d)",
3956 typename,
3957 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3958 DATE_GET_HOUR(self), DATE_GET_MINUTE(self));
3959 }
3960 baserepr = PyString_FromString(buffer);
3961 if (baserepr == NULL || ! HASTZINFO(self))
3962 return baserepr;
Tim Peters2a799bf2002-12-16 20:18:38 +00003963 return append_keyword_tzinfo(baserepr, self->tzinfo);
3964}
3965
Tim Petersa9bc1682003-01-11 03:39:11 +00003966static PyObject *
3967datetime_str(PyDateTime_DateTime *self)
3968{
3969 return PyObject_CallMethod((PyObject *)self, "isoformat", "(s)", " ");
3970}
Tim Peters2a799bf2002-12-16 20:18:38 +00003971
3972static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003973datetime_isoformat(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003974{
Tim Petersa9bc1682003-01-11 03:39:11 +00003975 char sep = 'T';
3976 static char *keywords[] = {"sep", NULL};
3977 char buffer[100];
3978 char *cp;
3979 PyObject *result;
Tim Peters2a799bf2002-12-16 20:18:38 +00003980
Tim Petersa9bc1682003-01-11 03:39:11 +00003981 if (!PyArg_ParseTupleAndKeywords(args, kw, "|c:isoformat", keywords,
3982 &sep))
3983 return NULL;
3984 cp = isoformat_date((PyDateTime_Date *)self, buffer, sizeof(buffer));
3985 assert(cp != NULL);
3986 *cp++ = sep;
3987 isoformat_time(self, cp, sizeof(buffer) - (cp - buffer));
3988 result = PyString_FromString(buffer);
3989 if (result == NULL || ! HASTZINFO(self))
Tim Peters2a799bf2002-12-16 20:18:38 +00003990 return result;
3991
3992 /* We need to append the UTC offset. */
Tim Petersa9bc1682003-01-11 03:39:11 +00003993 if (format_utcoffset(buffer, sizeof(buffer), ":", self->tzinfo,
Tim Peters2a799bf2002-12-16 20:18:38 +00003994 (PyObject *)self) < 0) {
3995 Py_DECREF(result);
3996 return NULL;
3997 }
Tim Petersa9bc1682003-01-11 03:39:11 +00003998 PyString_ConcatAndDel(&result, PyString_FromString(buffer));
Tim Peters2a799bf2002-12-16 20:18:38 +00003999 return result;
4000}
4001
Tim Petersa9bc1682003-01-11 03:39:11 +00004002static PyObject *
4003datetime_ctime(PyDateTime_DateTime *self)
4004{
4005 return format_ctime((PyDateTime_Date *)self,
4006 DATE_GET_HOUR(self),
4007 DATE_GET_MINUTE(self),
4008 DATE_GET_SECOND(self));
4009}
4010
Tim Peters2a799bf2002-12-16 20:18:38 +00004011/* Miscellaneous methods. */
4012
Tim Petersa9bc1682003-01-11 03:39:11 +00004013/* This is more natural as a tp_compare, but doesn't work then: for whatever
4014 * reason, Python's try_3way_compare ignores tp_compare unless
4015 * PyInstance_Check returns true, but these aren't old-style classes.
4016 */
4017static PyObject *
4018datetime_richcompare(PyDateTime_DateTime *self, PyObject *other, int op)
4019{
4020 int diff;
4021 naivety n1, n2;
4022 int offset1, offset2;
4023
4024 if (! PyDateTime_Check(other)) {
Tim Peters8d81a012003-01-24 22:36:34 +00004025 if (PyObject_HasAttrString(other, "timetuple")) {
4026 /* A hook for other kinds of datetime objects. */
4027 Py_INCREF(Py_NotImplemented);
4028 return Py_NotImplemented;
4029 }
Tim Peters07534a62003-02-07 22:50:28 +00004030 if (op == Py_EQ || op == Py_NE) {
4031 PyObject *result = op == Py_EQ ? Py_False : Py_True;
4032 Py_INCREF(result);
4033 return result;
4034 }
Tim Petersa9bc1682003-01-11 03:39:11 +00004035 /* Stop this from falling back to address comparison. */
Tim Peters07534a62003-02-07 22:50:28 +00004036 return cmperror((PyObject *)self, other);
Tim Petersa9bc1682003-01-11 03:39:11 +00004037 }
4038
4039 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1,
4040 (PyObject *)self,
4041 other, &offset2, &n2,
4042 other) < 0)
4043 return NULL;
4044 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
4045 /* If they're both naive, or both aware and have the same offsets,
4046 * we get off cheap. Note that if they're both naive, offset1 ==
4047 * offset2 == 0 at this point.
4048 */
4049 if (n1 == n2 && offset1 == offset2) {
4050 diff = memcmp(self->data, ((PyDateTime_DateTime *)other)->data,
4051 _PyDateTime_DATETIME_DATASIZE);
4052 return diff_to_bool(diff, op);
4053 }
4054
4055 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
4056 PyDateTime_Delta *delta;
4057
4058 assert(offset1 != offset2); /* else last "if" handled it */
4059 delta = (PyDateTime_Delta *)datetime_subtract((PyObject *)self,
4060 other);
4061 if (delta == NULL)
4062 return NULL;
4063 diff = GET_TD_DAYS(delta);
4064 if (diff == 0)
4065 diff = GET_TD_SECONDS(delta) |
4066 GET_TD_MICROSECONDS(delta);
4067 Py_DECREF(delta);
4068 return diff_to_bool(diff, op);
4069 }
4070
4071 assert(n1 != n2);
4072 PyErr_SetString(PyExc_TypeError,
4073 "can't compare offset-naive and "
4074 "offset-aware datetimes");
4075 return NULL;
4076}
4077
4078static long
4079datetime_hash(PyDateTime_DateTime *self)
4080{
4081 if (self->hashcode == -1) {
4082 naivety n;
4083 int offset;
4084 PyObject *temp;
4085
4086 n = classify_utcoffset((PyObject *)self, (PyObject *)self,
4087 &offset);
4088 assert(n != OFFSET_UNKNOWN);
4089 if (n == OFFSET_ERROR)
4090 return -1;
4091
4092 /* Reduce this to a hash of another object. */
4093 if (n == OFFSET_NAIVE)
4094 temp = PyString_FromStringAndSize(
4095 (char *)self->data,
4096 _PyDateTime_DATETIME_DATASIZE);
4097 else {
4098 int days;
4099 int seconds;
4100
4101 assert(n == OFFSET_AWARE);
4102 assert(HASTZINFO(self));
4103 days = ymd_to_ord(GET_YEAR(self),
4104 GET_MONTH(self),
4105 GET_DAY(self));
4106 seconds = DATE_GET_HOUR(self) * 3600 +
4107 (DATE_GET_MINUTE(self) - offset) * 60 +
4108 DATE_GET_SECOND(self);
4109 temp = new_delta(days,
4110 seconds,
4111 DATE_GET_MICROSECOND(self),
4112 1);
4113 }
4114 if (temp != NULL) {
4115 self->hashcode = PyObject_Hash(temp);
4116 Py_DECREF(temp);
4117 }
4118 }
4119 return self->hashcode;
4120}
Tim Peters2a799bf2002-12-16 20:18:38 +00004121
4122static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004123datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
Tim Peters12bf3392002-12-24 05:41:27 +00004124{
4125 PyObject *clone;
4126 PyObject *tuple;
4127 int y = GET_YEAR(self);
4128 int m = GET_MONTH(self);
4129 int d = GET_DAY(self);
4130 int hh = DATE_GET_HOUR(self);
4131 int mm = DATE_GET_MINUTE(self);
4132 int ss = DATE_GET_SECOND(self);
4133 int us = DATE_GET_MICROSECOND(self);
Tim Petersa9bc1682003-01-11 03:39:11 +00004134 PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
Tim Peters12bf3392002-12-24 05:41:27 +00004135
4136 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO:replace",
Tim Petersa9bc1682003-01-11 03:39:11 +00004137 datetime_kws,
Tim Peters12bf3392002-12-24 05:41:27 +00004138 &y, &m, &d, &hh, &mm, &ss, &us,
4139 &tzinfo))
4140 return NULL;
4141 tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
4142 if (tuple == NULL)
4143 return NULL;
Tim Petersa9bc1682003-01-11 03:39:11 +00004144 clone = datetime_new(self->ob_type, tuple, NULL);
Tim Peters12bf3392002-12-24 05:41:27 +00004145 Py_DECREF(tuple);
4146 return clone;
4147}
4148
4149static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004150datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
Tim Peters80475bb2002-12-25 07:40:55 +00004151{
Tim Peters52dcce22003-01-23 16:36:11 +00004152 int y, m, d, hh, mm, ss, us;
Tim Peters521fc152002-12-31 17:36:56 +00004153 PyObject *result;
Tim Peters52dcce22003-01-23 16:36:11 +00004154 int offset, none;
Tim Peters521fc152002-12-31 17:36:56 +00004155
Tim Peters80475bb2002-12-25 07:40:55 +00004156 PyObject *tzinfo;
4157 static char *keywords[] = {"tz", NULL};
4158
Tim Peters52dcce22003-01-23 16:36:11 +00004159 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:astimezone", keywords,
4160 &PyDateTime_TZInfoType, &tzinfo))
Tim Peters80475bb2002-12-25 07:40:55 +00004161 return NULL;
4162
Tim Peters52dcce22003-01-23 16:36:11 +00004163 if (!HASTZINFO(self) || self->tzinfo == Py_None)
4164 goto NeedAware;
Tim Peters521fc152002-12-31 17:36:56 +00004165
Tim Peters52dcce22003-01-23 16:36:11 +00004166 /* Conversion to self's own time zone is a NOP. */
4167 if (self->tzinfo == tzinfo) {
4168 Py_INCREF(self);
4169 return (PyObject *)self;
Tim Peters710fb152003-01-02 19:35:54 +00004170 }
Tim Peters521fc152002-12-31 17:36:56 +00004171
Tim Peters52dcce22003-01-23 16:36:11 +00004172 /* Convert self to UTC. */
4173 offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4174 if (offset == -1 && PyErr_Occurred())
4175 return NULL;
4176 if (none)
4177 goto NeedAware;
Tim Petersf3615152003-01-01 21:51:37 +00004178
Tim Peters52dcce22003-01-23 16:36:11 +00004179 y = GET_YEAR(self);
4180 m = GET_MONTH(self);
4181 d = GET_DAY(self);
4182 hh = DATE_GET_HOUR(self);
4183 mm = DATE_GET_MINUTE(self);
4184 ss = DATE_GET_SECOND(self);
4185 us = DATE_GET_MICROSECOND(self);
4186
4187 mm -= offset;
Tim Petersf3615152003-01-01 21:51:37 +00004188 if ((mm < 0 || mm >= 60) &&
4189 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters52dcce22003-01-23 16:36:11 +00004190 return NULL;
4191
4192 /* Attach new tzinfo and let fromutc() do the rest. */
4193 result = new_datetime(y, m, d, hh, mm, ss, us, tzinfo);
4194 if (result != NULL) {
4195 PyObject *temp = result;
4196
4197 result = PyObject_CallMethod(tzinfo, "fromutc", "O", temp);
4198 Py_DECREF(temp);
4199 }
Tim Petersadf64202003-01-04 06:03:15 +00004200 return result;
Tim Peters521fc152002-12-31 17:36:56 +00004201
Tim Peters52dcce22003-01-23 16:36:11 +00004202NeedAware:
4203 PyErr_SetString(PyExc_ValueError, "astimezone() cannot be applied to "
4204 "a naive datetime");
Tim Peters521fc152002-12-31 17:36:56 +00004205 return NULL;
Tim Peters80475bb2002-12-25 07:40:55 +00004206}
4207
4208static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004209datetime_timetuple(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00004210{
4211 int dstflag = -1;
4212
Tim Petersa9bc1682003-01-11 03:39:11 +00004213 if (HASTZINFO(self) && self->tzinfo != Py_None) {
Tim Peters2a799bf2002-12-16 20:18:38 +00004214 int none;
4215
4216 dstflag = call_dst(self->tzinfo, (PyObject *)self, &none);
4217 if (dstflag == -1 && PyErr_Occurred())
4218 return NULL;
4219
4220 if (none)
4221 dstflag = -1;
4222 else if (dstflag != 0)
4223 dstflag = 1;
4224
4225 }
4226 return build_struct_time(GET_YEAR(self),
4227 GET_MONTH(self),
4228 GET_DAY(self),
4229 DATE_GET_HOUR(self),
4230 DATE_GET_MINUTE(self),
4231 DATE_GET_SECOND(self),
4232 dstflag);
4233}
4234
4235static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004236datetime_getdate(PyDateTime_DateTime *self)
4237{
4238 return new_date(GET_YEAR(self),
4239 GET_MONTH(self),
4240 GET_DAY(self));
4241}
4242
4243static PyObject *
4244datetime_gettime(PyDateTime_DateTime *self)
4245{
4246 return new_time(DATE_GET_HOUR(self),
4247 DATE_GET_MINUTE(self),
4248 DATE_GET_SECOND(self),
4249 DATE_GET_MICROSECOND(self),
4250 Py_None);
4251}
4252
4253static PyObject *
4254datetime_gettimetz(PyDateTime_DateTime *self)
4255{
4256 return new_time(DATE_GET_HOUR(self),
4257 DATE_GET_MINUTE(self),
4258 DATE_GET_SECOND(self),
4259 DATE_GET_MICROSECOND(self),
4260 HASTZINFO(self) ? self->tzinfo : Py_None);
4261}
4262
4263static PyObject *
4264datetime_utctimetuple(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00004265{
4266 int y = GET_YEAR(self);
4267 int m = GET_MONTH(self);
4268 int d = GET_DAY(self);
4269 int hh = DATE_GET_HOUR(self);
4270 int mm = DATE_GET_MINUTE(self);
4271 int ss = DATE_GET_SECOND(self);
4272 int us = 0; /* microseconds are ignored in a timetuple */
4273 int offset = 0;
4274
Tim Petersa9bc1682003-01-11 03:39:11 +00004275 if (HASTZINFO(self) && self->tzinfo != Py_None) {
Tim Peters2a799bf2002-12-16 20:18:38 +00004276 int none;
4277
4278 offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4279 if (offset == -1 && PyErr_Occurred())
4280 return NULL;
4281 }
4282 /* Even if offset is 0, don't call timetuple() -- tm_isdst should be
4283 * 0 in a UTC timetuple regardless of what dst() says.
4284 */
4285 if (offset) {
4286 /* Subtract offset minutes & normalize. */
4287 int stat;
4288
4289 mm -= offset;
4290 stat = normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us);
4291 if (stat < 0) {
4292 /* At the edges, it's possible we overflowed
4293 * beyond MINYEAR or MAXYEAR.
4294 */
4295 if (PyErr_ExceptionMatches(PyExc_OverflowError))
4296 PyErr_Clear();
4297 else
4298 return NULL;
4299 }
4300 }
4301 return build_struct_time(y, m, d, hh, mm, ss, 0);
4302}
4303
Tim Peters371935f2003-02-01 01:52:50 +00004304/* Pickle support, a simple use of __reduce__. */
Tim Peters33e0f382003-01-10 02:05:14 +00004305
Tim Petersa9bc1682003-01-11 03:39:11 +00004306/* Let basestate be the non-tzinfo data string.
Tim Peters2a799bf2002-12-16 20:18:38 +00004307 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4308 * So it's a tuple in any (non-error) case.
Tim Petersb57f8f02003-02-01 02:54:15 +00004309 * __getstate__ isn't exposed.
Tim Peters2a799bf2002-12-16 20:18:38 +00004310 */
4311static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004312datetime_getstate(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00004313{
4314 PyObject *basestate;
4315 PyObject *result = NULL;
4316
Tim Peters33e0f382003-01-10 02:05:14 +00004317 basestate = PyString_FromStringAndSize((char *)self->data,
4318 _PyDateTime_DATETIME_DATASIZE);
Tim Peters2a799bf2002-12-16 20:18:38 +00004319 if (basestate != NULL) {
Tim Petersa9bc1682003-01-11 03:39:11 +00004320 if (! HASTZINFO(self) || self->tzinfo == Py_None)
Tim Peters2a799bf2002-12-16 20:18:38 +00004321 result = Py_BuildValue("(O)", basestate);
4322 else
4323 result = Py_BuildValue("OO", basestate, self->tzinfo);
4324 Py_DECREF(basestate);
4325 }
4326 return result;
4327}
4328
4329static PyObject *
Guido van Rossum177e41a2003-01-30 22:06:23 +00004330datetime_reduce(PyDateTime_DateTime *self, PyObject *arg)
Tim Peters2a799bf2002-12-16 20:18:38 +00004331{
Guido van Rossum177e41a2003-01-30 22:06:23 +00004332 return Py_BuildValue("(ON)", self->ob_type, datetime_getstate(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00004333}
4334
Tim Petersa9bc1682003-01-11 03:39:11 +00004335static PyMethodDef datetime_methods[] = {
Guido van Rossum177e41a2003-01-30 22:06:23 +00004336
Tim Peters2a799bf2002-12-16 20:18:38 +00004337 /* Class methods: */
Tim Peters2a799bf2002-12-16 20:18:38 +00004338
Tim Petersa9bc1682003-01-11 03:39:11 +00004339 {"now", (PyCFunction)datetime_now,
Tim Peters2a799bf2002-12-16 20:18:38 +00004340 METH_KEYWORDS | METH_CLASS,
Neal Norwitz2fbe5372003-01-23 21:09:05 +00004341 PyDoc_STR("[tz] -> new datetime with tz's local day and time.")},
Tim Peters2a799bf2002-12-16 20:18:38 +00004342
Tim Petersa9bc1682003-01-11 03:39:11 +00004343 {"utcnow", (PyCFunction)datetime_utcnow,
4344 METH_NOARGS | METH_CLASS,
4345 PyDoc_STR("Return a new datetime representing UTC day and time.")},
4346
4347 {"fromtimestamp", (PyCFunction)datetime_fromtimestamp,
Tim Peters2a799bf2002-12-16 20:18:38 +00004348 METH_KEYWORDS | METH_CLASS,
Tim Peters2a44a8d2003-01-23 20:53:10 +00004349 PyDoc_STR("timestamp[, tz] -> tz's local time from POSIX timestamp.")},
Tim Peters2a799bf2002-12-16 20:18:38 +00004350
Tim Petersa9bc1682003-01-11 03:39:11 +00004351 {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
4352 METH_VARARGS | METH_CLASS,
4353 PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp "
4354 "(like time.time()).")},
4355
4356 {"combine", (PyCFunction)datetime_combine,
4357 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
4358 PyDoc_STR("date, time -> datetime with same date and time fields")},
4359
Tim Peters2a799bf2002-12-16 20:18:38 +00004360 /* Instance methods: */
Guido van Rossum177e41a2003-01-30 22:06:23 +00004361
Tim Petersa9bc1682003-01-11 03:39:11 +00004362 {"date", (PyCFunction)datetime_getdate, METH_NOARGS,
4363 PyDoc_STR("Return date object with same year, month and day.")},
4364
4365 {"time", (PyCFunction)datetime_gettime, METH_NOARGS,
4366 PyDoc_STR("Return time object with same time but with tzinfo=None.")},
4367
4368 {"timetz", (PyCFunction)datetime_gettimetz, METH_NOARGS,
4369 PyDoc_STR("Return time object with same time and tzinfo.")},
4370
4371 {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
4372 PyDoc_STR("Return ctime() style string.")},
4373
4374 {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004375 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
4376
Tim Petersa9bc1682003-01-11 03:39:11 +00004377 {"utctimetuple", (PyCFunction)datetime_utctimetuple, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004378 PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")},
4379
Tim Petersa9bc1682003-01-11 03:39:11 +00004380 {"isoformat", (PyCFunction)datetime_isoformat, METH_KEYWORDS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004381 PyDoc_STR("[sep] -> string in ISO 8601 format, "
4382 "YYYY-MM-DDTHH:MM:SS[.mmmmmm][+HH:MM].\n\n"
4383 "sep is used to separate the year from the time, and "
4384 "defaults to 'T'.")},
4385
Tim Petersa9bc1682003-01-11 03:39:11 +00004386 {"utcoffset", (PyCFunction)datetime_utcoffset, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004387 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
4388
Tim Petersa9bc1682003-01-11 03:39:11 +00004389 {"tzname", (PyCFunction)datetime_tzname, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004390 PyDoc_STR("Return self.tzinfo.tzname(self).")},
4391
Tim Petersa9bc1682003-01-11 03:39:11 +00004392 {"dst", (PyCFunction)datetime_dst, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004393 PyDoc_STR("Return self.tzinfo.dst(self).")},
4394
Tim Petersa9bc1682003-01-11 03:39:11 +00004395 {"replace", (PyCFunction)datetime_replace, METH_KEYWORDS,
4396 PyDoc_STR("Return datetime with new specified fields.")},
Tim Peters12bf3392002-12-24 05:41:27 +00004397
Tim Petersa9bc1682003-01-11 03:39:11 +00004398 {"astimezone", (PyCFunction)datetime_astimezone, METH_KEYWORDS,
Tim Peters80475bb2002-12-25 07:40:55 +00004399 PyDoc_STR("tz -> convert to local time in new timezone tz\n")},
4400
Guido van Rossum177e41a2003-01-30 22:06:23 +00004401 {"__reduce__", (PyCFunction)datetime_reduce, METH_NOARGS,
4402 PyDoc_STR("__reduce__() -> (cls, state)")},
4403
Tim Peters2a799bf2002-12-16 20:18:38 +00004404 {NULL, NULL}
4405};
4406
Tim Petersa9bc1682003-01-11 03:39:11 +00004407static char datetime_doc[] =
Tim Peters2a799bf2002-12-16 20:18:38 +00004408PyDoc_STR("date/time type.");
4409
Tim Petersa9bc1682003-01-11 03:39:11 +00004410static PyNumberMethods datetime_as_number = {
4411 datetime_add, /* nb_add */
4412 datetime_subtract, /* nb_subtract */
Tim Peters2a799bf2002-12-16 20:18:38 +00004413 0, /* nb_multiply */
4414 0, /* nb_divide */
4415 0, /* nb_remainder */
4416 0, /* nb_divmod */
4417 0, /* nb_power */
4418 0, /* nb_negative */
4419 0, /* nb_positive */
4420 0, /* nb_absolute */
4421 0, /* nb_nonzero */
4422};
4423
Tim Petersa9bc1682003-01-11 03:39:11 +00004424statichere PyTypeObject PyDateTime_DateTimeType = {
Tim Peters2a799bf2002-12-16 20:18:38 +00004425 PyObject_HEAD_INIT(NULL)
4426 0, /* ob_size */
Tim Peters0bf60bd2003-01-08 20:40:01 +00004427 "datetime.datetime", /* tp_name */
Tim Petersa9bc1682003-01-11 03:39:11 +00004428 sizeof(PyDateTime_DateTime), /* tp_basicsize */
Tim Peters2a799bf2002-12-16 20:18:38 +00004429 0, /* tp_itemsize */
Tim Petersa9bc1682003-01-11 03:39:11 +00004430 (destructor)datetime_dealloc, /* tp_dealloc */
Tim Peters2a799bf2002-12-16 20:18:38 +00004431 0, /* tp_print */
4432 0, /* tp_getattr */
4433 0, /* tp_setattr */
4434 0, /* tp_compare */
Tim Petersa9bc1682003-01-11 03:39:11 +00004435 (reprfunc)datetime_repr, /* tp_repr */
4436 &datetime_as_number, /* tp_as_number */
Tim Peters2a799bf2002-12-16 20:18:38 +00004437 0, /* tp_as_sequence */
4438 0, /* tp_as_mapping */
Tim Petersa9bc1682003-01-11 03:39:11 +00004439 (hashfunc)datetime_hash, /* tp_hash */
Tim Peters2a799bf2002-12-16 20:18:38 +00004440 0, /* tp_call */
Tim Petersa9bc1682003-01-11 03:39:11 +00004441 (reprfunc)datetime_str, /* tp_str */
Tim Peters2a799bf2002-12-16 20:18:38 +00004442 PyObject_GenericGetAttr, /* tp_getattro */
4443 0, /* tp_setattro */
4444 0, /* tp_as_buffer */
4445 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4446 Py_TPFLAGS_BASETYPE, /* tp_flags */
Tim Petersa9bc1682003-01-11 03:39:11 +00004447 datetime_doc, /* tp_doc */
Tim Peters2a799bf2002-12-16 20:18:38 +00004448 0, /* tp_traverse */
4449 0, /* tp_clear */
Tim Petersa9bc1682003-01-11 03:39:11 +00004450 (richcmpfunc)datetime_richcompare, /* tp_richcompare */
Tim Peters2a799bf2002-12-16 20:18:38 +00004451 0, /* tp_weaklistoffset */
4452 0, /* tp_iter */
4453 0, /* tp_iternext */
Tim Petersa9bc1682003-01-11 03:39:11 +00004454 datetime_methods, /* tp_methods */
Tim Peters2a799bf2002-12-16 20:18:38 +00004455 0, /* tp_members */
Tim Petersa9bc1682003-01-11 03:39:11 +00004456 datetime_getset, /* tp_getset */
4457 &PyDateTime_DateType, /* tp_base */
Tim Peters2a799bf2002-12-16 20:18:38 +00004458 0, /* tp_dict */
4459 0, /* tp_descr_get */
4460 0, /* tp_descr_set */
4461 0, /* tp_dictoffset */
4462 0, /* tp_init */
4463 0, /* tp_alloc */
Tim Petersa9bc1682003-01-11 03:39:11 +00004464 datetime_new, /* tp_new */
Tim Peters2a799bf2002-12-16 20:18:38 +00004465 _PyObject_Del, /* tp_free */
4466};
4467
4468/* ---------------------------------------------------------------------------
4469 * Module methods and initialization.
4470 */
4471
4472static PyMethodDef module_methods[] = {
Tim Peters2a799bf2002-12-16 20:18:38 +00004473 {NULL, NULL}
4474};
4475
4476PyMODINIT_FUNC
4477initdatetime(void)
4478{
4479 PyObject *m; /* a module object */
4480 PyObject *d; /* its dict */
4481 PyObject *x;
4482
Tim Peters2a799bf2002-12-16 20:18:38 +00004483 m = Py_InitModule3("datetime", module_methods,
4484 "Fast implementation of the datetime type.");
4485
4486 if (PyType_Ready(&PyDateTime_DateType) < 0)
4487 return;
4488 if (PyType_Ready(&PyDateTime_DateTimeType) < 0)
4489 return;
4490 if (PyType_Ready(&PyDateTime_DeltaType) < 0)
4491 return;
4492 if (PyType_Ready(&PyDateTime_TimeType) < 0)
4493 return;
4494 if (PyType_Ready(&PyDateTime_TZInfoType) < 0)
4495 return;
Tim Peters2a799bf2002-12-16 20:18:38 +00004496
Tim Peters2a799bf2002-12-16 20:18:38 +00004497 /* timedelta values */
4498 d = PyDateTime_DeltaType.tp_dict;
4499
Tim Peters2a799bf2002-12-16 20:18:38 +00004500 x = new_delta(0, 0, 1, 0);
4501 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
4502 return;
4503 Py_DECREF(x);
4504
4505 x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0);
4506 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
4507 return;
4508 Py_DECREF(x);
4509
4510 x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0);
4511 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
4512 return;
4513 Py_DECREF(x);
4514
4515 /* date values */
4516 d = PyDateTime_DateType.tp_dict;
4517
4518 x = new_date(1, 1, 1);
4519 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
4520 return;
4521 Py_DECREF(x);
4522
4523 x = new_date(MAXYEAR, 12, 31);
4524 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
4525 return;
4526 Py_DECREF(x);
4527
4528 x = new_delta(1, 0, 0, 0);
4529 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
4530 return;
4531 Py_DECREF(x);
4532
Tim Peters37f39822003-01-10 03:49:02 +00004533 /* time values */
4534 d = PyDateTime_TimeType.tp_dict;
Tim Peters2a799bf2002-12-16 20:18:38 +00004535
Tim Peters37f39822003-01-10 03:49:02 +00004536 x = new_time(0, 0, 0, 0, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004537 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
4538 return;
4539 Py_DECREF(x);
4540
Tim Peters37f39822003-01-10 03:49:02 +00004541 x = new_time(23, 59, 59, 999999, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004542 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
4543 return;
4544 Py_DECREF(x);
4545
4546 x = new_delta(0, 0, 1, 0);
4547 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
4548 return;
4549 Py_DECREF(x);
4550
Tim Petersa9bc1682003-01-11 03:39:11 +00004551 /* datetime values */
4552 d = PyDateTime_DateTimeType.tp_dict;
Tim Peters2a799bf2002-12-16 20:18:38 +00004553
Tim Petersa9bc1682003-01-11 03:39:11 +00004554 x = new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004555 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
4556 return;
4557 Py_DECREF(x);
4558
Tim Petersa9bc1682003-01-11 03:39:11 +00004559 x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004560 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
4561 return;
4562 Py_DECREF(x);
4563
4564 x = new_delta(0, 0, 1, 0);
4565 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
4566 return;
4567 Py_DECREF(x);
4568
Tim Peters2a799bf2002-12-16 20:18:38 +00004569 /* module initialization */
4570 PyModule_AddIntConstant(m, "MINYEAR", MINYEAR);
4571 PyModule_AddIntConstant(m, "MAXYEAR", MAXYEAR);
4572
4573 Py_INCREF(&PyDateTime_DateType);
4574 PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType);
4575
Tim Petersa9bc1682003-01-11 03:39:11 +00004576 Py_INCREF(&PyDateTime_DateTimeType);
4577 PyModule_AddObject(m, "datetime",
4578 (PyObject *)&PyDateTime_DateTimeType);
4579
4580 Py_INCREF(&PyDateTime_TimeType);
4581 PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType);
4582
Tim Peters2a799bf2002-12-16 20:18:38 +00004583 Py_INCREF(&PyDateTime_DeltaType);
4584 PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType);
4585
Tim Peters2a799bf2002-12-16 20:18:38 +00004586 Py_INCREF(&PyDateTime_TZInfoType);
4587 PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
4588
Tim Peters2a799bf2002-12-16 20:18:38 +00004589 /* A 4-year cycle has an extra leap day over what we'd get from
4590 * pasting together 4 single years.
4591 */
4592 assert(DI4Y == 4 * 365 + 1);
4593 assert(DI4Y == days_before_year(4+1));
4594
4595 /* Similarly, a 400-year cycle has an extra leap day over what we'd
4596 * get from pasting together 4 100-year cycles.
4597 */
4598 assert(DI400Y == 4 * DI100Y + 1);
4599 assert(DI400Y == days_before_year(400+1));
4600
4601 /* OTOH, a 100-year cycle has one fewer leap day than we'd get from
4602 * pasting together 25 4-year cycles.
4603 */
4604 assert(DI100Y == 25 * DI4Y - 1);
4605 assert(DI100Y == days_before_year(100+1));
4606
4607 us_per_us = PyInt_FromLong(1);
4608 us_per_ms = PyInt_FromLong(1000);
4609 us_per_second = PyInt_FromLong(1000000);
4610 us_per_minute = PyInt_FromLong(60000000);
4611 seconds_per_day = PyInt_FromLong(24 * 3600);
4612 if (us_per_us == NULL || us_per_ms == NULL || us_per_second == NULL ||
4613 us_per_minute == NULL || seconds_per_day == NULL)
4614 return;
4615
4616 /* The rest are too big for 32-bit ints, but even
4617 * us_per_week fits in 40 bits, so doubles should be exact.
4618 */
4619 us_per_hour = PyLong_FromDouble(3600000000.0);
4620 us_per_day = PyLong_FromDouble(86400000000.0);
4621 us_per_week = PyLong_FromDouble(604800000000.0);
4622 if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL)
4623 return;
4624}
Tim Petersf3615152003-01-01 21:51:37 +00004625
4626/* ---------------------------------------------------------------------------
Tim Petersa9bc1682003-01-11 03:39:11 +00004627Some time zone algebra. For a datetime x, let
Tim Petersf3615152003-01-01 21:51:37 +00004628 x.n = x stripped of its timezone -- its naive time.
4629 x.o = x.utcoffset(), and assuming that doesn't raise an exception or
4630 return None
4631 x.d = x.dst(), and assuming that doesn't raise an exception or
4632 return None
4633 x.s = x's standard offset, x.o - x.d
4634
4635Now some derived rules, where k is a duration (timedelta).
4636
46371. x.o = x.s + x.d
4638 This follows from the definition of x.s.
4639
Tim Petersc5dc4da2003-01-02 17:55:03 +000046402. If x and y have the same tzinfo member, x.s = y.s.
Tim Petersf3615152003-01-01 21:51:37 +00004641 This is actually a requirement, an assumption we need to make about
4642 sane tzinfo classes.
4643
46443. The naive UTC time corresponding to x is x.n - x.o.
4645 This is again a requirement for a sane tzinfo class.
4646
46474. (x+k).s = x.s
Tim Peters8bb5ad22003-01-24 02:44:45 +00004648 This follows from #2, and that datimetimetz+timedelta preserves tzinfo.
Tim Petersf3615152003-01-01 21:51:37 +00004649
Tim Petersc5dc4da2003-01-02 17:55:03 +000046505. (x+k).n = x.n + k
Tim Petersf3615152003-01-01 21:51:37 +00004651 Again follows from how arithmetic is defined.
4652
Tim Peters8bb5ad22003-01-24 02:44:45 +00004653Now we can explain tz.fromutc(x). Let's assume it's an interesting case
Tim Petersf3615152003-01-01 21:51:37 +00004654(meaning that the various tzinfo methods exist, and don't blow up or return
4655None when called).
4656
Tim Petersa9bc1682003-01-11 03:39:11 +00004657The function wants to return a datetime y with timezone tz, equivalent to x.
Tim Peters8bb5ad22003-01-24 02:44:45 +00004658x is already in UTC.
Tim Petersf3615152003-01-01 21:51:37 +00004659
4660By #3, we want
4661
Tim Peters8bb5ad22003-01-24 02:44:45 +00004662 y.n - y.o = x.n [1]
Tim Petersf3615152003-01-01 21:51:37 +00004663
4664The algorithm starts by attaching tz to x.n, and calling that y. So
4665x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
4666becomes true; in effect, we want to solve [2] for k:
4667
Tim Peters8bb5ad22003-01-24 02:44:45 +00004668 (y+k).n - (y+k).o = x.n [2]
Tim Petersf3615152003-01-01 21:51:37 +00004669
4670By #1, this is the same as
4671
Tim Peters8bb5ad22003-01-24 02:44:45 +00004672 (y+k).n - ((y+k).s + (y+k).d) = x.n [3]
Tim Petersf3615152003-01-01 21:51:37 +00004673
4674By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
4675Substituting that into [3],
4676
Tim Peters8bb5ad22003-01-24 02:44:45 +00004677 x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving
4678 k - (y+k).s - (y+k).d = 0; rearranging,
4679 k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so
4680 k = y.s - (y+k).d
Tim Petersf3615152003-01-01 21:51:37 +00004681
Tim Peters8bb5ad22003-01-24 02:44:45 +00004682On the RHS, (y+k).d can't be computed directly, but y.s can be, and we
4683approximate k by ignoring the (y+k).d term at first. Note that k can't be
4684very large, since all offset-returning methods return a duration of magnitude
4685less than 24 hours. For that reason, if y is firmly in std time, (y+k).d must
4686be 0, so ignoring it has no consequence then.
Tim Petersf3615152003-01-01 21:51:37 +00004687
4688In any case, the new value is
4689
Tim Peters8bb5ad22003-01-24 02:44:45 +00004690 z = y + y.s [4]
Tim Petersf3615152003-01-01 21:51:37 +00004691
Tim Peters8bb5ad22003-01-24 02:44:45 +00004692It's helpful to step back at look at [4] from a higher level: it's simply
4693mapping from UTC to tz's standard time.
Tim Petersc5dc4da2003-01-02 17:55:03 +00004694
4695At this point, if
4696
Tim Peters8bb5ad22003-01-24 02:44:45 +00004697 z.n - z.o = x.n [5]
Tim Petersc5dc4da2003-01-02 17:55:03 +00004698
4699we have an equivalent time, and are almost done. The insecurity here is
Tim Petersf3615152003-01-01 21:51:37 +00004700at the start of daylight time. Picture US Eastern for concreteness. The wall
4701time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
Tim Peters8bb5ad22003-01-24 02:44:45 +00004702sense then. The docs ask that an Eastern tzinfo class consider such a time to
4703be EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST
4704on the day DST starts. We want to return the 1:MM EST spelling because that's
Tim Petersf3615152003-01-01 21:51:37 +00004705the only spelling that makes sense on the local wall clock.
4706
Tim Petersc5dc4da2003-01-02 17:55:03 +00004707In fact, if [5] holds at this point, we do have the standard-time spelling,
4708but that takes a bit of proof. We first prove a stronger result. What's the
4709difference between the LHS and RHS of [5]? Let
Tim Petersf3615152003-01-01 21:51:37 +00004710
Tim Peters8bb5ad22003-01-24 02:44:45 +00004711 diff = x.n - (z.n - z.o) [6]
Tim Petersf3615152003-01-01 21:51:37 +00004712
Tim Petersc5dc4da2003-01-02 17:55:03 +00004713Now
4714 z.n = by [4]
Tim Peters8bb5ad22003-01-24 02:44:45 +00004715 (y + y.s).n = by #5
4716 y.n + y.s = since y.n = x.n
4717 x.n + y.s = since z and y are have the same tzinfo member,
4718 y.s = z.s by #2
4719 x.n + z.s
Tim Petersf3615152003-01-01 21:51:37 +00004720
Tim Petersc5dc4da2003-01-02 17:55:03 +00004721Plugging that back into [6] gives
Tim Petersf3615152003-01-01 21:51:37 +00004722
Tim Petersc5dc4da2003-01-02 17:55:03 +00004723 diff =
Tim Peters8bb5ad22003-01-24 02:44:45 +00004724 x.n - ((x.n + z.s) - z.o) = expanding
4725 x.n - x.n - z.s + z.o = cancelling
4726 - z.s + z.o = by #2
Tim Petersc5dc4da2003-01-02 17:55:03 +00004727 z.d
Tim Petersf3615152003-01-01 21:51:37 +00004728
Tim Petersc5dc4da2003-01-02 17:55:03 +00004729So diff = z.d.
Tim Petersf3615152003-01-01 21:51:37 +00004730
Tim Petersc5dc4da2003-01-02 17:55:03 +00004731If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
Tim Peters8bb5ad22003-01-24 02:44:45 +00004732spelling we wanted in the endcase described above. We're done. Contrarily,
4733if z.d = 0, then we have a UTC equivalent, and are also done.
Tim Petersf3615152003-01-01 21:51:37 +00004734
Tim Petersc5dc4da2003-01-02 17:55:03 +00004735If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
4736add to z (in effect, z is in tz's standard time, and we need to shift the
Tim Peters8bb5ad22003-01-24 02:44:45 +00004737local clock into tz's daylight time).
Tim Petersf3615152003-01-01 21:51:37 +00004738
Tim Petersc5dc4da2003-01-02 17:55:03 +00004739Let
Tim Petersf3615152003-01-01 21:51:37 +00004740
Tim Peters4fede1a2003-01-04 00:26:59 +00004741 z' = z + z.d = z + diff [7]
Tim Petersc3bb26a2003-01-02 03:14:59 +00004742
Tim Peters4fede1a2003-01-04 00:26:59 +00004743and we can again ask whether
Tim Petersc3bb26a2003-01-02 03:14:59 +00004744
Tim Peters8bb5ad22003-01-24 02:44:45 +00004745 z'.n - z'.o = x.n [8]
Tim Petersc3bb26a2003-01-02 03:14:59 +00004746
Tim Peters8bb5ad22003-01-24 02:44:45 +00004747If so, we're done. If not, the tzinfo class is insane, according to the
4748assumptions we've made. This also requires a bit of proof. As before, let's
4749compute the difference between the LHS and RHS of [8] (and skipping some of
4750the justifications for the kinds of substitutions we've done several times
4751already):
Tim Peters4fede1a2003-01-04 00:26:59 +00004752
Tim Peters8bb5ad22003-01-24 02:44:45 +00004753 diff' = x.n - (z'.n - z'.o) = replacing z'.n via [7]
4754 x.n - (z.n + diff - z'.o) = replacing diff via [6]
4755 x.n - (z.n + x.n - (z.n - z.o) - z'.o) =
4756 x.n - z.n - x.n + z.n - z.o + z'.o = cancel x.n
4757 - z.n + z.n - z.o + z'.o = cancel z.n
Tim Peters4fede1a2003-01-04 00:26:59 +00004758 - z.o + z'.o = #1 twice
4759 -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
4760 z'.d - z.d
4761
4762So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
Tim Peters8bb5ad22003-01-24 02:44:45 +00004763we've found the UTC-equivalent so are done. In fact, we stop with [7] and
4764return z', not bothering to compute z'.d.
Tim Peters4fede1a2003-01-04 00:26:59 +00004765
Tim Peters8bb5ad22003-01-24 02:44:45 +00004766How could z.d and z'd differ? z' = z + z.d [7], so merely moving z' by
4767a dst() offset, and starting *from* a time already in DST (we know z.d != 0),
4768would have to change the result dst() returns: we start in DST, and moving
4769a little further into it takes us out of DST.
Tim Peters4fede1a2003-01-04 00:26:59 +00004770
Tim Peters8bb5ad22003-01-24 02:44:45 +00004771There isn't a sane case where this can happen. The closest it gets is at
4772the end of DST, where there's an hour in UTC with no spelling in a hybrid
4773tzinfo class. In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT. During
4774that hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM
4775UTC) because the docs insist on that, but 0:MM is taken as being in daylight
4776time (4:MM UTC). There is no local time mapping to 5:MM UTC. The local
4777clock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in
4778standard time. Since that's what the local clock *does*, we want to map both
4779UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
Tim Peters4fede1a2003-01-04 00:26:59 +00004780in local time, but so it goes -- it's the way the local clock works.
4781
Tim Peters8bb5ad22003-01-24 02:44:45 +00004782When x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
4783so z=0:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
4784z' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
Tim Peters4fede1a2003-01-04 00:26:59 +00004785(correctly) concludes that z' is not UTC-equivalent to x.
4786
4787Because we know z.d said z was in daylight time (else [5] would have held and
4788we would have stopped then), and we know z.d != z'.d (else [8] would have held
4789and we we have stopped then), and there are only 2 possible values dst() can
4790return in Eastern, it follows that z'.d must be 0 (which it is in the example,
4791but the reasoning doesn't depend on the example -- it depends on there being
4792two possible dst() outcomes, one zero and the other non-zero). Therefore
Tim Peters8bb5ad22003-01-24 02:44:45 +00004793z' must be in standard time, and is the spelling we want in this case.
4794
4795Note again that z' is not UTC-equivalent as far as the hybrid tzinfo class is
4796concerned (because it takes z' as being in standard time rather than the
4797daylight time we intend here), but returning it gives the real-life "local
4798clock repeats an hour" behavior when mapping the "unspellable" UTC hour into
4799tz.
4800
4801When the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with
4802the 1:MM standard time spelling we want.
4803
4804So how can this break? One of the assumptions must be violated. Two
4805possibilities:
4806
48071) [2] effectively says that y.s is invariant across all y belong to a given
4808 time zone. This isn't true if, for political reasons or continental drift,
4809 a region decides to change its base offset from UTC.
4810
48112) There may be versions of "double daylight" time where the tail end of
4812 the analysis gives up a step too early. I haven't thought about that
4813 enough to say.
4814
4815In any case, it's clear that the default fromutc() is strong enough to handle
4816"almost all" time zones: so long as the standard offset is invariant, it
4817doesn't matter if daylight time transition points change from year to year, or
4818if daylight time is skipped in some years; it doesn't matter how large or
4819small dst() may get within its bounds; and it doesn't even matter if some
4820perverse time zone returns a negative dst()). So a breaking case must be
4821pretty bizarre, and a tzinfo subclass can override fromutc() if it is.
Tim Petersf3615152003-01-01 21:51:37 +00004822--------------------------------------------------------------------------- */