blob: 82f5dd9f39e634f8907a4d3e7657260690f186a6 [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
1227/* ---------------------------------------------------------------------------
1228 * Helpers for setting object fields. These work on pointers to the
1229 * appropriate base class.
1230 */
1231
Tim Petersa9bc1682003-01-11 03:39:11 +00001232/* For date and datetime. */
Tim Peters2a799bf2002-12-16 20:18:38 +00001233static void
1234set_date_fields(PyDateTime_Date *self, int y, int m, int d)
1235{
1236 self->hashcode = -1;
1237 SET_YEAR(self, y);
1238 SET_MONTH(self, m);
1239 SET_DAY(self, d);
1240}
1241
Tim Peters2a799bf2002-12-16 20:18:38 +00001242/* ---------------------------------------------------------------------------
1243 * Create various objects, mostly without range checking.
1244 */
1245
1246/* Create a date instance with no range checking. */
1247static PyObject *
1248new_date(int year, int month, int day)
1249{
1250 PyDateTime_Date *self;
1251
1252 self = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
1253 if (self != NULL)
1254 set_date_fields(self, year, month, day);
1255 return (PyObject *) self;
1256}
1257
1258/* Create a datetime instance with no range checking. */
1259static PyObject *
1260new_datetime(int year, int month, int day, int hour, int minute,
Tim Petersa9bc1682003-01-11 03:39:11 +00001261 int second, int usecond, PyObject *tzinfo)
Tim Peters2a799bf2002-12-16 20:18:38 +00001262{
1263 PyDateTime_DateTime *self;
Tim Petersa9bc1682003-01-11 03:39:11 +00001264 char aware = tzinfo != Py_None;
Tim Peters2a799bf2002-12-16 20:18:38 +00001265
Tim Petersa9bc1682003-01-11 03:39:11 +00001266 self = (PyDateTime_DateTime *)PyObject_MALLOC(aware ?
1267 sizeof(PyDateTime_DateTime) :
1268 sizeof(_PyDateTime_BaseDateTime));
1269 if (self == NULL)
1270 return PyErr_NoMemory();
1271 self->hastzinfo = aware;
1272 set_date_fields((PyDateTime_Date *)self, year, month, day);
1273 DATE_SET_HOUR(self, hour);
1274 DATE_SET_MINUTE(self, minute);
1275 DATE_SET_SECOND(self, second);
1276 DATE_SET_MICROSECOND(self, usecond);
1277 if (aware) {
Tim Peters2a799bf2002-12-16 20:18:38 +00001278 Py_INCREF(tzinfo);
1279 self->tzinfo = tzinfo;
1280 }
Tim Petersa9bc1682003-01-11 03:39:11 +00001281 return (PyObject *)PyObject_INIT(self, &PyDateTime_DateTimeType);
Tim Peters2a799bf2002-12-16 20:18:38 +00001282}
1283
1284/* Create a time instance with no range checking. */
1285static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00001286new_time(int hour, int minute, int second, int usecond, PyObject *tzinfo)
Tim Peters2a799bf2002-12-16 20:18:38 +00001287{
1288 PyDateTime_Time *self;
Tim Peters37f39822003-01-10 03:49:02 +00001289 char aware = tzinfo != Py_None;
Tim Peters2a799bf2002-12-16 20:18:38 +00001290
Tim Peters37f39822003-01-10 03:49:02 +00001291 self = (PyDateTime_Time *)PyObject_MALLOC(aware ?
1292 sizeof(PyDateTime_Time) :
1293 sizeof(_PyDateTime_BaseTime));
1294 if (self == NULL)
1295 return PyErr_NoMemory();
1296 self->hastzinfo = aware;
Tim Petersa9bc1682003-01-11 03:39:11 +00001297 self->hashcode = -1;
1298 TIME_SET_HOUR(self, hour);
1299 TIME_SET_MINUTE(self, minute);
1300 TIME_SET_SECOND(self, second);
1301 TIME_SET_MICROSECOND(self, usecond);
Tim Peters37f39822003-01-10 03:49:02 +00001302 if (aware) {
Tim Peters2a799bf2002-12-16 20:18:38 +00001303 Py_INCREF(tzinfo);
1304 self->tzinfo = tzinfo;
1305 }
Tim Peters37f39822003-01-10 03:49:02 +00001306 return (PyObject *)PyObject_INIT(self, &PyDateTime_TimeType);
Tim Peters2a799bf2002-12-16 20:18:38 +00001307}
1308
1309/* Create a timedelta instance. Normalize the members iff normalize is
1310 * true. Passing false is a speed optimization, if you know for sure
1311 * that seconds and microseconds are already in their proper ranges. In any
1312 * case, raises OverflowError and returns NULL if the normalized days is out
1313 * of range).
1314 */
1315static PyObject *
1316new_delta(int days, int seconds, int microseconds, int normalize)
1317{
1318 PyDateTime_Delta *self;
1319
1320 if (normalize)
1321 normalize_d_s_us(&days, &seconds, &microseconds);
1322 assert(0 <= seconds && seconds < 24*3600);
1323 assert(0 <= microseconds && microseconds < 1000000);
1324
1325 if (check_delta_day_range(days) < 0)
1326 return NULL;
1327
1328 self = PyObject_New(PyDateTime_Delta, &PyDateTime_DeltaType);
1329 if (self != NULL) {
1330 self->hashcode = -1;
1331 SET_TD_DAYS(self, days);
1332 SET_TD_SECONDS(self, seconds);
1333 SET_TD_MICROSECONDS(self, microseconds);
1334 }
1335 return (PyObject *) self;
1336}
1337
1338
1339/* ---------------------------------------------------------------------------
1340 * Cached Python objects; these are set by the module init function.
1341 */
1342
1343/* Conversion factors. */
1344static PyObject *us_per_us = NULL; /* 1 */
1345static PyObject *us_per_ms = NULL; /* 1000 */
1346static PyObject *us_per_second = NULL; /* 1000000 */
1347static PyObject *us_per_minute = NULL; /* 1e6 * 60 as Python int */
1348static PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python long */
1349static PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python long */
1350static PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python long */
1351static PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */
1352
1353/* Callables to support unpickling. */
1354static PyObject *date_unpickler_object = NULL;
Tim Petersa9bc1682003-01-11 03:39:11 +00001355static PyObject *datetime_unpickler_object = NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00001356static PyObject *tzinfo_unpickler_object = NULL;
Tim Peters37f39822003-01-10 03:49:02 +00001357static PyObject *time_unpickler_object = NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00001358
1359/* ---------------------------------------------------------------------------
1360 * Class implementations.
1361 */
1362
1363/*
1364 * PyDateTime_Delta implementation.
1365 */
1366
1367/* Convert a timedelta to a number of us,
1368 * (24*3600*self.days + self.seconds)*1000000 + self.microseconds
1369 * as a Python int or long.
1370 * Doing mixed-radix arithmetic by hand instead is excruciating in C,
1371 * due to ubiquitous overflow possibilities.
1372 */
1373static PyObject *
1374delta_to_microseconds(PyDateTime_Delta *self)
1375{
1376 PyObject *x1 = NULL;
1377 PyObject *x2 = NULL;
1378 PyObject *x3 = NULL;
1379 PyObject *result = NULL;
1380
1381 x1 = PyInt_FromLong(GET_TD_DAYS(self));
1382 if (x1 == NULL)
1383 goto Done;
1384 x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */
1385 if (x2 == NULL)
1386 goto Done;
1387 Py_DECREF(x1);
1388 x1 = NULL;
1389
1390 /* x2 has days in seconds */
1391 x1 = PyInt_FromLong(GET_TD_SECONDS(self)); /* seconds */
1392 if (x1 == NULL)
1393 goto Done;
1394 x3 = PyNumber_Add(x1, x2); /* days and seconds in seconds */
1395 if (x3 == NULL)
1396 goto Done;
1397 Py_DECREF(x1);
1398 Py_DECREF(x2);
1399 x1 = x2 = NULL;
1400
1401 /* x3 has days+seconds in seconds */
1402 x1 = PyNumber_Multiply(x3, us_per_second); /* us */
1403 if (x1 == NULL)
1404 goto Done;
1405 Py_DECREF(x3);
1406 x3 = NULL;
1407
1408 /* x1 has days+seconds in us */
1409 x2 = PyInt_FromLong(GET_TD_MICROSECONDS(self));
1410 if (x2 == NULL)
1411 goto Done;
1412 result = PyNumber_Add(x1, x2);
1413
1414Done:
1415 Py_XDECREF(x1);
1416 Py_XDECREF(x2);
1417 Py_XDECREF(x3);
1418 return result;
1419}
1420
1421/* Convert a number of us (as a Python int or long) to a timedelta.
1422 */
1423static PyObject *
1424microseconds_to_delta(PyObject *pyus)
1425{
1426 int us;
1427 int s;
1428 int d;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001429 long temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001430
1431 PyObject *tuple = NULL;
1432 PyObject *num = NULL;
1433 PyObject *result = NULL;
1434
1435 tuple = PyNumber_Divmod(pyus, us_per_second);
1436 if (tuple == NULL)
1437 goto Done;
1438
1439 num = PyTuple_GetItem(tuple, 1); /* us */
1440 if (num == NULL)
1441 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001442 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001443 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001444 if (temp == -1 && PyErr_Occurred())
1445 goto Done;
1446 assert(0 <= temp && temp < 1000000);
1447 us = (int)temp;
Tim Peters2a799bf2002-12-16 20:18:38 +00001448 if (us < 0) {
1449 /* The divisor was positive, so this must be an error. */
1450 assert(PyErr_Occurred());
1451 goto Done;
1452 }
1453
1454 num = PyTuple_GetItem(tuple, 0); /* leftover seconds */
1455 if (num == NULL)
1456 goto Done;
1457 Py_INCREF(num);
1458 Py_DECREF(tuple);
1459
1460 tuple = PyNumber_Divmod(num, seconds_per_day);
1461 if (tuple == NULL)
1462 goto Done;
1463 Py_DECREF(num);
1464
1465 num = PyTuple_GetItem(tuple, 1); /* seconds */
1466 if (num == NULL)
1467 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001468 temp = PyLong_AsLong(num);
Tim Peters2a799bf2002-12-16 20:18:38 +00001469 num = NULL;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001470 if (temp == -1 && PyErr_Occurred())
1471 goto Done;
1472 assert(0 <= temp && temp < 24*3600);
1473 s = (int)temp;
1474
Tim Peters2a799bf2002-12-16 20:18:38 +00001475 if (s < 0) {
1476 /* The divisor was positive, so this must be an error. */
1477 assert(PyErr_Occurred());
1478 goto Done;
1479 }
1480
1481 num = PyTuple_GetItem(tuple, 0); /* leftover days */
1482 if (num == NULL)
1483 goto Done;
1484 Py_INCREF(num);
Tim Peters0b0f41c2002-12-19 01:44:38 +00001485 temp = PyLong_AsLong(num);
1486 if (temp == -1 && PyErr_Occurred())
Tim Peters2a799bf2002-12-16 20:18:38 +00001487 goto Done;
Tim Peters0b0f41c2002-12-19 01:44:38 +00001488 d = (int)temp;
1489 if ((long)d != temp) {
1490 PyErr_SetString(PyExc_OverflowError, "normalized days too "
1491 "large to fit in a C int");
1492 goto Done;
1493 }
Tim Peters2a799bf2002-12-16 20:18:38 +00001494 result = new_delta(d, s, us, 0);
1495
1496Done:
1497 Py_XDECREF(tuple);
1498 Py_XDECREF(num);
1499 return result;
1500}
1501
1502static PyObject *
1503multiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta)
1504{
1505 PyObject *pyus_in;
1506 PyObject *pyus_out;
1507 PyObject *result;
1508
1509 pyus_in = delta_to_microseconds(delta);
1510 if (pyus_in == NULL)
1511 return NULL;
1512
1513 pyus_out = PyNumber_Multiply(pyus_in, intobj);
1514 Py_DECREF(pyus_in);
1515 if (pyus_out == NULL)
1516 return NULL;
1517
1518 result = microseconds_to_delta(pyus_out);
1519 Py_DECREF(pyus_out);
1520 return result;
1521}
1522
1523static PyObject *
1524divide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj)
1525{
1526 PyObject *pyus_in;
1527 PyObject *pyus_out;
1528 PyObject *result;
1529
1530 pyus_in = delta_to_microseconds(delta);
1531 if (pyus_in == NULL)
1532 return NULL;
1533
1534 pyus_out = PyNumber_FloorDivide(pyus_in, intobj);
1535 Py_DECREF(pyus_in);
1536 if (pyus_out == NULL)
1537 return NULL;
1538
1539 result = microseconds_to_delta(pyus_out);
1540 Py_DECREF(pyus_out);
1541 return result;
1542}
1543
1544static PyObject *
1545delta_add(PyObject *left, PyObject *right)
1546{
1547 PyObject *result = Py_NotImplemented;
1548
1549 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1550 /* delta + delta */
1551 /* The C-level additions can't overflow because of the
1552 * invariant bounds.
1553 */
1554 int days = GET_TD_DAYS(left) + GET_TD_DAYS(right);
1555 int seconds = GET_TD_SECONDS(left) + GET_TD_SECONDS(right);
1556 int microseconds = GET_TD_MICROSECONDS(left) +
1557 GET_TD_MICROSECONDS(right);
1558 result = new_delta(days, seconds, microseconds, 1);
1559 }
1560
1561 if (result == Py_NotImplemented)
1562 Py_INCREF(result);
1563 return result;
1564}
1565
1566static PyObject *
1567delta_negative(PyDateTime_Delta *self)
1568{
1569 return new_delta(-GET_TD_DAYS(self),
1570 -GET_TD_SECONDS(self),
1571 -GET_TD_MICROSECONDS(self),
1572 1);
1573}
1574
1575static PyObject *
1576delta_positive(PyDateTime_Delta *self)
1577{
1578 /* Could optimize this (by returning self) if this isn't a
1579 * subclass -- but who uses unary + ? Approximately nobody.
1580 */
1581 return new_delta(GET_TD_DAYS(self),
1582 GET_TD_SECONDS(self),
1583 GET_TD_MICROSECONDS(self),
1584 0);
1585}
1586
1587static PyObject *
1588delta_abs(PyDateTime_Delta *self)
1589{
1590 PyObject *result;
1591
1592 assert(GET_TD_MICROSECONDS(self) >= 0);
1593 assert(GET_TD_SECONDS(self) >= 0);
1594
1595 if (GET_TD_DAYS(self) < 0)
1596 result = delta_negative(self);
1597 else
1598 result = delta_positive(self);
1599
1600 return result;
1601}
1602
1603static PyObject *
1604delta_subtract(PyObject *left, PyObject *right)
1605{
1606 PyObject *result = Py_NotImplemented;
1607
1608 if (PyDelta_Check(left) && PyDelta_Check(right)) {
1609 /* delta - delta */
1610 PyObject *minus_right = PyNumber_Negative(right);
1611 if (minus_right) {
1612 result = delta_add(left, minus_right);
1613 Py_DECREF(minus_right);
1614 }
1615 else
1616 result = NULL;
1617 }
1618
1619 if (result == Py_NotImplemented)
1620 Py_INCREF(result);
1621 return result;
1622}
1623
1624/* This is more natural as a tp_compare, but doesn't work then: for whatever
1625 * reason, Python's try_3way_compare ignores tp_compare unless
1626 * PyInstance_Check returns true, but these aren't old-style classes.
1627 */
1628static PyObject *
1629delta_richcompare(PyDateTime_Delta *self, PyObject *other, int op)
1630{
1631 int diff;
1632
1633 if (! PyDelta_CheckExact(other)) {
1634 PyErr_Format(PyExc_TypeError,
1635 "can't compare %s to %s instance",
1636 self->ob_type->tp_name, other->ob_type->tp_name);
1637 return NULL;
1638 }
1639 diff = GET_TD_DAYS(self) - GET_TD_DAYS(other);
1640 if (diff == 0) {
1641 diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other);
1642 if (diff == 0)
1643 diff = GET_TD_MICROSECONDS(self) -
1644 GET_TD_MICROSECONDS(other);
1645 }
1646 return diff_to_bool(diff, op);
1647}
1648
1649static PyObject *delta_getstate(PyDateTime_Delta *self);
1650
1651static long
1652delta_hash(PyDateTime_Delta *self)
1653{
1654 if (self->hashcode == -1) {
1655 PyObject *temp = delta_getstate(self);
1656 if (temp != NULL) {
1657 self->hashcode = PyObject_Hash(temp);
1658 Py_DECREF(temp);
1659 }
1660 }
1661 return self->hashcode;
1662}
1663
1664static PyObject *
1665delta_multiply(PyObject *left, PyObject *right)
1666{
1667 PyObject *result = Py_NotImplemented;
1668
1669 if (PyDelta_Check(left)) {
1670 /* delta * ??? */
1671 if (PyInt_Check(right) || PyLong_Check(right))
1672 result = multiply_int_timedelta(right,
1673 (PyDateTime_Delta *) left);
1674 }
1675 else if (PyInt_Check(left) || PyLong_Check(left))
1676 result = multiply_int_timedelta(left,
1677 (PyDateTime_Delta *) right);
1678
1679 if (result == Py_NotImplemented)
1680 Py_INCREF(result);
1681 return result;
1682}
1683
1684static PyObject *
1685delta_divide(PyObject *left, PyObject *right)
1686{
1687 PyObject *result = Py_NotImplemented;
1688
1689 if (PyDelta_Check(left)) {
1690 /* delta * ??? */
1691 if (PyInt_Check(right) || PyLong_Check(right))
1692 result = divide_timedelta_int(
1693 (PyDateTime_Delta *)left,
1694 right);
1695 }
1696
1697 if (result == Py_NotImplemented)
1698 Py_INCREF(result);
1699 return result;
1700}
1701
1702/* Fold in the value of the tag ("seconds", "weeks", etc) component of a
1703 * timedelta constructor. sofar is the # of microseconds accounted for
1704 * so far, and there are factor microseconds per current unit, the number
1705 * of which is given by num. num * factor is added to sofar in a
1706 * numerically careful way, and that's the result. Any fractional
1707 * microseconds left over (this can happen if num is a float type) are
1708 * added into *leftover.
1709 * Note that there are many ways this can give an error (NULL) return.
1710 */
1711static PyObject *
1712accum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor,
1713 double *leftover)
1714{
1715 PyObject *prod;
1716 PyObject *sum;
1717
1718 assert(num != NULL);
1719
1720 if (PyInt_Check(num) || PyLong_Check(num)) {
1721 prod = PyNumber_Multiply(num, factor);
1722 if (prod == NULL)
1723 return NULL;
1724 sum = PyNumber_Add(sofar, prod);
1725 Py_DECREF(prod);
1726 return sum;
1727 }
1728
1729 if (PyFloat_Check(num)) {
1730 double dnum;
1731 double fracpart;
1732 double intpart;
1733 PyObject *x;
1734 PyObject *y;
1735
1736 /* The Plan: decompose num into an integer part and a
1737 * fractional part, num = intpart + fracpart.
1738 * Then num * factor ==
1739 * intpart * factor + fracpart * factor
1740 * and the LHS can be computed exactly in long arithmetic.
1741 * The RHS is again broken into an int part and frac part.
1742 * and the frac part is added into *leftover.
1743 */
1744 dnum = PyFloat_AsDouble(num);
1745 if (dnum == -1.0 && PyErr_Occurred())
1746 return NULL;
1747 fracpart = modf(dnum, &intpart);
1748 x = PyLong_FromDouble(intpart);
1749 if (x == NULL)
1750 return NULL;
1751
1752 prod = PyNumber_Multiply(x, factor);
1753 Py_DECREF(x);
1754 if (prod == NULL)
1755 return NULL;
1756
1757 sum = PyNumber_Add(sofar, prod);
1758 Py_DECREF(prod);
1759 if (sum == NULL)
1760 return NULL;
1761
1762 if (fracpart == 0.0)
1763 return sum;
1764 /* So far we've lost no information. Dealing with the
1765 * fractional part requires float arithmetic, and may
1766 * lose a little info.
1767 */
1768 assert(PyInt_Check(factor) || PyLong_Check(factor));
1769 if (PyInt_Check(factor))
1770 dnum = (double)PyInt_AsLong(factor);
1771 else
1772 dnum = PyLong_AsDouble(factor);
1773
1774 dnum *= fracpart;
1775 fracpart = modf(dnum, &intpart);
1776 x = PyLong_FromDouble(intpart);
1777 if (x == NULL) {
1778 Py_DECREF(sum);
1779 return NULL;
1780 }
1781
1782 y = PyNumber_Add(sum, x);
1783 Py_DECREF(sum);
1784 Py_DECREF(x);
1785 *leftover += fracpart;
1786 return y;
1787 }
1788
1789 PyErr_Format(PyExc_TypeError,
1790 "unsupported type for timedelta %s component: %s",
1791 tag, num->ob_type->tp_name);
1792 return NULL;
1793}
1794
1795static PyObject *
1796delta_new(PyTypeObject *type, PyObject *args, PyObject *kw)
1797{
1798 PyObject *self = NULL;
1799
1800 /* Argument objects. */
1801 PyObject *day = NULL;
1802 PyObject *second = NULL;
1803 PyObject *us = NULL;
1804 PyObject *ms = NULL;
1805 PyObject *minute = NULL;
1806 PyObject *hour = NULL;
1807 PyObject *week = NULL;
1808
1809 PyObject *x = NULL; /* running sum of microseconds */
1810 PyObject *y = NULL; /* temp sum of microseconds */
1811 double leftover_us = 0.0;
1812
1813 static char *keywords[] = {
1814 "days", "seconds", "microseconds", "milliseconds",
1815 "minutes", "hours", "weeks", NULL
1816 };
1817
1818 if (PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOO:__new__",
1819 keywords,
1820 &day, &second, &us,
1821 &ms, &minute, &hour, &week) == 0)
1822 goto Done;
1823
1824 x = PyInt_FromLong(0);
1825 if (x == NULL)
1826 goto Done;
1827
1828#define CLEANUP \
1829 Py_DECREF(x); \
1830 x = y; \
1831 if (x == NULL) \
1832 goto Done
1833
1834 if (us) {
1835 y = accum("microseconds", x, us, us_per_us, &leftover_us);
1836 CLEANUP;
1837 }
1838 if (ms) {
1839 y = accum("milliseconds", x, ms, us_per_ms, &leftover_us);
1840 CLEANUP;
1841 }
1842 if (second) {
1843 y = accum("seconds", x, second, us_per_second, &leftover_us);
1844 CLEANUP;
1845 }
1846 if (minute) {
1847 y = accum("minutes", x, minute, us_per_minute, &leftover_us);
1848 CLEANUP;
1849 }
1850 if (hour) {
1851 y = accum("hours", x, hour, us_per_hour, &leftover_us);
1852 CLEANUP;
1853 }
1854 if (day) {
1855 y = accum("days", x, day, us_per_day, &leftover_us);
1856 CLEANUP;
1857 }
1858 if (week) {
1859 y = accum("weeks", x, week, us_per_week, &leftover_us);
1860 CLEANUP;
1861 }
1862 if (leftover_us) {
1863 /* Round to nearest whole # of us, and add into x. */
Tim Peters5d644dd2003-01-02 16:32:54 +00001864 PyObject *temp = PyLong_FromLong(round_to_long(leftover_us));
Tim Peters2a799bf2002-12-16 20:18:38 +00001865 if (temp == NULL) {
1866 Py_DECREF(x);
1867 goto Done;
1868 }
1869 y = PyNumber_Add(x, temp);
1870 Py_DECREF(temp);
1871 CLEANUP;
1872 }
1873
1874 self = microseconds_to_delta(x);
1875 Py_DECREF(x);
1876Done:
1877 return self;
1878
1879#undef CLEANUP
1880}
1881
1882static int
1883delta_nonzero(PyDateTime_Delta *self)
1884{
1885 return (GET_TD_DAYS(self) != 0
1886 || GET_TD_SECONDS(self) != 0
1887 || GET_TD_MICROSECONDS(self) != 0);
1888}
1889
1890static PyObject *
1891delta_repr(PyDateTime_Delta *self)
1892{
1893 if (GET_TD_MICROSECONDS(self) != 0)
1894 return PyString_FromFormat("%s(%d, %d, %d)",
1895 self->ob_type->tp_name,
1896 GET_TD_DAYS(self),
1897 GET_TD_SECONDS(self),
1898 GET_TD_MICROSECONDS(self));
1899 if (GET_TD_SECONDS(self) != 0)
1900 return PyString_FromFormat("%s(%d, %d)",
1901 self->ob_type->tp_name,
1902 GET_TD_DAYS(self),
1903 GET_TD_SECONDS(self));
1904
1905 return PyString_FromFormat("%s(%d)",
1906 self->ob_type->tp_name,
1907 GET_TD_DAYS(self));
1908}
1909
1910static PyObject *
1911delta_str(PyDateTime_Delta *self)
1912{
1913 int days = GET_TD_DAYS(self);
1914 int seconds = GET_TD_SECONDS(self);
1915 int us = GET_TD_MICROSECONDS(self);
1916 int hours;
1917 int minutes;
Tim Petersba873472002-12-18 20:19:21 +00001918 char buf[100];
1919 char *pbuf = buf;
1920 size_t buflen = sizeof(buf);
1921 int n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001922
1923 minutes = divmod(seconds, 60, &seconds);
1924 hours = divmod(minutes, 60, &minutes);
1925
1926 if (days) {
Tim Petersba873472002-12-18 20:19:21 +00001927 n = PyOS_snprintf(pbuf, buflen, "%d day%s, ", days,
1928 (days == 1 || days == -1) ? "" : "s");
1929 if (n < 0 || (size_t)n >= buflen)
1930 goto Fail;
1931 pbuf += n;
1932 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001933 }
1934
Tim Petersba873472002-12-18 20:19:21 +00001935 n = PyOS_snprintf(pbuf, buflen, "%d:%02d:%02d",
1936 hours, minutes, seconds);
1937 if (n < 0 || (size_t)n >= buflen)
1938 goto Fail;
1939 pbuf += n;
1940 buflen -= (size_t)n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001941
1942 if (us) {
Tim Petersba873472002-12-18 20:19:21 +00001943 n = PyOS_snprintf(pbuf, buflen, ".%06d", us);
1944 if (n < 0 || (size_t)n >= buflen)
1945 goto Fail;
1946 pbuf += n;
Tim Peters2a799bf2002-12-16 20:18:38 +00001947 }
1948
Tim Petersba873472002-12-18 20:19:21 +00001949 return PyString_FromStringAndSize(buf, pbuf - buf);
1950
1951 Fail:
1952 PyErr_SetString(PyExc_SystemError, "goofy result from PyOS_snprintf");
1953 return NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00001954}
1955
1956/* Pickle support. Quite a maze! While __getstate__/__setstate__ sufficed
1957 * in the Python implementation, the C implementation also requires
1958 * __reduce__, and a __safe_for_unpickling__ attr in the type object.
1959 */
1960static PyObject *
1961delta_getstate(PyDateTime_Delta *self)
1962{
1963 return Py_BuildValue("iii", GET_TD_DAYS(self),
1964 GET_TD_SECONDS(self),
1965 GET_TD_MICROSECONDS(self));
1966}
1967
1968static PyObject *
1969delta_setstate(PyDateTime_Delta *self, PyObject *state)
1970{
1971 int day;
1972 int second;
1973 int us;
1974
1975 if (!PyArg_ParseTuple(state, "iii:__setstate__", &day, &second, &us))
1976 return NULL;
1977
1978 self->hashcode = -1;
1979 SET_TD_DAYS(self, day);
1980 SET_TD_SECONDS(self, second);
1981 SET_TD_MICROSECONDS(self, us);
1982
1983 Py_INCREF(Py_None);
1984 return Py_None;
1985}
1986
1987static PyObject *
1988delta_reduce(PyDateTime_Delta* self)
1989{
1990 PyObject* result = NULL;
1991 PyObject* state = delta_getstate(self);
1992
1993 if (state != NULL) {
1994 /* The funky "()" in the format string creates an empty
1995 * tuple as the 2nd component of the result 3-tuple.
1996 */
1997 result = Py_BuildValue("O()O", self->ob_type, state);
1998 Py_DECREF(state);
1999 }
2000 return result;
2001}
2002
2003#define OFFSET(field) offsetof(PyDateTime_Delta, field)
2004
2005static PyMemberDef delta_members[] = {
Neal Norwitzdfb80862002-12-19 02:30:56 +00002006 {"days", T_INT, OFFSET(days), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002007 PyDoc_STR("Number of days.")},
2008
Neal Norwitzdfb80862002-12-19 02:30:56 +00002009 {"seconds", T_INT, OFFSET(seconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002010 PyDoc_STR("Number of seconds (>= 0 and less than 1 day).")},
2011
Neal Norwitzdfb80862002-12-19 02:30:56 +00002012 {"microseconds", T_INT, OFFSET(microseconds), READONLY,
Tim Peters2a799bf2002-12-16 20:18:38 +00002013 PyDoc_STR("Number of microseconds (>= 0 and less than 1 second).")},
2014 {NULL}
2015};
2016
2017static PyMethodDef delta_methods[] = {
2018 {"__setstate__", (PyCFunction)delta_setstate, METH_O,
2019 PyDoc_STR("__setstate__(state)")},
2020
2021 {"__reduce__", (PyCFunction)delta_reduce, METH_NOARGS,
2022 PyDoc_STR("__setstate__(state)")},
2023
2024 {"__getstate__", (PyCFunction)delta_getstate, METH_NOARGS,
2025 PyDoc_STR("__getstate__() -> state")},
2026 {NULL, NULL},
2027};
2028
2029static char delta_doc[] =
2030PyDoc_STR("Difference between two datetime values.");
2031
2032static PyNumberMethods delta_as_number = {
2033 delta_add, /* nb_add */
2034 delta_subtract, /* nb_subtract */
2035 delta_multiply, /* nb_multiply */
2036 delta_divide, /* nb_divide */
2037 0, /* nb_remainder */
2038 0, /* nb_divmod */
2039 0, /* nb_power */
2040 (unaryfunc)delta_negative, /* nb_negative */
2041 (unaryfunc)delta_positive, /* nb_positive */
2042 (unaryfunc)delta_abs, /* nb_absolute */
2043 (inquiry)delta_nonzero, /* nb_nonzero */
2044 0, /*nb_invert*/
2045 0, /*nb_lshift*/
2046 0, /*nb_rshift*/
2047 0, /*nb_and*/
2048 0, /*nb_xor*/
2049 0, /*nb_or*/
2050 0, /*nb_coerce*/
2051 0, /*nb_int*/
2052 0, /*nb_long*/
2053 0, /*nb_float*/
2054 0, /*nb_oct*/
2055 0, /*nb_hex*/
2056 0, /*nb_inplace_add*/
2057 0, /*nb_inplace_subtract*/
2058 0, /*nb_inplace_multiply*/
2059 0, /*nb_inplace_divide*/
2060 0, /*nb_inplace_remainder*/
2061 0, /*nb_inplace_power*/
2062 0, /*nb_inplace_lshift*/
2063 0, /*nb_inplace_rshift*/
2064 0, /*nb_inplace_and*/
2065 0, /*nb_inplace_xor*/
2066 0, /*nb_inplace_or*/
2067 delta_divide, /* nb_floor_divide */
2068 0, /* nb_true_divide */
2069 0, /* nb_inplace_floor_divide */
2070 0, /* nb_inplace_true_divide */
2071};
2072
2073static PyTypeObject PyDateTime_DeltaType = {
2074 PyObject_HEAD_INIT(NULL)
2075 0, /* ob_size */
2076 "datetime.timedelta", /* tp_name */
2077 sizeof(PyDateTime_Delta), /* tp_basicsize */
2078 0, /* tp_itemsize */
2079 0, /* tp_dealloc */
2080 0, /* tp_print */
2081 0, /* tp_getattr */
2082 0, /* tp_setattr */
2083 0, /* tp_compare */
2084 (reprfunc)delta_repr, /* tp_repr */
2085 &delta_as_number, /* tp_as_number */
2086 0, /* tp_as_sequence */
2087 0, /* tp_as_mapping */
2088 (hashfunc)delta_hash, /* tp_hash */
2089 0, /* tp_call */
2090 (reprfunc)delta_str, /* tp_str */
2091 PyObject_GenericGetAttr, /* tp_getattro */
2092 0, /* tp_setattro */
2093 0, /* tp_as_buffer */
2094 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES, /* tp_flags */
2095 delta_doc, /* tp_doc */
2096 0, /* tp_traverse */
2097 0, /* tp_clear */
2098 (richcmpfunc)delta_richcompare, /* tp_richcompare */
2099 0, /* tp_weaklistoffset */
2100 0, /* tp_iter */
2101 0, /* tp_iternext */
2102 delta_methods, /* tp_methods */
2103 delta_members, /* tp_members */
2104 0, /* tp_getset */
2105 0, /* tp_base */
2106 0, /* tp_dict */
2107 0, /* tp_descr_get */
2108 0, /* tp_descr_set */
2109 0, /* tp_dictoffset */
2110 0, /* tp_init */
2111 0, /* tp_alloc */
2112 delta_new, /* tp_new */
2113 _PyObject_Del, /* tp_free */
2114};
2115
2116/*
2117 * PyDateTime_Date implementation.
2118 */
2119
2120/* Accessor properties. */
2121
2122static PyObject *
2123date_year(PyDateTime_Date *self, void *unused)
2124{
2125 return PyInt_FromLong(GET_YEAR(self));
2126}
2127
2128static PyObject *
2129date_month(PyDateTime_Date *self, void *unused)
2130{
2131 return PyInt_FromLong(GET_MONTH(self));
2132}
2133
2134static PyObject *
2135date_day(PyDateTime_Date *self, void *unused)
2136{
2137 return PyInt_FromLong(GET_DAY(self));
2138}
2139
2140static PyGetSetDef date_getset[] = {
2141 {"year", (getter)date_year},
2142 {"month", (getter)date_month},
2143 {"day", (getter)date_day},
2144 {NULL}
2145};
2146
2147/* Constructors. */
2148
Tim Peters12bf3392002-12-24 05:41:27 +00002149static char *date_kws[] = {"year", "month", "day", NULL};
2150
Tim Peters2a799bf2002-12-16 20:18:38 +00002151static PyObject *
2152date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
2153{
2154 PyObject *self = NULL;
2155 int year;
2156 int month;
2157 int day;
2158
Tim Peters12bf3392002-12-24 05:41:27 +00002159 if (PyArg_ParseTupleAndKeywords(args, kw, "iii", date_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002160 &year, &month, &day)) {
2161 if (check_date_args(year, month, day) < 0)
2162 return NULL;
2163 self = new_date(year, month, day);
2164 }
2165 return self;
2166}
2167
2168/* Return new date from localtime(t). */
2169static PyObject *
2170date_local_from_time_t(PyObject *cls, time_t t)
2171{
2172 struct tm *tm;
2173 PyObject *result = NULL;
2174
2175 tm = localtime(&t);
2176 if (tm)
2177 result = PyObject_CallFunction(cls, "iii",
2178 tm->tm_year + 1900,
2179 tm->tm_mon + 1,
2180 tm->tm_mday);
2181 else
2182 PyErr_SetString(PyExc_ValueError,
2183 "timestamp out of range for "
2184 "platform localtime() function");
2185 return result;
2186}
2187
2188/* Return new date from current time.
2189 * We say this is equivalent to fromtimestamp(time.time()), and the
2190 * only way to be sure of that is to *call* time.time(). That's not
2191 * generally the same as calling C's time.
2192 */
2193static PyObject *
2194date_today(PyObject *cls, PyObject *dummy)
2195{
2196 PyObject *time;
2197 PyObject *result;
2198
2199 time = time_time();
2200 if (time == NULL)
2201 return NULL;
2202
2203 /* Note well: today() is a class method, so this may not call
2204 * date.fromtimestamp. For example, it may call
2205 * datetime.fromtimestamp. That's why we need all the accuracy
2206 * time.time() delivers; if someone were gonzo about optimization,
2207 * date.today() could get away with plain C time().
2208 */
2209 result = PyObject_CallMethod(cls, "fromtimestamp", "O", time);
2210 Py_DECREF(time);
2211 return result;
2212}
2213
2214/* Return new date from given timestamp (Python timestamp -- a double). */
2215static PyObject *
2216date_fromtimestamp(PyObject *cls, PyObject *args)
2217{
2218 double timestamp;
2219 PyObject *result = NULL;
2220
2221 if (PyArg_ParseTuple(args, "d:fromtimestamp", &timestamp))
2222 result = date_local_from_time_t(cls, (time_t)timestamp);
2223 return result;
2224}
2225
2226/* Return new date from proleptic Gregorian ordinal. Raises ValueError if
2227 * the ordinal is out of range.
2228 */
2229static PyObject *
2230date_fromordinal(PyObject *cls, PyObject *args)
2231{
2232 PyObject *result = NULL;
2233 int ordinal;
2234
2235 if (PyArg_ParseTuple(args, "i:fromordinal", &ordinal)) {
2236 int year;
2237 int month;
2238 int day;
2239
2240 if (ordinal < 1)
2241 PyErr_SetString(PyExc_ValueError, "ordinal must be "
2242 ">= 1");
2243 else {
2244 ord_to_ymd(ordinal, &year, &month, &day);
2245 result = PyObject_CallFunction(cls, "iii",
2246 year, month, day);
2247 }
2248 }
2249 return result;
2250}
2251
2252/*
2253 * Date arithmetic.
2254 */
2255
2256/* date + timedelta -> date. If arg negate is true, subtract the timedelta
2257 * instead.
2258 */
2259static PyObject *
2260add_date_timedelta(PyDateTime_Date *date, PyDateTime_Delta *delta, int negate)
2261{
2262 PyObject *result = NULL;
2263 int year = GET_YEAR(date);
2264 int month = GET_MONTH(date);
2265 int deltadays = GET_TD_DAYS(delta);
2266 /* C-level overflow is impossible because |deltadays| < 1e9. */
2267 int day = GET_DAY(date) + (negate ? -deltadays : deltadays);
2268
2269 if (normalize_date(&year, &month, &day) >= 0)
2270 result = new_date(year, month, day);
2271 return result;
2272}
2273
2274static PyObject *
2275date_add(PyObject *left, PyObject *right)
2276{
2277 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2278 Py_INCREF(Py_NotImplemented);
2279 return Py_NotImplemented;
2280 }
2281 if (PyDate_CheckExact(left)) {
2282 /* date + ??? */
2283 if (PyDelta_Check(right))
2284 /* date + delta */
2285 return add_date_timedelta((PyDateTime_Date *) left,
2286 (PyDateTime_Delta *) right,
2287 0);
2288 }
2289 else {
2290 /* ??? + date
2291 * 'right' must be one of us, or we wouldn't have been called
2292 */
2293 if (PyDelta_Check(left))
2294 /* delta + date */
2295 return add_date_timedelta((PyDateTime_Date *) right,
2296 (PyDateTime_Delta *) left,
2297 0);
2298 }
2299 Py_INCREF(Py_NotImplemented);
2300 return Py_NotImplemented;
2301}
2302
2303static PyObject *
2304date_subtract(PyObject *left, PyObject *right)
2305{
2306 if (PyDateTime_Check(left) || PyDateTime_Check(right)) {
2307 Py_INCREF(Py_NotImplemented);
2308 return Py_NotImplemented;
2309 }
2310 if (PyDate_CheckExact(left)) {
2311 if (PyDate_CheckExact(right)) {
2312 /* date - date */
2313 int left_ord = ymd_to_ord(GET_YEAR(left),
2314 GET_MONTH(left),
2315 GET_DAY(left));
2316 int right_ord = ymd_to_ord(GET_YEAR(right),
2317 GET_MONTH(right),
2318 GET_DAY(right));
2319 return new_delta(left_ord - right_ord, 0, 0, 0);
2320 }
2321 if (PyDelta_Check(right)) {
2322 /* date - delta */
2323 return add_date_timedelta((PyDateTime_Date *) left,
2324 (PyDateTime_Delta *) right,
2325 1);
2326 }
2327 }
2328 Py_INCREF(Py_NotImplemented);
2329 return Py_NotImplemented;
2330}
2331
2332
2333/* Various ways to turn a date into a string. */
2334
2335static PyObject *
2336date_repr(PyDateTime_Date *self)
2337{
2338 char buffer[1028];
2339 char *typename;
2340
2341 typename = self->ob_type->tp_name;
2342 PyOS_snprintf(buffer, sizeof(buffer), "%s(%d, %d, %d)",
2343 typename,
2344 GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2345
2346 return PyString_FromString(buffer);
2347}
2348
2349static PyObject *
2350date_isoformat(PyDateTime_Date *self)
2351{
2352 char buffer[128];
2353
2354 isoformat_date(self, buffer, sizeof(buffer));
2355 return PyString_FromString(buffer);
2356}
2357
2358/* str() calls the appropriate isofomat() method. */
2359static PyObject *
2360date_str(PyDateTime_Date *self)
2361{
2362 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
2363}
2364
2365
2366static PyObject *
2367date_ctime(PyDateTime_Date *self)
2368{
2369 return format_ctime(self, 0, 0, 0);
2370}
2371
2372static PyObject *
2373date_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2374{
2375 /* This method can be inherited, and needs to call the
2376 * timetuple() method appropriate to self's class.
2377 */
2378 PyObject *result;
2379 PyObject *format;
2380 PyObject *tuple;
2381 static char *keywords[] = {"format", NULL};
2382
2383 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
2384 &PyString_Type, &format))
2385 return NULL;
2386
2387 tuple = PyObject_CallMethod((PyObject *)self, "timetuple", "()");
2388 if (tuple == NULL)
2389 return NULL;
Tim Petersbad8ff02002-12-30 20:52:32 +00002390 result = wrap_strftime((PyObject *)self, format, tuple,
2391 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00002392 Py_DECREF(tuple);
2393 return result;
2394}
2395
2396/* ISO methods. */
2397
2398static PyObject *
2399date_isoweekday(PyDateTime_Date *self)
2400{
2401 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2402
2403 return PyInt_FromLong(dow + 1);
2404}
2405
2406static PyObject *
2407date_isocalendar(PyDateTime_Date *self)
2408{
2409 int year = GET_YEAR(self);
2410 int week1_monday = iso_week1_monday(year);
2411 int today = ymd_to_ord(year, GET_MONTH(self), GET_DAY(self));
2412 int week;
2413 int day;
2414
2415 week = divmod(today - week1_monday, 7, &day);
2416 if (week < 0) {
2417 --year;
2418 week1_monday = iso_week1_monday(year);
2419 week = divmod(today - week1_monday, 7, &day);
2420 }
2421 else if (week >= 52 && today >= iso_week1_monday(year + 1)) {
2422 ++year;
2423 week = 0;
2424 }
2425 return Py_BuildValue("iii", year, week + 1, day + 1);
2426}
2427
2428/* Miscellaneous methods. */
2429
2430/* This is more natural as a tp_compare, but doesn't work then: for whatever
2431 * reason, Python's try_3way_compare ignores tp_compare unless
2432 * PyInstance_Check returns true, but these aren't old-style classes.
2433 */
2434static PyObject *
2435date_richcompare(PyDateTime_Date *self, PyObject *other, int op)
2436{
2437 int diff;
2438
2439 if (! PyDate_Check(other)) {
2440 PyErr_Format(PyExc_TypeError,
2441 "can't compare date to %s instance",
2442 other->ob_type->tp_name);
2443 return NULL;
2444 }
2445 diff = memcmp(self->data, ((PyDateTime_Date *)other)->data,
2446 _PyDateTime_DATE_DATASIZE);
2447 return diff_to_bool(diff, op);
2448}
2449
2450static PyObject *
2451date_timetuple(PyDateTime_Date *self)
2452{
2453 return build_struct_time(GET_YEAR(self),
2454 GET_MONTH(self),
2455 GET_DAY(self),
2456 0, 0, 0, -1);
2457}
2458
Tim Peters12bf3392002-12-24 05:41:27 +00002459static PyObject *
2460date_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw)
2461{
2462 PyObject *clone;
2463 PyObject *tuple;
2464 int year = GET_YEAR(self);
2465 int month = GET_MONTH(self);
2466 int day = GET_DAY(self);
2467
2468 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iii:replace", date_kws,
2469 &year, &month, &day))
2470 return NULL;
2471 tuple = Py_BuildValue("iii", year, month, day);
2472 if (tuple == NULL)
2473 return NULL;
2474 clone = date_new(self->ob_type, tuple, NULL);
2475 Py_DECREF(tuple);
2476 return clone;
2477}
2478
Tim Peters2a799bf2002-12-16 20:18:38 +00002479static PyObject *date_getstate(PyDateTime_Date *self);
2480
2481static long
2482date_hash(PyDateTime_Date *self)
2483{
2484 if (self->hashcode == -1) {
2485 PyObject *temp = date_getstate(self);
2486 if (temp != NULL) {
2487 self->hashcode = PyObject_Hash(temp);
2488 Py_DECREF(temp);
2489 }
2490 }
2491 return self->hashcode;
2492}
2493
2494static PyObject *
2495date_toordinal(PyDateTime_Date *self)
2496{
2497 return PyInt_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self),
2498 GET_DAY(self)));
2499}
2500
2501static PyObject *
2502date_weekday(PyDateTime_Date *self)
2503{
2504 int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self));
2505
2506 return PyInt_FromLong(dow);
2507}
2508
2509/* Pickle support. Quite a maze! */
2510
2511static PyObject *
2512date_getstate(PyDateTime_Date *self)
2513{
Jack Jansenb8941f22003-01-08 16:28:45 +00002514 return PyString_FromStringAndSize((char *)self->data,
Tim Peters2a799bf2002-12-16 20:18:38 +00002515 _PyDateTime_DATE_DATASIZE);
2516}
2517
2518static PyObject *
2519date_setstate(PyDateTime_Date *self, PyObject *state)
2520{
2521 const int len = PyString_Size(state);
2522 unsigned char *pdata = (unsigned char*)PyString_AsString(state);
2523
2524 if (! PyString_Check(state) ||
2525 len != _PyDateTime_DATE_DATASIZE) {
2526 PyErr_SetString(PyExc_TypeError,
2527 "bad argument to date.__setstate__");
2528 return NULL;
2529 }
2530 memcpy(self->data, pdata, _PyDateTime_DATE_DATASIZE);
2531 self->hashcode = -1;
2532
2533 Py_INCREF(Py_None);
2534 return Py_None;
2535}
2536
2537/* XXX This seems a ridiculously inefficient way to pickle a short string. */
2538static PyObject *
2539date_pickler(PyObject *module, PyDateTime_Date *date)
2540{
2541 PyObject *state;
2542 PyObject *result = NULL;
2543
2544 if (! PyDate_CheckExact(date)) {
2545 PyErr_Format(PyExc_TypeError,
2546 "bad type passed to date pickler: %s",
2547 date->ob_type->tp_name);
2548 return NULL;
2549 }
2550 state = date_getstate(date);
2551 if (state) {
2552 result = Py_BuildValue("O(O)", date_unpickler_object, state);
2553 Py_DECREF(state);
2554 }
2555 return result;
2556}
2557
2558static PyObject *
2559date_unpickler(PyObject *module, PyObject *arg)
2560{
2561 PyDateTime_Date *self;
2562
2563 if (! PyString_CheckExact(arg)) {
2564 PyErr_Format(PyExc_TypeError,
2565 "bad type passed to date unpickler: %s",
2566 arg->ob_type->tp_name);
2567 return NULL;
2568 }
2569 self = PyObject_New(PyDateTime_Date, &PyDateTime_DateType);
2570 if (self != NULL) {
2571 PyObject *res = date_setstate(self, arg);
2572 if (res == NULL) {
2573 Py_DECREF(self);
2574 return NULL;
2575 }
2576 Py_DECREF(res);
2577 }
2578 return (PyObject *)self;
2579}
2580
2581static PyMethodDef date_methods[] = {
2582 /* Class methods: */
2583 {"fromtimestamp", (PyCFunction)date_fromtimestamp, METH_VARARGS |
2584 METH_CLASS,
2585 PyDoc_STR("timestamp -> local date from a POSIX timestamp (like "
2586 "time.time()).")},
2587
2588 {"fromordinal", (PyCFunction)date_fromordinal, METH_VARARGS |
2589 METH_CLASS,
2590 PyDoc_STR("int -> date corresponding to a proleptic Gregorian "
2591 "ordinal.")},
2592
2593 {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS,
2594 PyDoc_STR("Current date or datetime: same as "
2595 "self.__class__.fromtimestamp(time.time()).")},
2596
2597 /* Instance methods: */
2598
2599 {"ctime", (PyCFunction)date_ctime, METH_NOARGS,
2600 PyDoc_STR("Return ctime() style string.")},
2601
2602 {"strftime", (PyCFunction)date_strftime, METH_KEYWORDS,
2603 PyDoc_STR("format -> strftime() style string.")},
2604
2605 {"timetuple", (PyCFunction)date_timetuple, METH_NOARGS,
2606 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
2607
2608 {"isocalendar", (PyCFunction)date_isocalendar, METH_NOARGS,
2609 PyDoc_STR("Return a 3-tuple containing ISO year, week number, and "
2610 "weekday.")},
2611
2612 {"isoformat", (PyCFunction)date_isoformat, METH_NOARGS,
2613 PyDoc_STR("Return string in ISO 8601 format, YYYY-MM-DD.")},
2614
2615 {"isoweekday", (PyCFunction)date_isoweekday, METH_NOARGS,
2616 PyDoc_STR("Return the day of the week represented by the date.\n"
2617 "Monday == 1 ... Sunday == 7")},
2618
2619 {"toordinal", (PyCFunction)date_toordinal, METH_NOARGS,
2620 PyDoc_STR("Return proleptic Gregorian ordinal. January 1 of year "
2621 "1 is day 1.")},
2622
2623 {"weekday", (PyCFunction)date_weekday, METH_NOARGS,
2624 PyDoc_STR("Return the day of the week represented by the date.\n"
2625 "Monday == 0 ... Sunday == 6")},
2626
Tim Peters12bf3392002-12-24 05:41:27 +00002627 {"replace", (PyCFunction)date_replace, METH_KEYWORDS,
2628 PyDoc_STR("Return date with new specified fields.")},
2629
Tim Peters2a799bf2002-12-16 20:18:38 +00002630 {"__setstate__", (PyCFunction)date_setstate, METH_O,
2631 PyDoc_STR("__setstate__(state)")},
2632
2633 {"__getstate__", (PyCFunction)date_getstate, METH_NOARGS,
2634 PyDoc_STR("__getstate__() -> state")},
2635
2636 {NULL, NULL}
2637};
2638
2639static char date_doc[] =
2640PyDoc_STR("Basic date type.");
2641
2642static PyNumberMethods date_as_number = {
2643 date_add, /* nb_add */
2644 date_subtract, /* nb_subtract */
2645 0, /* nb_multiply */
2646 0, /* nb_divide */
2647 0, /* nb_remainder */
2648 0, /* nb_divmod */
2649 0, /* nb_power */
2650 0, /* nb_negative */
2651 0, /* nb_positive */
2652 0, /* nb_absolute */
2653 0, /* nb_nonzero */
2654};
2655
2656static PyTypeObject PyDateTime_DateType = {
2657 PyObject_HEAD_INIT(NULL)
2658 0, /* ob_size */
2659 "datetime.date", /* tp_name */
2660 sizeof(PyDateTime_Date), /* tp_basicsize */
2661 0, /* tp_itemsize */
2662 (destructor)PyObject_Del, /* tp_dealloc */
2663 0, /* tp_print */
2664 0, /* tp_getattr */
2665 0, /* tp_setattr */
2666 0, /* tp_compare */
2667 (reprfunc)date_repr, /* tp_repr */
2668 &date_as_number, /* tp_as_number */
2669 0, /* tp_as_sequence */
2670 0, /* tp_as_mapping */
2671 (hashfunc)date_hash, /* tp_hash */
2672 0, /* tp_call */
2673 (reprfunc)date_str, /* tp_str */
2674 PyObject_GenericGetAttr, /* tp_getattro */
2675 0, /* tp_setattro */
2676 0, /* tp_as_buffer */
2677 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
2678 Py_TPFLAGS_BASETYPE, /* tp_flags */
2679 date_doc, /* tp_doc */
2680 0, /* tp_traverse */
2681 0, /* tp_clear */
2682 (richcmpfunc)date_richcompare, /* tp_richcompare */
2683 0, /* tp_weaklistoffset */
2684 0, /* tp_iter */
2685 0, /* tp_iternext */
2686 date_methods, /* tp_methods */
2687 0, /* tp_members */
2688 date_getset, /* tp_getset */
2689 0, /* tp_base */
2690 0, /* tp_dict */
2691 0, /* tp_descr_get */
2692 0, /* tp_descr_set */
2693 0, /* tp_dictoffset */
2694 0, /* tp_init */
2695 0, /* tp_alloc */
2696 date_new, /* tp_new */
2697 _PyObject_Del, /* tp_free */
2698};
2699
2700/*
Tim Peters2a799bf2002-12-16 20:18:38 +00002701 * PyDateTime_TZInfo implementation.
2702 */
2703
2704/* This is a pure abstract base class, so doesn't do anything beyond
2705 * raising NotImplemented exceptions. Real tzinfo classes need
2706 * to derive from this. This is mostly for clarity, and for efficiency in
Tim Petersa9bc1682003-01-11 03:39:11 +00002707 * datetime and time constructors (their tzinfo arguments need to
Tim Peters2a799bf2002-12-16 20:18:38 +00002708 * be subclasses of this tzinfo class, which is easy and quick to check).
2709 *
2710 * Note: For reasons having to do with pickling of subclasses, we have
2711 * to allow tzinfo objects to be instantiated. This wasn't an issue
2712 * in the Python implementation (__init__() could raise NotImplementedError
2713 * there without ill effect), but doing so in the C implementation hit a
2714 * brick wall.
2715 */
2716
2717static PyObject *
2718tzinfo_nogo(const char* methodname)
2719{
2720 PyErr_Format(PyExc_NotImplementedError,
2721 "a tzinfo subclass must implement %s()",
2722 methodname);
2723 return NULL;
2724}
2725
2726/* Methods. A subclass must implement these. */
2727
Tim Peters52dcce22003-01-23 16:36:11 +00002728static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00002729tzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt)
2730{
2731 return tzinfo_nogo("tzname");
2732}
2733
Tim Peters52dcce22003-01-23 16:36:11 +00002734static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00002735tzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt)
2736{
2737 return tzinfo_nogo("utcoffset");
2738}
2739
Tim Peters52dcce22003-01-23 16:36:11 +00002740static PyObject *
Tim Peters2a799bf2002-12-16 20:18:38 +00002741tzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt)
2742{
2743 return tzinfo_nogo("dst");
2744}
2745
Tim Peters52dcce22003-01-23 16:36:11 +00002746static PyObject *
2747tzinfo_fromutc(PyDateTime_TZInfo *self, PyDateTime_DateTime *dt)
2748{
2749 int y, m, d, hh, mm, ss, us;
2750
2751 PyObject *result;
2752 int off, dst;
2753 int none;
2754 int delta;
2755
2756 if (! PyDateTime_Check(dt)) {
2757 PyErr_SetString(PyExc_TypeError,
2758 "fromutc: argument must be a datetime");
2759 return NULL;
2760 }
2761 if (! HASTZINFO(dt) || dt->tzinfo != (PyObject *)self) {
2762 PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo "
2763 "is not self");
2764 return NULL;
2765 }
2766
2767 off = call_utcoffset(dt->tzinfo, (PyObject *)dt, &none);
2768 if (off == -1 && PyErr_Occurred())
2769 return NULL;
2770 if (none) {
2771 PyErr_SetString(PyExc_ValueError, "fromutc: non-None "
2772 "utcoffset() result required");
2773 return NULL;
2774 }
2775
2776 dst = call_dst(dt->tzinfo, (PyObject *)dt, &none);
2777 if (dst == -1 && PyErr_Occurred())
2778 return NULL;
2779 if (none) {
2780 PyErr_SetString(PyExc_ValueError, "fromutc: non-None "
2781 "dst() result required");
2782 return NULL;
2783 }
2784
2785 y = GET_YEAR(dt);
2786 m = GET_MONTH(dt);
2787 d = GET_DAY(dt);
2788 hh = DATE_GET_HOUR(dt);
2789 mm = DATE_GET_MINUTE(dt);
2790 ss = DATE_GET_SECOND(dt);
2791 us = DATE_GET_MICROSECOND(dt);
2792
2793 delta = off - dst;
2794 mm += delta;
2795 if ((mm < 0 || mm >= 60) &&
2796 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Petersb1049e82003-01-23 17:20:36 +00002797 return NULL;
Tim Peters52dcce22003-01-23 16:36:11 +00002798 result = new_datetime(y, m, d, hh, mm, ss, us, dt->tzinfo);
2799 if (result == NULL)
2800 return result;
2801
2802 dst = call_dst(dt->tzinfo, result, &none);
2803 if (dst == -1 && PyErr_Occurred())
2804 goto Fail;
2805 if (none)
2806 goto Inconsistent;
2807 if (dst == 0)
2808 return result;
2809
2810 mm += dst;
2811 if ((mm < 0 || mm >= 60) &&
2812 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
2813 goto Fail;
2814 Py_DECREF(result);
2815 result = new_datetime(y, m, d, hh, mm, ss, us, dt->tzinfo);
2816 return result;
2817
2818Inconsistent:
2819 PyErr_SetString(PyExc_ValueError, "fromutc: tz.dst() gave"
2820 "inconsistent results; cannot convert");
2821
2822 /* fall thru to failure */
2823Fail:
2824 Py_DECREF(result);
2825 return NULL;
2826}
2827
Tim Peters2a799bf2002-12-16 20:18:38 +00002828/*
2829 * Pickle support. This is solely so that tzinfo subclasses can use
2830 * pickling -- tzinfo itself is supposed to be uninstantiable. The
2831 * pickler and unpickler functions are given module-level private
2832 * names, and registered with copy_reg, by the module init function.
2833 */
2834
2835static PyObject*
2836tzinfo_pickler(PyDateTime_TZInfo *self) {
2837 return Py_BuildValue("O()", tzinfo_unpickler_object);
2838}
2839
2840static PyObject*
2841tzinfo_unpickler(PyObject * unused) {
2842 return PyType_GenericNew(&PyDateTime_TZInfoType, NULL, NULL);
2843}
2844
2845
2846static PyMethodDef tzinfo_methods[] = {
2847 {"tzname", (PyCFunction)tzinfo_tzname, METH_O,
2848 PyDoc_STR("datetime -> string name of time zone.")},
2849
2850 {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O,
2851 PyDoc_STR("datetime -> minutes east of UTC (negative for "
2852 "west of UTC).")},
2853
2854 {"dst", (PyCFunction)tzinfo_dst, METH_O,
2855 PyDoc_STR("datetime -> DST offset in minutes east of UTC.")},
2856
Tim Peters52dcce22003-01-23 16:36:11 +00002857 {"fromutc", (PyCFunction)tzinfo_fromutc, METH_O,
2858 PyDoc_STR("datetime in UTC -> datetime in local time.")},
2859
Tim Peters2a799bf2002-12-16 20:18:38 +00002860 {NULL, NULL}
2861};
2862
2863static char tzinfo_doc[] =
2864PyDoc_STR("Abstract base class for time zone info objects.");
2865
2866 statichere PyTypeObject PyDateTime_TZInfoType = {
2867 PyObject_HEAD_INIT(NULL)
2868 0, /* ob_size */
2869 "datetime.tzinfo", /* tp_name */
2870 sizeof(PyDateTime_TZInfo), /* tp_basicsize */
2871 0, /* tp_itemsize */
2872 0, /* tp_dealloc */
2873 0, /* tp_print */
2874 0, /* tp_getattr */
2875 0, /* tp_setattr */
2876 0, /* tp_compare */
2877 0, /* tp_repr */
2878 0, /* tp_as_number */
2879 0, /* tp_as_sequence */
2880 0, /* tp_as_mapping */
2881 0, /* tp_hash */
2882 0, /* tp_call */
2883 0, /* tp_str */
2884 PyObject_GenericGetAttr, /* tp_getattro */
2885 0, /* tp_setattro */
2886 0, /* tp_as_buffer */
2887 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
2888 Py_TPFLAGS_BASETYPE, /* tp_flags */
2889 tzinfo_doc, /* tp_doc */
2890 0, /* tp_traverse */
2891 0, /* tp_clear */
2892 0, /* tp_richcompare */
2893 0, /* tp_weaklistoffset */
2894 0, /* tp_iter */
2895 0, /* tp_iternext */
2896 tzinfo_methods, /* tp_methods */
2897 0, /* tp_members */
2898 0, /* tp_getset */
2899 0, /* tp_base */
2900 0, /* tp_dict */
2901 0, /* tp_descr_get */
2902 0, /* tp_descr_set */
2903 0, /* tp_dictoffset */
2904 0, /* tp_init */
2905 0, /* tp_alloc */
2906 PyType_GenericNew, /* tp_new */
2907 0, /* tp_free */
2908};
2909
2910/*
Tim Peters37f39822003-01-10 03:49:02 +00002911 * PyDateTime_Time implementation.
Tim Peters2a799bf2002-12-16 20:18:38 +00002912 */
2913
Tim Peters37f39822003-01-10 03:49:02 +00002914/* Accessor properties.
Tim Peters2a799bf2002-12-16 20:18:38 +00002915 */
2916
2917static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00002918time_hour(PyDateTime_Time *self, void *unused)
Tim Peters2a799bf2002-12-16 20:18:38 +00002919{
Tim Peters37f39822003-01-10 03:49:02 +00002920 return PyInt_FromLong(TIME_GET_HOUR(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00002921}
2922
Tim Peters37f39822003-01-10 03:49:02 +00002923static PyObject *
2924time_minute(PyDateTime_Time *self, void *unused)
2925{
2926 return PyInt_FromLong(TIME_GET_MINUTE(self));
2927}
2928
2929/* The name time_second conflicted with some platform header file. */
2930static PyObject *
2931py_time_second(PyDateTime_Time *self, void *unused)
2932{
2933 return PyInt_FromLong(TIME_GET_SECOND(self));
2934}
2935
2936static PyObject *
2937time_microsecond(PyDateTime_Time *self, void *unused)
2938{
2939 return PyInt_FromLong(TIME_GET_MICROSECOND(self));
2940}
2941
2942static PyObject *
2943time_tzinfo(PyDateTime_Time *self, void *unused)
2944{
Tim Petersa032d2e2003-01-11 00:15:54 +00002945 PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
Tim Peters37f39822003-01-10 03:49:02 +00002946 Py_INCREF(result);
2947 return result;
2948}
2949
2950static PyGetSetDef time_getset[] = {
2951 {"hour", (getter)time_hour},
2952 {"minute", (getter)time_minute},
2953 {"second", (getter)py_time_second},
2954 {"microsecond", (getter)time_microsecond},
2955 {"tzinfo", (getter)time_tzinfo},
Tim Peters2a799bf2002-12-16 20:18:38 +00002956 {NULL}
2957};
2958
2959/*
2960 * Constructors.
2961 */
2962
Tim Peters37f39822003-01-10 03:49:02 +00002963static char *time_kws[] = {"hour", "minute", "second", "microsecond",
2964 "tzinfo", NULL};
Tim Peters12bf3392002-12-24 05:41:27 +00002965
Tim Peters2a799bf2002-12-16 20:18:38 +00002966static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00002967time_new(PyTypeObject *type, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00002968{
2969 PyObject *self = NULL;
2970 int hour = 0;
2971 int minute = 0;
2972 int second = 0;
2973 int usecond = 0;
2974 PyObject *tzinfo = Py_None;
2975
Tim Peters37f39822003-01-10 03:49:02 +00002976 if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO", time_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00002977 &hour, &minute, &second, &usecond,
2978 &tzinfo)) {
2979 if (check_time_args(hour, minute, second, usecond) < 0)
2980 return NULL;
2981 if (check_tzinfo_subclass(tzinfo) < 0)
2982 return NULL;
Tim Peters37f39822003-01-10 03:49:02 +00002983 self = new_time(hour, minute, second, usecond, tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00002984 }
2985 return self;
2986}
2987
2988/*
2989 * Destructor.
2990 */
2991
2992static void
Tim Peters37f39822003-01-10 03:49:02 +00002993time_dealloc(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00002994{
Tim Petersa032d2e2003-01-11 00:15:54 +00002995 if (HASTZINFO(self)) {
Tim Peters37f39822003-01-10 03:49:02 +00002996 Py_XDECREF(self->tzinfo);
Neal Norwitz8e914d92003-01-10 15:29:16 +00002997 }
Tim Peters2a799bf2002-12-16 20:18:38 +00002998 self->ob_type->tp_free((PyObject *)self);
2999}
3000
3001/*
Tim Peters855fe882002-12-22 03:43:39 +00003002 * Indirect access to tzinfo methods.
Tim Peters2a799bf2002-12-16 20:18:38 +00003003 */
3004
Tim Peters2a799bf2002-12-16 20:18:38 +00003005/* These are all METH_NOARGS, so don't need to check the arglist. */
3006static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003007time_utcoffset(PyDateTime_Time *self, PyObject *unused) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003008 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
Tim Peters37f39822003-01-10 03:49:02 +00003009 "utcoffset", Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003010}
3011
3012static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003013time_dst(PyDateTime_Time *self, PyObject *unused) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003014 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
Tim Peters37f39822003-01-10 03:49:02 +00003015 "dst", Py_None);
Tim Peters855fe882002-12-22 03:43:39 +00003016}
3017
3018static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003019time_tzname(PyDateTime_Time *self, PyObject *unused) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003020 return call_tzname(HASTZINFO(self) ? self->tzinfo : Py_None,
Tim Peters37f39822003-01-10 03:49:02 +00003021 Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003022}
3023
3024/*
Tim Peters37f39822003-01-10 03:49:02 +00003025 * Various ways to turn a time into a string.
Tim Peters2a799bf2002-12-16 20:18:38 +00003026 */
3027
3028static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003029time_repr(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003030{
Tim Peters37f39822003-01-10 03:49:02 +00003031 char buffer[100];
3032 char *typename = self->ob_type->tp_name;
3033 int h = TIME_GET_HOUR(self);
3034 int m = TIME_GET_MINUTE(self);
3035 int s = TIME_GET_SECOND(self);
3036 int us = TIME_GET_MICROSECOND(self);
3037 PyObject *result = NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00003038
Tim Peters37f39822003-01-10 03:49:02 +00003039 if (us)
3040 PyOS_snprintf(buffer, sizeof(buffer),
3041 "%s(%d, %d, %d, %d)", typename, h, m, s, us);
3042 else if (s)
3043 PyOS_snprintf(buffer, sizeof(buffer),
3044 "%s(%d, %d, %d)", typename, h, m, s);
3045 else
3046 PyOS_snprintf(buffer, sizeof(buffer),
3047 "%s(%d, %d)", typename, h, m);
3048 result = PyString_FromString(buffer);
Tim Petersa032d2e2003-01-11 00:15:54 +00003049 if (result != NULL && HASTZINFO(self))
Tim Peters37f39822003-01-10 03:49:02 +00003050 result = append_keyword_tzinfo(result, self->tzinfo);
3051 return result;
Tim Peters2a799bf2002-12-16 20:18:38 +00003052}
3053
Tim Peters37f39822003-01-10 03:49:02 +00003054static PyObject *
3055time_str(PyDateTime_Time *self)
3056{
3057 return PyObject_CallMethod((PyObject *)self, "isoformat", "()");
3058}
Tim Peters2a799bf2002-12-16 20:18:38 +00003059
3060static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003061time_isoformat(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003062{
3063 char buf[100];
Tim Peters37f39822003-01-10 03:49:02 +00003064 PyObject *result;
3065 /* Reuse the time format code from the datetime type. */
3066 PyDateTime_DateTime datetime;
3067 PyDateTime_DateTime *pdatetime = &datetime;
Tim Peters2a799bf2002-12-16 20:18:38 +00003068
Tim Peters37f39822003-01-10 03:49:02 +00003069 /* Copy over just the time bytes. */
3070 memcpy(pdatetime->data + _PyDateTime_DATE_DATASIZE,
3071 self->data,
3072 _PyDateTime_TIME_DATASIZE);
3073
3074 isoformat_time(pdatetime, buf, sizeof(buf));
3075 result = PyString_FromString(buf);
Tim Petersa032d2e2003-01-11 00:15:54 +00003076 if (result == NULL || ! HASTZINFO(self) || self->tzinfo == Py_None)
Tim Peters2a799bf2002-12-16 20:18:38 +00003077 return result;
3078
3079 /* We need to append the UTC offset. */
3080 if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo,
Tim Petersbad8ff02002-12-30 20:52:32 +00003081 Py_None) < 0) {
Tim Peters2a799bf2002-12-16 20:18:38 +00003082 Py_DECREF(result);
3083 return NULL;
3084 }
3085 PyString_ConcatAndDel(&result, PyString_FromString(buf));
3086 return result;
3087}
3088
Tim Peters37f39822003-01-10 03:49:02 +00003089static PyObject *
3090time_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw)
3091{
3092 PyObject *result;
3093 PyObject *format;
3094 PyObject *tuple;
3095 static char *keywords[] = {"format", NULL};
3096
3097 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:strftime", keywords,
3098 &PyString_Type, &format))
3099 return NULL;
3100
3101 /* Python's strftime does insane things with the year part of the
3102 * timetuple. The year is forced to (the otherwise nonsensical)
3103 * 1900 to worm around that.
3104 */
3105 tuple = Py_BuildValue("iiiiiiiii",
3106 1900, 0, 0, /* year, month, day */
3107 TIME_GET_HOUR(self),
3108 TIME_GET_MINUTE(self),
3109 TIME_GET_SECOND(self),
3110 0, 0, -1); /* weekday, daynum, dst */
3111 if (tuple == NULL)
3112 return NULL;
3113 assert(PyTuple_Size(tuple) == 9);
3114 result = wrap_strftime((PyObject *)self, format, tuple, Py_None);
3115 Py_DECREF(tuple);
3116 return result;
3117}
Tim Peters2a799bf2002-12-16 20:18:38 +00003118
3119/*
3120 * Miscellaneous methods.
3121 */
3122
Tim Peters37f39822003-01-10 03:49:02 +00003123/* This is more natural as a tp_compare, but doesn't work then: for whatever
3124 * reason, Python's try_3way_compare ignores tp_compare unless
3125 * PyInstance_Check returns true, but these aren't old-style classes.
3126 */
3127static PyObject *
3128time_richcompare(PyDateTime_Time *self, PyObject *other, int op)
3129{
3130 int diff;
3131 naivety n1, n2;
3132 int offset1, offset2;
3133
3134 if (! PyTime_Check(other)) {
3135 /* Stop this from falling back to address comparison. */
3136 PyErr_Format(PyExc_TypeError,
3137 "can't compare '%s' to '%s'",
3138 self->ob_type->tp_name,
3139 other->ob_type->tp_name);
3140 return NULL;
3141 }
3142 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1, Py_None,
3143 other, &offset2, &n2, Py_None) < 0)
3144 return NULL;
3145 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
3146 /* If they're both naive, or both aware and have the same offsets,
3147 * we get off cheap. Note that if they're both naive, offset1 ==
3148 * offset2 == 0 at this point.
3149 */
3150 if (n1 == n2 && offset1 == offset2) {
3151 diff = memcmp(self->data, ((PyDateTime_Time *)other)->data,
3152 _PyDateTime_TIME_DATASIZE);
3153 return diff_to_bool(diff, op);
3154 }
3155
3156 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
3157 assert(offset1 != offset2); /* else last "if" handled it */
3158 /* Convert everything except microseconds to seconds. These
3159 * can't overflow (no more than the # of seconds in 2 days).
3160 */
3161 offset1 = TIME_GET_HOUR(self) * 3600 +
3162 (TIME_GET_MINUTE(self) - offset1) * 60 +
3163 TIME_GET_SECOND(self);
3164 offset2 = TIME_GET_HOUR(other) * 3600 +
3165 (TIME_GET_MINUTE(other) - offset2) * 60 +
3166 TIME_GET_SECOND(other);
3167 diff = offset1 - offset2;
3168 if (diff == 0)
3169 diff = TIME_GET_MICROSECOND(self) -
3170 TIME_GET_MICROSECOND(other);
3171 return diff_to_bool(diff, op);
3172 }
3173
3174 assert(n1 != n2);
3175 PyErr_SetString(PyExc_TypeError,
3176 "can't compare offset-naive and "
3177 "offset-aware times");
3178 return NULL;
3179}
3180
3181static long
3182time_hash(PyDateTime_Time *self)
3183{
3184 if (self->hashcode == -1) {
3185 naivety n;
3186 int offset;
3187 PyObject *temp;
3188
3189 n = classify_utcoffset((PyObject *)self, Py_None, &offset);
3190 assert(n != OFFSET_UNKNOWN);
3191 if (n == OFFSET_ERROR)
3192 return -1;
3193
3194 /* Reduce this to a hash of another object. */
3195 if (offset == 0)
3196 temp = PyString_FromStringAndSize((char *)self->data,
3197 _PyDateTime_TIME_DATASIZE);
3198 else {
3199 int hour;
3200 int minute;
3201
3202 assert(n == OFFSET_AWARE);
Tim Petersa032d2e2003-01-11 00:15:54 +00003203 assert(HASTZINFO(self));
Tim Peters37f39822003-01-10 03:49:02 +00003204 hour = divmod(TIME_GET_HOUR(self) * 60 +
3205 TIME_GET_MINUTE(self) - offset,
3206 60,
3207 &minute);
3208 if (0 <= hour && hour < 24)
3209 temp = new_time(hour, minute,
3210 TIME_GET_SECOND(self),
3211 TIME_GET_MICROSECOND(self),
3212 Py_None);
3213 else
3214 temp = Py_BuildValue("iiii",
3215 hour, minute,
3216 TIME_GET_SECOND(self),
3217 TIME_GET_MICROSECOND(self));
3218 }
3219 if (temp != NULL) {
3220 self->hashcode = PyObject_Hash(temp);
3221 Py_DECREF(temp);
3222 }
3223 }
3224 return self->hashcode;
3225}
Tim Peters2a799bf2002-12-16 20:18:38 +00003226
Tim Peters12bf3392002-12-24 05:41:27 +00003227static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003228time_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw)
Tim Peters12bf3392002-12-24 05:41:27 +00003229{
3230 PyObject *clone;
3231 PyObject *tuple;
3232 int hh = TIME_GET_HOUR(self);
3233 int mm = TIME_GET_MINUTE(self);
3234 int ss = TIME_GET_SECOND(self);
3235 int us = TIME_GET_MICROSECOND(self);
Tim Petersa032d2e2003-01-11 00:15:54 +00003236 PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
Tim Peters12bf3392002-12-24 05:41:27 +00003237
3238 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
Tim Peters37f39822003-01-10 03:49:02 +00003239 time_kws,
Tim Peters12bf3392002-12-24 05:41:27 +00003240 &hh, &mm, &ss, &us, &tzinfo))
3241 return NULL;
3242 tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
3243 if (tuple == NULL)
3244 return NULL;
Tim Peters37f39822003-01-10 03:49:02 +00003245 clone = time_new(self->ob_type, tuple, NULL);
Tim Peters12bf3392002-12-24 05:41:27 +00003246 Py_DECREF(tuple);
3247 return clone;
3248}
3249
Tim Peters2a799bf2002-12-16 20:18:38 +00003250static int
Tim Peters37f39822003-01-10 03:49:02 +00003251time_nonzero(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003252{
3253 int offset;
3254 int none;
3255
3256 if (TIME_GET_SECOND(self) || TIME_GET_MICROSECOND(self)) {
3257 /* Since utcoffset is in whole minutes, nothing can
3258 * alter the conclusion that this is nonzero.
3259 */
3260 return 1;
3261 }
3262 offset = 0;
Tim Petersa032d2e2003-01-11 00:15:54 +00003263 if (HASTZINFO(self) && self->tzinfo != Py_None) {
Tim Petersbad8ff02002-12-30 20:52:32 +00003264 offset = call_utcoffset(self->tzinfo, Py_None, &none);
Tim Peters2a799bf2002-12-16 20:18:38 +00003265 if (offset == -1 && PyErr_Occurred())
3266 return -1;
3267 }
3268 return (TIME_GET_MINUTE(self) - offset + TIME_GET_HOUR(self)*60) != 0;
3269}
3270
3271/*
3272 * Pickle support. Quite a maze!
3273 */
3274
Tim Peters33e0f382003-01-10 02:05:14 +00003275/* Let basestate be the non-tzinfo data string.
Tim Peters2a799bf2002-12-16 20:18:38 +00003276 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
3277 * So it's a tuple in any (non-error) case.
3278 */
3279static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003280time_getstate(PyDateTime_Time *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003281{
3282 PyObject *basestate;
3283 PyObject *result = NULL;
3284
Tim Peters33e0f382003-01-10 02:05:14 +00003285 basestate = PyString_FromStringAndSize((char *)self->data,
3286 _PyDateTime_TIME_DATASIZE);
Tim Peters2a799bf2002-12-16 20:18:38 +00003287 if (basestate != NULL) {
Tim Petersa032d2e2003-01-11 00:15:54 +00003288 if (! HASTZINFO(self) || self->tzinfo == Py_None)
Tim Peters2a799bf2002-12-16 20:18:38 +00003289 result = Py_BuildValue("(O)", basestate);
3290 else
3291 result = Py_BuildValue("OO", basestate, self->tzinfo);
3292 Py_DECREF(basestate);
3293 }
3294 return result;
3295}
3296
3297static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003298time_setstate(PyDateTime_Time *self, PyObject *state)
Tim Peters2a799bf2002-12-16 20:18:38 +00003299{
Tim Peters2a799bf2002-12-16 20:18:38 +00003300 PyObject *basestate;
3301 PyObject *tzinfo = Py_None;
3302
3303 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
3304 &PyString_Type, &basestate,
3305 &tzinfo))
3306 return NULL;
Tim Peters33e0f382003-01-10 02:05:14 +00003307 if (PyString_Size(basestate) != _PyDateTime_TIME_DATASIZE ||
3308 check_tzinfo_subclass(tzinfo) < 0) {
3309 PyErr_SetString(PyExc_TypeError,
3310 "bad argument to time.__setstate__");
Tim Peters2a799bf2002-12-16 20:18:38 +00003311 return NULL;
Tim Peters33e0f382003-01-10 02:05:14 +00003312 }
Tim Petersa032d2e2003-01-11 00:15:54 +00003313 if (tzinfo != Py_None && ! HASTZINFO(self)) {
Tim Peters37f39822003-01-10 03:49:02 +00003314 PyErr_SetString(PyExc_ValueError, "time.__setstate__ can't "
3315 "add a non-None tzinfo to a time object that "
3316 "doesn't have one already");
3317 return NULL;
3318 }
Tim Peters33e0f382003-01-10 02:05:14 +00003319 memcpy((char *)self->data,
3320 PyString_AsString(basestate),
3321 _PyDateTime_TIME_DATASIZE);
3322 self->hashcode = -1;
Tim Petersa032d2e2003-01-11 00:15:54 +00003323 if (HASTZINFO(self)) {
Tim Peters37f39822003-01-10 03:49:02 +00003324 Py_INCREF(tzinfo);
3325 Py_XDECREF(self->tzinfo);
3326 self->tzinfo = tzinfo;
3327 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003328 Py_INCREF(Py_None);
3329 return Py_None;
3330}
3331
3332static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003333time_pickler(PyObject *module, PyDateTime_Time *time)
Tim Peters2a799bf2002-12-16 20:18:38 +00003334{
3335 PyObject *state;
3336 PyObject *result = NULL;
3337
Tim Peters37f39822003-01-10 03:49:02 +00003338 if (! PyTime_CheckExact(time)) {
Tim Peters2a799bf2002-12-16 20:18:38 +00003339 PyErr_Format(PyExc_TypeError,
Tim Peters37f39822003-01-10 03:49:02 +00003340 "bad type passed to time pickler: %s",
3341 time->ob_type->tp_name);
Tim Peters2a799bf2002-12-16 20:18:38 +00003342 return NULL;
3343 }
Tim Peters37f39822003-01-10 03:49:02 +00003344 state = time_getstate(time);
Tim Peters2a799bf2002-12-16 20:18:38 +00003345 if (state) {
3346 result = Py_BuildValue("O(O)",
Tim Peters37f39822003-01-10 03:49:02 +00003347 time_unpickler_object,
Tim Peters2a799bf2002-12-16 20:18:38 +00003348 state);
3349 Py_DECREF(state);
3350 }
3351 return result;
3352}
3353
3354static PyObject *
Tim Peters37f39822003-01-10 03:49:02 +00003355time_unpickler(PyObject *module, PyObject *arg)
Tim Peters2a799bf2002-12-16 20:18:38 +00003356{
Tim Peters37f39822003-01-10 03:49:02 +00003357 PyDateTime_Time *self;
Tim Peters2a799bf2002-12-16 20:18:38 +00003358
Tim Peters37f39822003-01-10 03:49:02 +00003359 /* We don't want to allocate space for tzinfo if it's not needed.
3360 * Figuring that out in advance is irritating, so for now we
3361 * realloc later.
3362 */
3363 self = PyObject_New(PyDateTime_Time, &PyDateTime_TimeType);
Tim Peters2a799bf2002-12-16 20:18:38 +00003364 if (self != NULL) {
3365 PyObject *res;
3366
Tim Peters37f39822003-01-10 03:49:02 +00003367 self->tzinfo = Py_None;
3368 Py_INCREF(self->tzinfo);
3369 self->hastzinfo = (char)1; /* true */
3370 res = time_setstate(self, arg);
Tim Peters2a799bf2002-12-16 20:18:38 +00003371 if (res == NULL) {
3372 Py_DECREF(self);
3373 return NULL;
3374 }
3375 Py_DECREF(res);
Tim Peters37f39822003-01-10 03:49:02 +00003376 if (self->tzinfo == Py_None) {
3377 /* shrinking; can't fail */
3378 Py_DECREF(self->tzinfo);
Tim Petersa9bc1682003-01-11 03:39:11 +00003379 self = (PyDateTime_Time *)PyObject_Realloc(self,
3380 sizeof(_PyDateTime_BaseTime));
3381 assert(self != NULL);
Tim Peters37f39822003-01-10 03:49:02 +00003382 self->hastzinfo = (char)0;
3383 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003384 }
3385 return (PyObject *)self;
3386}
3387
Tim Peters37f39822003-01-10 03:49:02 +00003388static PyMethodDef time_methods[] = {
3389 {"isoformat", (PyCFunction)time_isoformat, METH_KEYWORDS,
Tim Peters2a799bf2002-12-16 20:18:38 +00003390 PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]"
3391 "[+HH:MM].")},
3392
Tim Peters37f39822003-01-10 03:49:02 +00003393 {"strftime", (PyCFunction)time_strftime, METH_KEYWORDS,
3394 PyDoc_STR("format -> strftime() style string.")},
3395
3396 {"utcoffset", (PyCFunction)time_utcoffset, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00003397 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
3398
Tim Peters37f39822003-01-10 03:49:02 +00003399 {"tzname", (PyCFunction)time_tzname, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00003400 PyDoc_STR("Return self.tzinfo.tzname(self).")},
3401
Tim Peters37f39822003-01-10 03:49:02 +00003402 {"dst", (PyCFunction)time_dst, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00003403 PyDoc_STR("Return self.tzinfo.dst(self).")},
3404
Tim Peters37f39822003-01-10 03:49:02 +00003405 {"replace", (PyCFunction)time_replace, METH_KEYWORDS,
3406 PyDoc_STR("Return time with new specified fields.")},
Tim Peters12bf3392002-12-24 05:41:27 +00003407
Tim Peters37f39822003-01-10 03:49:02 +00003408 {"__setstate__", (PyCFunction)time_setstate, METH_O,
Tim Peters2a799bf2002-12-16 20:18:38 +00003409 PyDoc_STR("__setstate__(state)")},
3410
Tim Peters37f39822003-01-10 03:49:02 +00003411 {"__getstate__", (PyCFunction)time_getstate, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00003412 PyDoc_STR("__getstate__() -> state")},
3413 {NULL, NULL}
Tim Peters2a799bf2002-12-16 20:18:38 +00003414};
3415
Tim Peters37f39822003-01-10 03:49:02 +00003416static char time_doc[] =
Tim Peters2a799bf2002-12-16 20:18:38 +00003417PyDoc_STR("Time type.");
3418
Tim Peters37f39822003-01-10 03:49:02 +00003419static PyNumberMethods time_as_number = {
Tim Peters2a799bf2002-12-16 20:18:38 +00003420 0, /* nb_add */
3421 0, /* nb_subtract */
3422 0, /* nb_multiply */
3423 0, /* nb_divide */
3424 0, /* nb_remainder */
3425 0, /* nb_divmod */
3426 0, /* nb_power */
3427 0, /* nb_negative */
3428 0, /* nb_positive */
3429 0, /* nb_absolute */
Tim Peters37f39822003-01-10 03:49:02 +00003430 (inquiry)time_nonzero, /* nb_nonzero */
Tim Peters2a799bf2002-12-16 20:18:38 +00003431};
3432
Tim Peters37f39822003-01-10 03:49:02 +00003433statichere PyTypeObject PyDateTime_TimeType = {
Tim Peters2a799bf2002-12-16 20:18:38 +00003434 PyObject_HEAD_INIT(NULL)
3435 0, /* ob_size */
Tim Peters0bf60bd2003-01-08 20:40:01 +00003436 "datetime.time", /* tp_name */
Tim Peters37f39822003-01-10 03:49:02 +00003437 sizeof(PyDateTime_Time), /* tp_basicsize */
Tim Peters2a799bf2002-12-16 20:18:38 +00003438 0, /* tp_itemsize */
Tim Peters37f39822003-01-10 03:49:02 +00003439 (destructor)time_dealloc, /* tp_dealloc */
Tim Peters2a799bf2002-12-16 20:18:38 +00003440 0, /* tp_print */
3441 0, /* tp_getattr */
3442 0, /* tp_setattr */
3443 0, /* tp_compare */
Tim Peters37f39822003-01-10 03:49:02 +00003444 (reprfunc)time_repr, /* tp_repr */
3445 &time_as_number, /* tp_as_number */
Tim Peters2a799bf2002-12-16 20:18:38 +00003446 0, /* tp_as_sequence */
3447 0, /* tp_as_mapping */
Tim Peters37f39822003-01-10 03:49:02 +00003448 (hashfunc)time_hash, /* tp_hash */
Tim Peters2a799bf2002-12-16 20:18:38 +00003449 0, /* tp_call */
Tim Peters37f39822003-01-10 03:49:02 +00003450 (reprfunc)time_str, /* tp_str */
Tim Peters2a799bf2002-12-16 20:18:38 +00003451 PyObject_GenericGetAttr, /* tp_getattro */
3452 0, /* tp_setattro */
3453 0, /* tp_as_buffer */
3454 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
3455 Py_TPFLAGS_BASETYPE, /* tp_flags */
Tim Peters37f39822003-01-10 03:49:02 +00003456 time_doc, /* tp_doc */
Tim Peters2a799bf2002-12-16 20:18:38 +00003457 0, /* tp_traverse */
3458 0, /* tp_clear */
Tim Peters37f39822003-01-10 03:49:02 +00003459 (richcmpfunc)time_richcompare, /* tp_richcompare */
Tim Peters2a799bf2002-12-16 20:18:38 +00003460 0, /* tp_weaklistoffset */
3461 0, /* tp_iter */
3462 0, /* tp_iternext */
Tim Peters37f39822003-01-10 03:49:02 +00003463 time_methods, /* tp_methods */
Tim Peters2a799bf2002-12-16 20:18:38 +00003464 0, /* tp_members */
Tim Peters37f39822003-01-10 03:49:02 +00003465 time_getset, /* tp_getset */
3466 0, /* tp_base */
Tim Peters2a799bf2002-12-16 20:18:38 +00003467 0, /* tp_dict */
3468 0, /* tp_descr_get */
3469 0, /* tp_descr_set */
3470 0, /* tp_dictoffset */
3471 0, /* tp_init */
3472 0, /* tp_alloc */
Tim Peters37f39822003-01-10 03:49:02 +00003473 time_new, /* tp_new */
Tim Peters2a799bf2002-12-16 20:18:38 +00003474 _PyObject_Del, /* tp_free */
3475};
3476
3477/*
Tim Petersa9bc1682003-01-11 03:39:11 +00003478 * PyDateTime_DateTime implementation.
Tim Peters2a799bf2002-12-16 20:18:38 +00003479 */
3480
Tim Petersa9bc1682003-01-11 03:39:11 +00003481/* Accessor properties. Properties for day, month, and year are inherited
3482 * from date.
Tim Peters2a799bf2002-12-16 20:18:38 +00003483 */
3484
3485static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003486datetime_hour(PyDateTime_DateTime *self, void *unused)
Tim Peters2a799bf2002-12-16 20:18:38 +00003487{
Tim Petersa9bc1682003-01-11 03:39:11 +00003488 return PyInt_FromLong(DATE_GET_HOUR(self));
Tim Peters2a799bf2002-12-16 20:18:38 +00003489}
3490
Tim Petersa9bc1682003-01-11 03:39:11 +00003491static PyObject *
3492datetime_minute(PyDateTime_DateTime *self, void *unused)
3493{
3494 return PyInt_FromLong(DATE_GET_MINUTE(self));
3495}
3496
3497static PyObject *
3498datetime_second(PyDateTime_DateTime *self, void *unused)
3499{
3500 return PyInt_FromLong(DATE_GET_SECOND(self));
3501}
3502
3503static PyObject *
3504datetime_microsecond(PyDateTime_DateTime *self, void *unused)
3505{
3506 return PyInt_FromLong(DATE_GET_MICROSECOND(self));
3507}
3508
3509static PyObject *
3510datetime_tzinfo(PyDateTime_DateTime *self, void *unused)
3511{
3512 PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
3513 Py_INCREF(result);
3514 return result;
3515}
3516
3517static PyGetSetDef datetime_getset[] = {
3518 {"hour", (getter)datetime_hour},
3519 {"minute", (getter)datetime_minute},
3520 {"second", (getter)datetime_second},
3521 {"microsecond", (getter)datetime_microsecond},
3522 {"tzinfo", (getter)datetime_tzinfo},
Tim Peters2a799bf2002-12-16 20:18:38 +00003523 {NULL}
3524};
3525
3526/*
3527 * Constructors.
Tim Peters2a799bf2002-12-16 20:18:38 +00003528 */
3529
Tim Petersa9bc1682003-01-11 03:39:11 +00003530static char *datetime_kws[] = {
Tim Peters12bf3392002-12-24 05:41:27 +00003531 "year", "month", "day", "hour", "minute", "second",
3532 "microsecond", "tzinfo", NULL
3533};
3534
Tim Peters2a799bf2002-12-16 20:18:38 +00003535static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003536datetime_new(PyTypeObject *type, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003537{
3538 PyObject *self = NULL;
3539 int year;
3540 int month;
3541 int day;
3542 int hour = 0;
3543 int minute = 0;
3544 int second = 0;
3545 int usecond = 0;
3546 PyObject *tzinfo = Py_None;
3547
Tim Petersa9bc1682003-01-11 03:39:11 +00003548 if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO", datetime_kws,
Tim Peters2a799bf2002-12-16 20:18:38 +00003549 &year, &month, &day, &hour, &minute,
3550 &second, &usecond, &tzinfo)) {
3551 if (check_date_args(year, month, day) < 0)
3552 return NULL;
3553 if (check_time_args(hour, minute, second, usecond) < 0)
3554 return NULL;
3555 if (check_tzinfo_subclass(tzinfo) < 0)
3556 return NULL;
Tim Petersa9bc1682003-01-11 03:39:11 +00003557 self = new_datetime(year, month, day,
3558 hour, minute, second, usecond,
3559 tzinfo);
Tim Peters2a799bf2002-12-16 20:18:38 +00003560 }
3561 return self;
3562}
3563
Tim Petersa9bc1682003-01-11 03:39:11 +00003564/* TM_FUNC is the shared type of localtime() and gmtime(). */
3565typedef struct tm *(*TM_FUNC)(const time_t *timer);
3566
3567/* Internal helper.
3568 * Build datetime from a time_t and a distinct count of microseconds.
3569 * Pass localtime or gmtime for f, to control the interpretation of timet.
3570 */
3571static PyObject *
3572datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us,
3573 PyObject *tzinfo)
3574{
3575 struct tm *tm;
3576 PyObject *result = NULL;
3577
3578 tm = f(&timet);
3579 if (tm) {
3580 /* The platform localtime/gmtime may insert leap seconds,
3581 * indicated by tm->tm_sec > 59. We don't care about them,
3582 * except to the extent that passing them on to the datetime
3583 * constructor would raise ValueError for a reason that
3584 * made no sense to the user.
3585 */
3586 if (tm->tm_sec > 59)
3587 tm->tm_sec = 59;
3588 result = PyObject_CallFunction(cls, "iiiiiiiO",
3589 tm->tm_year + 1900,
3590 tm->tm_mon + 1,
3591 tm->tm_mday,
3592 tm->tm_hour,
3593 tm->tm_min,
3594 tm->tm_sec,
3595 us,
3596 tzinfo);
3597 }
3598 else
3599 PyErr_SetString(PyExc_ValueError,
3600 "timestamp out of range for "
3601 "platform localtime()/gmtime() function");
3602 return result;
3603}
3604
3605/* Internal helper.
3606 * Build datetime from a Python timestamp. Pass localtime or gmtime for f,
3607 * to control the interpretation of the timestamp. Since a double doesn't
3608 * have enough bits to cover a datetime's full range of precision, it's
3609 * better to call datetime_from_timet_and_us provided you have a way
3610 * to get that much precision (e.g., C time() isn't good enough).
3611 */
3612static PyObject *
3613datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp,
3614 PyObject *tzinfo)
3615{
3616 time_t timet = (time_t)timestamp;
3617 double fraction = timestamp - (double)timet;
3618 int us = (int)round_to_long(fraction * 1e6);
3619
3620 return datetime_from_timet_and_us(cls, f, timet, us, tzinfo);
3621}
3622
3623/* Internal helper.
3624 * Build most accurate possible datetime for current time. Pass localtime or
3625 * gmtime for f as appropriate.
3626 */
3627static PyObject *
3628datetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo)
3629{
3630#ifdef HAVE_GETTIMEOFDAY
3631 struct timeval t;
3632
3633#ifdef GETTIMEOFDAY_NO_TZ
3634 gettimeofday(&t);
3635#else
3636 gettimeofday(&t, (struct timezone *)NULL);
3637#endif
3638 return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec,
3639 tzinfo);
3640
3641#else /* ! HAVE_GETTIMEOFDAY */
3642 /* No flavor of gettimeofday exists on this platform. Python's
3643 * time.time() does a lot of other platform tricks to get the
3644 * best time it can on the platform, and we're not going to do
3645 * better than that (if we could, the better code would belong
3646 * in time.time()!) We're limited by the precision of a double,
3647 * though.
3648 */
3649 PyObject *time;
3650 double dtime;
3651
3652 time = time_time();
3653 if (time == NULL)
3654 return NULL;
3655 dtime = PyFloat_AsDouble(time);
3656 Py_DECREF(time);
3657 if (dtime == -1.0 && PyErr_Occurred())
3658 return NULL;
3659 return datetime_from_timestamp(cls, f, dtime, tzinfo);
3660#endif /* ! HAVE_GETTIMEOFDAY */
3661}
3662
Tim Peters2a799bf2002-12-16 20:18:38 +00003663/* Return best possible local time -- this isn't constrained by the
3664 * precision of a timestamp.
3665 */
3666static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003667datetime_now(PyObject *cls, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003668{
Tim Peters10cadce2003-01-23 19:58:02 +00003669 PyObject *self;
Tim Peters2a799bf2002-12-16 20:18:38 +00003670 PyObject *tzinfo = Py_None;
Tim Peters10cadce2003-01-23 19:58:02 +00003671 static char *keywords[] = {"tz", NULL};
Tim Peters2a799bf2002-12-16 20:18:38 +00003672
Tim Peters10cadce2003-01-23 19:58:02 +00003673 if (! PyArg_ParseTupleAndKeywords(args, kw, "|O:now", keywords,
3674 &tzinfo))
3675 return NULL;
3676 if (check_tzinfo_subclass(tzinfo) < 0)
3677 return NULL;
3678
3679 self = datetime_best_possible(cls,
3680 tzinfo == Py_None ? localtime : gmtime,
3681 tzinfo);
3682 if (self != NULL && tzinfo != Py_None) {
3683 /* Convert UTC to tzinfo's zone. */
3684 PyObject *temp = self;
Tim Peters2a44a8d2003-01-23 20:53:10 +00003685 self = PyObject_CallMethod(tzinfo, "fromutc", "O", self);
Tim Peters10cadce2003-01-23 19:58:02 +00003686 Py_DECREF(temp);
Tim Peters2a799bf2002-12-16 20:18:38 +00003687 }
3688 return self;
3689}
3690
Tim Petersa9bc1682003-01-11 03:39:11 +00003691/* Return best possible UTC time -- this isn't constrained by the
3692 * precision of a timestamp.
3693 */
3694static PyObject *
3695datetime_utcnow(PyObject *cls, PyObject *dummy)
3696{
3697 return datetime_best_possible(cls, gmtime, Py_None);
3698}
3699
Tim Peters2a799bf2002-12-16 20:18:38 +00003700/* Return new local datetime from timestamp (Python timestamp -- a double). */
3701static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003702datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003703{
Tim Peters2a44a8d2003-01-23 20:53:10 +00003704 PyObject *self;
Tim Peters2a799bf2002-12-16 20:18:38 +00003705 double timestamp;
3706 PyObject *tzinfo = Py_None;
Tim Peters2a44a8d2003-01-23 20:53:10 +00003707 static char *keywords[] = {"timestamp", "tz", NULL};
Tim Peters2a799bf2002-12-16 20:18:38 +00003708
Tim Peters2a44a8d2003-01-23 20:53:10 +00003709 if (! PyArg_ParseTupleAndKeywords(args, kw, "d|O:fromtimestamp",
3710 keywords, &timestamp, &tzinfo))
3711 return NULL;
3712 if (check_tzinfo_subclass(tzinfo) < 0)
3713 return NULL;
3714
3715 self = datetime_from_timestamp(cls,
3716 tzinfo == Py_None ? localtime : gmtime,
3717 timestamp,
3718 tzinfo);
3719 if (self != NULL && tzinfo != Py_None) {
3720 /* Convert UTC to tzinfo's zone. */
3721 PyObject *temp = self;
3722 self = PyObject_CallMethod(tzinfo, "fromutc", "O", self);
3723 Py_DECREF(temp);
Tim Peters2a799bf2002-12-16 20:18:38 +00003724 }
3725 return self;
3726}
3727
Tim Petersa9bc1682003-01-11 03:39:11 +00003728/* Return new UTC datetime from timestamp (Python timestamp -- a double). */
3729static PyObject *
3730datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
3731{
3732 double timestamp;
3733 PyObject *result = NULL;
Tim Peters2a799bf2002-12-16 20:18:38 +00003734
Tim Petersa9bc1682003-01-11 03:39:11 +00003735 if (PyArg_ParseTuple(args, "d:utcfromtimestamp", &timestamp))
3736 result = datetime_from_timestamp(cls, gmtime, timestamp,
3737 Py_None);
3738 return result;
3739}
3740
3741/* Return new datetime from date/datetime and time arguments. */
3742static PyObject *
3743datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
3744{
3745 static char *keywords[] = {"date", "time", NULL};
3746 PyObject *date;
3747 PyObject *time;
3748 PyObject *result = NULL;
3749
3750 if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!:combine", keywords,
3751 &PyDateTime_DateType, &date,
3752 &PyDateTime_TimeType, &time)) {
3753 PyObject *tzinfo = Py_None;
3754
3755 if (HASTZINFO(time))
3756 tzinfo = ((PyDateTime_Time *)time)->tzinfo;
3757 result = PyObject_CallFunction(cls, "iiiiiiiO",
3758 GET_YEAR(date),
3759 GET_MONTH(date),
3760 GET_DAY(date),
3761 TIME_GET_HOUR(time),
3762 TIME_GET_MINUTE(time),
3763 TIME_GET_SECOND(time),
3764 TIME_GET_MICROSECOND(time),
3765 tzinfo);
3766 }
3767 return result;
3768}
Tim Peters2a799bf2002-12-16 20:18:38 +00003769
3770/*
3771 * Destructor.
3772 */
3773
3774static void
Tim Petersa9bc1682003-01-11 03:39:11 +00003775datetime_dealloc(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003776{
Tim Petersa9bc1682003-01-11 03:39:11 +00003777 if (HASTZINFO(self)) {
3778 Py_XDECREF(self->tzinfo);
3779 }
Tim Peters2a799bf2002-12-16 20:18:38 +00003780 self->ob_type->tp_free((PyObject *)self);
3781}
3782
3783/*
3784 * Indirect access to tzinfo methods.
3785 */
3786
Tim Peters2a799bf2002-12-16 20:18:38 +00003787/* These are all METH_NOARGS, so don't need to check the arglist. */
3788static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003789datetime_utcoffset(PyDateTime_DateTime *self, PyObject *unused) {
3790 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
3791 "utcoffset", (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00003792}
3793
3794static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003795datetime_dst(PyDateTime_DateTime *self, PyObject *unused) {
3796 return offset_as_timedelta(HASTZINFO(self) ? self->tzinfo : Py_None,
3797 "dst", (PyObject *)self);
Tim Peters855fe882002-12-22 03:43:39 +00003798}
3799
3800static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003801datetime_tzname(PyDateTime_DateTime *self, PyObject *unused) {
3802 return call_tzname(HASTZINFO(self) ? self->tzinfo : Py_None,
3803 (PyObject *)self);
Tim Peters2a799bf2002-12-16 20:18:38 +00003804}
3805
3806/*
Tim Petersa9bc1682003-01-11 03:39:11 +00003807 * datetime arithmetic.
Tim Peters2a799bf2002-12-16 20:18:38 +00003808 */
3809
Tim Petersa9bc1682003-01-11 03:39:11 +00003810/* factor must be 1 (to add) or -1 (to subtract). The result inherits
3811 * the tzinfo state of date.
Tim Peters2a799bf2002-12-16 20:18:38 +00003812 */
3813static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003814add_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta,
3815 int factor)
Tim Peters2a799bf2002-12-16 20:18:38 +00003816{
Tim Petersa9bc1682003-01-11 03:39:11 +00003817 /* Note that the C-level additions can't overflow, because of
3818 * invariant bounds on the member values.
3819 */
3820 int year = GET_YEAR(date);
3821 int month = GET_MONTH(date);
3822 int day = GET_DAY(date) + GET_TD_DAYS(delta) * factor;
3823 int hour = DATE_GET_HOUR(date);
3824 int minute = DATE_GET_MINUTE(date);
3825 int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta) * factor;
3826 int microsecond = DATE_GET_MICROSECOND(date) +
3827 GET_TD_MICROSECONDS(delta) * factor;
Tim Peters2a799bf2002-12-16 20:18:38 +00003828
Tim Petersa9bc1682003-01-11 03:39:11 +00003829 assert(factor == 1 || factor == -1);
3830 if (normalize_datetime(&year, &month, &day,
3831 &hour, &minute, &second, &microsecond) < 0)
3832 return NULL;
3833 else
3834 return new_datetime(year, month, day,
3835 hour, minute, second, microsecond,
3836 HASTZINFO(date) ? date->tzinfo : Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00003837}
3838
3839static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003840datetime_add(PyObject *left, PyObject *right)
Tim Peters2a799bf2002-12-16 20:18:38 +00003841{
Tim Petersa9bc1682003-01-11 03:39:11 +00003842 if (PyDateTime_Check(left)) {
3843 /* datetime + ??? */
3844 if (PyDelta_Check(right))
3845 /* datetime + delta */
3846 return add_datetime_timedelta(
3847 (PyDateTime_DateTime *)left,
3848 (PyDateTime_Delta *)right,
3849 1);
3850 }
3851 else if (PyDelta_Check(left)) {
3852 /* delta + datetime */
3853 return add_datetime_timedelta((PyDateTime_DateTime *) right,
3854 (PyDateTime_Delta *) left,
3855 1);
3856 }
3857 Py_INCREF(Py_NotImplemented);
3858 return Py_NotImplemented;
Tim Peters2a799bf2002-12-16 20:18:38 +00003859}
3860
3861static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003862datetime_subtract(PyObject *left, PyObject *right)
Tim Peters2a799bf2002-12-16 20:18:38 +00003863{
3864 PyObject *result = Py_NotImplemented;
3865
3866 if (PyDateTime_Check(left)) {
3867 /* datetime - ??? */
3868 if (PyDateTime_Check(right)) {
3869 /* datetime - datetime */
3870 naivety n1, n2;
3871 int offset1, offset2;
Tim Petersa9bc1682003-01-11 03:39:11 +00003872 int delta_d, delta_s, delta_us;
Tim Peters2a799bf2002-12-16 20:18:38 +00003873
Tim Peterse39a80c2002-12-30 21:28:52 +00003874 if (classify_two_utcoffsets(left, &offset1, &n1, left,
3875 right, &offset2, &n2,
3876 right) < 0)
Tim Peters00237032002-12-27 02:21:51 +00003877 return NULL;
Tim Peters8702d5f2002-12-27 02:26:16 +00003878 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
Tim Peters2a799bf2002-12-16 20:18:38 +00003879 if (n1 != n2) {
3880 PyErr_SetString(PyExc_TypeError,
3881 "can't subtract offset-naive and "
3882 "offset-aware datetimes");
3883 return NULL;
3884 }
Tim Petersa9bc1682003-01-11 03:39:11 +00003885 delta_d = ymd_to_ord(GET_YEAR(left),
3886 GET_MONTH(left),
3887 GET_DAY(left)) -
3888 ymd_to_ord(GET_YEAR(right),
3889 GET_MONTH(right),
3890 GET_DAY(right));
3891 /* These can't overflow, since the values are
3892 * normalized. At most this gives the number of
3893 * seconds in one day.
3894 */
3895 delta_s = (DATE_GET_HOUR(left) -
3896 DATE_GET_HOUR(right)) * 3600 +
3897 (DATE_GET_MINUTE(left) -
3898 DATE_GET_MINUTE(right)) * 60 +
3899 (DATE_GET_SECOND(left) -
3900 DATE_GET_SECOND(right));
3901 delta_us = DATE_GET_MICROSECOND(left) -
3902 DATE_GET_MICROSECOND(right);
Tim Peters2a799bf2002-12-16 20:18:38 +00003903 /* (left - offset1) - (right - offset2) =
3904 * (left - right) + (offset2 - offset1)
3905 */
Tim Petersa9bc1682003-01-11 03:39:11 +00003906 delta_s += (offset2 - offset1) * 60;
3907 result = new_delta(delta_d, delta_s, delta_us, 1);
Tim Peters2a799bf2002-12-16 20:18:38 +00003908 }
3909 else if (PyDelta_Check(right)) {
Tim Petersa9bc1682003-01-11 03:39:11 +00003910 /* datetime - delta */
3911 result = add_datetime_timedelta(
Tim Peters2a799bf2002-12-16 20:18:38 +00003912 (PyDateTime_DateTime *)left,
Tim Petersa9bc1682003-01-11 03:39:11 +00003913 (PyDateTime_Delta *)right,
3914 -1);
Tim Peters2a799bf2002-12-16 20:18:38 +00003915 }
3916 }
3917
3918 if (result == Py_NotImplemented)
3919 Py_INCREF(result);
3920 return result;
3921}
3922
3923/* Various ways to turn a datetime into a string. */
3924
3925static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003926datetime_repr(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00003927{
Tim Petersa9bc1682003-01-11 03:39:11 +00003928 char buffer[1000];
3929 char *typename = self->ob_type->tp_name;
3930 PyObject *baserepr;
Tim Peters2a799bf2002-12-16 20:18:38 +00003931
Tim Petersa9bc1682003-01-11 03:39:11 +00003932 if (DATE_GET_MICROSECOND(self)) {
3933 PyOS_snprintf(buffer, sizeof(buffer),
3934 "%s(%d, %d, %d, %d, %d, %d, %d)",
3935 typename,
3936 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3937 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3938 DATE_GET_SECOND(self),
3939 DATE_GET_MICROSECOND(self));
3940 }
3941 else if (DATE_GET_SECOND(self)) {
3942 PyOS_snprintf(buffer, sizeof(buffer),
3943 "%s(%d, %d, %d, %d, %d, %d)",
3944 typename,
3945 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3946 DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
3947 DATE_GET_SECOND(self));
3948 }
3949 else {
3950 PyOS_snprintf(buffer, sizeof(buffer),
3951 "%s(%d, %d, %d, %d, %d)",
3952 typename,
3953 GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
3954 DATE_GET_HOUR(self), DATE_GET_MINUTE(self));
3955 }
3956 baserepr = PyString_FromString(buffer);
3957 if (baserepr == NULL || ! HASTZINFO(self))
3958 return baserepr;
Tim Peters2a799bf2002-12-16 20:18:38 +00003959 return append_keyword_tzinfo(baserepr, self->tzinfo);
3960}
3961
Tim Petersa9bc1682003-01-11 03:39:11 +00003962static PyObject *
3963datetime_str(PyDateTime_DateTime *self)
3964{
3965 return PyObject_CallMethod((PyObject *)self, "isoformat", "(s)", " ");
3966}
Tim Peters2a799bf2002-12-16 20:18:38 +00003967
3968static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00003969datetime_isoformat(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
Tim Peters2a799bf2002-12-16 20:18:38 +00003970{
Tim Petersa9bc1682003-01-11 03:39:11 +00003971 char sep = 'T';
3972 static char *keywords[] = {"sep", NULL};
3973 char buffer[100];
3974 char *cp;
3975 PyObject *result;
Tim Peters2a799bf2002-12-16 20:18:38 +00003976
Tim Petersa9bc1682003-01-11 03:39:11 +00003977 if (!PyArg_ParseTupleAndKeywords(args, kw, "|c:isoformat", keywords,
3978 &sep))
3979 return NULL;
3980 cp = isoformat_date((PyDateTime_Date *)self, buffer, sizeof(buffer));
3981 assert(cp != NULL);
3982 *cp++ = sep;
3983 isoformat_time(self, cp, sizeof(buffer) - (cp - buffer));
3984 result = PyString_FromString(buffer);
3985 if (result == NULL || ! HASTZINFO(self))
Tim Peters2a799bf2002-12-16 20:18:38 +00003986 return result;
3987
3988 /* We need to append the UTC offset. */
Tim Petersa9bc1682003-01-11 03:39:11 +00003989 if (format_utcoffset(buffer, sizeof(buffer), ":", self->tzinfo,
Tim Peters2a799bf2002-12-16 20:18:38 +00003990 (PyObject *)self) < 0) {
3991 Py_DECREF(result);
3992 return NULL;
3993 }
Tim Petersa9bc1682003-01-11 03:39:11 +00003994 PyString_ConcatAndDel(&result, PyString_FromString(buffer));
Tim Peters2a799bf2002-12-16 20:18:38 +00003995 return result;
3996}
3997
Tim Petersa9bc1682003-01-11 03:39:11 +00003998static PyObject *
3999datetime_ctime(PyDateTime_DateTime *self)
4000{
4001 return format_ctime((PyDateTime_Date *)self,
4002 DATE_GET_HOUR(self),
4003 DATE_GET_MINUTE(self),
4004 DATE_GET_SECOND(self));
4005}
4006
Tim Peters2a799bf2002-12-16 20:18:38 +00004007/* Miscellaneous methods. */
4008
Tim Petersa9bc1682003-01-11 03:39:11 +00004009/* This is more natural as a tp_compare, but doesn't work then: for whatever
4010 * reason, Python's try_3way_compare ignores tp_compare unless
4011 * PyInstance_Check returns true, but these aren't old-style classes.
4012 */
4013static PyObject *
4014datetime_richcompare(PyDateTime_DateTime *self, PyObject *other, int op)
4015{
4016 int diff;
4017 naivety n1, n2;
4018 int offset1, offset2;
4019
4020 if (! PyDateTime_Check(other)) {
4021 /* Stop this from falling back to address comparison. */
4022 PyErr_Format(PyExc_TypeError,
4023 "can't compare '%s' to '%s'",
4024 self->ob_type->tp_name,
4025 other->ob_type->tp_name);
4026 return NULL;
4027 }
4028
4029 if (classify_two_utcoffsets((PyObject *)self, &offset1, &n1,
4030 (PyObject *)self,
4031 other, &offset2, &n2,
4032 other) < 0)
4033 return NULL;
4034 assert(n1 != OFFSET_UNKNOWN && n2 != OFFSET_UNKNOWN);
4035 /* If they're both naive, or both aware and have the same offsets,
4036 * we get off cheap. Note that if they're both naive, offset1 ==
4037 * offset2 == 0 at this point.
4038 */
4039 if (n1 == n2 && offset1 == offset2) {
4040 diff = memcmp(self->data, ((PyDateTime_DateTime *)other)->data,
4041 _PyDateTime_DATETIME_DATASIZE);
4042 return diff_to_bool(diff, op);
4043 }
4044
4045 if (n1 == OFFSET_AWARE && n2 == OFFSET_AWARE) {
4046 PyDateTime_Delta *delta;
4047
4048 assert(offset1 != offset2); /* else last "if" handled it */
4049 delta = (PyDateTime_Delta *)datetime_subtract((PyObject *)self,
4050 other);
4051 if (delta == NULL)
4052 return NULL;
4053 diff = GET_TD_DAYS(delta);
4054 if (diff == 0)
4055 diff = GET_TD_SECONDS(delta) |
4056 GET_TD_MICROSECONDS(delta);
4057 Py_DECREF(delta);
4058 return diff_to_bool(diff, op);
4059 }
4060
4061 assert(n1 != n2);
4062 PyErr_SetString(PyExc_TypeError,
4063 "can't compare offset-naive and "
4064 "offset-aware datetimes");
4065 return NULL;
4066}
4067
4068static long
4069datetime_hash(PyDateTime_DateTime *self)
4070{
4071 if (self->hashcode == -1) {
4072 naivety n;
4073 int offset;
4074 PyObject *temp;
4075
4076 n = classify_utcoffset((PyObject *)self, (PyObject *)self,
4077 &offset);
4078 assert(n != OFFSET_UNKNOWN);
4079 if (n == OFFSET_ERROR)
4080 return -1;
4081
4082 /* Reduce this to a hash of another object. */
4083 if (n == OFFSET_NAIVE)
4084 temp = PyString_FromStringAndSize(
4085 (char *)self->data,
4086 _PyDateTime_DATETIME_DATASIZE);
4087 else {
4088 int days;
4089 int seconds;
4090
4091 assert(n == OFFSET_AWARE);
4092 assert(HASTZINFO(self));
4093 days = ymd_to_ord(GET_YEAR(self),
4094 GET_MONTH(self),
4095 GET_DAY(self));
4096 seconds = DATE_GET_HOUR(self) * 3600 +
4097 (DATE_GET_MINUTE(self) - offset) * 60 +
4098 DATE_GET_SECOND(self);
4099 temp = new_delta(days,
4100 seconds,
4101 DATE_GET_MICROSECOND(self),
4102 1);
4103 }
4104 if (temp != NULL) {
4105 self->hashcode = PyObject_Hash(temp);
4106 Py_DECREF(temp);
4107 }
4108 }
4109 return self->hashcode;
4110}
Tim Peters2a799bf2002-12-16 20:18:38 +00004111
4112static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004113datetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
Tim Peters12bf3392002-12-24 05:41:27 +00004114{
4115 PyObject *clone;
4116 PyObject *tuple;
4117 int y = GET_YEAR(self);
4118 int m = GET_MONTH(self);
4119 int d = GET_DAY(self);
4120 int hh = DATE_GET_HOUR(self);
4121 int mm = DATE_GET_MINUTE(self);
4122 int ss = DATE_GET_SECOND(self);
4123 int us = DATE_GET_MICROSECOND(self);
Tim Petersa9bc1682003-01-11 03:39:11 +00004124 PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
Tim Peters12bf3392002-12-24 05:41:27 +00004125
4126 if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO:replace",
Tim Petersa9bc1682003-01-11 03:39:11 +00004127 datetime_kws,
Tim Peters12bf3392002-12-24 05:41:27 +00004128 &y, &m, &d, &hh, &mm, &ss, &us,
4129 &tzinfo))
4130 return NULL;
4131 tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
4132 if (tuple == NULL)
4133 return NULL;
Tim Petersa9bc1682003-01-11 03:39:11 +00004134 clone = datetime_new(self->ob_type, tuple, NULL);
Tim Peters12bf3392002-12-24 05:41:27 +00004135 Py_DECREF(tuple);
4136 return clone;
4137}
4138
4139static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004140datetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw)
Tim Peters80475bb2002-12-25 07:40:55 +00004141{
Tim Peters52dcce22003-01-23 16:36:11 +00004142 int y, m, d, hh, mm, ss, us;
Tim Peters521fc152002-12-31 17:36:56 +00004143 PyObject *result;
Tim Peters52dcce22003-01-23 16:36:11 +00004144 int offset, none;
Tim Peters521fc152002-12-31 17:36:56 +00004145
Tim Peters80475bb2002-12-25 07:40:55 +00004146 PyObject *tzinfo;
4147 static char *keywords[] = {"tz", NULL};
4148
Tim Peters52dcce22003-01-23 16:36:11 +00004149 if (! PyArg_ParseTupleAndKeywords(args, kw, "O!:astimezone", keywords,
4150 &PyDateTime_TZInfoType, &tzinfo))
Tim Peters80475bb2002-12-25 07:40:55 +00004151 return NULL;
4152
Tim Peters52dcce22003-01-23 16:36:11 +00004153 if (!HASTZINFO(self) || self->tzinfo == Py_None)
4154 goto NeedAware;
Tim Peters521fc152002-12-31 17:36:56 +00004155
Tim Peters52dcce22003-01-23 16:36:11 +00004156 /* Conversion to self's own time zone is a NOP. */
4157 if (self->tzinfo == tzinfo) {
4158 Py_INCREF(self);
4159 return (PyObject *)self;
Tim Peters710fb152003-01-02 19:35:54 +00004160 }
Tim Peters521fc152002-12-31 17:36:56 +00004161
Tim Peters52dcce22003-01-23 16:36:11 +00004162 /* Convert self to UTC. */
4163 offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4164 if (offset == -1 && PyErr_Occurred())
4165 return NULL;
4166 if (none)
4167 goto NeedAware;
Tim Petersf3615152003-01-01 21:51:37 +00004168
Tim Peters52dcce22003-01-23 16:36:11 +00004169 y = GET_YEAR(self);
4170 m = GET_MONTH(self);
4171 d = GET_DAY(self);
4172 hh = DATE_GET_HOUR(self);
4173 mm = DATE_GET_MINUTE(self);
4174 ss = DATE_GET_SECOND(self);
4175 us = DATE_GET_MICROSECOND(self);
4176
4177 mm -= offset;
Tim Petersf3615152003-01-01 21:51:37 +00004178 if ((mm < 0 || mm >= 60) &&
4179 normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us) < 0)
Tim Peters52dcce22003-01-23 16:36:11 +00004180 return NULL;
4181
4182 /* Attach new tzinfo and let fromutc() do the rest. */
4183 result = new_datetime(y, m, d, hh, mm, ss, us, tzinfo);
4184 if (result != NULL) {
4185 PyObject *temp = result;
4186
4187 result = PyObject_CallMethod(tzinfo, "fromutc", "O", temp);
4188 Py_DECREF(temp);
4189 }
Tim Petersadf64202003-01-04 06:03:15 +00004190 return result;
Tim Peters521fc152002-12-31 17:36:56 +00004191
Tim Peters52dcce22003-01-23 16:36:11 +00004192NeedAware:
4193 PyErr_SetString(PyExc_ValueError, "astimezone() cannot be applied to "
4194 "a naive datetime");
Tim Peters521fc152002-12-31 17:36:56 +00004195 return NULL;
Tim Peters80475bb2002-12-25 07:40:55 +00004196}
4197
4198static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004199datetime_timetuple(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00004200{
4201 int dstflag = -1;
4202
Tim Petersa9bc1682003-01-11 03:39:11 +00004203 if (HASTZINFO(self) && self->tzinfo != Py_None) {
Tim Peters2a799bf2002-12-16 20:18:38 +00004204 int none;
4205
4206 dstflag = call_dst(self->tzinfo, (PyObject *)self, &none);
4207 if (dstflag == -1 && PyErr_Occurred())
4208 return NULL;
4209
4210 if (none)
4211 dstflag = -1;
4212 else if (dstflag != 0)
4213 dstflag = 1;
4214
4215 }
4216 return build_struct_time(GET_YEAR(self),
4217 GET_MONTH(self),
4218 GET_DAY(self),
4219 DATE_GET_HOUR(self),
4220 DATE_GET_MINUTE(self),
4221 DATE_GET_SECOND(self),
4222 dstflag);
4223}
4224
4225static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004226datetime_getdate(PyDateTime_DateTime *self)
4227{
4228 return new_date(GET_YEAR(self),
4229 GET_MONTH(self),
4230 GET_DAY(self));
4231}
4232
4233static PyObject *
4234datetime_gettime(PyDateTime_DateTime *self)
4235{
4236 return new_time(DATE_GET_HOUR(self),
4237 DATE_GET_MINUTE(self),
4238 DATE_GET_SECOND(self),
4239 DATE_GET_MICROSECOND(self),
4240 Py_None);
4241}
4242
4243static PyObject *
4244datetime_gettimetz(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 HASTZINFO(self) ? self->tzinfo : Py_None);
4251}
4252
4253static PyObject *
4254datetime_utctimetuple(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00004255{
4256 int y = GET_YEAR(self);
4257 int m = GET_MONTH(self);
4258 int d = GET_DAY(self);
4259 int hh = DATE_GET_HOUR(self);
4260 int mm = DATE_GET_MINUTE(self);
4261 int ss = DATE_GET_SECOND(self);
4262 int us = 0; /* microseconds are ignored in a timetuple */
4263 int offset = 0;
4264
Tim Petersa9bc1682003-01-11 03:39:11 +00004265 if (HASTZINFO(self) && self->tzinfo != Py_None) {
Tim Peters2a799bf2002-12-16 20:18:38 +00004266 int none;
4267
4268 offset = call_utcoffset(self->tzinfo, (PyObject *)self, &none);
4269 if (offset == -1 && PyErr_Occurred())
4270 return NULL;
4271 }
4272 /* Even if offset is 0, don't call timetuple() -- tm_isdst should be
4273 * 0 in a UTC timetuple regardless of what dst() says.
4274 */
4275 if (offset) {
4276 /* Subtract offset minutes & normalize. */
4277 int stat;
4278
4279 mm -= offset;
4280 stat = normalize_datetime(&y, &m, &d, &hh, &mm, &ss, &us);
4281 if (stat < 0) {
4282 /* At the edges, it's possible we overflowed
4283 * beyond MINYEAR or MAXYEAR.
4284 */
4285 if (PyErr_ExceptionMatches(PyExc_OverflowError))
4286 PyErr_Clear();
4287 else
4288 return NULL;
4289 }
4290 }
4291 return build_struct_time(y, m, d, hh, mm, ss, 0);
4292}
4293
Tim Peters33e0f382003-01-10 02:05:14 +00004294/* Pickle support. Quite a maze! */
4295
Tim Petersa9bc1682003-01-11 03:39:11 +00004296/* Let basestate be the non-tzinfo data string.
Tim Peters2a799bf2002-12-16 20:18:38 +00004297 * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo).
4298 * So it's a tuple in any (non-error) case.
4299 */
4300static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004301datetime_getstate(PyDateTime_DateTime *self)
Tim Peters2a799bf2002-12-16 20:18:38 +00004302{
4303 PyObject *basestate;
4304 PyObject *result = NULL;
4305
Tim Peters33e0f382003-01-10 02:05:14 +00004306 basestate = PyString_FromStringAndSize((char *)self->data,
4307 _PyDateTime_DATETIME_DATASIZE);
Tim Peters2a799bf2002-12-16 20:18:38 +00004308 if (basestate != NULL) {
Tim Petersa9bc1682003-01-11 03:39:11 +00004309 if (! HASTZINFO(self) || self->tzinfo == Py_None)
Tim Peters2a799bf2002-12-16 20:18:38 +00004310 result = Py_BuildValue("(O)", basestate);
4311 else
4312 result = Py_BuildValue("OO", basestate, self->tzinfo);
4313 Py_DECREF(basestate);
4314 }
4315 return result;
4316}
4317
4318static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004319datetime_setstate(PyDateTime_DateTime *self, PyObject *state)
Tim Peters2a799bf2002-12-16 20:18:38 +00004320{
Tim Peters2a799bf2002-12-16 20:18:38 +00004321 PyObject *basestate;
4322 PyObject *tzinfo = Py_None;
4323
4324 if (! PyArg_ParseTuple(state, "O!|O:__setstate__",
4325 &PyString_Type, &basestate,
4326 &tzinfo))
4327 return NULL;
Tim Peters33e0f382003-01-10 02:05:14 +00004328 if (PyString_Size(basestate) != _PyDateTime_DATETIME_DATASIZE ||
4329 check_tzinfo_subclass(tzinfo) < 0) {
4330 PyErr_SetString(PyExc_TypeError,
4331 "bad argument to datetime.__setstate__");
Tim Peters2a799bf2002-12-16 20:18:38 +00004332 return NULL;
Tim Peters33e0f382003-01-10 02:05:14 +00004333 }
Tim Petersa9bc1682003-01-11 03:39:11 +00004334 if (tzinfo != Py_None && ! HASTZINFO(self)) {
4335 PyErr_SetString(PyExc_ValueError, "datetime.__setstate__ "
4336 "can't add a non-None tzinfo to a datetime "
4337 "object that doesn't have one already");
4338 return NULL;
4339 }
Tim Peters33e0f382003-01-10 02:05:14 +00004340 memcpy((char *)self->data,
4341 PyString_AsString(basestate),
4342 _PyDateTime_DATETIME_DATASIZE);
4343 self->hashcode = -1;
Tim Petersa9bc1682003-01-11 03:39:11 +00004344 if (HASTZINFO(self)) {
4345 Py_INCREF(tzinfo);
4346 Py_XDECREF(self->tzinfo);
4347 self->tzinfo = tzinfo;
4348 }
Tim Peters2a799bf2002-12-16 20:18:38 +00004349 Py_INCREF(Py_None);
4350 return Py_None;
4351}
4352
4353static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004354datetime_pickler(PyObject *module, PyDateTime_DateTime *datetime)
Tim Peters2a799bf2002-12-16 20:18:38 +00004355{
4356 PyObject *state;
4357 PyObject *result = NULL;
4358
Tim Petersa9bc1682003-01-11 03:39:11 +00004359 if (! PyDateTime_CheckExact(datetime)) {
Tim Peters2a799bf2002-12-16 20:18:38 +00004360 PyErr_Format(PyExc_TypeError,
Tim Petersa9bc1682003-01-11 03:39:11 +00004361 "bad type passed to datetime pickler: %s",
4362 datetime->ob_type->tp_name);
Tim Peters2a799bf2002-12-16 20:18:38 +00004363 return NULL;
4364 }
Tim Petersa9bc1682003-01-11 03:39:11 +00004365 state = datetime_getstate(datetime);
Tim Peters2a799bf2002-12-16 20:18:38 +00004366 if (state) {
4367 result = Py_BuildValue("O(O)",
Tim Petersa9bc1682003-01-11 03:39:11 +00004368 datetime_unpickler_object,
Tim Peters2a799bf2002-12-16 20:18:38 +00004369 state);
4370 Py_DECREF(state);
4371 }
4372 return result;
4373}
4374
4375static PyObject *
Tim Petersa9bc1682003-01-11 03:39:11 +00004376datetime_unpickler(PyObject *module, PyObject *arg)
Tim Peters2a799bf2002-12-16 20:18:38 +00004377{
Tim Petersa9bc1682003-01-11 03:39:11 +00004378 PyDateTime_DateTime *self;
Tim Peters2a799bf2002-12-16 20:18:38 +00004379
Tim Petersa9bc1682003-01-11 03:39:11 +00004380 /* We don't want to allocate space for tzinfo if it's not needed.
4381 * Figuring that out in advance is irritating, so for now we
4382 * realloc later.
4383 */
4384 self = PyObject_New(PyDateTime_DateTime, &PyDateTime_DateTimeType);
Tim Peters2a799bf2002-12-16 20:18:38 +00004385 if (self != NULL) {
4386 PyObject *res;
4387
Tim Petersa9bc1682003-01-11 03:39:11 +00004388 self->tzinfo = Py_None;
4389 Py_INCREF(self->tzinfo);
4390 self->hastzinfo = (char)1; /* true */
4391 res = datetime_setstate(self, arg);
Tim Peters2a799bf2002-12-16 20:18:38 +00004392 if (res == NULL) {
4393 Py_DECREF(self);
4394 return NULL;
4395 }
4396 Py_DECREF(res);
Tim Petersa9bc1682003-01-11 03:39:11 +00004397 if (self->tzinfo == Py_None) {
4398 /* shrinking; can't fail */
4399 Py_DECREF(self->tzinfo);
4400 self = (PyDateTime_DateTime *)PyObject_Realloc(self,
4401 sizeof(_PyDateTime_BaseDateTime));
4402 assert(self != NULL);
4403 self->hastzinfo = (char)0;
4404 }
Tim Peters2a799bf2002-12-16 20:18:38 +00004405 }
4406 return (PyObject *)self;
4407}
4408
4409
Tim Petersa9bc1682003-01-11 03:39:11 +00004410static PyMethodDef datetime_methods[] = {
Tim Peters2a799bf2002-12-16 20:18:38 +00004411 /* Class methods: */
Tim Peters2a799bf2002-12-16 20:18:38 +00004412
Tim Petersa9bc1682003-01-11 03:39:11 +00004413 {"now", (PyCFunction)datetime_now,
Tim Peters2a799bf2002-12-16 20:18:38 +00004414 METH_KEYWORDS | METH_CLASS,
Neal Norwitz2fbe5372003-01-23 21:09:05 +00004415 PyDoc_STR("[tz] -> new datetime with tz's local day and time.")},
Tim Peters2a799bf2002-12-16 20:18:38 +00004416
Tim Petersa9bc1682003-01-11 03:39:11 +00004417 {"utcnow", (PyCFunction)datetime_utcnow,
4418 METH_NOARGS | METH_CLASS,
4419 PyDoc_STR("Return a new datetime representing UTC day and time.")},
4420
4421 {"fromtimestamp", (PyCFunction)datetime_fromtimestamp,
Tim Peters2a799bf2002-12-16 20:18:38 +00004422 METH_KEYWORDS | METH_CLASS,
Tim Peters2a44a8d2003-01-23 20:53:10 +00004423 PyDoc_STR("timestamp[, tz] -> tz's local time from POSIX timestamp.")},
Tim Peters2a799bf2002-12-16 20:18:38 +00004424
Tim Petersa9bc1682003-01-11 03:39:11 +00004425 {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
4426 METH_VARARGS | METH_CLASS,
4427 PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp "
4428 "(like time.time()).")},
4429
4430 {"combine", (PyCFunction)datetime_combine,
4431 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
4432 PyDoc_STR("date, time -> datetime with same date and time fields")},
4433
Tim Peters2a799bf2002-12-16 20:18:38 +00004434 /* Instance methods: */
Tim Petersa9bc1682003-01-11 03:39:11 +00004435 {"date", (PyCFunction)datetime_getdate, METH_NOARGS,
4436 PyDoc_STR("Return date object with same year, month and day.")},
4437
4438 {"time", (PyCFunction)datetime_gettime, METH_NOARGS,
4439 PyDoc_STR("Return time object with same time but with tzinfo=None.")},
4440
4441 {"timetz", (PyCFunction)datetime_gettimetz, METH_NOARGS,
4442 PyDoc_STR("Return time object with same time and tzinfo.")},
4443
4444 {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS,
4445 PyDoc_STR("Return ctime() style string.")},
4446
4447 {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004448 PyDoc_STR("Return time tuple, compatible with time.localtime().")},
4449
Tim Petersa9bc1682003-01-11 03:39:11 +00004450 {"utctimetuple", (PyCFunction)datetime_utctimetuple, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004451 PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")},
4452
Tim Petersa9bc1682003-01-11 03:39:11 +00004453 {"isoformat", (PyCFunction)datetime_isoformat, METH_KEYWORDS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004454 PyDoc_STR("[sep] -> string in ISO 8601 format, "
4455 "YYYY-MM-DDTHH:MM:SS[.mmmmmm][+HH:MM].\n\n"
4456 "sep is used to separate the year from the time, and "
4457 "defaults to 'T'.")},
4458
Tim Petersa9bc1682003-01-11 03:39:11 +00004459 {"utcoffset", (PyCFunction)datetime_utcoffset, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004460 PyDoc_STR("Return self.tzinfo.utcoffset(self).")},
4461
Tim Petersa9bc1682003-01-11 03:39:11 +00004462 {"tzname", (PyCFunction)datetime_tzname, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004463 PyDoc_STR("Return self.tzinfo.tzname(self).")},
4464
Tim Petersa9bc1682003-01-11 03:39:11 +00004465 {"dst", (PyCFunction)datetime_dst, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004466 PyDoc_STR("Return self.tzinfo.dst(self).")},
4467
Tim Petersa9bc1682003-01-11 03:39:11 +00004468 {"replace", (PyCFunction)datetime_replace, METH_KEYWORDS,
4469 PyDoc_STR("Return datetime with new specified fields.")},
Tim Peters12bf3392002-12-24 05:41:27 +00004470
Tim Petersa9bc1682003-01-11 03:39:11 +00004471 {"astimezone", (PyCFunction)datetime_astimezone, METH_KEYWORDS,
Tim Peters80475bb2002-12-25 07:40:55 +00004472 PyDoc_STR("tz -> convert to local time in new timezone tz\n")},
4473
Tim Petersa9bc1682003-01-11 03:39:11 +00004474 {"__setstate__", (PyCFunction)datetime_setstate, METH_O,
Tim Peters2a799bf2002-12-16 20:18:38 +00004475 PyDoc_STR("__setstate__(state)")},
4476
Tim Petersa9bc1682003-01-11 03:39:11 +00004477 {"__getstate__", (PyCFunction)datetime_getstate, METH_NOARGS,
Tim Peters2a799bf2002-12-16 20:18:38 +00004478 PyDoc_STR("__getstate__() -> state")},
4479 {NULL, NULL}
4480};
4481
Tim Petersa9bc1682003-01-11 03:39:11 +00004482static char datetime_doc[] =
Tim Peters2a799bf2002-12-16 20:18:38 +00004483PyDoc_STR("date/time type.");
4484
Tim Petersa9bc1682003-01-11 03:39:11 +00004485static PyNumberMethods datetime_as_number = {
4486 datetime_add, /* nb_add */
4487 datetime_subtract, /* nb_subtract */
Tim Peters2a799bf2002-12-16 20:18:38 +00004488 0, /* nb_multiply */
4489 0, /* nb_divide */
4490 0, /* nb_remainder */
4491 0, /* nb_divmod */
4492 0, /* nb_power */
4493 0, /* nb_negative */
4494 0, /* nb_positive */
4495 0, /* nb_absolute */
4496 0, /* nb_nonzero */
4497};
4498
Tim Petersa9bc1682003-01-11 03:39:11 +00004499statichere PyTypeObject PyDateTime_DateTimeType = {
Tim Peters2a799bf2002-12-16 20:18:38 +00004500 PyObject_HEAD_INIT(NULL)
4501 0, /* ob_size */
Tim Peters0bf60bd2003-01-08 20:40:01 +00004502 "datetime.datetime", /* tp_name */
Tim Petersa9bc1682003-01-11 03:39:11 +00004503 sizeof(PyDateTime_DateTime), /* tp_basicsize */
Tim Peters2a799bf2002-12-16 20:18:38 +00004504 0, /* tp_itemsize */
Tim Petersa9bc1682003-01-11 03:39:11 +00004505 (destructor)datetime_dealloc, /* tp_dealloc */
Tim Peters2a799bf2002-12-16 20:18:38 +00004506 0, /* tp_print */
4507 0, /* tp_getattr */
4508 0, /* tp_setattr */
4509 0, /* tp_compare */
Tim Petersa9bc1682003-01-11 03:39:11 +00004510 (reprfunc)datetime_repr, /* tp_repr */
4511 &datetime_as_number, /* tp_as_number */
Tim Peters2a799bf2002-12-16 20:18:38 +00004512 0, /* tp_as_sequence */
4513 0, /* tp_as_mapping */
Tim Petersa9bc1682003-01-11 03:39:11 +00004514 (hashfunc)datetime_hash, /* tp_hash */
Tim Peters2a799bf2002-12-16 20:18:38 +00004515 0, /* tp_call */
Tim Petersa9bc1682003-01-11 03:39:11 +00004516 (reprfunc)datetime_str, /* tp_str */
Tim Peters2a799bf2002-12-16 20:18:38 +00004517 PyObject_GenericGetAttr, /* tp_getattro */
4518 0, /* tp_setattro */
4519 0, /* tp_as_buffer */
4520 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES |
4521 Py_TPFLAGS_BASETYPE, /* tp_flags */
Tim Petersa9bc1682003-01-11 03:39:11 +00004522 datetime_doc, /* tp_doc */
Tim Peters2a799bf2002-12-16 20:18:38 +00004523 0, /* tp_traverse */
4524 0, /* tp_clear */
Tim Petersa9bc1682003-01-11 03:39:11 +00004525 (richcmpfunc)datetime_richcompare, /* tp_richcompare */
Tim Peters2a799bf2002-12-16 20:18:38 +00004526 0, /* tp_weaklistoffset */
4527 0, /* tp_iter */
4528 0, /* tp_iternext */
Tim Petersa9bc1682003-01-11 03:39:11 +00004529 datetime_methods, /* tp_methods */
Tim Peters2a799bf2002-12-16 20:18:38 +00004530 0, /* tp_members */
Tim Petersa9bc1682003-01-11 03:39:11 +00004531 datetime_getset, /* tp_getset */
4532 &PyDateTime_DateType, /* tp_base */
Tim Peters2a799bf2002-12-16 20:18:38 +00004533 0, /* tp_dict */
4534 0, /* tp_descr_get */
4535 0, /* tp_descr_set */
4536 0, /* tp_dictoffset */
4537 0, /* tp_init */
4538 0, /* tp_alloc */
Tim Petersa9bc1682003-01-11 03:39:11 +00004539 datetime_new, /* tp_new */
Tim Peters2a799bf2002-12-16 20:18:38 +00004540 _PyObject_Del, /* tp_free */
4541};
4542
4543/* ---------------------------------------------------------------------------
4544 * Module methods and initialization.
4545 */
4546
4547static PyMethodDef module_methods[] = {
4548 /* Private functions for pickling support, registered with the
4549 * copy_reg module by the module init function.
4550 */
4551 {"_date_pickler", (PyCFunction)date_pickler, METH_O, NULL},
4552 {"_date_unpickler", (PyCFunction)date_unpickler, METH_O, NULL},
Tim Petersa9bc1682003-01-11 03:39:11 +00004553 {"_datetime_pickler", (PyCFunction)datetime_pickler, METH_O, NULL},
4554 {"_datetime_unpickler", (PyCFunction)datetime_unpickler,METH_O, NULL},
Tim Peters37f39822003-01-10 03:49:02 +00004555 {"_time_pickler", (PyCFunction)time_pickler, METH_O, NULL},
4556 {"_time_unpickler", (PyCFunction)time_unpickler, METH_O, NULL},
Tim Peters2a799bf2002-12-16 20:18:38 +00004557 {"_tzinfo_pickler", (PyCFunction)tzinfo_pickler, METH_O, NULL},
4558 {"_tzinfo_unpickler", (PyCFunction)tzinfo_unpickler, METH_NOARGS,
4559 NULL},
4560 {NULL, NULL}
4561};
4562
4563PyMODINIT_FUNC
4564initdatetime(void)
4565{
4566 PyObject *m; /* a module object */
4567 PyObject *d; /* its dict */
4568 PyObject *x;
4569
4570 /* Types that use __reduce__ for pickling need to set the following
4571 * magical attr in the type dict, with a true value.
4572 */
4573 PyObject *safepickle = PyString_FromString("__safe_for_unpickling__");
4574 if (safepickle == NULL)
4575 return;
4576
4577 m = Py_InitModule3("datetime", module_methods,
4578 "Fast implementation of the datetime type.");
4579
4580 if (PyType_Ready(&PyDateTime_DateType) < 0)
4581 return;
4582 if (PyType_Ready(&PyDateTime_DateTimeType) < 0)
4583 return;
4584 if (PyType_Ready(&PyDateTime_DeltaType) < 0)
4585 return;
4586 if (PyType_Ready(&PyDateTime_TimeType) < 0)
4587 return;
4588 if (PyType_Ready(&PyDateTime_TZInfoType) < 0)
4589 return;
Tim Peters2a799bf2002-12-16 20:18:38 +00004590
4591 /* Pickling support, via registering functions with copy_reg. */
4592 {
4593 PyObject *pickler;
4594 PyObject *copyreg = PyImport_ImportModule("copy_reg");
4595
4596 if (copyreg == NULL) return;
4597
4598 pickler = PyObject_GetAttrString(m, "_date_pickler");
4599 if (pickler == NULL) return;
4600 date_unpickler_object = PyObject_GetAttrString(m,
4601 "_date_unpickler");
4602 if (date_unpickler_object == NULL) return;
4603 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
4604 &PyDateTime_DateType,
4605 pickler,
4606 date_unpickler_object);
4607 if (x == NULL) return;
4608 Py_DECREF(x);
4609 Py_DECREF(pickler);
4610
Tim Peters37f39822003-01-10 03:49:02 +00004611 pickler = PyObject_GetAttrString(m, "_time_pickler");
Tim Peters2a799bf2002-12-16 20:18:38 +00004612 if (pickler == NULL) return;
Tim Peters37f39822003-01-10 03:49:02 +00004613 time_unpickler_object = PyObject_GetAttrString(m,
4614 "_time_unpickler");
4615 if (time_unpickler_object == NULL) return;
Tim Peters2a799bf2002-12-16 20:18:38 +00004616 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
Tim Peters37f39822003-01-10 03:49:02 +00004617 &PyDateTime_TimeType,
Tim Peters2a799bf2002-12-16 20:18:38 +00004618 pickler,
Tim Peters37f39822003-01-10 03:49:02 +00004619 time_unpickler_object);
Tim Peters2a799bf2002-12-16 20:18:38 +00004620 if (x == NULL) return;
4621 Py_DECREF(x);
4622 Py_DECREF(pickler);
4623
4624 pickler = PyObject_GetAttrString(m, "_tzinfo_pickler");
4625 if (pickler == NULL) return;
4626 tzinfo_unpickler_object = PyObject_GetAttrString(m,
4627 "_tzinfo_unpickler");
4628 if (tzinfo_unpickler_object == NULL) return;
4629 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
4630 &PyDateTime_TZInfoType,
4631 pickler,
4632 tzinfo_unpickler_object);
4633 if (x== NULL) return;
4634 Py_DECREF(x);
4635 Py_DECREF(pickler);
4636
Tim Petersa9bc1682003-01-11 03:39:11 +00004637 pickler = PyObject_GetAttrString(m, "_datetime_pickler");
Tim Peters2a799bf2002-12-16 20:18:38 +00004638 if (pickler == NULL) return;
Tim Petersa9bc1682003-01-11 03:39:11 +00004639 datetime_unpickler_object = PyObject_GetAttrString(m,
4640 "_datetime_unpickler");
4641 if (datetime_unpickler_object == NULL) return;
Tim Peters2a799bf2002-12-16 20:18:38 +00004642 x = PyObject_CallMethod(copyreg, "pickle", "OOO",
Tim Petersa9bc1682003-01-11 03:39:11 +00004643 &PyDateTime_DateTimeType,
Tim Peters2a799bf2002-12-16 20:18:38 +00004644 pickler,
Tim Petersa9bc1682003-01-11 03:39:11 +00004645 datetime_unpickler_object);
Tim Peters2a799bf2002-12-16 20:18:38 +00004646 if (x== NULL) return;
4647 Py_DECREF(x);
4648 Py_DECREF(pickler);
4649
4650 Py_DECREF(copyreg);
4651 }
4652
4653 /* timedelta values */
4654 d = PyDateTime_DeltaType.tp_dict;
4655
4656 if (PyDict_SetItem(d, safepickle, Py_True) < 0)
4657 return;
4658
4659 x = new_delta(0, 0, 1, 0);
4660 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
4661 return;
4662 Py_DECREF(x);
4663
4664 x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0);
4665 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
4666 return;
4667 Py_DECREF(x);
4668
4669 x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0);
4670 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
4671 return;
4672 Py_DECREF(x);
4673
4674 /* date values */
4675 d = PyDateTime_DateType.tp_dict;
4676
4677 x = new_date(1, 1, 1);
4678 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
4679 return;
4680 Py_DECREF(x);
4681
4682 x = new_date(MAXYEAR, 12, 31);
4683 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
4684 return;
4685 Py_DECREF(x);
4686
4687 x = new_delta(1, 0, 0, 0);
4688 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
4689 return;
4690 Py_DECREF(x);
4691
Tim Peters37f39822003-01-10 03:49:02 +00004692 /* time values */
4693 d = PyDateTime_TimeType.tp_dict;
Tim Peters2a799bf2002-12-16 20:18:38 +00004694
Tim Peters37f39822003-01-10 03:49:02 +00004695 x = new_time(0, 0, 0, 0, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004696 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
4697 return;
4698 Py_DECREF(x);
4699
Tim Peters37f39822003-01-10 03:49:02 +00004700 x = new_time(23, 59, 59, 999999, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004701 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
4702 return;
4703 Py_DECREF(x);
4704
4705 x = new_delta(0, 0, 1, 0);
4706 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
4707 return;
4708 Py_DECREF(x);
4709
Tim Petersa9bc1682003-01-11 03:39:11 +00004710 /* datetime values */
4711 d = PyDateTime_DateTimeType.tp_dict;
Tim Peters2a799bf2002-12-16 20:18:38 +00004712
Tim Petersa9bc1682003-01-11 03:39:11 +00004713 x = new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004714 if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
4715 return;
4716 Py_DECREF(x);
4717
Tim Petersa9bc1682003-01-11 03:39:11 +00004718 x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None);
Tim Peters2a799bf2002-12-16 20:18:38 +00004719 if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
4720 return;
4721 Py_DECREF(x);
4722
4723 x = new_delta(0, 0, 1, 0);
4724 if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
4725 return;
4726 Py_DECREF(x);
4727
4728 Py_DECREF(safepickle);
4729
4730 /* module initialization */
4731 PyModule_AddIntConstant(m, "MINYEAR", MINYEAR);
4732 PyModule_AddIntConstant(m, "MAXYEAR", MAXYEAR);
4733
4734 Py_INCREF(&PyDateTime_DateType);
4735 PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType);
4736
Tim Petersa9bc1682003-01-11 03:39:11 +00004737 Py_INCREF(&PyDateTime_DateTimeType);
4738 PyModule_AddObject(m, "datetime",
4739 (PyObject *)&PyDateTime_DateTimeType);
4740
4741 Py_INCREF(&PyDateTime_TimeType);
4742 PyModule_AddObject(m, "time", (PyObject *) &PyDateTime_TimeType);
4743
Tim Peters2a799bf2002-12-16 20:18:38 +00004744 Py_INCREF(&PyDateTime_DeltaType);
4745 PyModule_AddObject(m, "timedelta", (PyObject *) &PyDateTime_DeltaType);
4746
Tim Peters2a799bf2002-12-16 20:18:38 +00004747 Py_INCREF(&PyDateTime_TZInfoType);
4748 PyModule_AddObject(m, "tzinfo", (PyObject *) &PyDateTime_TZInfoType);
4749
Tim Peters2a799bf2002-12-16 20:18:38 +00004750 /* A 4-year cycle has an extra leap day over what we'd get from
4751 * pasting together 4 single years.
4752 */
4753 assert(DI4Y == 4 * 365 + 1);
4754 assert(DI4Y == days_before_year(4+1));
4755
4756 /* Similarly, a 400-year cycle has an extra leap day over what we'd
4757 * get from pasting together 4 100-year cycles.
4758 */
4759 assert(DI400Y == 4 * DI100Y + 1);
4760 assert(DI400Y == days_before_year(400+1));
4761
4762 /* OTOH, a 100-year cycle has one fewer leap day than we'd get from
4763 * pasting together 25 4-year cycles.
4764 */
4765 assert(DI100Y == 25 * DI4Y - 1);
4766 assert(DI100Y == days_before_year(100+1));
4767
4768 us_per_us = PyInt_FromLong(1);
4769 us_per_ms = PyInt_FromLong(1000);
4770 us_per_second = PyInt_FromLong(1000000);
4771 us_per_minute = PyInt_FromLong(60000000);
4772 seconds_per_day = PyInt_FromLong(24 * 3600);
4773 if (us_per_us == NULL || us_per_ms == NULL || us_per_second == NULL ||
4774 us_per_minute == NULL || seconds_per_day == NULL)
4775 return;
4776
4777 /* The rest are too big for 32-bit ints, but even
4778 * us_per_week fits in 40 bits, so doubles should be exact.
4779 */
4780 us_per_hour = PyLong_FromDouble(3600000000.0);
4781 us_per_day = PyLong_FromDouble(86400000000.0);
4782 us_per_week = PyLong_FromDouble(604800000000.0);
4783 if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL)
4784 return;
4785}
Tim Petersf3615152003-01-01 21:51:37 +00004786
4787/* ---------------------------------------------------------------------------
Tim Petersa9bc1682003-01-11 03:39:11 +00004788Some time zone algebra. For a datetime x, let
Tim Petersf3615152003-01-01 21:51:37 +00004789 x.n = x stripped of its timezone -- its naive time.
4790 x.o = x.utcoffset(), and assuming that doesn't raise an exception or
4791 return None
4792 x.d = x.dst(), and assuming that doesn't raise an exception or
4793 return None
4794 x.s = x's standard offset, x.o - x.d
4795
4796Now some derived rules, where k is a duration (timedelta).
4797
47981. x.o = x.s + x.d
4799 This follows from the definition of x.s.
4800
Tim Petersc5dc4da2003-01-02 17:55:03 +000048012. If x and y have the same tzinfo member, x.s = y.s.
Tim Petersf3615152003-01-01 21:51:37 +00004802 This is actually a requirement, an assumption we need to make about
4803 sane tzinfo classes.
4804
48053. The naive UTC time corresponding to x is x.n - x.o.
4806 This is again a requirement for a sane tzinfo class.
4807
48084. (x+k).s = x.s
Tim Petersa9bc1682003-01-11 03:39:11 +00004809 This follows from #2, and that datimetime+timedelta preserves tzinfo.
Tim Petersf3615152003-01-01 21:51:37 +00004810
Tim Petersc5dc4da2003-01-02 17:55:03 +000048115. (x+k).n = x.n + k
Tim Petersf3615152003-01-01 21:51:37 +00004812 Again follows from how arithmetic is defined.
4813
4814Now we can explain x.astimezone(tz). Let's assume it's an interesting case
4815(meaning that the various tzinfo methods exist, and don't blow up or return
4816None when called).
4817
Tim Petersa9bc1682003-01-11 03:39:11 +00004818The function wants to return a datetime y with timezone tz, equivalent to x.
Tim Petersf3615152003-01-01 21:51:37 +00004819
4820By #3, we want
4821
4822 y.n - y.o = x.n - x.o [1]
4823
4824The algorithm starts by attaching tz to x.n, and calling that y. So
4825x.n = y.n at the start. Then it wants to add a duration k to y, so that [1]
4826becomes true; in effect, we want to solve [2] for k:
4827
4828 (y+k).n - (y+k).o = x.n - x.o [2]
4829
4830By #1, this is the same as
4831
4832 (y+k).n - ((y+k).s + (y+k).d) = x.n - x.o [3]
4833
4834By #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start.
4835Substituting that into [3],
4836
4837 x.n + k - (y+k).s - (y+k).d = x.n - x.o; the x.n terms cancel, leaving
4838 k - (y+k).s - (y+k).d = - x.o; rearranging,
4839 k = (y+k).s - x.o - (y+k).d; by #4, (y+k).s == y.s, so
4840 k = y.s - x.o - (y+k).d; then by #1, y.s = y.o - y.d, so
4841 k = y.o - y.d - x.o - (y+k).d
4842
4843On the RHS, (y+k).d can't be computed directly, but all the rest can be, and
4844we approximate k by ignoring the (y+k).d term at first. Note that k can't
4845be very large, since all offset-returning methods return a duration of
4846magnitude less than 24 hours. For that reason, if y is firmly in std time,
4847(y+k).d must be 0, so ignoring it has no consequence then.
4848
4849In any case, the new value is
4850
Tim Petersc5dc4da2003-01-02 17:55:03 +00004851 z = y + y.o - y.d - x.o [4]
Tim Petersf3615152003-01-01 21:51:37 +00004852
Tim Petersc5dc4da2003-01-02 17:55:03 +00004853It's helpful to step back at look at [4] from a higher level: rewrite it as
Tim Petersf3615152003-01-01 21:51:37 +00004854
Tim Petersc5dc4da2003-01-02 17:55:03 +00004855 z = (y - x.o) + (y.o - y.d)
4856
4857(y - x.o).n = [by #5] y.n - x.o = [since y.n=x.n] x.n - x.o = [by #3] x's
4858UTC equivalent time. So the y-x.o part essentially converts x to UTC. Then
4859the y.o-y.d part essentially converts x's UTC equivalent into tz's standard
4860time (y.o-y.d=y.s by #1).
4861
4862At this point, if
4863
4864 z.n - z.o = x.n - x.o [5]
4865
4866we have an equivalent time, and are almost done. The insecurity here is
Tim Petersf3615152003-01-01 21:51:37 +00004867at the start of daylight time. Picture US Eastern for concreteness. The wall
4868time jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good
4869sense then. A sensible Eastern tzinfo class will consider such a time to be
4870EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST on the
4871day DST starts. We want to return the 1:MM EST spelling because that's
4872the only spelling that makes sense on the local wall clock.
4873
Tim Petersc5dc4da2003-01-02 17:55:03 +00004874In fact, if [5] holds at this point, we do have the standard-time spelling,
4875but that takes a bit of proof. We first prove a stronger result. What's the
4876difference between the LHS and RHS of [5]? Let
Tim Petersf3615152003-01-01 21:51:37 +00004877
Tim Petersc5dc4da2003-01-02 17:55:03 +00004878 diff = (x.n - x.o) - (z.n - z.o) [6]
Tim Petersf3615152003-01-01 21:51:37 +00004879
Tim Petersc5dc4da2003-01-02 17:55:03 +00004880Now
4881 z.n = by [4]
4882 (y + y.o - y.d - x.o).n = by #5
4883 y.n + y.o - y.d - x.o = since y.n = x.n
4884 x.n + y.o - y.d - x.o = since y.o = y.s + y.d by #1
4885 x.n + (y.s + y.d) - y.d - x.o = cancelling the y.d terms
4886 x.n + y.s - x.o = since z and y are have the same tzinfo member,
4887 y.s = z.s by #2
4888 x.n + z.s - x.o
Tim Petersf3615152003-01-01 21:51:37 +00004889
Tim Petersc5dc4da2003-01-02 17:55:03 +00004890Plugging that back into [6] gives
Tim Petersf3615152003-01-01 21:51:37 +00004891
Tim Petersc5dc4da2003-01-02 17:55:03 +00004892 diff =
4893 (x.n - x.o) - ((x.n + z.s - x.o) - z.o) = expanding
4894 x.n - x.o - x.n - z.s + x.o + z.o = cancelling
4895 - z.s + z.o = by #2
4896 z.d
Tim Petersf3615152003-01-01 21:51:37 +00004897
Tim Petersc5dc4da2003-01-02 17:55:03 +00004898So diff = z.d.
Tim Petersf3615152003-01-01 21:51:37 +00004899
Tim Petersc5dc4da2003-01-02 17:55:03 +00004900If [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time
4901spelling we wanted in the endcase described above. We're done.
Tim Petersf3615152003-01-01 21:51:37 +00004902
Tim Petersc5dc4da2003-01-02 17:55:03 +00004903If [5] is not true now, diff = z.d != 0, and z.d is the offset we need to
4904add to z (in effect, z is in tz's standard time, and we need to shift the
4905offset into tz's daylight time).
Tim Petersf3615152003-01-01 21:51:37 +00004906
Tim Petersc5dc4da2003-01-02 17:55:03 +00004907Let
Tim Petersf3615152003-01-01 21:51:37 +00004908
Tim Peters4fede1a2003-01-04 00:26:59 +00004909 z' = z + z.d = z + diff [7]
Tim Petersc3bb26a2003-01-02 03:14:59 +00004910
Tim Peters4fede1a2003-01-04 00:26:59 +00004911and we can again ask whether
Tim Petersc3bb26a2003-01-02 03:14:59 +00004912
Tim Peters4fede1a2003-01-04 00:26:59 +00004913 z'.n - z'.o = x.n - x.o [8]
Tim Petersc3bb26a2003-01-02 03:14:59 +00004914
4915If so, we're done. If not, the tzinfo class is insane, or we're trying to
Tim Peters4fede1a2003-01-04 00:26:59 +00004916convert to the hour that can't be spelled in tz. This also requires a
4917bit of proof. As before, let's compute the difference between the LHS and
4918RHS of [8] (and skipping some of the justifications for the kinds of
4919substitutions we've done several times already):
4920
4921 diff' = (x.n - x.o) - (z'.n - z'.o) = replacing z'.n via [7]
4922 (x.n - x.o) - (z.n + diff - z'.o) = replacing diff via [6]
4923 (x.n - x.o) - (z.n + (x.n - x.o) - (z.n - z.o) - z'.o) =
4924 x.n - x.o - z.n - x.n + x.o + z.n - z.o + z'.o = cancel x.n
4925 - x.o - z.n + x.o + z.n - z.o + z'.o = cancel x.o
4926 - z.n + z.n - z.o + z'.o = cancel z.n
4927 - z.o + z'.o = #1 twice
4928 -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo
4929 z'.d - z.d
4930
4931So z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal,
4932we've found the UTC-equivalent so are done.
4933
4934How could they differ? z' = z + z.d [7], so merely moving z' by a dst()
4935offset, and starting *from* a time already in DST (we know z.d != 0), would
4936have to change the result dst() returns: we start in DST, and moving a
4937little further into it takes us out of DST.
4938
4939There's (only) one sane case where this can happen: at the end of DST,
4940there's an hour in UTC with no spelling in a hybrid tzinfo class. In US
4941Eastern, that's 6:MM UTC = 1:MM EST = 2:MM EDT. During that hour, on an
4942Eastern clock 1:MM is taken as being in daylight time (5:MM UTC), but 2:MM is
4943taken as being in standard time (7:MM UTC). There is no local time mapping to
49446:MM UTC. The local clock jumps from 1:59 back to 1:00 again, and repeats the
49451:MM hour in standard time. Since that's what the local clock *does*, we want
4946to map both UTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous
4947in local time, but so it goes -- it's the way the local clock works.
4948
4949When x = 6:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0,
4950so z=1:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going.
4951z' = z + z.d = 2:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8]
4952(correctly) concludes that z' is not UTC-equivalent to x.
4953
4954Because we know z.d said z was in daylight time (else [5] would have held and
4955we would have stopped then), and we know z.d != z'.d (else [8] would have held
4956and we we have stopped then), and there are only 2 possible values dst() can
4957return in Eastern, it follows that z'.d must be 0 (which it is in the example,
4958but the reasoning doesn't depend on the example -- it depends on there being
4959two possible dst() outcomes, one zero and the other non-zero). Therefore
4960z' must be in standard time, and is not the spelling we want in this case.
4961z is in daylight time, and is the spelling we want. Note again that z is
4962not UTC-equivalent as far as the hybrid tzinfo class is concerned (because
4963it takes z as being in standard time rather than the daylight time we intend
4964here), but returning it gives the real-life "local clock repeats an hour"
4965behavior when mapping the "unspellable" UTC hour into tz.
Tim Petersf3615152003-01-01 21:51:37 +00004966--------------------------------------------------------------------------- */