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