17db96d56Sopenharmony_ci/* C implementation for the date/time type documented at 27db96d56Sopenharmony_ci * https://www.zope.dev/Members/fdrake/DateTimeWiki/FrontPage 37db96d56Sopenharmony_ci */ 47db96d56Sopenharmony_ci 57db96d56Sopenharmony_ci/* bpo-35081: Defining this prevents including the C API capsule; 67db96d56Sopenharmony_ci * internal versions of the Py*_Check macros which do not require 77db96d56Sopenharmony_ci * the capsule are defined below */ 87db96d56Sopenharmony_ci#define _PY_DATETIME_IMPL 97db96d56Sopenharmony_ci 107db96d56Sopenharmony_ci#ifndef Py_BUILD_CORE_BUILTIN 117db96d56Sopenharmony_ci# define Py_BUILD_CORE_MODULE 1 127db96d56Sopenharmony_ci#endif 137db96d56Sopenharmony_ci#define NEEDS_PY_IDENTIFIER 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ci#include "Python.h" 167db96d56Sopenharmony_ci#include "pycore_long.h" // _PyLong_GetOne() 177db96d56Sopenharmony_ci#include "pycore_object.h" // _PyObject_Init() 187db96d56Sopenharmony_ci#include "datetime.h" 197db96d56Sopenharmony_ci#include "structmember.h" // PyMemberDef 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ci#include <time.h> 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_ci#ifdef MS_WINDOWS 247db96d56Sopenharmony_ci# include <winsock2.h> /* struct timeval */ 257db96d56Sopenharmony_ci#endif 267db96d56Sopenharmony_ci 277db96d56Sopenharmony_ci#define PyDate_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateType) 287db96d56Sopenharmony_ci#define PyDate_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_DateType) 297db96d56Sopenharmony_ci 307db96d56Sopenharmony_ci#define PyDateTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_DateTimeType) 317db96d56Sopenharmony_ci#define PyDateTime_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_DateTimeType) 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci#define PyTime_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeType) 347db96d56Sopenharmony_ci#define PyTime_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_TimeType) 357db96d56Sopenharmony_ci 367db96d56Sopenharmony_ci#define PyDelta_Check(op) PyObject_TypeCheck(op, &PyDateTime_DeltaType) 377db96d56Sopenharmony_ci#define PyDelta_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_DeltaType) 387db96d56Sopenharmony_ci 397db96d56Sopenharmony_ci#define PyTZInfo_Check(op) PyObject_TypeCheck(op, &PyDateTime_TZInfoType) 407db96d56Sopenharmony_ci#define PyTZInfo_CheckExact(op) Py_IS_TYPE(op, &PyDateTime_TZInfoType) 417db96d56Sopenharmony_ci 427db96d56Sopenharmony_ci#define PyTimezone_Check(op) PyObject_TypeCheck(op, &PyDateTime_TimeZoneType) 437db96d56Sopenharmony_ci 447db96d56Sopenharmony_ci/*[clinic input] 457db96d56Sopenharmony_cimodule datetime 467db96d56Sopenharmony_ciclass datetime.datetime "PyDateTime_DateTime *" "&PyDateTime_DateTimeType" 477db96d56Sopenharmony_ciclass datetime.date "PyDateTime_Date *" "&PyDateTime_DateType" 487db96d56Sopenharmony_ciclass datetime.IsoCalendarDate "PyDateTime_IsoCalendarDate *" "&PyDateTime_IsoCalendarDateType" 497db96d56Sopenharmony_ci[clinic start generated code]*/ 507db96d56Sopenharmony_ci/*[clinic end generated code: output=da39a3ee5e6b4b0d input=81bec0fa19837f63]*/ 517db96d56Sopenharmony_ci 527db96d56Sopenharmony_ci#include "clinic/_datetimemodule.c.h" 537db96d56Sopenharmony_ci 547db96d56Sopenharmony_ci/* We require that C int be at least 32 bits, and use int virtually 557db96d56Sopenharmony_ci * everywhere. In just a few cases we use a temp long, where a Python 567db96d56Sopenharmony_ci * API returns a C long. In such cases, we have to ensure that the 577db96d56Sopenharmony_ci * final result fits in a C int (this can be an issue on 64-bit boxes). 587db96d56Sopenharmony_ci */ 597db96d56Sopenharmony_ci#if SIZEOF_INT < 4 607db96d56Sopenharmony_ci# error "_datetime.c requires that C int have at least 32 bits" 617db96d56Sopenharmony_ci#endif 627db96d56Sopenharmony_ci 637db96d56Sopenharmony_ci#define MINYEAR 1 647db96d56Sopenharmony_ci#define MAXYEAR 9999 657db96d56Sopenharmony_ci#define MAXORDINAL 3652059 /* date(9999,12,31).toordinal() */ 667db96d56Sopenharmony_ci 677db96d56Sopenharmony_ci/* Nine decimal digits is easy to communicate, and leaves enough room 687db96d56Sopenharmony_ci * so that two delta days can be added w/o fear of overflowing a signed 697db96d56Sopenharmony_ci * 32-bit int, and with plenty of room left over to absorb any possible 707db96d56Sopenharmony_ci * carries from adding seconds. 717db96d56Sopenharmony_ci */ 727db96d56Sopenharmony_ci#define MAX_DELTA_DAYS 999999999 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_ci/* Rename the long macros in datetime.h to more reasonable short names. */ 757db96d56Sopenharmony_ci#define GET_YEAR PyDateTime_GET_YEAR 767db96d56Sopenharmony_ci#define GET_MONTH PyDateTime_GET_MONTH 777db96d56Sopenharmony_ci#define GET_DAY PyDateTime_GET_DAY 787db96d56Sopenharmony_ci#define DATE_GET_HOUR PyDateTime_DATE_GET_HOUR 797db96d56Sopenharmony_ci#define DATE_GET_MINUTE PyDateTime_DATE_GET_MINUTE 807db96d56Sopenharmony_ci#define DATE_GET_SECOND PyDateTime_DATE_GET_SECOND 817db96d56Sopenharmony_ci#define DATE_GET_MICROSECOND PyDateTime_DATE_GET_MICROSECOND 827db96d56Sopenharmony_ci#define DATE_GET_FOLD PyDateTime_DATE_GET_FOLD 837db96d56Sopenharmony_ci 847db96d56Sopenharmony_ci/* Date accessors for date and datetime. */ 857db96d56Sopenharmony_ci#define SET_YEAR(o, v) (((o)->data[0] = ((v) & 0xff00) >> 8), \ 867db96d56Sopenharmony_ci ((o)->data[1] = ((v) & 0x00ff))) 877db96d56Sopenharmony_ci#define SET_MONTH(o, v) (PyDateTime_GET_MONTH(o) = (v)) 887db96d56Sopenharmony_ci#define SET_DAY(o, v) (PyDateTime_GET_DAY(o) = (v)) 897db96d56Sopenharmony_ci 907db96d56Sopenharmony_ci/* Date/Time accessors for datetime. */ 917db96d56Sopenharmony_ci#define DATE_SET_HOUR(o, v) (PyDateTime_DATE_GET_HOUR(o) = (v)) 927db96d56Sopenharmony_ci#define DATE_SET_MINUTE(o, v) (PyDateTime_DATE_GET_MINUTE(o) = (v)) 937db96d56Sopenharmony_ci#define DATE_SET_SECOND(o, v) (PyDateTime_DATE_GET_SECOND(o) = (v)) 947db96d56Sopenharmony_ci#define DATE_SET_MICROSECOND(o, v) \ 957db96d56Sopenharmony_ci (((o)->data[7] = ((v) & 0xff0000) >> 16), \ 967db96d56Sopenharmony_ci ((o)->data[8] = ((v) & 0x00ff00) >> 8), \ 977db96d56Sopenharmony_ci ((o)->data[9] = ((v) & 0x0000ff))) 987db96d56Sopenharmony_ci#define DATE_SET_FOLD(o, v) (PyDateTime_DATE_GET_FOLD(o) = (v)) 997db96d56Sopenharmony_ci 1007db96d56Sopenharmony_ci/* Time accessors for time. */ 1017db96d56Sopenharmony_ci#define TIME_GET_HOUR PyDateTime_TIME_GET_HOUR 1027db96d56Sopenharmony_ci#define TIME_GET_MINUTE PyDateTime_TIME_GET_MINUTE 1037db96d56Sopenharmony_ci#define TIME_GET_SECOND PyDateTime_TIME_GET_SECOND 1047db96d56Sopenharmony_ci#define TIME_GET_MICROSECOND PyDateTime_TIME_GET_MICROSECOND 1057db96d56Sopenharmony_ci#define TIME_GET_FOLD PyDateTime_TIME_GET_FOLD 1067db96d56Sopenharmony_ci#define TIME_SET_HOUR(o, v) (PyDateTime_TIME_GET_HOUR(o) = (v)) 1077db96d56Sopenharmony_ci#define TIME_SET_MINUTE(o, v) (PyDateTime_TIME_GET_MINUTE(o) = (v)) 1087db96d56Sopenharmony_ci#define TIME_SET_SECOND(o, v) (PyDateTime_TIME_GET_SECOND(o) = (v)) 1097db96d56Sopenharmony_ci#define TIME_SET_MICROSECOND(o, v) \ 1107db96d56Sopenharmony_ci (((o)->data[3] = ((v) & 0xff0000) >> 16), \ 1117db96d56Sopenharmony_ci ((o)->data[4] = ((v) & 0x00ff00) >> 8), \ 1127db96d56Sopenharmony_ci ((o)->data[5] = ((v) & 0x0000ff))) 1137db96d56Sopenharmony_ci#define TIME_SET_FOLD(o, v) (PyDateTime_TIME_GET_FOLD(o) = (v)) 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci/* Delta accessors for timedelta. */ 1167db96d56Sopenharmony_ci#define GET_TD_DAYS(o) (((PyDateTime_Delta *)(o))->days) 1177db96d56Sopenharmony_ci#define GET_TD_SECONDS(o) (((PyDateTime_Delta *)(o))->seconds) 1187db96d56Sopenharmony_ci#define GET_TD_MICROSECONDS(o) (((PyDateTime_Delta *)(o))->microseconds) 1197db96d56Sopenharmony_ci 1207db96d56Sopenharmony_ci#define SET_TD_DAYS(o, v) ((o)->days = (v)) 1217db96d56Sopenharmony_ci#define SET_TD_SECONDS(o, v) ((o)->seconds = (v)) 1227db96d56Sopenharmony_ci#define SET_TD_MICROSECONDS(o, v) ((o)->microseconds = (v)) 1237db96d56Sopenharmony_ci 1247db96d56Sopenharmony_ci#define HASTZINFO _PyDateTime_HAS_TZINFO 1257db96d56Sopenharmony_ci#define GET_TIME_TZINFO PyDateTime_TIME_GET_TZINFO 1267db96d56Sopenharmony_ci#define GET_DT_TZINFO PyDateTime_DATE_GET_TZINFO 1277db96d56Sopenharmony_ci/* M is a char or int claiming to be a valid month. The macro is equivalent 1287db96d56Sopenharmony_ci * to the two-sided Python test 1297db96d56Sopenharmony_ci * 1 <= M <= 12 1307db96d56Sopenharmony_ci */ 1317db96d56Sopenharmony_ci#define MONTH_IS_SANE(M) ((unsigned int)(M) - 1 < 12) 1327db96d56Sopenharmony_ci 1337db96d56Sopenharmony_ci/* Forward declarations. */ 1347db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_DateType; 1357db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_DateTimeType; 1367db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_DeltaType; 1377db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_IsoCalendarDateType; 1387db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_TimeType; 1397db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_TZInfoType; 1407db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_TimeZoneType; 1417db96d56Sopenharmony_ci 1427db96d56Sopenharmony_cistatic int check_tzinfo_subclass(PyObject *p); 1437db96d56Sopenharmony_ci 1447db96d56Sopenharmony_ci_Py_IDENTIFIER(as_integer_ratio); 1457db96d56Sopenharmony_ci_Py_IDENTIFIER(fromutc); 1467db96d56Sopenharmony_ci_Py_IDENTIFIER(isoformat); 1477db96d56Sopenharmony_ci_Py_IDENTIFIER(strftime); 1487db96d56Sopenharmony_ci 1497db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 1507db96d56Sopenharmony_ci * Math utilities. 1517db96d56Sopenharmony_ci */ 1527db96d56Sopenharmony_ci 1537db96d56Sopenharmony_ci/* k = i+j overflows iff k differs in sign from both inputs, 1547db96d56Sopenharmony_ci * iff k^i has sign bit set and k^j has sign bit set, 1557db96d56Sopenharmony_ci * iff (k^i)&(k^j) has sign bit set. 1567db96d56Sopenharmony_ci */ 1577db96d56Sopenharmony_ci#define SIGNED_ADD_OVERFLOWED(RESULT, I, J) \ 1587db96d56Sopenharmony_ci ((((RESULT) ^ (I)) & ((RESULT) ^ (J))) < 0) 1597db96d56Sopenharmony_ci 1607db96d56Sopenharmony_ci/* Compute Python divmod(x, y), returning the quotient and storing the 1617db96d56Sopenharmony_ci * remainder into *r. The quotient is the floor of x/y, and that's 1627db96d56Sopenharmony_ci * the real point of this. C will probably truncate instead (C99 1637db96d56Sopenharmony_ci * requires truncation; C89 left it implementation-defined). 1647db96d56Sopenharmony_ci * Simplification: we *require* that y > 0 here. That's appropriate 1657db96d56Sopenharmony_ci * for all the uses made of it. This simplifies the code and makes 1667db96d56Sopenharmony_ci * the overflow case impossible (divmod(LONG_MIN, -1) is the only 1677db96d56Sopenharmony_ci * overflow case). 1687db96d56Sopenharmony_ci */ 1697db96d56Sopenharmony_cistatic int 1707db96d56Sopenharmony_cidivmod(int x, int y, int *r) 1717db96d56Sopenharmony_ci{ 1727db96d56Sopenharmony_ci int quo; 1737db96d56Sopenharmony_ci 1747db96d56Sopenharmony_ci assert(y > 0); 1757db96d56Sopenharmony_ci quo = x / y; 1767db96d56Sopenharmony_ci *r = x - quo * y; 1777db96d56Sopenharmony_ci if (*r < 0) { 1787db96d56Sopenharmony_ci --quo; 1797db96d56Sopenharmony_ci *r += y; 1807db96d56Sopenharmony_ci } 1817db96d56Sopenharmony_ci assert(0 <= *r && *r < y); 1827db96d56Sopenharmony_ci return quo; 1837db96d56Sopenharmony_ci} 1847db96d56Sopenharmony_ci 1857db96d56Sopenharmony_ci/* Nearest integer to m / n for integers m and n. Half-integer results 1867db96d56Sopenharmony_ci * are rounded to even. 1877db96d56Sopenharmony_ci */ 1887db96d56Sopenharmony_cistatic PyObject * 1897db96d56Sopenharmony_cidivide_nearest(PyObject *m, PyObject *n) 1907db96d56Sopenharmony_ci{ 1917db96d56Sopenharmony_ci PyObject *result; 1927db96d56Sopenharmony_ci PyObject *temp; 1937db96d56Sopenharmony_ci 1947db96d56Sopenharmony_ci temp = _PyLong_DivmodNear(m, n); 1957db96d56Sopenharmony_ci if (temp == NULL) 1967db96d56Sopenharmony_ci return NULL; 1977db96d56Sopenharmony_ci result = PyTuple_GET_ITEM(temp, 0); 1987db96d56Sopenharmony_ci Py_INCREF(result); 1997db96d56Sopenharmony_ci Py_DECREF(temp); 2007db96d56Sopenharmony_ci 2017db96d56Sopenharmony_ci return result; 2027db96d56Sopenharmony_ci} 2037db96d56Sopenharmony_ci 2047db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 2057db96d56Sopenharmony_ci * General calendrical helper functions 2067db96d56Sopenharmony_ci */ 2077db96d56Sopenharmony_ci 2087db96d56Sopenharmony_ci/* For each month ordinal in 1..12, the number of days in that month, 2097db96d56Sopenharmony_ci * and the number of days before that month in the same year. These 2107db96d56Sopenharmony_ci * are correct for non-leap years only. 2117db96d56Sopenharmony_ci */ 2127db96d56Sopenharmony_cistatic const int _days_in_month[] = { 2137db96d56Sopenharmony_ci 0, /* unused; this vector uses 1-based indexing */ 2147db96d56Sopenharmony_ci 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 2157db96d56Sopenharmony_ci}; 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_cistatic const int _days_before_month[] = { 2187db96d56Sopenharmony_ci 0, /* unused; this vector uses 1-based indexing */ 2197db96d56Sopenharmony_ci 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 2207db96d56Sopenharmony_ci}; 2217db96d56Sopenharmony_ci 2227db96d56Sopenharmony_ci/* year -> 1 if leap year, else 0. */ 2237db96d56Sopenharmony_cistatic int 2247db96d56Sopenharmony_ciis_leap(int year) 2257db96d56Sopenharmony_ci{ 2267db96d56Sopenharmony_ci /* Cast year to unsigned. The result is the same either way, but 2277db96d56Sopenharmony_ci * C can generate faster code for unsigned mod than for signed 2287db96d56Sopenharmony_ci * mod (especially for % 4 -- a good compiler should just grab 2297db96d56Sopenharmony_ci * the last 2 bits when the LHS is unsigned). 2307db96d56Sopenharmony_ci */ 2317db96d56Sopenharmony_ci const unsigned int ayear = (unsigned int)year; 2327db96d56Sopenharmony_ci return ayear % 4 == 0 && (ayear % 100 != 0 || ayear % 400 == 0); 2337db96d56Sopenharmony_ci} 2347db96d56Sopenharmony_ci 2357db96d56Sopenharmony_ci/* year, month -> number of days in that month in that year */ 2367db96d56Sopenharmony_cistatic int 2377db96d56Sopenharmony_cidays_in_month(int year, int month) 2387db96d56Sopenharmony_ci{ 2397db96d56Sopenharmony_ci assert(month >= 1); 2407db96d56Sopenharmony_ci assert(month <= 12); 2417db96d56Sopenharmony_ci if (month == 2 && is_leap(year)) 2427db96d56Sopenharmony_ci return 29; 2437db96d56Sopenharmony_ci else 2447db96d56Sopenharmony_ci return _days_in_month[month]; 2457db96d56Sopenharmony_ci} 2467db96d56Sopenharmony_ci 2477db96d56Sopenharmony_ci/* year, month -> number of days in year preceding first day of month */ 2487db96d56Sopenharmony_cistatic int 2497db96d56Sopenharmony_cidays_before_month(int year, int month) 2507db96d56Sopenharmony_ci{ 2517db96d56Sopenharmony_ci int days; 2527db96d56Sopenharmony_ci 2537db96d56Sopenharmony_ci assert(month >= 1); 2547db96d56Sopenharmony_ci assert(month <= 12); 2557db96d56Sopenharmony_ci days = _days_before_month[month]; 2567db96d56Sopenharmony_ci if (month > 2 && is_leap(year)) 2577db96d56Sopenharmony_ci ++days; 2587db96d56Sopenharmony_ci return days; 2597db96d56Sopenharmony_ci} 2607db96d56Sopenharmony_ci 2617db96d56Sopenharmony_ci/* year -> number of days before January 1st of year. Remember that we 2627db96d56Sopenharmony_ci * start with year 1, so days_before_year(1) == 0. 2637db96d56Sopenharmony_ci */ 2647db96d56Sopenharmony_cistatic int 2657db96d56Sopenharmony_cidays_before_year(int year) 2667db96d56Sopenharmony_ci{ 2677db96d56Sopenharmony_ci int y = year - 1; 2687db96d56Sopenharmony_ci /* This is incorrect if year <= 0; we really want the floor 2697db96d56Sopenharmony_ci * here. But so long as MINYEAR is 1, the smallest year this 2707db96d56Sopenharmony_ci * can see is 1. 2717db96d56Sopenharmony_ci */ 2727db96d56Sopenharmony_ci assert (year >= 1); 2737db96d56Sopenharmony_ci return y*365 + y/4 - y/100 + y/400; 2747db96d56Sopenharmony_ci} 2757db96d56Sopenharmony_ci 2767db96d56Sopenharmony_ci/* Number of days in 4, 100, and 400 year cycles. That these have 2777db96d56Sopenharmony_ci * the correct values is asserted in the module init function. 2787db96d56Sopenharmony_ci */ 2797db96d56Sopenharmony_ci#define DI4Y 1461 /* days_before_year(5); days in 4 years */ 2807db96d56Sopenharmony_ci#define DI100Y 36524 /* days_before_year(101); days in 100 years */ 2817db96d56Sopenharmony_ci#define DI400Y 146097 /* days_before_year(401); days in 400 years */ 2827db96d56Sopenharmony_ci 2837db96d56Sopenharmony_ci/* ordinal -> year, month, day, considering 01-Jan-0001 as day 1. */ 2847db96d56Sopenharmony_cistatic void 2857db96d56Sopenharmony_ciord_to_ymd(int ordinal, int *year, int *month, int *day) 2867db96d56Sopenharmony_ci{ 2877db96d56Sopenharmony_ci int n, n1, n4, n100, n400, leapyear, preceding; 2887db96d56Sopenharmony_ci 2897db96d56Sopenharmony_ci /* ordinal is a 1-based index, starting at 1-Jan-1. The pattern of 2907db96d56Sopenharmony_ci * leap years repeats exactly every 400 years. The basic strategy is 2917db96d56Sopenharmony_ci * to find the closest 400-year boundary at or before ordinal, then 2927db96d56Sopenharmony_ci * work with the offset from that boundary to ordinal. Life is much 2937db96d56Sopenharmony_ci * clearer if we subtract 1 from ordinal first -- then the values 2947db96d56Sopenharmony_ci * of ordinal at 400-year boundaries are exactly those divisible 2957db96d56Sopenharmony_ci * by DI400Y: 2967db96d56Sopenharmony_ci * 2977db96d56Sopenharmony_ci * D M Y n n-1 2987db96d56Sopenharmony_ci * -- --- ---- ---------- ---------------- 2997db96d56Sopenharmony_ci * 31 Dec -400 -DI400Y -DI400Y -1 3007db96d56Sopenharmony_ci * 1 Jan -399 -DI400Y +1 -DI400Y 400-year boundary 3017db96d56Sopenharmony_ci * ... 3027db96d56Sopenharmony_ci * 30 Dec 000 -1 -2 3037db96d56Sopenharmony_ci * 31 Dec 000 0 -1 3047db96d56Sopenharmony_ci * 1 Jan 001 1 0 400-year boundary 3057db96d56Sopenharmony_ci * 2 Jan 001 2 1 3067db96d56Sopenharmony_ci * 3 Jan 001 3 2 3077db96d56Sopenharmony_ci * ... 3087db96d56Sopenharmony_ci * 31 Dec 400 DI400Y DI400Y -1 3097db96d56Sopenharmony_ci * 1 Jan 401 DI400Y +1 DI400Y 400-year boundary 3107db96d56Sopenharmony_ci */ 3117db96d56Sopenharmony_ci assert(ordinal >= 1); 3127db96d56Sopenharmony_ci --ordinal; 3137db96d56Sopenharmony_ci n400 = ordinal / DI400Y; 3147db96d56Sopenharmony_ci n = ordinal % DI400Y; 3157db96d56Sopenharmony_ci *year = n400 * 400 + 1; 3167db96d56Sopenharmony_ci 3177db96d56Sopenharmony_ci /* Now n is the (non-negative) offset, in days, from January 1 of 3187db96d56Sopenharmony_ci * year, to the desired date. Now compute how many 100-year cycles 3197db96d56Sopenharmony_ci * precede n. 3207db96d56Sopenharmony_ci * Note that it's possible for n100 to equal 4! In that case 4 full 3217db96d56Sopenharmony_ci * 100-year cycles precede the desired day, which implies the 3227db96d56Sopenharmony_ci * desired day is December 31 at the end of a 400-year cycle. 3237db96d56Sopenharmony_ci */ 3247db96d56Sopenharmony_ci n100 = n / DI100Y; 3257db96d56Sopenharmony_ci n = n % DI100Y; 3267db96d56Sopenharmony_ci 3277db96d56Sopenharmony_ci /* Now compute how many 4-year cycles precede it. */ 3287db96d56Sopenharmony_ci n4 = n / DI4Y; 3297db96d56Sopenharmony_ci n = n % DI4Y; 3307db96d56Sopenharmony_ci 3317db96d56Sopenharmony_ci /* And now how many single years. Again n1 can be 4, and again 3327db96d56Sopenharmony_ci * meaning that the desired day is December 31 at the end of the 3337db96d56Sopenharmony_ci * 4-year cycle. 3347db96d56Sopenharmony_ci */ 3357db96d56Sopenharmony_ci n1 = n / 365; 3367db96d56Sopenharmony_ci n = n % 365; 3377db96d56Sopenharmony_ci 3387db96d56Sopenharmony_ci *year += n100 * 100 + n4 * 4 + n1; 3397db96d56Sopenharmony_ci if (n1 == 4 || n100 == 4) { 3407db96d56Sopenharmony_ci assert(n == 0); 3417db96d56Sopenharmony_ci *year -= 1; 3427db96d56Sopenharmony_ci *month = 12; 3437db96d56Sopenharmony_ci *day = 31; 3447db96d56Sopenharmony_ci return; 3457db96d56Sopenharmony_ci } 3467db96d56Sopenharmony_ci 3477db96d56Sopenharmony_ci /* Now the year is correct, and n is the offset from January 1. We 3487db96d56Sopenharmony_ci * find the month via an estimate that's either exact or one too 3497db96d56Sopenharmony_ci * large. 3507db96d56Sopenharmony_ci */ 3517db96d56Sopenharmony_ci leapyear = n1 == 3 && (n4 != 24 || n100 == 3); 3527db96d56Sopenharmony_ci assert(leapyear == is_leap(*year)); 3537db96d56Sopenharmony_ci *month = (n + 50) >> 5; 3547db96d56Sopenharmony_ci preceding = (_days_before_month[*month] + (*month > 2 && leapyear)); 3557db96d56Sopenharmony_ci if (preceding > n) { 3567db96d56Sopenharmony_ci /* estimate is too large */ 3577db96d56Sopenharmony_ci *month -= 1; 3587db96d56Sopenharmony_ci preceding -= days_in_month(*year, *month); 3597db96d56Sopenharmony_ci } 3607db96d56Sopenharmony_ci n -= preceding; 3617db96d56Sopenharmony_ci assert(0 <= n); 3627db96d56Sopenharmony_ci assert(n < days_in_month(*year, *month)); 3637db96d56Sopenharmony_ci 3647db96d56Sopenharmony_ci *day = n + 1; 3657db96d56Sopenharmony_ci} 3667db96d56Sopenharmony_ci 3677db96d56Sopenharmony_ci/* year, month, day -> ordinal, considering 01-Jan-0001 as day 1. */ 3687db96d56Sopenharmony_cistatic int 3697db96d56Sopenharmony_ciymd_to_ord(int year, int month, int day) 3707db96d56Sopenharmony_ci{ 3717db96d56Sopenharmony_ci return days_before_year(year) + days_before_month(year, month) + day; 3727db96d56Sopenharmony_ci} 3737db96d56Sopenharmony_ci 3747db96d56Sopenharmony_ci/* Day of week, where Monday==0, ..., Sunday==6. 1/1/1 was a Monday. */ 3757db96d56Sopenharmony_cistatic int 3767db96d56Sopenharmony_ciweekday(int year, int month, int day) 3777db96d56Sopenharmony_ci{ 3787db96d56Sopenharmony_ci return (ymd_to_ord(year, month, day) + 6) % 7; 3797db96d56Sopenharmony_ci} 3807db96d56Sopenharmony_ci 3817db96d56Sopenharmony_ci/* Ordinal of the Monday starting week 1 of the ISO year. Week 1 is the 3827db96d56Sopenharmony_ci * first calendar week containing a Thursday. 3837db96d56Sopenharmony_ci */ 3847db96d56Sopenharmony_cistatic int 3857db96d56Sopenharmony_ciiso_week1_monday(int year) 3867db96d56Sopenharmony_ci{ 3877db96d56Sopenharmony_ci int first_day = ymd_to_ord(year, 1, 1); /* ord of 1/1 */ 3887db96d56Sopenharmony_ci /* 0 if 1/1 is a Monday, 1 if a Tue, etc. */ 3897db96d56Sopenharmony_ci int first_weekday = (first_day + 6) % 7; 3907db96d56Sopenharmony_ci /* ordinal of closest Monday at or before 1/1 */ 3917db96d56Sopenharmony_ci int week1_monday = first_day - first_weekday; 3927db96d56Sopenharmony_ci 3937db96d56Sopenharmony_ci if (first_weekday > 3) /* if 1/1 was Fri, Sat, Sun */ 3947db96d56Sopenharmony_ci week1_monday += 7; 3957db96d56Sopenharmony_ci return week1_monday; 3967db96d56Sopenharmony_ci} 3977db96d56Sopenharmony_ci 3987db96d56Sopenharmony_cistatic int 3997db96d56Sopenharmony_ciiso_to_ymd(const int iso_year, const int iso_week, const int iso_day, 4007db96d56Sopenharmony_ci int *year, int *month, int *day) { 4017db96d56Sopenharmony_ci if (iso_week <= 0 || iso_week >= 53) { 4027db96d56Sopenharmony_ci int out_of_range = 1; 4037db96d56Sopenharmony_ci if (iso_week == 53) { 4047db96d56Sopenharmony_ci // ISO years have 53 weeks in it on years starting with a Thursday 4057db96d56Sopenharmony_ci // and on leap years starting on Wednesday 4067db96d56Sopenharmony_ci int first_weekday = weekday(iso_year, 1, 1); 4077db96d56Sopenharmony_ci if (first_weekday == 3 || (first_weekday == 2 && is_leap(iso_year))) { 4087db96d56Sopenharmony_ci out_of_range = 0; 4097db96d56Sopenharmony_ci } 4107db96d56Sopenharmony_ci } 4117db96d56Sopenharmony_ci 4127db96d56Sopenharmony_ci if (out_of_range) { 4137db96d56Sopenharmony_ci return -2; 4147db96d56Sopenharmony_ci } 4157db96d56Sopenharmony_ci } 4167db96d56Sopenharmony_ci 4177db96d56Sopenharmony_ci if (iso_day <= 0 || iso_day >= 8) { 4187db96d56Sopenharmony_ci return -3; 4197db96d56Sopenharmony_ci } 4207db96d56Sopenharmony_ci 4217db96d56Sopenharmony_ci // Convert (Y, W, D) to (Y, M, D) in-place 4227db96d56Sopenharmony_ci int day_1 = iso_week1_monday(iso_year); 4237db96d56Sopenharmony_ci 4247db96d56Sopenharmony_ci int day_offset = (iso_week - 1)*7 + iso_day - 1; 4257db96d56Sopenharmony_ci 4267db96d56Sopenharmony_ci ord_to_ymd(day_1 + day_offset, year, month, day); 4277db96d56Sopenharmony_ci return 0; 4287db96d56Sopenharmony_ci} 4297db96d56Sopenharmony_ci 4307db96d56Sopenharmony_ci 4317db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 4327db96d56Sopenharmony_ci * Range checkers. 4337db96d56Sopenharmony_ci */ 4347db96d56Sopenharmony_ci 4357db96d56Sopenharmony_ci/* Check that -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS. If so, return 0. 4367db96d56Sopenharmony_ci * If not, raise OverflowError and return -1. 4377db96d56Sopenharmony_ci */ 4387db96d56Sopenharmony_cistatic int 4397db96d56Sopenharmony_cicheck_delta_day_range(int days) 4407db96d56Sopenharmony_ci{ 4417db96d56Sopenharmony_ci if (-MAX_DELTA_DAYS <= days && days <= MAX_DELTA_DAYS) 4427db96d56Sopenharmony_ci return 0; 4437db96d56Sopenharmony_ci PyErr_Format(PyExc_OverflowError, 4447db96d56Sopenharmony_ci "days=%d; must have magnitude <= %d", 4457db96d56Sopenharmony_ci days, MAX_DELTA_DAYS); 4467db96d56Sopenharmony_ci return -1; 4477db96d56Sopenharmony_ci} 4487db96d56Sopenharmony_ci 4497db96d56Sopenharmony_ci/* Check that date arguments are in range. Return 0 if they are. If they 4507db96d56Sopenharmony_ci * aren't, raise ValueError and return -1. 4517db96d56Sopenharmony_ci */ 4527db96d56Sopenharmony_cistatic int 4537db96d56Sopenharmony_cicheck_date_args(int year, int month, int day) 4547db96d56Sopenharmony_ci{ 4557db96d56Sopenharmony_ci 4567db96d56Sopenharmony_ci if (year < MINYEAR || year > MAXYEAR) { 4577db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "year %i is out of range", year); 4587db96d56Sopenharmony_ci return -1; 4597db96d56Sopenharmony_ci } 4607db96d56Sopenharmony_ci if (month < 1 || month > 12) { 4617db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 4627db96d56Sopenharmony_ci "month must be in 1..12"); 4637db96d56Sopenharmony_ci return -1; 4647db96d56Sopenharmony_ci } 4657db96d56Sopenharmony_ci if (day < 1 || day > days_in_month(year, month)) { 4667db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 4677db96d56Sopenharmony_ci "day is out of range for month"); 4687db96d56Sopenharmony_ci return -1; 4697db96d56Sopenharmony_ci } 4707db96d56Sopenharmony_ci return 0; 4717db96d56Sopenharmony_ci} 4727db96d56Sopenharmony_ci 4737db96d56Sopenharmony_ci/* Check that time arguments are in range. Return 0 if they are. If they 4747db96d56Sopenharmony_ci * aren't, raise ValueError and return -1. 4757db96d56Sopenharmony_ci */ 4767db96d56Sopenharmony_cistatic int 4777db96d56Sopenharmony_cicheck_time_args(int h, int m, int s, int us, int fold) 4787db96d56Sopenharmony_ci{ 4797db96d56Sopenharmony_ci if (h < 0 || h > 23) { 4807db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 4817db96d56Sopenharmony_ci "hour must be in 0..23"); 4827db96d56Sopenharmony_ci return -1; 4837db96d56Sopenharmony_ci } 4847db96d56Sopenharmony_ci if (m < 0 || m > 59) { 4857db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 4867db96d56Sopenharmony_ci "minute must be in 0..59"); 4877db96d56Sopenharmony_ci return -1; 4887db96d56Sopenharmony_ci } 4897db96d56Sopenharmony_ci if (s < 0 || s > 59) { 4907db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 4917db96d56Sopenharmony_ci "second must be in 0..59"); 4927db96d56Sopenharmony_ci return -1; 4937db96d56Sopenharmony_ci } 4947db96d56Sopenharmony_ci if (us < 0 || us > 999999) { 4957db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 4967db96d56Sopenharmony_ci "microsecond must be in 0..999999"); 4977db96d56Sopenharmony_ci return -1; 4987db96d56Sopenharmony_ci } 4997db96d56Sopenharmony_ci if (fold != 0 && fold != 1) { 5007db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 5017db96d56Sopenharmony_ci "fold must be either 0 or 1"); 5027db96d56Sopenharmony_ci return -1; 5037db96d56Sopenharmony_ci } 5047db96d56Sopenharmony_ci return 0; 5057db96d56Sopenharmony_ci} 5067db96d56Sopenharmony_ci 5077db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 5087db96d56Sopenharmony_ci * Normalization utilities. 5097db96d56Sopenharmony_ci */ 5107db96d56Sopenharmony_ci 5117db96d56Sopenharmony_ci/* One step of a mixed-radix conversion. A "hi" unit is equivalent to 5127db96d56Sopenharmony_ci * factor "lo" units. factor must be > 0. If *lo is less than 0, or 5137db96d56Sopenharmony_ci * at least factor, enough of *lo is converted into "hi" units so that 5147db96d56Sopenharmony_ci * 0 <= *lo < factor. The input values must be such that int overflow 5157db96d56Sopenharmony_ci * is impossible. 5167db96d56Sopenharmony_ci */ 5177db96d56Sopenharmony_cistatic void 5187db96d56Sopenharmony_cinormalize_pair(int *hi, int *lo, int factor) 5197db96d56Sopenharmony_ci{ 5207db96d56Sopenharmony_ci assert(factor > 0); 5217db96d56Sopenharmony_ci assert(lo != hi); 5227db96d56Sopenharmony_ci if (*lo < 0 || *lo >= factor) { 5237db96d56Sopenharmony_ci const int num_hi = divmod(*lo, factor, lo); 5247db96d56Sopenharmony_ci const int new_hi = *hi + num_hi; 5257db96d56Sopenharmony_ci assert(! SIGNED_ADD_OVERFLOWED(new_hi, *hi, num_hi)); 5267db96d56Sopenharmony_ci *hi = new_hi; 5277db96d56Sopenharmony_ci } 5287db96d56Sopenharmony_ci assert(0 <= *lo && *lo < factor); 5297db96d56Sopenharmony_ci} 5307db96d56Sopenharmony_ci 5317db96d56Sopenharmony_ci/* Fiddle days (d), seconds (s), and microseconds (us) so that 5327db96d56Sopenharmony_ci * 0 <= *s < 24*3600 5337db96d56Sopenharmony_ci * 0 <= *us < 1000000 5347db96d56Sopenharmony_ci * The input values must be such that the internals don't overflow. 5357db96d56Sopenharmony_ci * The way this routine is used, we don't get close. 5367db96d56Sopenharmony_ci */ 5377db96d56Sopenharmony_cistatic void 5387db96d56Sopenharmony_cinormalize_d_s_us(int *d, int *s, int *us) 5397db96d56Sopenharmony_ci{ 5407db96d56Sopenharmony_ci if (*us < 0 || *us >= 1000000) { 5417db96d56Sopenharmony_ci normalize_pair(s, us, 1000000); 5427db96d56Sopenharmony_ci /* |s| can't be bigger than about 5437db96d56Sopenharmony_ci * |original s| + |original us|/1000000 now. 5447db96d56Sopenharmony_ci */ 5457db96d56Sopenharmony_ci 5467db96d56Sopenharmony_ci } 5477db96d56Sopenharmony_ci if (*s < 0 || *s >= 24*3600) { 5487db96d56Sopenharmony_ci normalize_pair(d, s, 24*3600); 5497db96d56Sopenharmony_ci /* |d| can't be bigger than about 5507db96d56Sopenharmony_ci * |original d| + 5517db96d56Sopenharmony_ci * (|original s| + |original us|/1000000) / (24*3600) now. 5527db96d56Sopenharmony_ci */ 5537db96d56Sopenharmony_ci } 5547db96d56Sopenharmony_ci assert(0 <= *s && *s < 24*3600); 5557db96d56Sopenharmony_ci assert(0 <= *us && *us < 1000000); 5567db96d56Sopenharmony_ci} 5577db96d56Sopenharmony_ci 5587db96d56Sopenharmony_ci/* Fiddle years (y), months (m), and days (d) so that 5597db96d56Sopenharmony_ci * 1 <= *m <= 12 5607db96d56Sopenharmony_ci * 1 <= *d <= days_in_month(*y, *m) 5617db96d56Sopenharmony_ci * The input values must be such that the internals don't overflow. 5627db96d56Sopenharmony_ci * The way this routine is used, we don't get close. 5637db96d56Sopenharmony_ci */ 5647db96d56Sopenharmony_cistatic int 5657db96d56Sopenharmony_cinormalize_y_m_d(int *y, int *m, int *d) 5667db96d56Sopenharmony_ci{ 5677db96d56Sopenharmony_ci int dim; /* # of days in month */ 5687db96d56Sopenharmony_ci 5697db96d56Sopenharmony_ci /* In actual use, m is always the month component extracted from a 5707db96d56Sopenharmony_ci * date/datetime object. Therefore it is always in [1, 12] range. 5717db96d56Sopenharmony_ci */ 5727db96d56Sopenharmony_ci 5737db96d56Sopenharmony_ci assert(1 <= *m && *m <= 12); 5747db96d56Sopenharmony_ci 5757db96d56Sopenharmony_ci /* Now only day can be out of bounds (year may also be out of bounds 5767db96d56Sopenharmony_ci * for a datetime object, but we don't care about that here). 5777db96d56Sopenharmony_ci * If day is out of bounds, what to do is arguable, but at least the 5787db96d56Sopenharmony_ci * method here is principled and explainable. 5797db96d56Sopenharmony_ci */ 5807db96d56Sopenharmony_ci dim = days_in_month(*y, *m); 5817db96d56Sopenharmony_ci if (*d < 1 || *d > dim) { 5827db96d56Sopenharmony_ci /* Move day-1 days from the first of the month. First try to 5837db96d56Sopenharmony_ci * get off cheap if we're only one day out of range 5847db96d56Sopenharmony_ci * (adjustments for timezone alone can't be worse than that). 5857db96d56Sopenharmony_ci */ 5867db96d56Sopenharmony_ci if (*d == 0) { 5877db96d56Sopenharmony_ci --*m; 5887db96d56Sopenharmony_ci if (*m > 0) 5897db96d56Sopenharmony_ci *d = days_in_month(*y, *m); 5907db96d56Sopenharmony_ci else { 5917db96d56Sopenharmony_ci --*y; 5927db96d56Sopenharmony_ci *m = 12; 5937db96d56Sopenharmony_ci *d = 31; 5947db96d56Sopenharmony_ci } 5957db96d56Sopenharmony_ci } 5967db96d56Sopenharmony_ci else if (*d == dim + 1) { 5977db96d56Sopenharmony_ci /* move forward a day */ 5987db96d56Sopenharmony_ci ++*m; 5997db96d56Sopenharmony_ci *d = 1; 6007db96d56Sopenharmony_ci if (*m > 12) { 6017db96d56Sopenharmony_ci *m = 1; 6027db96d56Sopenharmony_ci ++*y; 6037db96d56Sopenharmony_ci } 6047db96d56Sopenharmony_ci } 6057db96d56Sopenharmony_ci else { 6067db96d56Sopenharmony_ci int ordinal = ymd_to_ord(*y, *m, 1) + 6077db96d56Sopenharmony_ci *d - 1; 6087db96d56Sopenharmony_ci if (ordinal < 1 || ordinal > MAXORDINAL) { 6097db96d56Sopenharmony_ci goto error; 6107db96d56Sopenharmony_ci } else { 6117db96d56Sopenharmony_ci ord_to_ymd(ordinal, y, m, d); 6127db96d56Sopenharmony_ci return 0; 6137db96d56Sopenharmony_ci } 6147db96d56Sopenharmony_ci } 6157db96d56Sopenharmony_ci } 6167db96d56Sopenharmony_ci assert(*m > 0); 6177db96d56Sopenharmony_ci assert(*d > 0); 6187db96d56Sopenharmony_ci if (MINYEAR <= *y && *y <= MAXYEAR) 6197db96d56Sopenharmony_ci return 0; 6207db96d56Sopenharmony_ci error: 6217db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, 6227db96d56Sopenharmony_ci "date value out of range"); 6237db96d56Sopenharmony_ci return -1; 6247db96d56Sopenharmony_ci 6257db96d56Sopenharmony_ci} 6267db96d56Sopenharmony_ci 6277db96d56Sopenharmony_ci/* Fiddle out-of-bounds months and days so that the result makes some kind 6287db96d56Sopenharmony_ci * of sense. The parameters are both inputs and outputs. Returns < 0 on 6297db96d56Sopenharmony_ci * failure, where failure means the adjusted year is out of bounds. 6307db96d56Sopenharmony_ci */ 6317db96d56Sopenharmony_cistatic int 6327db96d56Sopenharmony_cinormalize_date(int *year, int *month, int *day) 6337db96d56Sopenharmony_ci{ 6347db96d56Sopenharmony_ci return normalize_y_m_d(year, month, day); 6357db96d56Sopenharmony_ci} 6367db96d56Sopenharmony_ci 6377db96d56Sopenharmony_ci/* Force all the datetime fields into range. The parameters are both 6387db96d56Sopenharmony_ci * inputs and outputs. Returns < 0 on error. 6397db96d56Sopenharmony_ci */ 6407db96d56Sopenharmony_cistatic int 6417db96d56Sopenharmony_cinormalize_datetime(int *year, int *month, int *day, 6427db96d56Sopenharmony_ci int *hour, int *minute, int *second, 6437db96d56Sopenharmony_ci int *microsecond) 6447db96d56Sopenharmony_ci{ 6457db96d56Sopenharmony_ci normalize_pair(second, microsecond, 1000000); 6467db96d56Sopenharmony_ci normalize_pair(minute, second, 60); 6477db96d56Sopenharmony_ci normalize_pair(hour, minute, 60); 6487db96d56Sopenharmony_ci normalize_pair(day, hour, 24); 6497db96d56Sopenharmony_ci return normalize_date(year, month, day); 6507db96d56Sopenharmony_ci} 6517db96d56Sopenharmony_ci 6527db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 6537db96d56Sopenharmony_ci * Basic object allocation: tp_alloc implementations. These allocate 6547db96d56Sopenharmony_ci * Python objects of the right size and type, and do the Python object- 6557db96d56Sopenharmony_ci * initialization bit. If there's not enough memory, they return NULL after 6567db96d56Sopenharmony_ci * setting MemoryError. All data members remain uninitialized trash. 6577db96d56Sopenharmony_ci * 6587db96d56Sopenharmony_ci * We abuse the tp_alloc "nitems" argument to communicate whether a tzinfo 6597db96d56Sopenharmony_ci * member is needed. This is ugly, imprecise, and possibly insecure. 6607db96d56Sopenharmony_ci * tp_basicsize for the time and datetime types is set to the size of the 6617db96d56Sopenharmony_ci * struct that has room for the tzinfo member, so subclasses in Python will 6627db96d56Sopenharmony_ci * allocate enough space for a tzinfo member whether or not one is actually 6637db96d56Sopenharmony_ci * needed. That's the "ugly and imprecise" parts. The "possibly insecure" 6647db96d56Sopenharmony_ci * part is that PyType_GenericAlloc() (which subclasses in Python end up 6657db96d56Sopenharmony_ci * using) just happens today to effectively ignore the nitems argument 6667db96d56Sopenharmony_ci * when tp_itemsize is 0, which it is for these type objects. If that 6677db96d56Sopenharmony_ci * changes, perhaps the callers of tp_alloc slots in this file should 6687db96d56Sopenharmony_ci * be changed to force a 0 nitems argument unless the type being allocated 6697db96d56Sopenharmony_ci * is a base type implemented in this file (so that tp_alloc is time_alloc 6707db96d56Sopenharmony_ci * or datetime_alloc below, which know about the nitems abuse). 6717db96d56Sopenharmony_ci */ 6727db96d56Sopenharmony_ci 6737db96d56Sopenharmony_cistatic PyObject * 6747db96d56Sopenharmony_citime_alloc(PyTypeObject *type, Py_ssize_t aware) 6757db96d56Sopenharmony_ci{ 6767db96d56Sopenharmony_ci size_t size = aware ? sizeof(PyDateTime_Time) : sizeof(_PyDateTime_BaseTime); 6777db96d56Sopenharmony_ci PyObject *self = (PyObject *)PyObject_Malloc(size); 6787db96d56Sopenharmony_ci if (self == NULL) { 6797db96d56Sopenharmony_ci return PyErr_NoMemory(); 6807db96d56Sopenharmony_ci } 6817db96d56Sopenharmony_ci _PyObject_Init(self, type); 6827db96d56Sopenharmony_ci return self; 6837db96d56Sopenharmony_ci} 6847db96d56Sopenharmony_ci 6857db96d56Sopenharmony_cistatic PyObject * 6867db96d56Sopenharmony_cidatetime_alloc(PyTypeObject *type, Py_ssize_t aware) 6877db96d56Sopenharmony_ci{ 6887db96d56Sopenharmony_ci size_t size = aware ? sizeof(PyDateTime_DateTime) : sizeof(_PyDateTime_BaseDateTime); 6897db96d56Sopenharmony_ci PyObject *self = (PyObject *)PyObject_Malloc(size); 6907db96d56Sopenharmony_ci if (self == NULL) { 6917db96d56Sopenharmony_ci return PyErr_NoMemory(); 6927db96d56Sopenharmony_ci } 6937db96d56Sopenharmony_ci _PyObject_Init(self, type); 6947db96d56Sopenharmony_ci return self; 6957db96d56Sopenharmony_ci} 6967db96d56Sopenharmony_ci 6977db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 6987db96d56Sopenharmony_ci * Helpers for setting object fields. These work on pointers to the 6997db96d56Sopenharmony_ci * appropriate base class. 7007db96d56Sopenharmony_ci */ 7017db96d56Sopenharmony_ci 7027db96d56Sopenharmony_ci/* For date and datetime. */ 7037db96d56Sopenharmony_cistatic void 7047db96d56Sopenharmony_ciset_date_fields(PyDateTime_Date *self, int y, int m, int d) 7057db96d56Sopenharmony_ci{ 7067db96d56Sopenharmony_ci self->hashcode = -1; 7077db96d56Sopenharmony_ci SET_YEAR(self, y); 7087db96d56Sopenharmony_ci SET_MONTH(self, m); 7097db96d56Sopenharmony_ci SET_DAY(self, d); 7107db96d56Sopenharmony_ci} 7117db96d56Sopenharmony_ci 7127db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 7137db96d56Sopenharmony_ci * String parsing utilities and helper functions 7147db96d56Sopenharmony_ci */ 7157db96d56Sopenharmony_ci 7167db96d56Sopenharmony_cistatic unsigned char 7177db96d56Sopenharmony_ciis_digit(const char c) { 7187db96d56Sopenharmony_ci return ((unsigned int)(c - '0')) < 10; 7197db96d56Sopenharmony_ci} 7207db96d56Sopenharmony_ci 7217db96d56Sopenharmony_cistatic const char * 7227db96d56Sopenharmony_ciparse_digits(const char *ptr, int *var, size_t num_digits) 7237db96d56Sopenharmony_ci{ 7247db96d56Sopenharmony_ci for (size_t i = 0; i < num_digits; ++i) { 7257db96d56Sopenharmony_ci unsigned int tmp = (unsigned int)(*(ptr++) - '0'); 7267db96d56Sopenharmony_ci if (tmp > 9) { 7277db96d56Sopenharmony_ci return NULL; 7287db96d56Sopenharmony_ci } 7297db96d56Sopenharmony_ci *var *= 10; 7307db96d56Sopenharmony_ci *var += (signed int)tmp; 7317db96d56Sopenharmony_ci } 7327db96d56Sopenharmony_ci 7337db96d56Sopenharmony_ci return ptr; 7347db96d56Sopenharmony_ci} 7357db96d56Sopenharmony_ci 7367db96d56Sopenharmony_cistatic int 7377db96d56Sopenharmony_ciparse_isoformat_date(const char *dtstr, const size_t len, int *year, int *month, int *day) 7387db96d56Sopenharmony_ci{ 7397db96d56Sopenharmony_ci /* Parse the date components of the result of date.isoformat() 7407db96d56Sopenharmony_ci * 7417db96d56Sopenharmony_ci * Return codes: 7427db96d56Sopenharmony_ci * 0: Success 7437db96d56Sopenharmony_ci * -1: Failed to parse date component 7447db96d56Sopenharmony_ci * -2: Inconsistent date separator usage 7457db96d56Sopenharmony_ci * -3: Failed to parse ISO week. 7467db96d56Sopenharmony_ci * -4: Failed to parse ISO day. 7477db96d56Sopenharmony_ci * -5, -6: Failure in iso_to_ymd 7487db96d56Sopenharmony_ci */ 7497db96d56Sopenharmony_ci const char *p = dtstr; 7507db96d56Sopenharmony_ci p = parse_digits(p, year, 4); 7517db96d56Sopenharmony_ci if (NULL == p) { 7527db96d56Sopenharmony_ci return -1; 7537db96d56Sopenharmony_ci } 7547db96d56Sopenharmony_ci 7557db96d56Sopenharmony_ci const unsigned char uses_separator = (*p == '-'); 7567db96d56Sopenharmony_ci if (uses_separator) { 7577db96d56Sopenharmony_ci ++p; 7587db96d56Sopenharmony_ci } 7597db96d56Sopenharmony_ci 7607db96d56Sopenharmony_ci if(*p == 'W') { 7617db96d56Sopenharmony_ci // This is an isocalendar-style date string 7627db96d56Sopenharmony_ci p++; 7637db96d56Sopenharmony_ci int iso_week = 0; 7647db96d56Sopenharmony_ci int iso_day = 0; 7657db96d56Sopenharmony_ci 7667db96d56Sopenharmony_ci p = parse_digits(p, &iso_week, 2); 7677db96d56Sopenharmony_ci if (NULL == p) { 7687db96d56Sopenharmony_ci return -3; 7697db96d56Sopenharmony_ci } 7707db96d56Sopenharmony_ci 7717db96d56Sopenharmony_ci assert(p > dtstr); 7727db96d56Sopenharmony_ci if ((size_t)(p - dtstr) < len) { 7737db96d56Sopenharmony_ci if (uses_separator && *(p++) != '-') { 7747db96d56Sopenharmony_ci return -2; 7757db96d56Sopenharmony_ci } 7767db96d56Sopenharmony_ci 7777db96d56Sopenharmony_ci p = parse_digits(p, &iso_day, 1); 7787db96d56Sopenharmony_ci if (NULL == p) { 7797db96d56Sopenharmony_ci return -4; 7807db96d56Sopenharmony_ci } 7817db96d56Sopenharmony_ci } else { 7827db96d56Sopenharmony_ci iso_day = 1; 7837db96d56Sopenharmony_ci } 7847db96d56Sopenharmony_ci 7857db96d56Sopenharmony_ci int rv = iso_to_ymd(*year, iso_week, iso_day, year, month, day); 7867db96d56Sopenharmony_ci if (rv) { 7877db96d56Sopenharmony_ci return -3 + rv; 7887db96d56Sopenharmony_ci } else { 7897db96d56Sopenharmony_ci return 0; 7907db96d56Sopenharmony_ci } 7917db96d56Sopenharmony_ci } 7927db96d56Sopenharmony_ci 7937db96d56Sopenharmony_ci p = parse_digits(p, month, 2); 7947db96d56Sopenharmony_ci if (NULL == p) { 7957db96d56Sopenharmony_ci return -1; 7967db96d56Sopenharmony_ci } 7977db96d56Sopenharmony_ci 7987db96d56Sopenharmony_ci if (uses_separator && *(p++) != '-') { 7997db96d56Sopenharmony_ci return -2; 8007db96d56Sopenharmony_ci } 8017db96d56Sopenharmony_ci p = parse_digits(p, day, 2); 8027db96d56Sopenharmony_ci if (p == NULL) { 8037db96d56Sopenharmony_ci return -1; 8047db96d56Sopenharmony_ci } 8057db96d56Sopenharmony_ci return 0; 8067db96d56Sopenharmony_ci} 8077db96d56Sopenharmony_ci 8087db96d56Sopenharmony_cistatic int 8097db96d56Sopenharmony_ciparse_hh_mm_ss_ff(const char *tstr, const char *tstr_end, int *hour, 8107db96d56Sopenharmony_ci int *minute, int *second, int *microsecond) 8117db96d56Sopenharmony_ci{ 8127db96d56Sopenharmony_ci *hour = *minute = *second = *microsecond = 0; 8137db96d56Sopenharmony_ci const char *p = tstr; 8147db96d56Sopenharmony_ci const char *p_end = tstr_end; 8157db96d56Sopenharmony_ci int *vals[3] = {hour, minute, second}; 8167db96d56Sopenharmony_ci // This is initialized to satisfy an erroneous compiler warning. 8177db96d56Sopenharmony_ci unsigned char has_separator = 1; 8187db96d56Sopenharmony_ci 8197db96d56Sopenharmony_ci // Parse [HH[:?MM[:?SS]]] 8207db96d56Sopenharmony_ci for (size_t i = 0; i < 3; ++i) { 8217db96d56Sopenharmony_ci p = parse_digits(p, vals[i], 2); 8227db96d56Sopenharmony_ci if (NULL == p) { 8237db96d56Sopenharmony_ci return -3; 8247db96d56Sopenharmony_ci } 8257db96d56Sopenharmony_ci 8267db96d56Sopenharmony_ci char c = *(p++); 8277db96d56Sopenharmony_ci if (i == 0) { 8287db96d56Sopenharmony_ci has_separator = (c == ':'); 8297db96d56Sopenharmony_ci } 8307db96d56Sopenharmony_ci 8317db96d56Sopenharmony_ci if (p >= p_end) { 8327db96d56Sopenharmony_ci return c != '\0'; 8337db96d56Sopenharmony_ci } 8347db96d56Sopenharmony_ci else if (has_separator && (c == ':')) { 8357db96d56Sopenharmony_ci continue; 8367db96d56Sopenharmony_ci } 8377db96d56Sopenharmony_ci else if (c == '.' || c == ',') { 8387db96d56Sopenharmony_ci break; 8397db96d56Sopenharmony_ci } else if (!has_separator) { 8407db96d56Sopenharmony_ci --p; 8417db96d56Sopenharmony_ci } else { 8427db96d56Sopenharmony_ci return -4; // Malformed time separator 8437db96d56Sopenharmony_ci } 8447db96d56Sopenharmony_ci } 8457db96d56Sopenharmony_ci 8467db96d56Sopenharmony_ci // Parse fractional components 8477db96d56Sopenharmony_ci size_t len_remains = p_end - p; 8487db96d56Sopenharmony_ci size_t to_parse = len_remains; 8497db96d56Sopenharmony_ci if (len_remains >= 6) { 8507db96d56Sopenharmony_ci to_parse = 6; 8517db96d56Sopenharmony_ci } 8527db96d56Sopenharmony_ci 8537db96d56Sopenharmony_ci p = parse_digits(p, microsecond, to_parse); 8547db96d56Sopenharmony_ci if (NULL == p) { 8557db96d56Sopenharmony_ci return -3; 8567db96d56Sopenharmony_ci } 8577db96d56Sopenharmony_ci 8587db96d56Sopenharmony_ci static int correction[] = { 8597db96d56Sopenharmony_ci 100000, 10000, 1000, 100, 10 8607db96d56Sopenharmony_ci }; 8617db96d56Sopenharmony_ci 8627db96d56Sopenharmony_ci if (to_parse < 6) { 8637db96d56Sopenharmony_ci *microsecond *= correction[to_parse-1]; 8647db96d56Sopenharmony_ci } 8657db96d56Sopenharmony_ci 8667db96d56Sopenharmony_ci while (is_digit(*p)){ 8677db96d56Sopenharmony_ci ++p; // skip truncated digits 8687db96d56Sopenharmony_ci } 8697db96d56Sopenharmony_ci 8707db96d56Sopenharmony_ci // Return 1 if it's not the end of the string 8717db96d56Sopenharmony_ci return *p != '\0'; 8727db96d56Sopenharmony_ci} 8737db96d56Sopenharmony_ci 8747db96d56Sopenharmony_cistatic int 8757db96d56Sopenharmony_ciparse_isoformat_time(const char *dtstr, size_t dtlen, int *hour, int *minute, 8767db96d56Sopenharmony_ci int *second, int *microsecond, int *tzoffset, 8777db96d56Sopenharmony_ci int *tzmicrosecond) 8787db96d56Sopenharmony_ci{ 8797db96d56Sopenharmony_ci // Parse the time portion of a datetime.isoformat() string 8807db96d56Sopenharmony_ci // 8817db96d56Sopenharmony_ci // Return codes: 8827db96d56Sopenharmony_ci // 0: Success (no tzoffset) 8837db96d56Sopenharmony_ci // 1: Success (with tzoffset) 8847db96d56Sopenharmony_ci // -3: Failed to parse time component 8857db96d56Sopenharmony_ci // -4: Failed to parse time separator 8867db96d56Sopenharmony_ci // -5: Malformed timezone string 8877db96d56Sopenharmony_ci 8887db96d56Sopenharmony_ci const char *p = dtstr; 8897db96d56Sopenharmony_ci const char *p_end = dtstr + dtlen; 8907db96d56Sopenharmony_ci 8917db96d56Sopenharmony_ci const char *tzinfo_pos = p; 8927db96d56Sopenharmony_ci do { 8937db96d56Sopenharmony_ci if (*tzinfo_pos == 'Z' || *tzinfo_pos == '+' || *tzinfo_pos == '-') { 8947db96d56Sopenharmony_ci break; 8957db96d56Sopenharmony_ci } 8967db96d56Sopenharmony_ci } while (++tzinfo_pos < p_end); 8977db96d56Sopenharmony_ci 8987db96d56Sopenharmony_ci int rv = parse_hh_mm_ss_ff(dtstr, tzinfo_pos, hour, minute, second, 8997db96d56Sopenharmony_ci microsecond); 9007db96d56Sopenharmony_ci 9017db96d56Sopenharmony_ci if (rv < 0) { 9027db96d56Sopenharmony_ci return rv; 9037db96d56Sopenharmony_ci } 9047db96d56Sopenharmony_ci else if (tzinfo_pos == p_end) { 9057db96d56Sopenharmony_ci // We know that there's no time zone, so if there's stuff at the 9067db96d56Sopenharmony_ci // end of the string it's an error. 9077db96d56Sopenharmony_ci if (rv == 1) { 9087db96d56Sopenharmony_ci return -5; 9097db96d56Sopenharmony_ci } 9107db96d56Sopenharmony_ci else { 9117db96d56Sopenharmony_ci return 0; 9127db96d56Sopenharmony_ci } 9137db96d56Sopenharmony_ci } 9147db96d56Sopenharmony_ci 9157db96d56Sopenharmony_ci // Special case UTC / Zulu time. 9167db96d56Sopenharmony_ci if (*tzinfo_pos == 'Z') { 9177db96d56Sopenharmony_ci *tzoffset = 0; 9187db96d56Sopenharmony_ci *tzmicrosecond = 0; 9197db96d56Sopenharmony_ci 9207db96d56Sopenharmony_ci if (*(tzinfo_pos + 1) != '\0') { 9217db96d56Sopenharmony_ci return -5; 9227db96d56Sopenharmony_ci } else { 9237db96d56Sopenharmony_ci return 1; 9247db96d56Sopenharmony_ci } 9257db96d56Sopenharmony_ci } 9267db96d56Sopenharmony_ci 9277db96d56Sopenharmony_ci int tzsign = (*tzinfo_pos == '-') ? -1 : 1; 9287db96d56Sopenharmony_ci tzinfo_pos++; 9297db96d56Sopenharmony_ci int tzhour = 0, tzminute = 0, tzsecond = 0; 9307db96d56Sopenharmony_ci rv = parse_hh_mm_ss_ff(tzinfo_pos, p_end, &tzhour, &tzminute, &tzsecond, 9317db96d56Sopenharmony_ci tzmicrosecond); 9327db96d56Sopenharmony_ci 9337db96d56Sopenharmony_ci *tzoffset = tzsign * ((tzhour * 3600) + (tzminute * 60) + tzsecond); 9347db96d56Sopenharmony_ci *tzmicrosecond *= tzsign; 9357db96d56Sopenharmony_ci 9367db96d56Sopenharmony_ci return rv ? -5 : 1; 9377db96d56Sopenharmony_ci} 9387db96d56Sopenharmony_ci 9397db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 9407db96d56Sopenharmony_ci * Create various objects, mostly without range checking. 9417db96d56Sopenharmony_ci */ 9427db96d56Sopenharmony_ci 9437db96d56Sopenharmony_ci/* Create a date instance with no range checking. */ 9447db96d56Sopenharmony_cistatic PyObject * 9457db96d56Sopenharmony_cinew_date_ex(int year, int month, int day, PyTypeObject *type) 9467db96d56Sopenharmony_ci{ 9477db96d56Sopenharmony_ci PyDateTime_Date *self; 9487db96d56Sopenharmony_ci 9497db96d56Sopenharmony_ci if (check_date_args(year, month, day) < 0) { 9507db96d56Sopenharmony_ci return NULL; 9517db96d56Sopenharmony_ci } 9527db96d56Sopenharmony_ci 9537db96d56Sopenharmony_ci self = (PyDateTime_Date *)(type->tp_alloc(type, 0)); 9547db96d56Sopenharmony_ci if (self != NULL) 9557db96d56Sopenharmony_ci set_date_fields(self, year, month, day); 9567db96d56Sopenharmony_ci return (PyObject *)self; 9577db96d56Sopenharmony_ci} 9587db96d56Sopenharmony_ci 9597db96d56Sopenharmony_ci#define new_date(year, month, day) \ 9607db96d56Sopenharmony_ci new_date_ex(year, month, day, &PyDateTime_DateType) 9617db96d56Sopenharmony_ci 9627db96d56Sopenharmony_ci// Forward declaration 9637db96d56Sopenharmony_cistatic PyObject * 9647db96d56Sopenharmony_cinew_datetime_ex(int, int, int, int, int, int, int, PyObject *, PyTypeObject *); 9657db96d56Sopenharmony_ci 9667db96d56Sopenharmony_ci/* Create date instance with no range checking, or call subclass constructor */ 9677db96d56Sopenharmony_cistatic PyObject * 9687db96d56Sopenharmony_cinew_date_subclass_ex(int year, int month, int day, PyObject *cls) 9697db96d56Sopenharmony_ci{ 9707db96d56Sopenharmony_ci PyObject *result; 9717db96d56Sopenharmony_ci // We have "fast path" constructors for two subclasses: date and datetime 9727db96d56Sopenharmony_ci if ((PyTypeObject *)cls == &PyDateTime_DateType) { 9737db96d56Sopenharmony_ci result = new_date_ex(year, month, day, (PyTypeObject *)cls); 9747db96d56Sopenharmony_ci } 9757db96d56Sopenharmony_ci else if ((PyTypeObject *)cls == &PyDateTime_DateTimeType) { 9767db96d56Sopenharmony_ci result = new_datetime_ex(year, month, day, 0, 0, 0, 0, Py_None, 9777db96d56Sopenharmony_ci (PyTypeObject *)cls); 9787db96d56Sopenharmony_ci } 9797db96d56Sopenharmony_ci else { 9807db96d56Sopenharmony_ci result = PyObject_CallFunction(cls, "iii", year, month, day); 9817db96d56Sopenharmony_ci } 9827db96d56Sopenharmony_ci 9837db96d56Sopenharmony_ci return result; 9847db96d56Sopenharmony_ci} 9857db96d56Sopenharmony_ci 9867db96d56Sopenharmony_ci/* Create a datetime instance with no range checking. */ 9877db96d56Sopenharmony_cistatic PyObject * 9887db96d56Sopenharmony_cinew_datetime_ex2(int year, int month, int day, int hour, int minute, 9897db96d56Sopenharmony_ci int second, int usecond, PyObject *tzinfo, int fold, PyTypeObject *type) 9907db96d56Sopenharmony_ci{ 9917db96d56Sopenharmony_ci PyDateTime_DateTime *self; 9927db96d56Sopenharmony_ci char aware = tzinfo != Py_None; 9937db96d56Sopenharmony_ci 9947db96d56Sopenharmony_ci if (check_date_args(year, month, day) < 0) { 9957db96d56Sopenharmony_ci return NULL; 9967db96d56Sopenharmony_ci } 9977db96d56Sopenharmony_ci if (check_time_args(hour, minute, second, usecond, fold) < 0) { 9987db96d56Sopenharmony_ci return NULL; 9997db96d56Sopenharmony_ci } 10007db96d56Sopenharmony_ci if (check_tzinfo_subclass(tzinfo) < 0) { 10017db96d56Sopenharmony_ci return NULL; 10027db96d56Sopenharmony_ci } 10037db96d56Sopenharmony_ci 10047db96d56Sopenharmony_ci self = (PyDateTime_DateTime *) (type->tp_alloc(type, aware)); 10057db96d56Sopenharmony_ci if (self != NULL) { 10067db96d56Sopenharmony_ci self->hastzinfo = aware; 10077db96d56Sopenharmony_ci set_date_fields((PyDateTime_Date *)self, year, month, day); 10087db96d56Sopenharmony_ci DATE_SET_HOUR(self, hour); 10097db96d56Sopenharmony_ci DATE_SET_MINUTE(self, minute); 10107db96d56Sopenharmony_ci DATE_SET_SECOND(self, second); 10117db96d56Sopenharmony_ci DATE_SET_MICROSECOND(self, usecond); 10127db96d56Sopenharmony_ci if (aware) { 10137db96d56Sopenharmony_ci Py_INCREF(tzinfo); 10147db96d56Sopenharmony_ci self->tzinfo = tzinfo; 10157db96d56Sopenharmony_ci } 10167db96d56Sopenharmony_ci DATE_SET_FOLD(self, fold); 10177db96d56Sopenharmony_ci } 10187db96d56Sopenharmony_ci return (PyObject *)self; 10197db96d56Sopenharmony_ci} 10207db96d56Sopenharmony_ci 10217db96d56Sopenharmony_cistatic PyObject * 10227db96d56Sopenharmony_cinew_datetime_ex(int year, int month, int day, int hour, int minute, 10237db96d56Sopenharmony_ci int second, int usecond, PyObject *tzinfo, PyTypeObject *type) 10247db96d56Sopenharmony_ci{ 10257db96d56Sopenharmony_ci return new_datetime_ex2(year, month, day, hour, minute, second, usecond, 10267db96d56Sopenharmony_ci tzinfo, 0, type); 10277db96d56Sopenharmony_ci} 10287db96d56Sopenharmony_ci 10297db96d56Sopenharmony_ci#define new_datetime(y, m, d, hh, mm, ss, us, tzinfo, fold) \ 10307db96d56Sopenharmony_ci new_datetime_ex2(y, m, d, hh, mm, ss, us, tzinfo, fold, \ 10317db96d56Sopenharmony_ci &PyDateTime_DateTimeType) 10327db96d56Sopenharmony_ci 10337db96d56Sopenharmony_cistatic PyObject * 10347db96d56Sopenharmony_cinew_datetime_subclass_fold_ex(int year, int month, int day, int hour, int minute, 10357db96d56Sopenharmony_ci int second, int usecond, PyObject *tzinfo, 10367db96d56Sopenharmony_ci int fold, PyObject *cls) { 10377db96d56Sopenharmony_ci PyObject* dt; 10387db96d56Sopenharmony_ci if ((PyTypeObject*)cls == &PyDateTime_DateTimeType) { 10397db96d56Sopenharmony_ci // Use the fast path constructor 10407db96d56Sopenharmony_ci dt = new_datetime(year, month, day, hour, minute, second, usecond, 10417db96d56Sopenharmony_ci tzinfo, fold); 10427db96d56Sopenharmony_ci } else { 10437db96d56Sopenharmony_ci // Subclass 10447db96d56Sopenharmony_ci dt = PyObject_CallFunction(cls, "iiiiiiiO", 10457db96d56Sopenharmony_ci year, 10467db96d56Sopenharmony_ci month, 10477db96d56Sopenharmony_ci day, 10487db96d56Sopenharmony_ci hour, 10497db96d56Sopenharmony_ci minute, 10507db96d56Sopenharmony_ci second, 10517db96d56Sopenharmony_ci usecond, 10527db96d56Sopenharmony_ci tzinfo); 10537db96d56Sopenharmony_ci } 10547db96d56Sopenharmony_ci 10557db96d56Sopenharmony_ci return dt; 10567db96d56Sopenharmony_ci} 10577db96d56Sopenharmony_ci 10587db96d56Sopenharmony_cistatic PyObject * 10597db96d56Sopenharmony_cinew_datetime_subclass_ex(int year, int month, int day, int hour, int minute, 10607db96d56Sopenharmony_ci int second, int usecond, PyObject *tzinfo, 10617db96d56Sopenharmony_ci PyObject *cls) { 10627db96d56Sopenharmony_ci return new_datetime_subclass_fold_ex(year, month, day, hour, minute, 10637db96d56Sopenharmony_ci second, usecond, tzinfo, 0, 10647db96d56Sopenharmony_ci cls); 10657db96d56Sopenharmony_ci} 10667db96d56Sopenharmony_ci 10677db96d56Sopenharmony_ci/* Create a time instance with no range checking. */ 10687db96d56Sopenharmony_cistatic PyObject * 10697db96d56Sopenharmony_cinew_time_ex2(int hour, int minute, int second, int usecond, 10707db96d56Sopenharmony_ci PyObject *tzinfo, int fold, PyTypeObject *type) 10717db96d56Sopenharmony_ci{ 10727db96d56Sopenharmony_ci PyDateTime_Time *self; 10737db96d56Sopenharmony_ci char aware = tzinfo != Py_None; 10747db96d56Sopenharmony_ci 10757db96d56Sopenharmony_ci if (check_time_args(hour, minute, second, usecond, fold) < 0) { 10767db96d56Sopenharmony_ci return NULL; 10777db96d56Sopenharmony_ci } 10787db96d56Sopenharmony_ci if (check_tzinfo_subclass(tzinfo) < 0) { 10797db96d56Sopenharmony_ci return NULL; 10807db96d56Sopenharmony_ci } 10817db96d56Sopenharmony_ci 10827db96d56Sopenharmony_ci self = (PyDateTime_Time *) (type->tp_alloc(type, aware)); 10837db96d56Sopenharmony_ci if (self != NULL) { 10847db96d56Sopenharmony_ci self->hastzinfo = aware; 10857db96d56Sopenharmony_ci self->hashcode = -1; 10867db96d56Sopenharmony_ci TIME_SET_HOUR(self, hour); 10877db96d56Sopenharmony_ci TIME_SET_MINUTE(self, minute); 10887db96d56Sopenharmony_ci TIME_SET_SECOND(self, second); 10897db96d56Sopenharmony_ci TIME_SET_MICROSECOND(self, usecond); 10907db96d56Sopenharmony_ci if (aware) { 10917db96d56Sopenharmony_ci Py_INCREF(tzinfo); 10927db96d56Sopenharmony_ci self->tzinfo = tzinfo; 10937db96d56Sopenharmony_ci } 10947db96d56Sopenharmony_ci TIME_SET_FOLD(self, fold); 10957db96d56Sopenharmony_ci } 10967db96d56Sopenharmony_ci return (PyObject *)self; 10977db96d56Sopenharmony_ci} 10987db96d56Sopenharmony_ci 10997db96d56Sopenharmony_cistatic PyObject * 11007db96d56Sopenharmony_cinew_time_ex(int hour, int minute, int second, int usecond, 11017db96d56Sopenharmony_ci PyObject *tzinfo, PyTypeObject *type) 11027db96d56Sopenharmony_ci{ 11037db96d56Sopenharmony_ci return new_time_ex2(hour, minute, second, usecond, tzinfo, 0, type); 11047db96d56Sopenharmony_ci} 11057db96d56Sopenharmony_ci 11067db96d56Sopenharmony_ci#define new_time(hh, mm, ss, us, tzinfo, fold) \ 11077db96d56Sopenharmony_ci new_time_ex2(hh, mm, ss, us, tzinfo, fold, &PyDateTime_TimeType) 11087db96d56Sopenharmony_ci 11097db96d56Sopenharmony_ci/* Create a timedelta instance. Normalize the members iff normalize is 11107db96d56Sopenharmony_ci * true. Passing false is a speed optimization, if you know for sure 11117db96d56Sopenharmony_ci * that seconds and microseconds are already in their proper ranges. In any 11127db96d56Sopenharmony_ci * case, raises OverflowError and returns NULL if the normalized days is out 11137db96d56Sopenharmony_ci * of range. 11147db96d56Sopenharmony_ci */ 11157db96d56Sopenharmony_cistatic PyObject * 11167db96d56Sopenharmony_cinew_delta_ex(int days, int seconds, int microseconds, int normalize, 11177db96d56Sopenharmony_ci PyTypeObject *type) 11187db96d56Sopenharmony_ci{ 11197db96d56Sopenharmony_ci PyDateTime_Delta *self; 11207db96d56Sopenharmony_ci 11217db96d56Sopenharmony_ci if (normalize) 11227db96d56Sopenharmony_ci normalize_d_s_us(&days, &seconds, µseconds); 11237db96d56Sopenharmony_ci assert(0 <= seconds && seconds < 24*3600); 11247db96d56Sopenharmony_ci assert(0 <= microseconds && microseconds < 1000000); 11257db96d56Sopenharmony_ci 11267db96d56Sopenharmony_ci if (check_delta_day_range(days) < 0) 11277db96d56Sopenharmony_ci return NULL; 11287db96d56Sopenharmony_ci 11297db96d56Sopenharmony_ci self = (PyDateTime_Delta *) (type->tp_alloc(type, 0)); 11307db96d56Sopenharmony_ci if (self != NULL) { 11317db96d56Sopenharmony_ci self->hashcode = -1; 11327db96d56Sopenharmony_ci SET_TD_DAYS(self, days); 11337db96d56Sopenharmony_ci SET_TD_SECONDS(self, seconds); 11347db96d56Sopenharmony_ci SET_TD_MICROSECONDS(self, microseconds); 11357db96d56Sopenharmony_ci } 11367db96d56Sopenharmony_ci return (PyObject *) self; 11377db96d56Sopenharmony_ci} 11387db96d56Sopenharmony_ci 11397db96d56Sopenharmony_ci#define new_delta(d, s, us, normalize) \ 11407db96d56Sopenharmony_ci new_delta_ex(d, s, us, normalize, &PyDateTime_DeltaType) 11417db96d56Sopenharmony_ci 11427db96d56Sopenharmony_ci 11437db96d56Sopenharmony_citypedef struct 11447db96d56Sopenharmony_ci{ 11457db96d56Sopenharmony_ci PyObject_HEAD 11467db96d56Sopenharmony_ci PyObject *offset; 11477db96d56Sopenharmony_ci PyObject *name; 11487db96d56Sopenharmony_ci} PyDateTime_TimeZone; 11497db96d56Sopenharmony_ci 11507db96d56Sopenharmony_ci/* The interned UTC timezone instance */ 11517db96d56Sopenharmony_cistatic PyObject *PyDateTime_TimeZone_UTC; 11527db96d56Sopenharmony_ci/* The interned Epoch datetime instance */ 11537db96d56Sopenharmony_cistatic PyObject *PyDateTime_Epoch; 11547db96d56Sopenharmony_ci 11557db96d56Sopenharmony_ci/* Create new timezone instance checking offset range. This 11567db96d56Sopenharmony_ci function does not check the name argument. Caller must assure 11577db96d56Sopenharmony_ci that offset is a timedelta instance and name is either NULL 11587db96d56Sopenharmony_ci or a unicode object. */ 11597db96d56Sopenharmony_cistatic PyObject * 11607db96d56Sopenharmony_cicreate_timezone(PyObject *offset, PyObject *name) 11617db96d56Sopenharmony_ci{ 11627db96d56Sopenharmony_ci PyDateTime_TimeZone *self; 11637db96d56Sopenharmony_ci PyTypeObject *type = &PyDateTime_TimeZoneType; 11647db96d56Sopenharmony_ci 11657db96d56Sopenharmony_ci assert(offset != NULL); 11667db96d56Sopenharmony_ci assert(PyDelta_Check(offset)); 11677db96d56Sopenharmony_ci assert(name == NULL || PyUnicode_Check(name)); 11687db96d56Sopenharmony_ci 11697db96d56Sopenharmony_ci self = (PyDateTime_TimeZone *)(type->tp_alloc(type, 0)); 11707db96d56Sopenharmony_ci if (self == NULL) { 11717db96d56Sopenharmony_ci return NULL; 11727db96d56Sopenharmony_ci } 11737db96d56Sopenharmony_ci Py_INCREF(offset); 11747db96d56Sopenharmony_ci self->offset = offset; 11757db96d56Sopenharmony_ci Py_XINCREF(name); 11767db96d56Sopenharmony_ci self->name = name; 11777db96d56Sopenharmony_ci return (PyObject *)self; 11787db96d56Sopenharmony_ci} 11797db96d56Sopenharmony_ci 11807db96d56Sopenharmony_cistatic int delta_bool(PyDateTime_Delta *self); 11817db96d56Sopenharmony_ci 11827db96d56Sopenharmony_cistatic PyObject * 11837db96d56Sopenharmony_cinew_timezone(PyObject *offset, PyObject *name) 11847db96d56Sopenharmony_ci{ 11857db96d56Sopenharmony_ci assert(offset != NULL); 11867db96d56Sopenharmony_ci assert(PyDelta_Check(offset)); 11877db96d56Sopenharmony_ci assert(name == NULL || PyUnicode_Check(name)); 11887db96d56Sopenharmony_ci 11897db96d56Sopenharmony_ci if (name == NULL && delta_bool((PyDateTime_Delta *)offset) == 0) { 11907db96d56Sopenharmony_ci Py_INCREF(PyDateTime_TimeZone_UTC); 11917db96d56Sopenharmony_ci return PyDateTime_TimeZone_UTC; 11927db96d56Sopenharmony_ci } 11937db96d56Sopenharmony_ci if ((GET_TD_DAYS(offset) == -1 && 11947db96d56Sopenharmony_ci GET_TD_SECONDS(offset) == 0 && 11957db96d56Sopenharmony_ci GET_TD_MICROSECONDS(offset) < 1) || 11967db96d56Sopenharmony_ci GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) { 11977db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "offset must be a timedelta" 11987db96d56Sopenharmony_ci " strictly between -timedelta(hours=24) and" 11997db96d56Sopenharmony_ci " timedelta(hours=24)," 12007db96d56Sopenharmony_ci " not %R.", offset); 12017db96d56Sopenharmony_ci return NULL; 12027db96d56Sopenharmony_ci } 12037db96d56Sopenharmony_ci 12047db96d56Sopenharmony_ci return create_timezone(offset, name); 12057db96d56Sopenharmony_ci} 12067db96d56Sopenharmony_ci 12077db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 12087db96d56Sopenharmony_ci * tzinfo helpers. 12097db96d56Sopenharmony_ci */ 12107db96d56Sopenharmony_ci 12117db96d56Sopenharmony_ci/* Ensure that p is None or of a tzinfo subclass. Return 0 if OK; if not 12127db96d56Sopenharmony_ci * raise TypeError and return -1. 12137db96d56Sopenharmony_ci */ 12147db96d56Sopenharmony_cistatic int 12157db96d56Sopenharmony_cicheck_tzinfo_subclass(PyObject *p) 12167db96d56Sopenharmony_ci{ 12177db96d56Sopenharmony_ci if (p == Py_None || PyTZInfo_Check(p)) 12187db96d56Sopenharmony_ci return 0; 12197db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 12207db96d56Sopenharmony_ci "tzinfo argument must be None or of a tzinfo subclass, " 12217db96d56Sopenharmony_ci "not type '%s'", 12227db96d56Sopenharmony_ci Py_TYPE(p)->tp_name); 12237db96d56Sopenharmony_ci return -1; 12247db96d56Sopenharmony_ci} 12257db96d56Sopenharmony_ci 12267db96d56Sopenharmony_ci/* If self has a tzinfo member, return a BORROWED reference to it. Else 12277db96d56Sopenharmony_ci * return NULL, which is NOT AN ERROR. There are no error returns here, 12287db96d56Sopenharmony_ci * and the caller must not decref the result. 12297db96d56Sopenharmony_ci */ 12307db96d56Sopenharmony_cistatic PyObject * 12317db96d56Sopenharmony_ciget_tzinfo_member(PyObject *self) 12327db96d56Sopenharmony_ci{ 12337db96d56Sopenharmony_ci PyObject *tzinfo = NULL; 12347db96d56Sopenharmony_ci 12357db96d56Sopenharmony_ci if (PyDateTime_Check(self) && HASTZINFO(self)) 12367db96d56Sopenharmony_ci tzinfo = ((PyDateTime_DateTime *)self)->tzinfo; 12377db96d56Sopenharmony_ci else if (PyTime_Check(self) && HASTZINFO(self)) 12387db96d56Sopenharmony_ci tzinfo = ((PyDateTime_Time *)self)->tzinfo; 12397db96d56Sopenharmony_ci 12407db96d56Sopenharmony_ci return tzinfo; 12417db96d56Sopenharmony_ci} 12427db96d56Sopenharmony_ci 12437db96d56Sopenharmony_ci/* Call getattr(tzinfo, name)(tzinfoarg), and check the result. tzinfo must 12447db96d56Sopenharmony_ci * be an instance of the tzinfo class. If the method returns None, this 12457db96d56Sopenharmony_ci * returns None. If the method doesn't return None or timedelta, TypeError is 12467db96d56Sopenharmony_ci * raised and this returns NULL. If it returns a timedelta and the value is 12477db96d56Sopenharmony_ci * out of range or isn't a whole number of minutes, ValueError is raised and 12487db96d56Sopenharmony_ci * this returns NULL. Else result is returned. 12497db96d56Sopenharmony_ci */ 12507db96d56Sopenharmony_cistatic PyObject * 12517db96d56Sopenharmony_cicall_tzinfo_method(PyObject *tzinfo, const char *name, PyObject *tzinfoarg) 12527db96d56Sopenharmony_ci{ 12537db96d56Sopenharmony_ci PyObject *offset; 12547db96d56Sopenharmony_ci 12557db96d56Sopenharmony_ci assert(tzinfo != NULL); 12567db96d56Sopenharmony_ci assert(PyTZInfo_Check(tzinfo) || tzinfo == Py_None); 12577db96d56Sopenharmony_ci assert(tzinfoarg != NULL); 12587db96d56Sopenharmony_ci 12597db96d56Sopenharmony_ci if (tzinfo == Py_None) 12607db96d56Sopenharmony_ci Py_RETURN_NONE; 12617db96d56Sopenharmony_ci offset = PyObject_CallMethod(tzinfo, name, "O", tzinfoarg); 12627db96d56Sopenharmony_ci if (offset == Py_None || offset == NULL) 12637db96d56Sopenharmony_ci return offset; 12647db96d56Sopenharmony_ci if (PyDelta_Check(offset)) { 12657db96d56Sopenharmony_ci if ((GET_TD_DAYS(offset) == -1 && 12667db96d56Sopenharmony_ci GET_TD_SECONDS(offset) == 0 && 12677db96d56Sopenharmony_ci GET_TD_MICROSECONDS(offset) < 1) || 12687db96d56Sopenharmony_ci GET_TD_DAYS(offset) < -1 || GET_TD_DAYS(offset) >= 1) { 12697db96d56Sopenharmony_ci Py_DECREF(offset); 12707db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "offset must be a timedelta" 12717db96d56Sopenharmony_ci " strictly between -timedelta(hours=24) and" 12727db96d56Sopenharmony_ci " timedelta(hours=24)."); 12737db96d56Sopenharmony_ci return NULL; 12747db96d56Sopenharmony_ci } 12757db96d56Sopenharmony_ci } 12767db96d56Sopenharmony_ci else { 12777db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 12787db96d56Sopenharmony_ci "tzinfo.%s() must return None or " 12797db96d56Sopenharmony_ci "timedelta, not '%.200s'", 12807db96d56Sopenharmony_ci name, Py_TYPE(offset)->tp_name); 12817db96d56Sopenharmony_ci Py_DECREF(offset); 12827db96d56Sopenharmony_ci return NULL; 12837db96d56Sopenharmony_ci } 12847db96d56Sopenharmony_ci 12857db96d56Sopenharmony_ci return offset; 12867db96d56Sopenharmony_ci} 12877db96d56Sopenharmony_ci 12887db96d56Sopenharmony_ci/* Call tzinfo.utcoffset(tzinfoarg), and extract an integer from the 12897db96d56Sopenharmony_ci * result. tzinfo must be an instance of the tzinfo class. If utcoffset() 12907db96d56Sopenharmony_ci * returns None, call_utcoffset returns 0 and sets *none to 1. If uctoffset() 12917db96d56Sopenharmony_ci * doesn't return None or timedelta, TypeError is raised and this returns -1. 12927db96d56Sopenharmony_ci * If utcoffset() returns an out of range timedelta, 12937db96d56Sopenharmony_ci * ValueError is raised and this returns -1. Else *none is 12947db96d56Sopenharmony_ci * set to 0 and the offset is returned (as timedelta, positive east of UTC). 12957db96d56Sopenharmony_ci */ 12967db96d56Sopenharmony_cistatic PyObject * 12977db96d56Sopenharmony_cicall_utcoffset(PyObject *tzinfo, PyObject *tzinfoarg) 12987db96d56Sopenharmony_ci{ 12997db96d56Sopenharmony_ci return call_tzinfo_method(tzinfo, "utcoffset", tzinfoarg); 13007db96d56Sopenharmony_ci} 13017db96d56Sopenharmony_ci 13027db96d56Sopenharmony_ci/* Call tzinfo.dst(tzinfoarg), and extract an integer from the 13037db96d56Sopenharmony_ci * result. tzinfo must be an instance of the tzinfo class. If dst() 13047db96d56Sopenharmony_ci * returns None, call_dst returns 0 and sets *none to 1. If dst() 13057db96d56Sopenharmony_ci * doesn't return None or timedelta, TypeError is raised and this 13067db96d56Sopenharmony_ci * returns -1. If dst() returns an invalid timedelta for a UTC offset, 13077db96d56Sopenharmony_ci * ValueError is raised and this returns -1. Else *none is set to 0 and 13087db96d56Sopenharmony_ci * the offset is returned (as timedelta, positive east of UTC). 13097db96d56Sopenharmony_ci */ 13107db96d56Sopenharmony_cistatic PyObject * 13117db96d56Sopenharmony_cicall_dst(PyObject *tzinfo, PyObject *tzinfoarg) 13127db96d56Sopenharmony_ci{ 13137db96d56Sopenharmony_ci return call_tzinfo_method(tzinfo, "dst", tzinfoarg); 13147db96d56Sopenharmony_ci} 13157db96d56Sopenharmony_ci 13167db96d56Sopenharmony_ci/* Call tzinfo.tzname(tzinfoarg), and return the result. tzinfo must be 13177db96d56Sopenharmony_ci * an instance of the tzinfo class or None. If tzinfo isn't None, and 13187db96d56Sopenharmony_ci * tzname() doesn't return None or a string, TypeError is raised and this 13197db96d56Sopenharmony_ci * returns NULL. If the result is a string, we ensure it is a Unicode 13207db96d56Sopenharmony_ci * string. 13217db96d56Sopenharmony_ci */ 13227db96d56Sopenharmony_cistatic PyObject * 13237db96d56Sopenharmony_cicall_tzname(PyObject *tzinfo, PyObject *tzinfoarg) 13247db96d56Sopenharmony_ci{ 13257db96d56Sopenharmony_ci PyObject *result; 13267db96d56Sopenharmony_ci _Py_IDENTIFIER(tzname); 13277db96d56Sopenharmony_ci 13287db96d56Sopenharmony_ci assert(tzinfo != NULL); 13297db96d56Sopenharmony_ci assert(check_tzinfo_subclass(tzinfo) >= 0); 13307db96d56Sopenharmony_ci assert(tzinfoarg != NULL); 13317db96d56Sopenharmony_ci 13327db96d56Sopenharmony_ci if (tzinfo == Py_None) 13337db96d56Sopenharmony_ci Py_RETURN_NONE; 13347db96d56Sopenharmony_ci 13357db96d56Sopenharmony_ci result = _PyObject_CallMethodIdOneArg(tzinfo, &PyId_tzname, tzinfoarg); 13367db96d56Sopenharmony_ci 13377db96d56Sopenharmony_ci if (result == NULL || result == Py_None) 13387db96d56Sopenharmony_ci return result; 13397db96d56Sopenharmony_ci 13407db96d56Sopenharmony_ci if (!PyUnicode_Check(result)) { 13417db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, "tzinfo.tzname() must " 13427db96d56Sopenharmony_ci "return None or a string, not '%s'", 13437db96d56Sopenharmony_ci Py_TYPE(result)->tp_name); 13447db96d56Sopenharmony_ci Py_DECREF(result); 13457db96d56Sopenharmony_ci result = NULL; 13467db96d56Sopenharmony_ci } 13477db96d56Sopenharmony_ci 13487db96d56Sopenharmony_ci return result; 13497db96d56Sopenharmony_ci} 13507db96d56Sopenharmony_ci 13517db96d56Sopenharmony_ci/* repr is like "someclass(arg1, arg2)". If tzinfo isn't None, 13527db96d56Sopenharmony_ci * stuff 13537db96d56Sopenharmony_ci * ", tzinfo=" + repr(tzinfo) 13547db96d56Sopenharmony_ci * before the closing ")". 13557db96d56Sopenharmony_ci */ 13567db96d56Sopenharmony_cistatic PyObject * 13577db96d56Sopenharmony_ciappend_keyword_tzinfo(PyObject *repr, PyObject *tzinfo) 13587db96d56Sopenharmony_ci{ 13597db96d56Sopenharmony_ci PyObject *temp; 13607db96d56Sopenharmony_ci 13617db96d56Sopenharmony_ci assert(PyUnicode_Check(repr)); 13627db96d56Sopenharmony_ci assert(tzinfo); 13637db96d56Sopenharmony_ci if (tzinfo == Py_None) 13647db96d56Sopenharmony_ci return repr; 13657db96d56Sopenharmony_ci /* Get rid of the trailing ')'. */ 13667db96d56Sopenharmony_ci assert(PyUnicode_READ_CHAR(repr, PyUnicode_GET_LENGTH(repr)-1) == ')'); 13677db96d56Sopenharmony_ci temp = PyUnicode_Substring(repr, 0, PyUnicode_GET_LENGTH(repr) - 1); 13687db96d56Sopenharmony_ci Py_DECREF(repr); 13697db96d56Sopenharmony_ci if (temp == NULL) 13707db96d56Sopenharmony_ci return NULL; 13717db96d56Sopenharmony_ci repr = PyUnicode_FromFormat("%U, tzinfo=%R)", temp, tzinfo); 13727db96d56Sopenharmony_ci Py_DECREF(temp); 13737db96d56Sopenharmony_ci return repr; 13747db96d56Sopenharmony_ci} 13757db96d56Sopenharmony_ci 13767db96d56Sopenharmony_ci/* repr is like "someclass(arg1, arg2)". If fold isn't 0, 13777db96d56Sopenharmony_ci * stuff 13787db96d56Sopenharmony_ci * ", fold=" + repr(tzinfo) 13797db96d56Sopenharmony_ci * before the closing ")". 13807db96d56Sopenharmony_ci */ 13817db96d56Sopenharmony_cistatic PyObject * 13827db96d56Sopenharmony_ciappend_keyword_fold(PyObject *repr, int fold) 13837db96d56Sopenharmony_ci{ 13847db96d56Sopenharmony_ci PyObject *temp; 13857db96d56Sopenharmony_ci 13867db96d56Sopenharmony_ci assert(PyUnicode_Check(repr)); 13877db96d56Sopenharmony_ci if (fold == 0) 13887db96d56Sopenharmony_ci return repr; 13897db96d56Sopenharmony_ci /* Get rid of the trailing ')'. */ 13907db96d56Sopenharmony_ci assert(PyUnicode_READ_CHAR(repr, PyUnicode_GET_LENGTH(repr)-1) == ')'); 13917db96d56Sopenharmony_ci temp = PyUnicode_Substring(repr, 0, PyUnicode_GET_LENGTH(repr) - 1); 13927db96d56Sopenharmony_ci Py_DECREF(repr); 13937db96d56Sopenharmony_ci if (temp == NULL) 13947db96d56Sopenharmony_ci return NULL; 13957db96d56Sopenharmony_ci repr = PyUnicode_FromFormat("%U, fold=%d)", temp, fold); 13967db96d56Sopenharmony_ci Py_DECREF(temp); 13977db96d56Sopenharmony_ci return repr; 13987db96d56Sopenharmony_ci} 13997db96d56Sopenharmony_ci 14007db96d56Sopenharmony_cistatic inline PyObject * 14017db96d56Sopenharmony_citzinfo_from_isoformat_results(int rv, int tzoffset, int tz_useconds) 14027db96d56Sopenharmony_ci{ 14037db96d56Sopenharmony_ci PyObject *tzinfo; 14047db96d56Sopenharmony_ci if (rv == 1) { 14057db96d56Sopenharmony_ci // Create a timezone from offset in seconds (0 returns UTC) 14067db96d56Sopenharmony_ci if (tzoffset == 0) { 14077db96d56Sopenharmony_ci Py_INCREF(PyDateTime_TimeZone_UTC); 14087db96d56Sopenharmony_ci return PyDateTime_TimeZone_UTC; 14097db96d56Sopenharmony_ci } 14107db96d56Sopenharmony_ci 14117db96d56Sopenharmony_ci PyObject *delta = new_delta(0, tzoffset, tz_useconds, 1); 14127db96d56Sopenharmony_ci if (delta == NULL) { 14137db96d56Sopenharmony_ci return NULL; 14147db96d56Sopenharmony_ci } 14157db96d56Sopenharmony_ci tzinfo = new_timezone(delta, NULL); 14167db96d56Sopenharmony_ci Py_DECREF(delta); 14177db96d56Sopenharmony_ci } 14187db96d56Sopenharmony_ci else { 14197db96d56Sopenharmony_ci tzinfo = Py_None; 14207db96d56Sopenharmony_ci Py_INCREF(Py_None); 14217db96d56Sopenharmony_ci } 14227db96d56Sopenharmony_ci 14237db96d56Sopenharmony_ci return tzinfo; 14247db96d56Sopenharmony_ci} 14257db96d56Sopenharmony_ci 14267db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 14277db96d56Sopenharmony_ci * String format helpers. 14287db96d56Sopenharmony_ci */ 14297db96d56Sopenharmony_ci 14307db96d56Sopenharmony_cistatic PyObject * 14317db96d56Sopenharmony_ciformat_ctime(PyDateTime_Date *date, int hours, int minutes, int seconds) 14327db96d56Sopenharmony_ci{ 14337db96d56Sopenharmony_ci static const char * const DayNames[] = { 14347db96d56Sopenharmony_ci "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" 14357db96d56Sopenharmony_ci }; 14367db96d56Sopenharmony_ci static const char * const MonthNames[] = { 14377db96d56Sopenharmony_ci "Jan", "Feb", "Mar", "Apr", "May", "Jun", 14387db96d56Sopenharmony_ci "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 14397db96d56Sopenharmony_ci }; 14407db96d56Sopenharmony_ci 14417db96d56Sopenharmony_ci int wday = weekday(GET_YEAR(date), GET_MONTH(date), GET_DAY(date)); 14427db96d56Sopenharmony_ci 14437db96d56Sopenharmony_ci return PyUnicode_FromFormat("%s %s %2d %02d:%02d:%02d %04d", 14447db96d56Sopenharmony_ci DayNames[wday], MonthNames[GET_MONTH(date)-1], 14457db96d56Sopenharmony_ci GET_DAY(date), hours, minutes, seconds, 14467db96d56Sopenharmony_ci GET_YEAR(date)); 14477db96d56Sopenharmony_ci} 14487db96d56Sopenharmony_ci 14497db96d56Sopenharmony_cistatic PyObject *delta_negative(PyDateTime_Delta *self); 14507db96d56Sopenharmony_ci 14517db96d56Sopenharmony_ci/* Add formatted UTC offset string to buf. buf has no more than 14527db96d56Sopenharmony_ci * buflen bytes remaining. The UTC offset is gotten by calling 14537db96d56Sopenharmony_ci * tzinfo.uctoffset(tzinfoarg). If that returns None, \0 is stored into 14547db96d56Sopenharmony_ci * *buf, and that's all. Else the returned value is checked for sanity (an 14557db96d56Sopenharmony_ci * integer in range), and if that's OK it's converted to an hours & minutes 14567db96d56Sopenharmony_ci * string of the form 14577db96d56Sopenharmony_ci * sign HH sep MM [sep SS [. UUUUUU]] 14587db96d56Sopenharmony_ci * Returns 0 if everything is OK. If the return value from utcoffset() is 14597db96d56Sopenharmony_ci * bogus, an appropriate exception is set and -1 is returned. 14607db96d56Sopenharmony_ci */ 14617db96d56Sopenharmony_cistatic int 14627db96d56Sopenharmony_ciformat_utcoffset(char *buf, size_t buflen, const char *sep, 14637db96d56Sopenharmony_ci PyObject *tzinfo, PyObject *tzinfoarg) 14647db96d56Sopenharmony_ci{ 14657db96d56Sopenharmony_ci PyObject *offset; 14667db96d56Sopenharmony_ci int hours, minutes, seconds, microseconds; 14677db96d56Sopenharmony_ci char sign; 14687db96d56Sopenharmony_ci 14697db96d56Sopenharmony_ci assert(buflen >= 1); 14707db96d56Sopenharmony_ci 14717db96d56Sopenharmony_ci offset = call_utcoffset(tzinfo, tzinfoarg); 14727db96d56Sopenharmony_ci if (offset == NULL) 14737db96d56Sopenharmony_ci return -1; 14747db96d56Sopenharmony_ci if (offset == Py_None) { 14757db96d56Sopenharmony_ci Py_DECREF(offset); 14767db96d56Sopenharmony_ci *buf = '\0'; 14777db96d56Sopenharmony_ci return 0; 14787db96d56Sopenharmony_ci } 14797db96d56Sopenharmony_ci /* Offset is normalized, so it is negative if days < 0 */ 14807db96d56Sopenharmony_ci if (GET_TD_DAYS(offset) < 0) { 14817db96d56Sopenharmony_ci sign = '-'; 14827db96d56Sopenharmony_ci Py_SETREF(offset, delta_negative((PyDateTime_Delta *)offset)); 14837db96d56Sopenharmony_ci if (offset == NULL) 14847db96d56Sopenharmony_ci return -1; 14857db96d56Sopenharmony_ci } 14867db96d56Sopenharmony_ci else { 14877db96d56Sopenharmony_ci sign = '+'; 14887db96d56Sopenharmony_ci } 14897db96d56Sopenharmony_ci /* Offset is not negative here. */ 14907db96d56Sopenharmony_ci microseconds = GET_TD_MICROSECONDS(offset); 14917db96d56Sopenharmony_ci seconds = GET_TD_SECONDS(offset); 14927db96d56Sopenharmony_ci Py_DECREF(offset); 14937db96d56Sopenharmony_ci minutes = divmod(seconds, 60, &seconds); 14947db96d56Sopenharmony_ci hours = divmod(minutes, 60, &minutes); 14957db96d56Sopenharmony_ci if (microseconds) { 14967db96d56Sopenharmony_ci PyOS_snprintf(buf, buflen, "%c%02d%s%02d%s%02d.%06d", sign, 14977db96d56Sopenharmony_ci hours, sep, minutes, sep, seconds, microseconds); 14987db96d56Sopenharmony_ci return 0; 14997db96d56Sopenharmony_ci } 15007db96d56Sopenharmony_ci if (seconds) { 15017db96d56Sopenharmony_ci PyOS_snprintf(buf, buflen, "%c%02d%s%02d%s%02d", sign, hours, 15027db96d56Sopenharmony_ci sep, minutes, sep, seconds); 15037db96d56Sopenharmony_ci return 0; 15047db96d56Sopenharmony_ci } 15057db96d56Sopenharmony_ci PyOS_snprintf(buf, buflen, "%c%02d%s%02d", sign, hours, sep, minutes); 15067db96d56Sopenharmony_ci return 0; 15077db96d56Sopenharmony_ci} 15087db96d56Sopenharmony_ci 15097db96d56Sopenharmony_cistatic PyObject * 15107db96d56Sopenharmony_cimake_Zreplacement(PyObject *object, PyObject *tzinfoarg) 15117db96d56Sopenharmony_ci{ 15127db96d56Sopenharmony_ci PyObject *temp; 15137db96d56Sopenharmony_ci PyObject *tzinfo = get_tzinfo_member(object); 15147db96d56Sopenharmony_ci PyObject *Zreplacement = PyUnicode_FromStringAndSize(NULL, 0); 15157db96d56Sopenharmony_ci _Py_IDENTIFIER(replace); 15167db96d56Sopenharmony_ci 15177db96d56Sopenharmony_ci if (Zreplacement == NULL) 15187db96d56Sopenharmony_ci return NULL; 15197db96d56Sopenharmony_ci if (tzinfo == Py_None || tzinfo == NULL) 15207db96d56Sopenharmony_ci return Zreplacement; 15217db96d56Sopenharmony_ci 15227db96d56Sopenharmony_ci assert(tzinfoarg != NULL); 15237db96d56Sopenharmony_ci temp = call_tzname(tzinfo, tzinfoarg); 15247db96d56Sopenharmony_ci if (temp == NULL) 15257db96d56Sopenharmony_ci goto Error; 15267db96d56Sopenharmony_ci if (temp == Py_None) { 15277db96d56Sopenharmony_ci Py_DECREF(temp); 15287db96d56Sopenharmony_ci return Zreplacement; 15297db96d56Sopenharmony_ci } 15307db96d56Sopenharmony_ci 15317db96d56Sopenharmony_ci assert(PyUnicode_Check(temp)); 15327db96d56Sopenharmony_ci /* Since the tzname is getting stuffed into the 15337db96d56Sopenharmony_ci * format, we have to double any % signs so that 15347db96d56Sopenharmony_ci * strftime doesn't treat them as format codes. 15357db96d56Sopenharmony_ci */ 15367db96d56Sopenharmony_ci Py_DECREF(Zreplacement); 15377db96d56Sopenharmony_ci Zreplacement = _PyObject_CallMethodId(temp, &PyId_replace, "ss", "%", "%%"); 15387db96d56Sopenharmony_ci Py_DECREF(temp); 15397db96d56Sopenharmony_ci if (Zreplacement == NULL) 15407db96d56Sopenharmony_ci return NULL; 15417db96d56Sopenharmony_ci if (!PyUnicode_Check(Zreplacement)) { 15427db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 15437db96d56Sopenharmony_ci "tzname.replace() did not return a string"); 15447db96d56Sopenharmony_ci goto Error; 15457db96d56Sopenharmony_ci } 15467db96d56Sopenharmony_ci return Zreplacement; 15477db96d56Sopenharmony_ci 15487db96d56Sopenharmony_ci Error: 15497db96d56Sopenharmony_ci Py_DECREF(Zreplacement); 15507db96d56Sopenharmony_ci return NULL; 15517db96d56Sopenharmony_ci} 15527db96d56Sopenharmony_ci 15537db96d56Sopenharmony_cistatic PyObject * 15547db96d56Sopenharmony_cimake_freplacement(PyObject *object) 15557db96d56Sopenharmony_ci{ 15567db96d56Sopenharmony_ci char freplacement[64]; 15577db96d56Sopenharmony_ci if (PyTime_Check(object)) 15587db96d56Sopenharmony_ci sprintf(freplacement, "%06d", TIME_GET_MICROSECOND(object)); 15597db96d56Sopenharmony_ci else if (PyDateTime_Check(object)) 15607db96d56Sopenharmony_ci sprintf(freplacement, "%06d", DATE_GET_MICROSECOND(object)); 15617db96d56Sopenharmony_ci else 15627db96d56Sopenharmony_ci sprintf(freplacement, "%06d", 0); 15637db96d56Sopenharmony_ci 15647db96d56Sopenharmony_ci return PyBytes_FromStringAndSize(freplacement, strlen(freplacement)); 15657db96d56Sopenharmony_ci} 15667db96d56Sopenharmony_ci 15677db96d56Sopenharmony_ci/* I sure don't want to reproduce the strftime code from the time module, 15687db96d56Sopenharmony_ci * so this imports the module and calls it. All the hair is due to 15697db96d56Sopenharmony_ci * giving special meanings to the %z, %Z and %f format codes via a 15707db96d56Sopenharmony_ci * preprocessing step on the format string. 15717db96d56Sopenharmony_ci * tzinfoarg is the argument to pass to the object's tzinfo method, if 15727db96d56Sopenharmony_ci * needed. 15737db96d56Sopenharmony_ci */ 15747db96d56Sopenharmony_cistatic PyObject * 15757db96d56Sopenharmony_ciwrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, 15767db96d56Sopenharmony_ci PyObject *tzinfoarg) 15777db96d56Sopenharmony_ci{ 15787db96d56Sopenharmony_ci PyObject *result = NULL; /* guilty until proved innocent */ 15797db96d56Sopenharmony_ci 15807db96d56Sopenharmony_ci PyObject *zreplacement = NULL; /* py string, replacement for %z */ 15817db96d56Sopenharmony_ci PyObject *Zreplacement = NULL; /* py string, replacement for %Z */ 15827db96d56Sopenharmony_ci PyObject *freplacement = NULL; /* py string, replacement for %f */ 15837db96d56Sopenharmony_ci 15847db96d56Sopenharmony_ci const char *pin; /* pointer to next char in input format */ 15857db96d56Sopenharmony_ci Py_ssize_t flen; /* length of input format */ 15867db96d56Sopenharmony_ci char ch; /* next char in input format */ 15877db96d56Sopenharmony_ci 15887db96d56Sopenharmony_ci PyObject *newfmt = NULL; /* py string, the output format */ 15897db96d56Sopenharmony_ci char *pnew; /* pointer to available byte in output format */ 15907db96d56Sopenharmony_ci size_t totalnew; /* number bytes total in output format buffer, 15917db96d56Sopenharmony_ci exclusive of trailing \0 */ 15927db96d56Sopenharmony_ci size_t usednew; /* number bytes used so far in output format buffer */ 15937db96d56Sopenharmony_ci 15947db96d56Sopenharmony_ci const char *ptoappend; /* ptr to string to append to output buffer */ 15957db96d56Sopenharmony_ci Py_ssize_t ntoappend; /* # of bytes to append to output buffer */ 15967db96d56Sopenharmony_ci 15977db96d56Sopenharmony_ci assert(object && format && timetuple); 15987db96d56Sopenharmony_ci assert(PyUnicode_Check(format)); 15997db96d56Sopenharmony_ci /* Convert the input format to a C string and size */ 16007db96d56Sopenharmony_ci pin = PyUnicode_AsUTF8AndSize(format, &flen); 16017db96d56Sopenharmony_ci if (!pin) 16027db96d56Sopenharmony_ci return NULL; 16037db96d56Sopenharmony_ci 16047db96d56Sopenharmony_ci /* Scan the input format, looking for %z/%Z/%f escapes, building 16057db96d56Sopenharmony_ci * a new format. Since computing the replacements for those codes 16067db96d56Sopenharmony_ci * is expensive, don't unless they're actually used. 16077db96d56Sopenharmony_ci */ 16087db96d56Sopenharmony_ci if (flen > INT_MAX - 1) { 16097db96d56Sopenharmony_ci PyErr_NoMemory(); 16107db96d56Sopenharmony_ci goto Done; 16117db96d56Sopenharmony_ci } 16127db96d56Sopenharmony_ci 16137db96d56Sopenharmony_ci totalnew = flen + 1; /* realistic if no %z/%Z */ 16147db96d56Sopenharmony_ci newfmt = PyBytes_FromStringAndSize(NULL, totalnew); 16157db96d56Sopenharmony_ci if (newfmt == NULL) goto Done; 16167db96d56Sopenharmony_ci pnew = PyBytes_AsString(newfmt); 16177db96d56Sopenharmony_ci usednew = 0; 16187db96d56Sopenharmony_ci 16197db96d56Sopenharmony_ci while ((ch = *pin++) != '\0') { 16207db96d56Sopenharmony_ci if (ch != '%') { 16217db96d56Sopenharmony_ci ptoappend = pin - 1; 16227db96d56Sopenharmony_ci ntoappend = 1; 16237db96d56Sopenharmony_ci } 16247db96d56Sopenharmony_ci else if ((ch = *pin++) == '\0') { 16257db96d56Sopenharmony_ci /* Null byte follows %, copy only '%'. 16267db96d56Sopenharmony_ci * 16277db96d56Sopenharmony_ci * Back the pin up one char so that we catch the null check 16287db96d56Sopenharmony_ci * the next time through the loop.*/ 16297db96d56Sopenharmony_ci pin--; 16307db96d56Sopenharmony_ci ptoappend = pin - 1; 16317db96d56Sopenharmony_ci ntoappend = 1; 16327db96d56Sopenharmony_ci } 16337db96d56Sopenharmony_ci /* A % has been seen and ch is the character after it. */ 16347db96d56Sopenharmony_ci else if (ch == 'z') { 16357db96d56Sopenharmony_ci if (zreplacement == NULL) { 16367db96d56Sopenharmony_ci /* format utcoffset */ 16377db96d56Sopenharmony_ci char buf[100]; 16387db96d56Sopenharmony_ci PyObject *tzinfo = get_tzinfo_member(object); 16397db96d56Sopenharmony_ci zreplacement = PyBytes_FromStringAndSize("", 0); 16407db96d56Sopenharmony_ci if (zreplacement == NULL) goto Done; 16417db96d56Sopenharmony_ci if (tzinfo != Py_None && tzinfo != NULL) { 16427db96d56Sopenharmony_ci assert(tzinfoarg != NULL); 16437db96d56Sopenharmony_ci if (format_utcoffset(buf, 16447db96d56Sopenharmony_ci sizeof(buf), 16457db96d56Sopenharmony_ci "", 16467db96d56Sopenharmony_ci tzinfo, 16477db96d56Sopenharmony_ci tzinfoarg) < 0) 16487db96d56Sopenharmony_ci goto Done; 16497db96d56Sopenharmony_ci Py_DECREF(zreplacement); 16507db96d56Sopenharmony_ci zreplacement = 16517db96d56Sopenharmony_ci PyBytes_FromStringAndSize(buf, 16527db96d56Sopenharmony_ci strlen(buf)); 16537db96d56Sopenharmony_ci if (zreplacement == NULL) 16547db96d56Sopenharmony_ci goto Done; 16557db96d56Sopenharmony_ci } 16567db96d56Sopenharmony_ci } 16577db96d56Sopenharmony_ci assert(zreplacement != NULL); 16587db96d56Sopenharmony_ci ptoappend = PyBytes_AS_STRING(zreplacement); 16597db96d56Sopenharmony_ci ntoappend = PyBytes_GET_SIZE(zreplacement); 16607db96d56Sopenharmony_ci } 16617db96d56Sopenharmony_ci else if (ch == 'Z') { 16627db96d56Sopenharmony_ci /* format tzname */ 16637db96d56Sopenharmony_ci if (Zreplacement == NULL) { 16647db96d56Sopenharmony_ci Zreplacement = make_Zreplacement(object, 16657db96d56Sopenharmony_ci tzinfoarg); 16667db96d56Sopenharmony_ci if (Zreplacement == NULL) 16677db96d56Sopenharmony_ci goto Done; 16687db96d56Sopenharmony_ci } 16697db96d56Sopenharmony_ci assert(Zreplacement != NULL); 16707db96d56Sopenharmony_ci assert(PyUnicode_Check(Zreplacement)); 16717db96d56Sopenharmony_ci ptoappend = PyUnicode_AsUTF8AndSize(Zreplacement, 16727db96d56Sopenharmony_ci &ntoappend); 16737db96d56Sopenharmony_ci if (ptoappend == NULL) 16747db96d56Sopenharmony_ci goto Done; 16757db96d56Sopenharmony_ci } 16767db96d56Sopenharmony_ci else if (ch == 'f') { 16777db96d56Sopenharmony_ci /* format microseconds */ 16787db96d56Sopenharmony_ci if (freplacement == NULL) { 16797db96d56Sopenharmony_ci freplacement = make_freplacement(object); 16807db96d56Sopenharmony_ci if (freplacement == NULL) 16817db96d56Sopenharmony_ci goto Done; 16827db96d56Sopenharmony_ci } 16837db96d56Sopenharmony_ci assert(freplacement != NULL); 16847db96d56Sopenharmony_ci assert(PyBytes_Check(freplacement)); 16857db96d56Sopenharmony_ci ptoappend = PyBytes_AS_STRING(freplacement); 16867db96d56Sopenharmony_ci ntoappend = PyBytes_GET_SIZE(freplacement); 16877db96d56Sopenharmony_ci } 16887db96d56Sopenharmony_ci else { 16897db96d56Sopenharmony_ci /* percent followed by neither z nor Z */ 16907db96d56Sopenharmony_ci ptoappend = pin - 2; 16917db96d56Sopenharmony_ci ntoappend = 2; 16927db96d56Sopenharmony_ci } 16937db96d56Sopenharmony_ci 16947db96d56Sopenharmony_ci /* Append the ntoappend chars starting at ptoappend to 16957db96d56Sopenharmony_ci * the new format. 16967db96d56Sopenharmony_ci */ 16977db96d56Sopenharmony_ci if (ntoappend == 0) 16987db96d56Sopenharmony_ci continue; 16997db96d56Sopenharmony_ci assert(ptoappend != NULL); 17007db96d56Sopenharmony_ci assert(ntoappend > 0); 17017db96d56Sopenharmony_ci while (usednew + ntoappend > totalnew) { 17027db96d56Sopenharmony_ci if (totalnew > (PY_SSIZE_T_MAX >> 1)) { /* overflow */ 17037db96d56Sopenharmony_ci PyErr_NoMemory(); 17047db96d56Sopenharmony_ci goto Done; 17057db96d56Sopenharmony_ci } 17067db96d56Sopenharmony_ci totalnew <<= 1; 17077db96d56Sopenharmony_ci if (_PyBytes_Resize(&newfmt, totalnew) < 0) 17087db96d56Sopenharmony_ci goto Done; 17097db96d56Sopenharmony_ci pnew = PyBytes_AsString(newfmt) + usednew; 17107db96d56Sopenharmony_ci } 17117db96d56Sopenharmony_ci memcpy(pnew, ptoappend, ntoappend); 17127db96d56Sopenharmony_ci pnew += ntoappend; 17137db96d56Sopenharmony_ci usednew += ntoappend; 17147db96d56Sopenharmony_ci assert(usednew <= totalnew); 17157db96d56Sopenharmony_ci } /* end while() */ 17167db96d56Sopenharmony_ci 17177db96d56Sopenharmony_ci if (_PyBytes_Resize(&newfmt, usednew) < 0) 17187db96d56Sopenharmony_ci goto Done; 17197db96d56Sopenharmony_ci { 17207db96d56Sopenharmony_ci PyObject *format; 17217db96d56Sopenharmony_ci PyObject *time = PyImport_ImportModule("time"); 17227db96d56Sopenharmony_ci 17237db96d56Sopenharmony_ci if (time == NULL) 17247db96d56Sopenharmony_ci goto Done; 17257db96d56Sopenharmony_ci format = PyUnicode_FromString(PyBytes_AS_STRING(newfmt)); 17267db96d56Sopenharmony_ci if (format != NULL) { 17277db96d56Sopenharmony_ci result = _PyObject_CallMethodIdObjArgs(time, &PyId_strftime, 17287db96d56Sopenharmony_ci format, timetuple, NULL); 17297db96d56Sopenharmony_ci Py_DECREF(format); 17307db96d56Sopenharmony_ci } 17317db96d56Sopenharmony_ci Py_DECREF(time); 17327db96d56Sopenharmony_ci } 17337db96d56Sopenharmony_ci Done: 17347db96d56Sopenharmony_ci Py_XDECREF(freplacement); 17357db96d56Sopenharmony_ci Py_XDECREF(zreplacement); 17367db96d56Sopenharmony_ci Py_XDECREF(Zreplacement); 17377db96d56Sopenharmony_ci Py_XDECREF(newfmt); 17387db96d56Sopenharmony_ci return result; 17397db96d56Sopenharmony_ci} 17407db96d56Sopenharmony_ci 17417db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 17427db96d56Sopenharmony_ci * Wrap functions from the time module. These aren't directly available 17437db96d56Sopenharmony_ci * from C. Perhaps they should be. 17447db96d56Sopenharmony_ci */ 17457db96d56Sopenharmony_ci 17467db96d56Sopenharmony_ci/* Call time.time() and return its result (a Python float). */ 17477db96d56Sopenharmony_cistatic PyObject * 17487db96d56Sopenharmony_citime_time(void) 17497db96d56Sopenharmony_ci{ 17507db96d56Sopenharmony_ci PyObject *result = NULL; 17517db96d56Sopenharmony_ci PyObject *time = PyImport_ImportModule("time"); 17527db96d56Sopenharmony_ci 17537db96d56Sopenharmony_ci if (time != NULL) { 17547db96d56Sopenharmony_ci _Py_IDENTIFIER(time); 17557db96d56Sopenharmony_ci 17567db96d56Sopenharmony_ci result = _PyObject_CallMethodIdNoArgs(time, &PyId_time); 17577db96d56Sopenharmony_ci Py_DECREF(time); 17587db96d56Sopenharmony_ci } 17597db96d56Sopenharmony_ci return result; 17607db96d56Sopenharmony_ci} 17617db96d56Sopenharmony_ci 17627db96d56Sopenharmony_ci/* Build a time.struct_time. The weekday and day number are automatically 17637db96d56Sopenharmony_ci * computed from the y,m,d args. 17647db96d56Sopenharmony_ci */ 17657db96d56Sopenharmony_cistatic PyObject * 17667db96d56Sopenharmony_cibuild_struct_time(int y, int m, int d, int hh, int mm, int ss, int dstflag) 17677db96d56Sopenharmony_ci{ 17687db96d56Sopenharmony_ci PyObject *time; 17697db96d56Sopenharmony_ci PyObject *result; 17707db96d56Sopenharmony_ci _Py_IDENTIFIER(struct_time); 17717db96d56Sopenharmony_ci PyObject *args; 17727db96d56Sopenharmony_ci 17737db96d56Sopenharmony_ci 17747db96d56Sopenharmony_ci time = PyImport_ImportModule("time"); 17757db96d56Sopenharmony_ci if (time == NULL) { 17767db96d56Sopenharmony_ci return NULL; 17777db96d56Sopenharmony_ci } 17787db96d56Sopenharmony_ci 17797db96d56Sopenharmony_ci args = Py_BuildValue("iiiiiiiii", 17807db96d56Sopenharmony_ci y, m, d, 17817db96d56Sopenharmony_ci hh, mm, ss, 17827db96d56Sopenharmony_ci weekday(y, m, d), 17837db96d56Sopenharmony_ci days_before_month(y, m) + d, 17847db96d56Sopenharmony_ci dstflag); 17857db96d56Sopenharmony_ci if (args == NULL) { 17867db96d56Sopenharmony_ci Py_DECREF(time); 17877db96d56Sopenharmony_ci return NULL; 17887db96d56Sopenharmony_ci } 17897db96d56Sopenharmony_ci 17907db96d56Sopenharmony_ci result = _PyObject_CallMethodIdOneArg(time, &PyId_struct_time, args); 17917db96d56Sopenharmony_ci Py_DECREF(time); 17927db96d56Sopenharmony_ci Py_DECREF(args); 17937db96d56Sopenharmony_ci return result; 17947db96d56Sopenharmony_ci} 17957db96d56Sopenharmony_ci 17967db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 17977db96d56Sopenharmony_ci * Miscellaneous helpers. 17987db96d56Sopenharmony_ci */ 17997db96d56Sopenharmony_ci 18007db96d56Sopenharmony_ci/* The comparisons here all most naturally compute a cmp()-like result. 18017db96d56Sopenharmony_ci * This little helper turns that into a bool result for rich comparisons. 18027db96d56Sopenharmony_ci */ 18037db96d56Sopenharmony_cistatic PyObject * 18047db96d56Sopenharmony_cidiff_to_bool(int diff, int op) 18057db96d56Sopenharmony_ci{ 18067db96d56Sopenharmony_ci Py_RETURN_RICHCOMPARE(diff, 0, op); 18077db96d56Sopenharmony_ci} 18087db96d56Sopenharmony_ci 18097db96d56Sopenharmony_ci/* Raises a "can't compare" TypeError and returns NULL. */ 18107db96d56Sopenharmony_cistatic PyObject * 18117db96d56Sopenharmony_cicmperror(PyObject *a, PyObject *b) 18127db96d56Sopenharmony_ci{ 18137db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 18147db96d56Sopenharmony_ci "can't compare %s to %s", 18157db96d56Sopenharmony_ci Py_TYPE(a)->tp_name, Py_TYPE(b)->tp_name); 18167db96d56Sopenharmony_ci return NULL; 18177db96d56Sopenharmony_ci} 18187db96d56Sopenharmony_ci 18197db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 18207db96d56Sopenharmony_ci * Cached Python objects; these are set by the module init function. 18217db96d56Sopenharmony_ci */ 18227db96d56Sopenharmony_ci 18237db96d56Sopenharmony_ci/* Conversion factors. */ 18247db96d56Sopenharmony_cistatic PyObject *us_per_ms = NULL; /* 1000 */ 18257db96d56Sopenharmony_cistatic PyObject *us_per_second = NULL; /* 1000000 */ 18267db96d56Sopenharmony_cistatic PyObject *us_per_minute = NULL; /* 1e6 * 60 as Python int */ 18277db96d56Sopenharmony_cistatic PyObject *us_per_hour = NULL; /* 1e6 * 3600 as Python int */ 18287db96d56Sopenharmony_cistatic PyObject *us_per_day = NULL; /* 1e6 * 3600 * 24 as Python int */ 18297db96d56Sopenharmony_cistatic PyObject *us_per_week = NULL; /* 1e6*3600*24*7 as Python int */ 18307db96d56Sopenharmony_cistatic PyObject *seconds_per_day = NULL; /* 3600*24 as Python int */ 18317db96d56Sopenharmony_ci 18327db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 18337db96d56Sopenharmony_ci * Class implementations. 18347db96d56Sopenharmony_ci */ 18357db96d56Sopenharmony_ci 18367db96d56Sopenharmony_ci/* 18377db96d56Sopenharmony_ci * PyDateTime_Delta implementation. 18387db96d56Sopenharmony_ci */ 18397db96d56Sopenharmony_ci 18407db96d56Sopenharmony_ci/* Convert a timedelta to a number of us, 18417db96d56Sopenharmony_ci * (24*3600*self.days + self.seconds)*1000000 + self.microseconds 18427db96d56Sopenharmony_ci * as a Python int. 18437db96d56Sopenharmony_ci * Doing mixed-radix arithmetic by hand instead is excruciating in C, 18447db96d56Sopenharmony_ci * due to ubiquitous overflow possibilities. 18457db96d56Sopenharmony_ci */ 18467db96d56Sopenharmony_cistatic PyObject * 18477db96d56Sopenharmony_cidelta_to_microseconds(PyDateTime_Delta *self) 18487db96d56Sopenharmony_ci{ 18497db96d56Sopenharmony_ci PyObject *x1 = NULL; 18507db96d56Sopenharmony_ci PyObject *x2 = NULL; 18517db96d56Sopenharmony_ci PyObject *x3 = NULL; 18527db96d56Sopenharmony_ci PyObject *result = NULL; 18537db96d56Sopenharmony_ci 18547db96d56Sopenharmony_ci x1 = PyLong_FromLong(GET_TD_DAYS(self)); 18557db96d56Sopenharmony_ci if (x1 == NULL) 18567db96d56Sopenharmony_ci goto Done; 18577db96d56Sopenharmony_ci x2 = PyNumber_Multiply(x1, seconds_per_day); /* days in seconds */ 18587db96d56Sopenharmony_ci if (x2 == NULL) 18597db96d56Sopenharmony_ci goto Done; 18607db96d56Sopenharmony_ci Py_DECREF(x1); 18617db96d56Sopenharmony_ci x1 = NULL; 18627db96d56Sopenharmony_ci 18637db96d56Sopenharmony_ci /* x2 has days in seconds */ 18647db96d56Sopenharmony_ci x1 = PyLong_FromLong(GET_TD_SECONDS(self)); /* seconds */ 18657db96d56Sopenharmony_ci if (x1 == NULL) 18667db96d56Sopenharmony_ci goto Done; 18677db96d56Sopenharmony_ci x3 = PyNumber_Add(x1, x2); /* days and seconds in seconds */ 18687db96d56Sopenharmony_ci if (x3 == NULL) 18697db96d56Sopenharmony_ci goto Done; 18707db96d56Sopenharmony_ci Py_DECREF(x1); 18717db96d56Sopenharmony_ci Py_DECREF(x2); 18727db96d56Sopenharmony_ci /* x1 = */ x2 = NULL; 18737db96d56Sopenharmony_ci 18747db96d56Sopenharmony_ci /* x3 has days+seconds in seconds */ 18757db96d56Sopenharmony_ci x1 = PyNumber_Multiply(x3, us_per_second); /* us */ 18767db96d56Sopenharmony_ci if (x1 == NULL) 18777db96d56Sopenharmony_ci goto Done; 18787db96d56Sopenharmony_ci Py_DECREF(x3); 18797db96d56Sopenharmony_ci x3 = NULL; 18807db96d56Sopenharmony_ci 18817db96d56Sopenharmony_ci /* x1 has days+seconds in us */ 18827db96d56Sopenharmony_ci x2 = PyLong_FromLong(GET_TD_MICROSECONDS(self)); 18837db96d56Sopenharmony_ci if (x2 == NULL) 18847db96d56Sopenharmony_ci goto Done; 18857db96d56Sopenharmony_ci result = PyNumber_Add(x1, x2); 18867db96d56Sopenharmony_ci assert(result == NULL || PyLong_CheckExact(result)); 18877db96d56Sopenharmony_ci 18887db96d56Sopenharmony_ciDone: 18897db96d56Sopenharmony_ci Py_XDECREF(x1); 18907db96d56Sopenharmony_ci Py_XDECREF(x2); 18917db96d56Sopenharmony_ci Py_XDECREF(x3); 18927db96d56Sopenharmony_ci return result; 18937db96d56Sopenharmony_ci} 18947db96d56Sopenharmony_ci 18957db96d56Sopenharmony_cistatic PyObject * 18967db96d56Sopenharmony_cichecked_divmod(PyObject *a, PyObject *b) 18977db96d56Sopenharmony_ci{ 18987db96d56Sopenharmony_ci PyObject *result = PyNumber_Divmod(a, b); 18997db96d56Sopenharmony_ci if (result != NULL) { 19007db96d56Sopenharmony_ci if (!PyTuple_Check(result)) { 19017db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 19027db96d56Sopenharmony_ci "divmod() returned non-tuple (type %.200s)", 19037db96d56Sopenharmony_ci Py_TYPE(result)->tp_name); 19047db96d56Sopenharmony_ci Py_DECREF(result); 19057db96d56Sopenharmony_ci return NULL; 19067db96d56Sopenharmony_ci } 19077db96d56Sopenharmony_ci if (PyTuple_GET_SIZE(result) != 2) { 19087db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 19097db96d56Sopenharmony_ci "divmod() returned a tuple of size %zd", 19107db96d56Sopenharmony_ci PyTuple_GET_SIZE(result)); 19117db96d56Sopenharmony_ci Py_DECREF(result); 19127db96d56Sopenharmony_ci return NULL; 19137db96d56Sopenharmony_ci } 19147db96d56Sopenharmony_ci } 19157db96d56Sopenharmony_ci return result; 19167db96d56Sopenharmony_ci} 19177db96d56Sopenharmony_ci 19187db96d56Sopenharmony_ci/* Convert a number of us (as a Python int) to a timedelta. 19197db96d56Sopenharmony_ci */ 19207db96d56Sopenharmony_cistatic PyObject * 19217db96d56Sopenharmony_cimicroseconds_to_delta_ex(PyObject *pyus, PyTypeObject *type) 19227db96d56Sopenharmony_ci{ 19237db96d56Sopenharmony_ci int us; 19247db96d56Sopenharmony_ci int s; 19257db96d56Sopenharmony_ci int d; 19267db96d56Sopenharmony_ci 19277db96d56Sopenharmony_ci PyObject *tuple = NULL; 19287db96d56Sopenharmony_ci PyObject *num = NULL; 19297db96d56Sopenharmony_ci PyObject *result = NULL; 19307db96d56Sopenharmony_ci 19317db96d56Sopenharmony_ci tuple = checked_divmod(pyus, us_per_second); 19327db96d56Sopenharmony_ci if (tuple == NULL) { 19337db96d56Sopenharmony_ci goto Done; 19347db96d56Sopenharmony_ci } 19357db96d56Sopenharmony_ci 19367db96d56Sopenharmony_ci num = PyTuple_GET_ITEM(tuple, 1); /* us */ 19377db96d56Sopenharmony_ci us = _PyLong_AsInt(num); 19387db96d56Sopenharmony_ci num = NULL; 19397db96d56Sopenharmony_ci if (us == -1 && PyErr_Occurred()) { 19407db96d56Sopenharmony_ci goto Done; 19417db96d56Sopenharmony_ci } 19427db96d56Sopenharmony_ci if (!(0 <= us && us < 1000000)) { 19437db96d56Sopenharmony_ci goto BadDivmod; 19447db96d56Sopenharmony_ci } 19457db96d56Sopenharmony_ci 19467db96d56Sopenharmony_ci num = PyTuple_GET_ITEM(tuple, 0); /* leftover seconds */ 19477db96d56Sopenharmony_ci Py_INCREF(num); 19487db96d56Sopenharmony_ci Py_DECREF(tuple); 19497db96d56Sopenharmony_ci 19507db96d56Sopenharmony_ci tuple = checked_divmod(num, seconds_per_day); 19517db96d56Sopenharmony_ci if (tuple == NULL) 19527db96d56Sopenharmony_ci goto Done; 19537db96d56Sopenharmony_ci Py_DECREF(num); 19547db96d56Sopenharmony_ci 19557db96d56Sopenharmony_ci num = PyTuple_GET_ITEM(tuple, 1); /* seconds */ 19567db96d56Sopenharmony_ci s = _PyLong_AsInt(num); 19577db96d56Sopenharmony_ci num = NULL; 19587db96d56Sopenharmony_ci if (s == -1 && PyErr_Occurred()) { 19597db96d56Sopenharmony_ci goto Done; 19607db96d56Sopenharmony_ci } 19617db96d56Sopenharmony_ci if (!(0 <= s && s < 24*3600)) { 19627db96d56Sopenharmony_ci goto BadDivmod; 19637db96d56Sopenharmony_ci } 19647db96d56Sopenharmony_ci 19657db96d56Sopenharmony_ci num = PyTuple_GET_ITEM(tuple, 0); /* leftover days */ 19667db96d56Sopenharmony_ci Py_INCREF(num); 19677db96d56Sopenharmony_ci d = _PyLong_AsInt(num); 19687db96d56Sopenharmony_ci if (d == -1 && PyErr_Occurred()) { 19697db96d56Sopenharmony_ci goto Done; 19707db96d56Sopenharmony_ci } 19717db96d56Sopenharmony_ci result = new_delta_ex(d, s, us, 0, type); 19727db96d56Sopenharmony_ci 19737db96d56Sopenharmony_ciDone: 19747db96d56Sopenharmony_ci Py_XDECREF(tuple); 19757db96d56Sopenharmony_ci Py_XDECREF(num); 19767db96d56Sopenharmony_ci return result; 19777db96d56Sopenharmony_ci 19787db96d56Sopenharmony_ciBadDivmod: 19797db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 19807db96d56Sopenharmony_ci "divmod() returned a value out of range"); 19817db96d56Sopenharmony_ci goto Done; 19827db96d56Sopenharmony_ci} 19837db96d56Sopenharmony_ci 19847db96d56Sopenharmony_ci#define microseconds_to_delta(pymicros) \ 19857db96d56Sopenharmony_ci microseconds_to_delta_ex(pymicros, &PyDateTime_DeltaType) 19867db96d56Sopenharmony_ci 19877db96d56Sopenharmony_cistatic PyObject * 19887db96d56Sopenharmony_cimultiply_int_timedelta(PyObject *intobj, PyDateTime_Delta *delta) 19897db96d56Sopenharmony_ci{ 19907db96d56Sopenharmony_ci PyObject *pyus_in; 19917db96d56Sopenharmony_ci PyObject *pyus_out; 19927db96d56Sopenharmony_ci PyObject *result; 19937db96d56Sopenharmony_ci 19947db96d56Sopenharmony_ci pyus_in = delta_to_microseconds(delta); 19957db96d56Sopenharmony_ci if (pyus_in == NULL) 19967db96d56Sopenharmony_ci return NULL; 19977db96d56Sopenharmony_ci 19987db96d56Sopenharmony_ci pyus_out = PyNumber_Multiply(intobj, pyus_in); 19997db96d56Sopenharmony_ci Py_DECREF(pyus_in); 20007db96d56Sopenharmony_ci if (pyus_out == NULL) 20017db96d56Sopenharmony_ci return NULL; 20027db96d56Sopenharmony_ci 20037db96d56Sopenharmony_ci result = microseconds_to_delta(pyus_out); 20047db96d56Sopenharmony_ci Py_DECREF(pyus_out); 20057db96d56Sopenharmony_ci return result; 20067db96d56Sopenharmony_ci} 20077db96d56Sopenharmony_ci 20087db96d56Sopenharmony_cistatic PyObject * 20097db96d56Sopenharmony_ciget_float_as_integer_ratio(PyObject *floatobj) 20107db96d56Sopenharmony_ci{ 20117db96d56Sopenharmony_ci PyObject *ratio; 20127db96d56Sopenharmony_ci 20137db96d56Sopenharmony_ci assert(floatobj && PyFloat_Check(floatobj)); 20147db96d56Sopenharmony_ci ratio = _PyObject_CallMethodIdNoArgs(floatobj, &PyId_as_integer_ratio); 20157db96d56Sopenharmony_ci if (ratio == NULL) { 20167db96d56Sopenharmony_ci return NULL; 20177db96d56Sopenharmony_ci } 20187db96d56Sopenharmony_ci if (!PyTuple_Check(ratio)) { 20197db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 20207db96d56Sopenharmony_ci "unexpected return type from as_integer_ratio(): " 20217db96d56Sopenharmony_ci "expected tuple, got '%.200s'", 20227db96d56Sopenharmony_ci Py_TYPE(ratio)->tp_name); 20237db96d56Sopenharmony_ci Py_DECREF(ratio); 20247db96d56Sopenharmony_ci return NULL; 20257db96d56Sopenharmony_ci } 20267db96d56Sopenharmony_ci if (PyTuple_Size(ratio) != 2) { 20277db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 20287db96d56Sopenharmony_ci "as_integer_ratio() must return a 2-tuple"); 20297db96d56Sopenharmony_ci Py_DECREF(ratio); 20307db96d56Sopenharmony_ci return NULL; 20317db96d56Sopenharmony_ci } 20327db96d56Sopenharmony_ci return ratio; 20337db96d56Sopenharmony_ci} 20347db96d56Sopenharmony_ci 20357db96d56Sopenharmony_ci/* op is 0 for multiplication, 1 for division */ 20367db96d56Sopenharmony_cistatic PyObject * 20377db96d56Sopenharmony_cimultiply_truedivide_timedelta_float(PyDateTime_Delta *delta, PyObject *floatobj, int op) 20387db96d56Sopenharmony_ci{ 20397db96d56Sopenharmony_ci PyObject *result = NULL; 20407db96d56Sopenharmony_ci PyObject *pyus_in = NULL, *temp, *pyus_out; 20417db96d56Sopenharmony_ci PyObject *ratio = NULL; 20427db96d56Sopenharmony_ci 20437db96d56Sopenharmony_ci pyus_in = delta_to_microseconds(delta); 20447db96d56Sopenharmony_ci if (pyus_in == NULL) 20457db96d56Sopenharmony_ci return NULL; 20467db96d56Sopenharmony_ci ratio = get_float_as_integer_ratio(floatobj); 20477db96d56Sopenharmony_ci if (ratio == NULL) { 20487db96d56Sopenharmony_ci goto error; 20497db96d56Sopenharmony_ci } 20507db96d56Sopenharmony_ci temp = PyNumber_Multiply(pyus_in, PyTuple_GET_ITEM(ratio, op)); 20517db96d56Sopenharmony_ci Py_DECREF(pyus_in); 20527db96d56Sopenharmony_ci pyus_in = NULL; 20537db96d56Sopenharmony_ci if (temp == NULL) 20547db96d56Sopenharmony_ci goto error; 20557db96d56Sopenharmony_ci pyus_out = divide_nearest(temp, PyTuple_GET_ITEM(ratio, !op)); 20567db96d56Sopenharmony_ci Py_DECREF(temp); 20577db96d56Sopenharmony_ci if (pyus_out == NULL) 20587db96d56Sopenharmony_ci goto error; 20597db96d56Sopenharmony_ci result = microseconds_to_delta(pyus_out); 20607db96d56Sopenharmony_ci Py_DECREF(pyus_out); 20617db96d56Sopenharmony_ci error: 20627db96d56Sopenharmony_ci Py_XDECREF(pyus_in); 20637db96d56Sopenharmony_ci Py_XDECREF(ratio); 20647db96d56Sopenharmony_ci 20657db96d56Sopenharmony_ci return result; 20667db96d56Sopenharmony_ci} 20677db96d56Sopenharmony_ci 20687db96d56Sopenharmony_cistatic PyObject * 20697db96d56Sopenharmony_cidivide_timedelta_int(PyDateTime_Delta *delta, PyObject *intobj) 20707db96d56Sopenharmony_ci{ 20717db96d56Sopenharmony_ci PyObject *pyus_in; 20727db96d56Sopenharmony_ci PyObject *pyus_out; 20737db96d56Sopenharmony_ci PyObject *result; 20747db96d56Sopenharmony_ci 20757db96d56Sopenharmony_ci pyus_in = delta_to_microseconds(delta); 20767db96d56Sopenharmony_ci if (pyus_in == NULL) 20777db96d56Sopenharmony_ci return NULL; 20787db96d56Sopenharmony_ci 20797db96d56Sopenharmony_ci pyus_out = PyNumber_FloorDivide(pyus_in, intobj); 20807db96d56Sopenharmony_ci Py_DECREF(pyus_in); 20817db96d56Sopenharmony_ci if (pyus_out == NULL) 20827db96d56Sopenharmony_ci return NULL; 20837db96d56Sopenharmony_ci 20847db96d56Sopenharmony_ci result = microseconds_to_delta(pyus_out); 20857db96d56Sopenharmony_ci Py_DECREF(pyus_out); 20867db96d56Sopenharmony_ci return result; 20877db96d56Sopenharmony_ci} 20887db96d56Sopenharmony_ci 20897db96d56Sopenharmony_cistatic PyObject * 20907db96d56Sopenharmony_cidivide_timedelta_timedelta(PyDateTime_Delta *left, PyDateTime_Delta *right) 20917db96d56Sopenharmony_ci{ 20927db96d56Sopenharmony_ci PyObject *pyus_left; 20937db96d56Sopenharmony_ci PyObject *pyus_right; 20947db96d56Sopenharmony_ci PyObject *result; 20957db96d56Sopenharmony_ci 20967db96d56Sopenharmony_ci pyus_left = delta_to_microseconds(left); 20977db96d56Sopenharmony_ci if (pyus_left == NULL) 20987db96d56Sopenharmony_ci return NULL; 20997db96d56Sopenharmony_ci 21007db96d56Sopenharmony_ci pyus_right = delta_to_microseconds(right); 21017db96d56Sopenharmony_ci if (pyus_right == NULL) { 21027db96d56Sopenharmony_ci Py_DECREF(pyus_left); 21037db96d56Sopenharmony_ci return NULL; 21047db96d56Sopenharmony_ci } 21057db96d56Sopenharmony_ci 21067db96d56Sopenharmony_ci result = PyNumber_FloorDivide(pyus_left, pyus_right); 21077db96d56Sopenharmony_ci Py_DECREF(pyus_left); 21087db96d56Sopenharmony_ci Py_DECREF(pyus_right); 21097db96d56Sopenharmony_ci return result; 21107db96d56Sopenharmony_ci} 21117db96d56Sopenharmony_ci 21127db96d56Sopenharmony_cistatic PyObject * 21137db96d56Sopenharmony_citruedivide_timedelta_timedelta(PyDateTime_Delta *left, PyDateTime_Delta *right) 21147db96d56Sopenharmony_ci{ 21157db96d56Sopenharmony_ci PyObject *pyus_left; 21167db96d56Sopenharmony_ci PyObject *pyus_right; 21177db96d56Sopenharmony_ci PyObject *result; 21187db96d56Sopenharmony_ci 21197db96d56Sopenharmony_ci pyus_left = delta_to_microseconds(left); 21207db96d56Sopenharmony_ci if (pyus_left == NULL) 21217db96d56Sopenharmony_ci return NULL; 21227db96d56Sopenharmony_ci 21237db96d56Sopenharmony_ci pyus_right = delta_to_microseconds(right); 21247db96d56Sopenharmony_ci if (pyus_right == NULL) { 21257db96d56Sopenharmony_ci Py_DECREF(pyus_left); 21267db96d56Sopenharmony_ci return NULL; 21277db96d56Sopenharmony_ci } 21287db96d56Sopenharmony_ci 21297db96d56Sopenharmony_ci result = PyNumber_TrueDivide(pyus_left, pyus_right); 21307db96d56Sopenharmony_ci Py_DECREF(pyus_left); 21317db96d56Sopenharmony_ci Py_DECREF(pyus_right); 21327db96d56Sopenharmony_ci return result; 21337db96d56Sopenharmony_ci} 21347db96d56Sopenharmony_ci 21357db96d56Sopenharmony_cistatic PyObject * 21367db96d56Sopenharmony_citruedivide_timedelta_int(PyDateTime_Delta *delta, PyObject *i) 21377db96d56Sopenharmony_ci{ 21387db96d56Sopenharmony_ci PyObject *result; 21397db96d56Sopenharmony_ci PyObject *pyus_in, *pyus_out; 21407db96d56Sopenharmony_ci pyus_in = delta_to_microseconds(delta); 21417db96d56Sopenharmony_ci if (pyus_in == NULL) 21427db96d56Sopenharmony_ci return NULL; 21437db96d56Sopenharmony_ci pyus_out = divide_nearest(pyus_in, i); 21447db96d56Sopenharmony_ci Py_DECREF(pyus_in); 21457db96d56Sopenharmony_ci if (pyus_out == NULL) 21467db96d56Sopenharmony_ci return NULL; 21477db96d56Sopenharmony_ci result = microseconds_to_delta(pyus_out); 21487db96d56Sopenharmony_ci Py_DECREF(pyus_out); 21497db96d56Sopenharmony_ci 21507db96d56Sopenharmony_ci return result; 21517db96d56Sopenharmony_ci} 21527db96d56Sopenharmony_ci 21537db96d56Sopenharmony_cistatic PyObject * 21547db96d56Sopenharmony_cidelta_add(PyObject *left, PyObject *right) 21557db96d56Sopenharmony_ci{ 21567db96d56Sopenharmony_ci PyObject *result = Py_NotImplemented; 21577db96d56Sopenharmony_ci 21587db96d56Sopenharmony_ci if (PyDelta_Check(left) && PyDelta_Check(right)) { 21597db96d56Sopenharmony_ci /* delta + delta */ 21607db96d56Sopenharmony_ci /* The C-level additions can't overflow because of the 21617db96d56Sopenharmony_ci * invariant bounds. 21627db96d56Sopenharmony_ci */ 21637db96d56Sopenharmony_ci int days = GET_TD_DAYS(left) + GET_TD_DAYS(right); 21647db96d56Sopenharmony_ci int seconds = GET_TD_SECONDS(left) + GET_TD_SECONDS(right); 21657db96d56Sopenharmony_ci int microseconds = GET_TD_MICROSECONDS(left) + 21667db96d56Sopenharmony_ci GET_TD_MICROSECONDS(right); 21677db96d56Sopenharmony_ci result = new_delta(days, seconds, microseconds, 1); 21687db96d56Sopenharmony_ci } 21697db96d56Sopenharmony_ci 21707db96d56Sopenharmony_ci if (result == Py_NotImplemented) 21717db96d56Sopenharmony_ci Py_INCREF(result); 21727db96d56Sopenharmony_ci return result; 21737db96d56Sopenharmony_ci} 21747db96d56Sopenharmony_ci 21757db96d56Sopenharmony_cistatic PyObject * 21767db96d56Sopenharmony_cidelta_negative(PyDateTime_Delta *self) 21777db96d56Sopenharmony_ci{ 21787db96d56Sopenharmony_ci return new_delta(-GET_TD_DAYS(self), 21797db96d56Sopenharmony_ci -GET_TD_SECONDS(self), 21807db96d56Sopenharmony_ci -GET_TD_MICROSECONDS(self), 21817db96d56Sopenharmony_ci 1); 21827db96d56Sopenharmony_ci} 21837db96d56Sopenharmony_ci 21847db96d56Sopenharmony_cistatic PyObject * 21857db96d56Sopenharmony_cidelta_positive(PyDateTime_Delta *self) 21867db96d56Sopenharmony_ci{ 21877db96d56Sopenharmony_ci /* Could optimize this (by returning self) if this isn't a 21887db96d56Sopenharmony_ci * subclass -- but who uses unary + ? Approximately nobody. 21897db96d56Sopenharmony_ci */ 21907db96d56Sopenharmony_ci return new_delta(GET_TD_DAYS(self), 21917db96d56Sopenharmony_ci GET_TD_SECONDS(self), 21927db96d56Sopenharmony_ci GET_TD_MICROSECONDS(self), 21937db96d56Sopenharmony_ci 0); 21947db96d56Sopenharmony_ci} 21957db96d56Sopenharmony_ci 21967db96d56Sopenharmony_cistatic PyObject * 21977db96d56Sopenharmony_cidelta_abs(PyDateTime_Delta *self) 21987db96d56Sopenharmony_ci{ 21997db96d56Sopenharmony_ci PyObject *result; 22007db96d56Sopenharmony_ci 22017db96d56Sopenharmony_ci assert(GET_TD_MICROSECONDS(self) >= 0); 22027db96d56Sopenharmony_ci assert(GET_TD_SECONDS(self) >= 0); 22037db96d56Sopenharmony_ci 22047db96d56Sopenharmony_ci if (GET_TD_DAYS(self) < 0) 22057db96d56Sopenharmony_ci result = delta_negative(self); 22067db96d56Sopenharmony_ci else 22077db96d56Sopenharmony_ci result = delta_positive(self); 22087db96d56Sopenharmony_ci 22097db96d56Sopenharmony_ci return result; 22107db96d56Sopenharmony_ci} 22117db96d56Sopenharmony_ci 22127db96d56Sopenharmony_cistatic PyObject * 22137db96d56Sopenharmony_cidelta_subtract(PyObject *left, PyObject *right) 22147db96d56Sopenharmony_ci{ 22157db96d56Sopenharmony_ci PyObject *result = Py_NotImplemented; 22167db96d56Sopenharmony_ci 22177db96d56Sopenharmony_ci if (PyDelta_Check(left) && PyDelta_Check(right)) { 22187db96d56Sopenharmony_ci /* delta - delta */ 22197db96d56Sopenharmony_ci /* The C-level additions can't overflow because of the 22207db96d56Sopenharmony_ci * invariant bounds. 22217db96d56Sopenharmony_ci */ 22227db96d56Sopenharmony_ci int days = GET_TD_DAYS(left) - GET_TD_DAYS(right); 22237db96d56Sopenharmony_ci int seconds = GET_TD_SECONDS(left) - GET_TD_SECONDS(right); 22247db96d56Sopenharmony_ci int microseconds = GET_TD_MICROSECONDS(left) - 22257db96d56Sopenharmony_ci GET_TD_MICROSECONDS(right); 22267db96d56Sopenharmony_ci result = new_delta(days, seconds, microseconds, 1); 22277db96d56Sopenharmony_ci } 22287db96d56Sopenharmony_ci 22297db96d56Sopenharmony_ci if (result == Py_NotImplemented) 22307db96d56Sopenharmony_ci Py_INCREF(result); 22317db96d56Sopenharmony_ci return result; 22327db96d56Sopenharmony_ci} 22337db96d56Sopenharmony_ci 22347db96d56Sopenharmony_cistatic int 22357db96d56Sopenharmony_cidelta_cmp(PyObject *self, PyObject *other) 22367db96d56Sopenharmony_ci{ 22377db96d56Sopenharmony_ci int diff = GET_TD_DAYS(self) - GET_TD_DAYS(other); 22387db96d56Sopenharmony_ci if (diff == 0) { 22397db96d56Sopenharmony_ci diff = GET_TD_SECONDS(self) - GET_TD_SECONDS(other); 22407db96d56Sopenharmony_ci if (diff == 0) 22417db96d56Sopenharmony_ci diff = GET_TD_MICROSECONDS(self) - 22427db96d56Sopenharmony_ci GET_TD_MICROSECONDS(other); 22437db96d56Sopenharmony_ci } 22447db96d56Sopenharmony_ci return diff; 22457db96d56Sopenharmony_ci} 22467db96d56Sopenharmony_ci 22477db96d56Sopenharmony_cistatic PyObject * 22487db96d56Sopenharmony_cidelta_richcompare(PyObject *self, PyObject *other, int op) 22497db96d56Sopenharmony_ci{ 22507db96d56Sopenharmony_ci if (PyDelta_Check(other)) { 22517db96d56Sopenharmony_ci int diff = delta_cmp(self, other); 22527db96d56Sopenharmony_ci return diff_to_bool(diff, op); 22537db96d56Sopenharmony_ci } 22547db96d56Sopenharmony_ci else { 22557db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 22567db96d56Sopenharmony_ci } 22577db96d56Sopenharmony_ci} 22587db96d56Sopenharmony_ci 22597db96d56Sopenharmony_cistatic PyObject *delta_getstate(PyDateTime_Delta *self); 22607db96d56Sopenharmony_ci 22617db96d56Sopenharmony_cistatic Py_hash_t 22627db96d56Sopenharmony_cidelta_hash(PyDateTime_Delta *self) 22637db96d56Sopenharmony_ci{ 22647db96d56Sopenharmony_ci if (self->hashcode == -1) { 22657db96d56Sopenharmony_ci PyObject *temp = delta_getstate(self); 22667db96d56Sopenharmony_ci if (temp != NULL) { 22677db96d56Sopenharmony_ci self->hashcode = PyObject_Hash(temp); 22687db96d56Sopenharmony_ci Py_DECREF(temp); 22697db96d56Sopenharmony_ci } 22707db96d56Sopenharmony_ci } 22717db96d56Sopenharmony_ci return self->hashcode; 22727db96d56Sopenharmony_ci} 22737db96d56Sopenharmony_ci 22747db96d56Sopenharmony_cistatic PyObject * 22757db96d56Sopenharmony_cidelta_multiply(PyObject *left, PyObject *right) 22767db96d56Sopenharmony_ci{ 22777db96d56Sopenharmony_ci PyObject *result = Py_NotImplemented; 22787db96d56Sopenharmony_ci 22797db96d56Sopenharmony_ci if (PyDelta_Check(left)) { 22807db96d56Sopenharmony_ci /* delta * ??? */ 22817db96d56Sopenharmony_ci if (PyLong_Check(right)) 22827db96d56Sopenharmony_ci result = multiply_int_timedelta(right, 22837db96d56Sopenharmony_ci (PyDateTime_Delta *) left); 22847db96d56Sopenharmony_ci else if (PyFloat_Check(right)) 22857db96d56Sopenharmony_ci result = multiply_truedivide_timedelta_float( 22867db96d56Sopenharmony_ci (PyDateTime_Delta *) left, right, 0); 22877db96d56Sopenharmony_ci } 22887db96d56Sopenharmony_ci else if (PyLong_Check(left)) 22897db96d56Sopenharmony_ci result = multiply_int_timedelta(left, 22907db96d56Sopenharmony_ci (PyDateTime_Delta *) right); 22917db96d56Sopenharmony_ci else if (PyFloat_Check(left)) 22927db96d56Sopenharmony_ci result = multiply_truedivide_timedelta_float( 22937db96d56Sopenharmony_ci (PyDateTime_Delta *) right, left, 0); 22947db96d56Sopenharmony_ci 22957db96d56Sopenharmony_ci if (result == Py_NotImplemented) 22967db96d56Sopenharmony_ci Py_INCREF(result); 22977db96d56Sopenharmony_ci return result; 22987db96d56Sopenharmony_ci} 22997db96d56Sopenharmony_ci 23007db96d56Sopenharmony_cistatic PyObject * 23017db96d56Sopenharmony_cidelta_divide(PyObject *left, PyObject *right) 23027db96d56Sopenharmony_ci{ 23037db96d56Sopenharmony_ci PyObject *result = Py_NotImplemented; 23047db96d56Sopenharmony_ci 23057db96d56Sopenharmony_ci if (PyDelta_Check(left)) { 23067db96d56Sopenharmony_ci /* delta * ??? */ 23077db96d56Sopenharmony_ci if (PyLong_Check(right)) 23087db96d56Sopenharmony_ci result = divide_timedelta_int( 23097db96d56Sopenharmony_ci (PyDateTime_Delta *)left, 23107db96d56Sopenharmony_ci right); 23117db96d56Sopenharmony_ci else if (PyDelta_Check(right)) 23127db96d56Sopenharmony_ci result = divide_timedelta_timedelta( 23137db96d56Sopenharmony_ci (PyDateTime_Delta *)left, 23147db96d56Sopenharmony_ci (PyDateTime_Delta *)right); 23157db96d56Sopenharmony_ci } 23167db96d56Sopenharmony_ci 23177db96d56Sopenharmony_ci if (result == Py_NotImplemented) 23187db96d56Sopenharmony_ci Py_INCREF(result); 23197db96d56Sopenharmony_ci return result; 23207db96d56Sopenharmony_ci} 23217db96d56Sopenharmony_ci 23227db96d56Sopenharmony_cistatic PyObject * 23237db96d56Sopenharmony_cidelta_truedivide(PyObject *left, PyObject *right) 23247db96d56Sopenharmony_ci{ 23257db96d56Sopenharmony_ci PyObject *result = Py_NotImplemented; 23267db96d56Sopenharmony_ci 23277db96d56Sopenharmony_ci if (PyDelta_Check(left)) { 23287db96d56Sopenharmony_ci if (PyDelta_Check(right)) 23297db96d56Sopenharmony_ci result = truedivide_timedelta_timedelta( 23307db96d56Sopenharmony_ci (PyDateTime_Delta *)left, 23317db96d56Sopenharmony_ci (PyDateTime_Delta *)right); 23327db96d56Sopenharmony_ci else if (PyFloat_Check(right)) 23337db96d56Sopenharmony_ci result = multiply_truedivide_timedelta_float( 23347db96d56Sopenharmony_ci (PyDateTime_Delta *)left, right, 1); 23357db96d56Sopenharmony_ci else if (PyLong_Check(right)) 23367db96d56Sopenharmony_ci result = truedivide_timedelta_int( 23377db96d56Sopenharmony_ci (PyDateTime_Delta *)left, right); 23387db96d56Sopenharmony_ci } 23397db96d56Sopenharmony_ci 23407db96d56Sopenharmony_ci if (result == Py_NotImplemented) 23417db96d56Sopenharmony_ci Py_INCREF(result); 23427db96d56Sopenharmony_ci return result; 23437db96d56Sopenharmony_ci} 23447db96d56Sopenharmony_ci 23457db96d56Sopenharmony_cistatic PyObject * 23467db96d56Sopenharmony_cidelta_remainder(PyObject *left, PyObject *right) 23477db96d56Sopenharmony_ci{ 23487db96d56Sopenharmony_ci PyObject *pyus_left; 23497db96d56Sopenharmony_ci PyObject *pyus_right; 23507db96d56Sopenharmony_ci PyObject *pyus_remainder; 23517db96d56Sopenharmony_ci PyObject *remainder; 23527db96d56Sopenharmony_ci 23537db96d56Sopenharmony_ci if (!PyDelta_Check(left) || !PyDelta_Check(right)) 23547db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 23557db96d56Sopenharmony_ci 23567db96d56Sopenharmony_ci pyus_left = delta_to_microseconds((PyDateTime_Delta *)left); 23577db96d56Sopenharmony_ci if (pyus_left == NULL) 23587db96d56Sopenharmony_ci return NULL; 23597db96d56Sopenharmony_ci 23607db96d56Sopenharmony_ci pyus_right = delta_to_microseconds((PyDateTime_Delta *)right); 23617db96d56Sopenharmony_ci if (pyus_right == NULL) { 23627db96d56Sopenharmony_ci Py_DECREF(pyus_left); 23637db96d56Sopenharmony_ci return NULL; 23647db96d56Sopenharmony_ci } 23657db96d56Sopenharmony_ci 23667db96d56Sopenharmony_ci pyus_remainder = PyNumber_Remainder(pyus_left, pyus_right); 23677db96d56Sopenharmony_ci Py_DECREF(pyus_left); 23687db96d56Sopenharmony_ci Py_DECREF(pyus_right); 23697db96d56Sopenharmony_ci if (pyus_remainder == NULL) 23707db96d56Sopenharmony_ci return NULL; 23717db96d56Sopenharmony_ci 23727db96d56Sopenharmony_ci remainder = microseconds_to_delta(pyus_remainder); 23737db96d56Sopenharmony_ci Py_DECREF(pyus_remainder); 23747db96d56Sopenharmony_ci if (remainder == NULL) 23757db96d56Sopenharmony_ci return NULL; 23767db96d56Sopenharmony_ci 23777db96d56Sopenharmony_ci return remainder; 23787db96d56Sopenharmony_ci} 23797db96d56Sopenharmony_ci 23807db96d56Sopenharmony_cistatic PyObject * 23817db96d56Sopenharmony_cidelta_divmod(PyObject *left, PyObject *right) 23827db96d56Sopenharmony_ci{ 23837db96d56Sopenharmony_ci PyObject *pyus_left; 23847db96d56Sopenharmony_ci PyObject *pyus_right; 23857db96d56Sopenharmony_ci PyObject *divmod; 23867db96d56Sopenharmony_ci PyObject *delta; 23877db96d56Sopenharmony_ci PyObject *result; 23887db96d56Sopenharmony_ci 23897db96d56Sopenharmony_ci if (!PyDelta_Check(left) || !PyDelta_Check(right)) 23907db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 23917db96d56Sopenharmony_ci 23927db96d56Sopenharmony_ci pyus_left = delta_to_microseconds((PyDateTime_Delta *)left); 23937db96d56Sopenharmony_ci if (pyus_left == NULL) 23947db96d56Sopenharmony_ci return NULL; 23957db96d56Sopenharmony_ci 23967db96d56Sopenharmony_ci pyus_right = delta_to_microseconds((PyDateTime_Delta *)right); 23977db96d56Sopenharmony_ci if (pyus_right == NULL) { 23987db96d56Sopenharmony_ci Py_DECREF(pyus_left); 23997db96d56Sopenharmony_ci return NULL; 24007db96d56Sopenharmony_ci } 24017db96d56Sopenharmony_ci 24027db96d56Sopenharmony_ci divmod = checked_divmod(pyus_left, pyus_right); 24037db96d56Sopenharmony_ci Py_DECREF(pyus_left); 24047db96d56Sopenharmony_ci Py_DECREF(pyus_right); 24057db96d56Sopenharmony_ci if (divmod == NULL) 24067db96d56Sopenharmony_ci return NULL; 24077db96d56Sopenharmony_ci 24087db96d56Sopenharmony_ci delta = microseconds_to_delta(PyTuple_GET_ITEM(divmod, 1)); 24097db96d56Sopenharmony_ci if (delta == NULL) { 24107db96d56Sopenharmony_ci Py_DECREF(divmod); 24117db96d56Sopenharmony_ci return NULL; 24127db96d56Sopenharmony_ci } 24137db96d56Sopenharmony_ci result = PyTuple_Pack(2, PyTuple_GET_ITEM(divmod, 0), delta); 24147db96d56Sopenharmony_ci Py_DECREF(delta); 24157db96d56Sopenharmony_ci Py_DECREF(divmod); 24167db96d56Sopenharmony_ci return result; 24177db96d56Sopenharmony_ci} 24187db96d56Sopenharmony_ci 24197db96d56Sopenharmony_ci/* Fold in the value of the tag ("seconds", "weeks", etc) component of a 24207db96d56Sopenharmony_ci * timedelta constructor. sofar is the # of microseconds accounted for 24217db96d56Sopenharmony_ci * so far, and there are factor microseconds per current unit, the number 24227db96d56Sopenharmony_ci * of which is given by num. num * factor is added to sofar in a 24237db96d56Sopenharmony_ci * numerically careful way, and that's the result. Any fractional 24247db96d56Sopenharmony_ci * microseconds left over (this can happen if num is a float type) are 24257db96d56Sopenharmony_ci * added into *leftover. 24267db96d56Sopenharmony_ci * Note that there are many ways this can give an error (NULL) return. 24277db96d56Sopenharmony_ci */ 24287db96d56Sopenharmony_cistatic PyObject * 24297db96d56Sopenharmony_ciaccum(const char* tag, PyObject *sofar, PyObject *num, PyObject *factor, 24307db96d56Sopenharmony_ci double *leftover) 24317db96d56Sopenharmony_ci{ 24327db96d56Sopenharmony_ci PyObject *prod; 24337db96d56Sopenharmony_ci PyObject *sum; 24347db96d56Sopenharmony_ci 24357db96d56Sopenharmony_ci assert(num != NULL); 24367db96d56Sopenharmony_ci 24377db96d56Sopenharmony_ci if (PyLong_Check(num)) { 24387db96d56Sopenharmony_ci prod = PyNumber_Multiply(num, factor); 24397db96d56Sopenharmony_ci if (prod == NULL) 24407db96d56Sopenharmony_ci return NULL; 24417db96d56Sopenharmony_ci sum = PyNumber_Add(sofar, prod); 24427db96d56Sopenharmony_ci Py_DECREF(prod); 24437db96d56Sopenharmony_ci return sum; 24447db96d56Sopenharmony_ci } 24457db96d56Sopenharmony_ci 24467db96d56Sopenharmony_ci if (PyFloat_Check(num)) { 24477db96d56Sopenharmony_ci double dnum; 24487db96d56Sopenharmony_ci double fracpart; 24497db96d56Sopenharmony_ci double intpart; 24507db96d56Sopenharmony_ci PyObject *x; 24517db96d56Sopenharmony_ci PyObject *y; 24527db96d56Sopenharmony_ci 24537db96d56Sopenharmony_ci /* The Plan: decompose num into an integer part and a 24547db96d56Sopenharmony_ci * fractional part, num = intpart + fracpart. 24557db96d56Sopenharmony_ci * Then num * factor == 24567db96d56Sopenharmony_ci * intpart * factor + fracpart * factor 24577db96d56Sopenharmony_ci * and the LHS can be computed exactly in long arithmetic. 24587db96d56Sopenharmony_ci * The RHS is again broken into an int part and frac part. 24597db96d56Sopenharmony_ci * and the frac part is added into *leftover. 24607db96d56Sopenharmony_ci */ 24617db96d56Sopenharmony_ci dnum = PyFloat_AsDouble(num); 24627db96d56Sopenharmony_ci if (dnum == -1.0 && PyErr_Occurred()) 24637db96d56Sopenharmony_ci return NULL; 24647db96d56Sopenharmony_ci fracpart = modf(dnum, &intpart); 24657db96d56Sopenharmony_ci x = PyLong_FromDouble(intpart); 24667db96d56Sopenharmony_ci if (x == NULL) 24677db96d56Sopenharmony_ci return NULL; 24687db96d56Sopenharmony_ci 24697db96d56Sopenharmony_ci prod = PyNumber_Multiply(x, factor); 24707db96d56Sopenharmony_ci Py_DECREF(x); 24717db96d56Sopenharmony_ci if (prod == NULL) 24727db96d56Sopenharmony_ci return NULL; 24737db96d56Sopenharmony_ci 24747db96d56Sopenharmony_ci sum = PyNumber_Add(sofar, prod); 24757db96d56Sopenharmony_ci Py_DECREF(prod); 24767db96d56Sopenharmony_ci if (sum == NULL) 24777db96d56Sopenharmony_ci return NULL; 24787db96d56Sopenharmony_ci 24797db96d56Sopenharmony_ci if (fracpart == 0.0) 24807db96d56Sopenharmony_ci return sum; 24817db96d56Sopenharmony_ci /* So far we've lost no information. Dealing with the 24827db96d56Sopenharmony_ci * fractional part requires float arithmetic, and may 24837db96d56Sopenharmony_ci * lose a little info. 24847db96d56Sopenharmony_ci */ 24857db96d56Sopenharmony_ci assert(PyLong_CheckExact(factor)); 24867db96d56Sopenharmony_ci dnum = PyLong_AsDouble(factor); 24877db96d56Sopenharmony_ci 24887db96d56Sopenharmony_ci dnum *= fracpart; 24897db96d56Sopenharmony_ci fracpart = modf(dnum, &intpart); 24907db96d56Sopenharmony_ci x = PyLong_FromDouble(intpart); 24917db96d56Sopenharmony_ci if (x == NULL) { 24927db96d56Sopenharmony_ci Py_DECREF(sum); 24937db96d56Sopenharmony_ci return NULL; 24947db96d56Sopenharmony_ci } 24957db96d56Sopenharmony_ci 24967db96d56Sopenharmony_ci y = PyNumber_Add(sum, x); 24977db96d56Sopenharmony_ci Py_DECREF(sum); 24987db96d56Sopenharmony_ci Py_DECREF(x); 24997db96d56Sopenharmony_ci *leftover += fracpart; 25007db96d56Sopenharmony_ci return y; 25017db96d56Sopenharmony_ci } 25027db96d56Sopenharmony_ci 25037db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, 25047db96d56Sopenharmony_ci "unsupported type for timedelta %s component: %s", 25057db96d56Sopenharmony_ci tag, Py_TYPE(num)->tp_name); 25067db96d56Sopenharmony_ci return NULL; 25077db96d56Sopenharmony_ci} 25087db96d56Sopenharmony_ci 25097db96d56Sopenharmony_cistatic PyObject * 25107db96d56Sopenharmony_cidelta_new(PyTypeObject *type, PyObject *args, PyObject *kw) 25117db96d56Sopenharmony_ci{ 25127db96d56Sopenharmony_ci PyObject *self = NULL; 25137db96d56Sopenharmony_ci 25147db96d56Sopenharmony_ci /* Argument objects. */ 25157db96d56Sopenharmony_ci PyObject *day = NULL; 25167db96d56Sopenharmony_ci PyObject *second = NULL; 25177db96d56Sopenharmony_ci PyObject *us = NULL; 25187db96d56Sopenharmony_ci PyObject *ms = NULL; 25197db96d56Sopenharmony_ci PyObject *minute = NULL; 25207db96d56Sopenharmony_ci PyObject *hour = NULL; 25217db96d56Sopenharmony_ci PyObject *week = NULL; 25227db96d56Sopenharmony_ci 25237db96d56Sopenharmony_ci PyObject *x = NULL; /* running sum of microseconds */ 25247db96d56Sopenharmony_ci PyObject *y = NULL; /* temp sum of microseconds */ 25257db96d56Sopenharmony_ci double leftover_us = 0.0; 25267db96d56Sopenharmony_ci 25277db96d56Sopenharmony_ci static char *keywords[] = { 25287db96d56Sopenharmony_ci "days", "seconds", "microseconds", "milliseconds", 25297db96d56Sopenharmony_ci "minutes", "hours", "weeks", NULL 25307db96d56Sopenharmony_ci }; 25317db96d56Sopenharmony_ci 25327db96d56Sopenharmony_ci if (PyArg_ParseTupleAndKeywords(args, kw, "|OOOOOOO:__new__", 25337db96d56Sopenharmony_ci keywords, 25347db96d56Sopenharmony_ci &day, &second, &us, 25357db96d56Sopenharmony_ci &ms, &minute, &hour, &week) == 0) 25367db96d56Sopenharmony_ci goto Done; 25377db96d56Sopenharmony_ci 25387db96d56Sopenharmony_ci x = PyLong_FromLong(0); 25397db96d56Sopenharmony_ci if (x == NULL) 25407db96d56Sopenharmony_ci goto Done; 25417db96d56Sopenharmony_ci 25427db96d56Sopenharmony_ci#define CLEANUP \ 25437db96d56Sopenharmony_ci Py_DECREF(x); \ 25447db96d56Sopenharmony_ci x = y; \ 25457db96d56Sopenharmony_ci if (x == NULL) \ 25467db96d56Sopenharmony_ci goto Done 25477db96d56Sopenharmony_ci 25487db96d56Sopenharmony_ci if (us) { 25497db96d56Sopenharmony_ci y = accum("microseconds", x, us, _PyLong_GetOne(), &leftover_us); 25507db96d56Sopenharmony_ci CLEANUP; 25517db96d56Sopenharmony_ci } 25527db96d56Sopenharmony_ci if (ms) { 25537db96d56Sopenharmony_ci y = accum("milliseconds", x, ms, us_per_ms, &leftover_us); 25547db96d56Sopenharmony_ci CLEANUP; 25557db96d56Sopenharmony_ci } 25567db96d56Sopenharmony_ci if (second) { 25577db96d56Sopenharmony_ci y = accum("seconds", x, second, us_per_second, &leftover_us); 25587db96d56Sopenharmony_ci CLEANUP; 25597db96d56Sopenharmony_ci } 25607db96d56Sopenharmony_ci if (minute) { 25617db96d56Sopenharmony_ci y = accum("minutes", x, minute, us_per_minute, &leftover_us); 25627db96d56Sopenharmony_ci CLEANUP; 25637db96d56Sopenharmony_ci } 25647db96d56Sopenharmony_ci if (hour) { 25657db96d56Sopenharmony_ci y = accum("hours", x, hour, us_per_hour, &leftover_us); 25667db96d56Sopenharmony_ci CLEANUP; 25677db96d56Sopenharmony_ci } 25687db96d56Sopenharmony_ci if (day) { 25697db96d56Sopenharmony_ci y = accum("days", x, day, us_per_day, &leftover_us); 25707db96d56Sopenharmony_ci CLEANUP; 25717db96d56Sopenharmony_ci } 25727db96d56Sopenharmony_ci if (week) { 25737db96d56Sopenharmony_ci y = accum("weeks", x, week, us_per_week, &leftover_us); 25747db96d56Sopenharmony_ci CLEANUP; 25757db96d56Sopenharmony_ci } 25767db96d56Sopenharmony_ci if (leftover_us) { 25777db96d56Sopenharmony_ci /* Round to nearest whole # of us, and add into x. */ 25787db96d56Sopenharmony_ci double whole_us = round(leftover_us); 25797db96d56Sopenharmony_ci int x_is_odd; 25807db96d56Sopenharmony_ci PyObject *temp; 25817db96d56Sopenharmony_ci 25827db96d56Sopenharmony_ci if (fabs(whole_us - leftover_us) == 0.5) { 25837db96d56Sopenharmony_ci /* We're exactly halfway between two integers. In order 25847db96d56Sopenharmony_ci * to do round-half-to-even, we must determine whether x 25857db96d56Sopenharmony_ci * is odd. Note that x is odd when it's last bit is 1. The 25867db96d56Sopenharmony_ci * code below uses bitwise and operation to check the last 25877db96d56Sopenharmony_ci * bit. */ 25887db96d56Sopenharmony_ci temp = PyNumber_And(x, _PyLong_GetOne()); /* temp <- x & 1 */ 25897db96d56Sopenharmony_ci if (temp == NULL) { 25907db96d56Sopenharmony_ci Py_DECREF(x); 25917db96d56Sopenharmony_ci goto Done; 25927db96d56Sopenharmony_ci } 25937db96d56Sopenharmony_ci x_is_odd = PyObject_IsTrue(temp); 25947db96d56Sopenharmony_ci Py_DECREF(temp); 25957db96d56Sopenharmony_ci if (x_is_odd == -1) { 25967db96d56Sopenharmony_ci Py_DECREF(x); 25977db96d56Sopenharmony_ci goto Done; 25987db96d56Sopenharmony_ci } 25997db96d56Sopenharmony_ci whole_us = 2.0 * round((leftover_us + x_is_odd) * 0.5) - x_is_odd; 26007db96d56Sopenharmony_ci } 26017db96d56Sopenharmony_ci 26027db96d56Sopenharmony_ci temp = PyLong_FromLong((long)whole_us); 26037db96d56Sopenharmony_ci 26047db96d56Sopenharmony_ci if (temp == NULL) { 26057db96d56Sopenharmony_ci Py_DECREF(x); 26067db96d56Sopenharmony_ci goto Done; 26077db96d56Sopenharmony_ci } 26087db96d56Sopenharmony_ci y = PyNumber_Add(x, temp); 26097db96d56Sopenharmony_ci Py_DECREF(temp); 26107db96d56Sopenharmony_ci CLEANUP; 26117db96d56Sopenharmony_ci } 26127db96d56Sopenharmony_ci 26137db96d56Sopenharmony_ci self = microseconds_to_delta_ex(x, type); 26147db96d56Sopenharmony_ci Py_DECREF(x); 26157db96d56Sopenharmony_ciDone: 26167db96d56Sopenharmony_ci return self; 26177db96d56Sopenharmony_ci 26187db96d56Sopenharmony_ci#undef CLEANUP 26197db96d56Sopenharmony_ci} 26207db96d56Sopenharmony_ci 26217db96d56Sopenharmony_cistatic int 26227db96d56Sopenharmony_cidelta_bool(PyDateTime_Delta *self) 26237db96d56Sopenharmony_ci{ 26247db96d56Sopenharmony_ci return (GET_TD_DAYS(self) != 0 26257db96d56Sopenharmony_ci || GET_TD_SECONDS(self) != 0 26267db96d56Sopenharmony_ci || GET_TD_MICROSECONDS(self) != 0); 26277db96d56Sopenharmony_ci} 26287db96d56Sopenharmony_ci 26297db96d56Sopenharmony_cistatic PyObject * 26307db96d56Sopenharmony_cidelta_repr(PyDateTime_Delta *self) 26317db96d56Sopenharmony_ci{ 26327db96d56Sopenharmony_ci PyObject *args = PyUnicode_FromString(""); 26337db96d56Sopenharmony_ci 26347db96d56Sopenharmony_ci if (args == NULL) { 26357db96d56Sopenharmony_ci return NULL; 26367db96d56Sopenharmony_ci } 26377db96d56Sopenharmony_ci 26387db96d56Sopenharmony_ci const char *sep = ""; 26397db96d56Sopenharmony_ci 26407db96d56Sopenharmony_ci if (GET_TD_DAYS(self) != 0) { 26417db96d56Sopenharmony_ci Py_SETREF(args, PyUnicode_FromFormat("days=%d", GET_TD_DAYS(self))); 26427db96d56Sopenharmony_ci if (args == NULL) { 26437db96d56Sopenharmony_ci return NULL; 26447db96d56Sopenharmony_ci } 26457db96d56Sopenharmony_ci sep = ", "; 26467db96d56Sopenharmony_ci } 26477db96d56Sopenharmony_ci 26487db96d56Sopenharmony_ci if (GET_TD_SECONDS(self) != 0) { 26497db96d56Sopenharmony_ci Py_SETREF(args, PyUnicode_FromFormat("%U%sseconds=%d", args, sep, 26507db96d56Sopenharmony_ci GET_TD_SECONDS(self))); 26517db96d56Sopenharmony_ci if (args == NULL) { 26527db96d56Sopenharmony_ci return NULL; 26537db96d56Sopenharmony_ci } 26547db96d56Sopenharmony_ci sep = ", "; 26557db96d56Sopenharmony_ci } 26567db96d56Sopenharmony_ci 26577db96d56Sopenharmony_ci if (GET_TD_MICROSECONDS(self) != 0) { 26587db96d56Sopenharmony_ci Py_SETREF(args, PyUnicode_FromFormat("%U%smicroseconds=%d", args, sep, 26597db96d56Sopenharmony_ci GET_TD_MICROSECONDS(self))); 26607db96d56Sopenharmony_ci if (args == NULL) { 26617db96d56Sopenharmony_ci return NULL; 26627db96d56Sopenharmony_ci } 26637db96d56Sopenharmony_ci } 26647db96d56Sopenharmony_ci 26657db96d56Sopenharmony_ci if (PyUnicode_GET_LENGTH(args) == 0) { 26667db96d56Sopenharmony_ci Py_SETREF(args, PyUnicode_FromString("0")); 26677db96d56Sopenharmony_ci if (args == NULL) { 26687db96d56Sopenharmony_ci return NULL; 26697db96d56Sopenharmony_ci } 26707db96d56Sopenharmony_ci } 26717db96d56Sopenharmony_ci 26727db96d56Sopenharmony_ci PyObject *repr = PyUnicode_FromFormat("%s(%S)", Py_TYPE(self)->tp_name, 26737db96d56Sopenharmony_ci args); 26747db96d56Sopenharmony_ci Py_DECREF(args); 26757db96d56Sopenharmony_ci return repr; 26767db96d56Sopenharmony_ci} 26777db96d56Sopenharmony_ci 26787db96d56Sopenharmony_cistatic PyObject * 26797db96d56Sopenharmony_cidelta_str(PyDateTime_Delta *self) 26807db96d56Sopenharmony_ci{ 26817db96d56Sopenharmony_ci int us = GET_TD_MICROSECONDS(self); 26827db96d56Sopenharmony_ci int seconds = GET_TD_SECONDS(self); 26837db96d56Sopenharmony_ci int minutes = divmod(seconds, 60, &seconds); 26847db96d56Sopenharmony_ci int hours = divmod(minutes, 60, &minutes); 26857db96d56Sopenharmony_ci int days = GET_TD_DAYS(self); 26867db96d56Sopenharmony_ci 26877db96d56Sopenharmony_ci if (days) { 26887db96d56Sopenharmony_ci if (us) 26897db96d56Sopenharmony_ci return PyUnicode_FromFormat("%d day%s, %d:%02d:%02d.%06d", 26907db96d56Sopenharmony_ci days, (days == 1 || days == -1) ? "" : "s", 26917db96d56Sopenharmony_ci hours, minutes, seconds, us); 26927db96d56Sopenharmony_ci else 26937db96d56Sopenharmony_ci return PyUnicode_FromFormat("%d day%s, %d:%02d:%02d", 26947db96d56Sopenharmony_ci days, (days == 1 || days == -1) ? "" : "s", 26957db96d56Sopenharmony_ci hours, minutes, seconds); 26967db96d56Sopenharmony_ci } else { 26977db96d56Sopenharmony_ci if (us) 26987db96d56Sopenharmony_ci return PyUnicode_FromFormat("%d:%02d:%02d.%06d", 26997db96d56Sopenharmony_ci hours, minutes, seconds, us); 27007db96d56Sopenharmony_ci else 27017db96d56Sopenharmony_ci return PyUnicode_FromFormat("%d:%02d:%02d", 27027db96d56Sopenharmony_ci hours, minutes, seconds); 27037db96d56Sopenharmony_ci } 27047db96d56Sopenharmony_ci 27057db96d56Sopenharmony_ci} 27067db96d56Sopenharmony_ci 27077db96d56Sopenharmony_ci/* Pickle support, a simple use of __reduce__. */ 27087db96d56Sopenharmony_ci 27097db96d56Sopenharmony_ci/* __getstate__ isn't exposed */ 27107db96d56Sopenharmony_cistatic PyObject * 27117db96d56Sopenharmony_cidelta_getstate(PyDateTime_Delta *self) 27127db96d56Sopenharmony_ci{ 27137db96d56Sopenharmony_ci return Py_BuildValue("iii", GET_TD_DAYS(self), 27147db96d56Sopenharmony_ci GET_TD_SECONDS(self), 27157db96d56Sopenharmony_ci GET_TD_MICROSECONDS(self)); 27167db96d56Sopenharmony_ci} 27177db96d56Sopenharmony_ci 27187db96d56Sopenharmony_cistatic PyObject * 27197db96d56Sopenharmony_cidelta_total_seconds(PyObject *self, PyObject *Py_UNUSED(ignored)) 27207db96d56Sopenharmony_ci{ 27217db96d56Sopenharmony_ci PyObject *total_seconds; 27227db96d56Sopenharmony_ci PyObject *total_microseconds; 27237db96d56Sopenharmony_ci 27247db96d56Sopenharmony_ci total_microseconds = delta_to_microseconds((PyDateTime_Delta *)self); 27257db96d56Sopenharmony_ci if (total_microseconds == NULL) 27267db96d56Sopenharmony_ci return NULL; 27277db96d56Sopenharmony_ci 27287db96d56Sopenharmony_ci total_seconds = PyNumber_TrueDivide(total_microseconds, us_per_second); 27297db96d56Sopenharmony_ci 27307db96d56Sopenharmony_ci Py_DECREF(total_microseconds); 27317db96d56Sopenharmony_ci return total_seconds; 27327db96d56Sopenharmony_ci} 27337db96d56Sopenharmony_ci 27347db96d56Sopenharmony_cistatic PyObject * 27357db96d56Sopenharmony_cidelta_reduce(PyDateTime_Delta* self, PyObject *Py_UNUSED(ignored)) 27367db96d56Sopenharmony_ci{ 27377db96d56Sopenharmony_ci return Py_BuildValue("ON", Py_TYPE(self), delta_getstate(self)); 27387db96d56Sopenharmony_ci} 27397db96d56Sopenharmony_ci 27407db96d56Sopenharmony_ci#define OFFSET(field) offsetof(PyDateTime_Delta, field) 27417db96d56Sopenharmony_ci 27427db96d56Sopenharmony_cistatic PyMemberDef delta_members[] = { 27437db96d56Sopenharmony_ci 27447db96d56Sopenharmony_ci {"days", T_INT, OFFSET(days), READONLY, 27457db96d56Sopenharmony_ci PyDoc_STR("Number of days.")}, 27467db96d56Sopenharmony_ci 27477db96d56Sopenharmony_ci {"seconds", T_INT, OFFSET(seconds), READONLY, 27487db96d56Sopenharmony_ci PyDoc_STR("Number of seconds (>= 0 and less than 1 day).")}, 27497db96d56Sopenharmony_ci 27507db96d56Sopenharmony_ci {"microseconds", T_INT, OFFSET(microseconds), READONLY, 27517db96d56Sopenharmony_ci PyDoc_STR("Number of microseconds (>= 0 and less than 1 second).")}, 27527db96d56Sopenharmony_ci {NULL} 27537db96d56Sopenharmony_ci}; 27547db96d56Sopenharmony_ci 27557db96d56Sopenharmony_cistatic PyMethodDef delta_methods[] = { 27567db96d56Sopenharmony_ci {"total_seconds", delta_total_seconds, METH_NOARGS, 27577db96d56Sopenharmony_ci PyDoc_STR("Total seconds in the duration.")}, 27587db96d56Sopenharmony_ci 27597db96d56Sopenharmony_ci {"__reduce__", (PyCFunction)delta_reduce, METH_NOARGS, 27607db96d56Sopenharmony_ci PyDoc_STR("__reduce__() -> (cls, state)")}, 27617db96d56Sopenharmony_ci 27627db96d56Sopenharmony_ci {NULL, NULL}, 27637db96d56Sopenharmony_ci}; 27647db96d56Sopenharmony_ci 27657db96d56Sopenharmony_cistatic const char delta_doc[] = 27667db96d56Sopenharmony_ciPyDoc_STR("Difference between two datetime values.\n\n" 27677db96d56Sopenharmony_ci "timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, " 27687db96d56Sopenharmony_ci "minutes=0, hours=0, weeks=0)\n\n" 27697db96d56Sopenharmony_ci "All arguments are optional and default to 0.\n" 27707db96d56Sopenharmony_ci "Arguments may be integers or floats, and may be positive or negative."); 27717db96d56Sopenharmony_ci 27727db96d56Sopenharmony_cistatic PyNumberMethods delta_as_number = { 27737db96d56Sopenharmony_ci delta_add, /* nb_add */ 27747db96d56Sopenharmony_ci delta_subtract, /* nb_subtract */ 27757db96d56Sopenharmony_ci delta_multiply, /* nb_multiply */ 27767db96d56Sopenharmony_ci delta_remainder, /* nb_remainder */ 27777db96d56Sopenharmony_ci delta_divmod, /* nb_divmod */ 27787db96d56Sopenharmony_ci 0, /* nb_power */ 27797db96d56Sopenharmony_ci (unaryfunc)delta_negative, /* nb_negative */ 27807db96d56Sopenharmony_ci (unaryfunc)delta_positive, /* nb_positive */ 27817db96d56Sopenharmony_ci (unaryfunc)delta_abs, /* nb_absolute */ 27827db96d56Sopenharmony_ci (inquiry)delta_bool, /* nb_bool */ 27837db96d56Sopenharmony_ci 0, /*nb_invert*/ 27847db96d56Sopenharmony_ci 0, /*nb_lshift*/ 27857db96d56Sopenharmony_ci 0, /*nb_rshift*/ 27867db96d56Sopenharmony_ci 0, /*nb_and*/ 27877db96d56Sopenharmony_ci 0, /*nb_xor*/ 27887db96d56Sopenharmony_ci 0, /*nb_or*/ 27897db96d56Sopenharmony_ci 0, /*nb_int*/ 27907db96d56Sopenharmony_ci 0, /*nb_reserved*/ 27917db96d56Sopenharmony_ci 0, /*nb_float*/ 27927db96d56Sopenharmony_ci 0, /*nb_inplace_add*/ 27937db96d56Sopenharmony_ci 0, /*nb_inplace_subtract*/ 27947db96d56Sopenharmony_ci 0, /*nb_inplace_multiply*/ 27957db96d56Sopenharmony_ci 0, /*nb_inplace_remainder*/ 27967db96d56Sopenharmony_ci 0, /*nb_inplace_power*/ 27977db96d56Sopenharmony_ci 0, /*nb_inplace_lshift*/ 27987db96d56Sopenharmony_ci 0, /*nb_inplace_rshift*/ 27997db96d56Sopenharmony_ci 0, /*nb_inplace_and*/ 28007db96d56Sopenharmony_ci 0, /*nb_inplace_xor*/ 28017db96d56Sopenharmony_ci 0, /*nb_inplace_or*/ 28027db96d56Sopenharmony_ci delta_divide, /* nb_floor_divide */ 28037db96d56Sopenharmony_ci delta_truedivide, /* nb_true_divide */ 28047db96d56Sopenharmony_ci 0, /* nb_inplace_floor_divide */ 28057db96d56Sopenharmony_ci 0, /* nb_inplace_true_divide */ 28067db96d56Sopenharmony_ci}; 28077db96d56Sopenharmony_ci 28087db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_DeltaType = { 28097db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 28107db96d56Sopenharmony_ci "datetime.timedelta", /* tp_name */ 28117db96d56Sopenharmony_ci sizeof(PyDateTime_Delta), /* tp_basicsize */ 28127db96d56Sopenharmony_ci 0, /* tp_itemsize */ 28137db96d56Sopenharmony_ci 0, /* tp_dealloc */ 28147db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 28157db96d56Sopenharmony_ci 0, /* tp_getattr */ 28167db96d56Sopenharmony_ci 0, /* tp_setattr */ 28177db96d56Sopenharmony_ci 0, /* tp_as_async */ 28187db96d56Sopenharmony_ci (reprfunc)delta_repr, /* tp_repr */ 28197db96d56Sopenharmony_ci &delta_as_number, /* tp_as_number */ 28207db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 28217db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 28227db96d56Sopenharmony_ci (hashfunc)delta_hash, /* tp_hash */ 28237db96d56Sopenharmony_ci 0, /* tp_call */ 28247db96d56Sopenharmony_ci (reprfunc)delta_str, /* tp_str */ 28257db96d56Sopenharmony_ci PyObject_GenericGetAttr, /* tp_getattro */ 28267db96d56Sopenharmony_ci 0, /* tp_setattro */ 28277db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 28287db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 28297db96d56Sopenharmony_ci delta_doc, /* tp_doc */ 28307db96d56Sopenharmony_ci 0, /* tp_traverse */ 28317db96d56Sopenharmony_ci 0, /* tp_clear */ 28327db96d56Sopenharmony_ci delta_richcompare, /* tp_richcompare */ 28337db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 28347db96d56Sopenharmony_ci 0, /* tp_iter */ 28357db96d56Sopenharmony_ci 0, /* tp_iternext */ 28367db96d56Sopenharmony_ci delta_methods, /* tp_methods */ 28377db96d56Sopenharmony_ci delta_members, /* tp_members */ 28387db96d56Sopenharmony_ci 0, /* tp_getset */ 28397db96d56Sopenharmony_ci 0, /* tp_base */ 28407db96d56Sopenharmony_ci 0, /* tp_dict */ 28417db96d56Sopenharmony_ci 0, /* tp_descr_get */ 28427db96d56Sopenharmony_ci 0, /* tp_descr_set */ 28437db96d56Sopenharmony_ci 0, /* tp_dictoffset */ 28447db96d56Sopenharmony_ci 0, /* tp_init */ 28457db96d56Sopenharmony_ci 0, /* tp_alloc */ 28467db96d56Sopenharmony_ci delta_new, /* tp_new */ 28477db96d56Sopenharmony_ci 0, /* tp_free */ 28487db96d56Sopenharmony_ci}; 28497db96d56Sopenharmony_ci 28507db96d56Sopenharmony_ci/* 28517db96d56Sopenharmony_ci * PyDateTime_Date implementation. 28527db96d56Sopenharmony_ci */ 28537db96d56Sopenharmony_ci 28547db96d56Sopenharmony_ci/* Accessor properties. */ 28557db96d56Sopenharmony_ci 28567db96d56Sopenharmony_cistatic PyObject * 28577db96d56Sopenharmony_cidate_year(PyDateTime_Date *self, void *unused) 28587db96d56Sopenharmony_ci{ 28597db96d56Sopenharmony_ci return PyLong_FromLong(GET_YEAR(self)); 28607db96d56Sopenharmony_ci} 28617db96d56Sopenharmony_ci 28627db96d56Sopenharmony_cistatic PyObject * 28637db96d56Sopenharmony_cidate_month(PyDateTime_Date *self, void *unused) 28647db96d56Sopenharmony_ci{ 28657db96d56Sopenharmony_ci return PyLong_FromLong(GET_MONTH(self)); 28667db96d56Sopenharmony_ci} 28677db96d56Sopenharmony_ci 28687db96d56Sopenharmony_cistatic PyObject * 28697db96d56Sopenharmony_cidate_day(PyDateTime_Date *self, void *unused) 28707db96d56Sopenharmony_ci{ 28717db96d56Sopenharmony_ci return PyLong_FromLong(GET_DAY(self)); 28727db96d56Sopenharmony_ci} 28737db96d56Sopenharmony_ci 28747db96d56Sopenharmony_cistatic PyGetSetDef date_getset[] = { 28757db96d56Sopenharmony_ci {"year", (getter)date_year}, 28767db96d56Sopenharmony_ci {"month", (getter)date_month}, 28777db96d56Sopenharmony_ci {"day", (getter)date_day}, 28787db96d56Sopenharmony_ci {NULL} 28797db96d56Sopenharmony_ci}; 28807db96d56Sopenharmony_ci 28817db96d56Sopenharmony_ci/* Constructors. */ 28827db96d56Sopenharmony_ci 28837db96d56Sopenharmony_cistatic char *date_kws[] = {"year", "month", "day", NULL}; 28847db96d56Sopenharmony_ci 28857db96d56Sopenharmony_cistatic PyObject * 28867db96d56Sopenharmony_cidate_from_pickle(PyTypeObject *type, PyObject *state) 28877db96d56Sopenharmony_ci{ 28887db96d56Sopenharmony_ci PyDateTime_Date *me; 28897db96d56Sopenharmony_ci 28907db96d56Sopenharmony_ci me = (PyDateTime_Date *) (type->tp_alloc(type, 0)); 28917db96d56Sopenharmony_ci if (me != NULL) { 28927db96d56Sopenharmony_ci const char *pdata = PyBytes_AS_STRING(state); 28937db96d56Sopenharmony_ci memcpy(me->data, pdata, _PyDateTime_DATE_DATASIZE); 28947db96d56Sopenharmony_ci me->hashcode = -1; 28957db96d56Sopenharmony_ci } 28967db96d56Sopenharmony_ci return (PyObject *)me; 28977db96d56Sopenharmony_ci} 28987db96d56Sopenharmony_ci 28997db96d56Sopenharmony_cistatic PyObject * 29007db96d56Sopenharmony_cidate_new(PyTypeObject *type, PyObject *args, PyObject *kw) 29017db96d56Sopenharmony_ci{ 29027db96d56Sopenharmony_ci PyObject *self = NULL; 29037db96d56Sopenharmony_ci int year; 29047db96d56Sopenharmony_ci int month; 29057db96d56Sopenharmony_ci int day; 29067db96d56Sopenharmony_ci 29077db96d56Sopenharmony_ci /* Check for invocation from pickle with __getstate__ state */ 29087db96d56Sopenharmony_ci if (PyTuple_GET_SIZE(args) == 1) { 29097db96d56Sopenharmony_ci PyObject *state = PyTuple_GET_ITEM(args, 0); 29107db96d56Sopenharmony_ci if (PyBytes_Check(state)) { 29117db96d56Sopenharmony_ci if (PyBytes_GET_SIZE(state) == _PyDateTime_DATE_DATASIZE && 29127db96d56Sopenharmony_ci MONTH_IS_SANE(PyBytes_AS_STRING(state)[2])) 29137db96d56Sopenharmony_ci { 29147db96d56Sopenharmony_ci return date_from_pickle(type, state); 29157db96d56Sopenharmony_ci } 29167db96d56Sopenharmony_ci } 29177db96d56Sopenharmony_ci else if (PyUnicode_Check(state)) { 29187db96d56Sopenharmony_ci if (PyUnicode_READY(state)) { 29197db96d56Sopenharmony_ci return NULL; 29207db96d56Sopenharmony_ci } 29217db96d56Sopenharmony_ci if (PyUnicode_GET_LENGTH(state) == _PyDateTime_DATE_DATASIZE && 29227db96d56Sopenharmony_ci MONTH_IS_SANE(PyUnicode_READ_CHAR(state, 2))) 29237db96d56Sopenharmony_ci { 29247db96d56Sopenharmony_ci state = PyUnicode_AsLatin1String(state); 29257db96d56Sopenharmony_ci if (state == NULL) { 29267db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) { 29277db96d56Sopenharmony_ci /* More informative error message. */ 29287db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 29297db96d56Sopenharmony_ci "Failed to encode latin1 string when unpickling " 29307db96d56Sopenharmony_ci "a date object. " 29317db96d56Sopenharmony_ci "pickle.load(data, encoding='latin1') is assumed."); 29327db96d56Sopenharmony_ci } 29337db96d56Sopenharmony_ci return NULL; 29347db96d56Sopenharmony_ci } 29357db96d56Sopenharmony_ci self = date_from_pickle(type, state); 29367db96d56Sopenharmony_ci Py_DECREF(state); 29377db96d56Sopenharmony_ci return self; 29387db96d56Sopenharmony_ci } 29397db96d56Sopenharmony_ci } 29407db96d56Sopenharmony_ci } 29417db96d56Sopenharmony_ci 29427db96d56Sopenharmony_ci if (PyArg_ParseTupleAndKeywords(args, kw, "iii", date_kws, 29437db96d56Sopenharmony_ci &year, &month, &day)) { 29447db96d56Sopenharmony_ci self = new_date_ex(year, month, day, type); 29457db96d56Sopenharmony_ci } 29467db96d56Sopenharmony_ci return self; 29477db96d56Sopenharmony_ci} 29487db96d56Sopenharmony_ci 29497db96d56Sopenharmony_cistatic PyObject * 29507db96d56Sopenharmony_cidate_fromtimestamp(PyObject *cls, PyObject *obj) 29517db96d56Sopenharmony_ci{ 29527db96d56Sopenharmony_ci struct tm tm; 29537db96d56Sopenharmony_ci time_t t; 29547db96d56Sopenharmony_ci 29557db96d56Sopenharmony_ci if (_PyTime_ObjectToTime_t(obj, &t, _PyTime_ROUND_FLOOR) == -1) 29567db96d56Sopenharmony_ci return NULL; 29577db96d56Sopenharmony_ci 29587db96d56Sopenharmony_ci if (_PyTime_localtime(t, &tm) != 0) 29597db96d56Sopenharmony_ci return NULL; 29607db96d56Sopenharmony_ci 29617db96d56Sopenharmony_ci return new_date_subclass_ex(tm.tm_year + 1900, 29627db96d56Sopenharmony_ci tm.tm_mon + 1, 29637db96d56Sopenharmony_ci tm.tm_mday, 29647db96d56Sopenharmony_ci cls); 29657db96d56Sopenharmony_ci} 29667db96d56Sopenharmony_ci 29677db96d56Sopenharmony_ci/* Return new date from current time. 29687db96d56Sopenharmony_ci * We say this is equivalent to fromtimestamp(time.time()), and the 29697db96d56Sopenharmony_ci * only way to be sure of that is to *call* time.time(). That's not 29707db96d56Sopenharmony_ci * generally the same as calling C's time. 29717db96d56Sopenharmony_ci */ 29727db96d56Sopenharmony_cistatic PyObject * 29737db96d56Sopenharmony_cidate_today(PyObject *cls, PyObject *dummy) 29747db96d56Sopenharmony_ci{ 29757db96d56Sopenharmony_ci PyObject *time; 29767db96d56Sopenharmony_ci PyObject *result; 29777db96d56Sopenharmony_ci _Py_IDENTIFIER(fromtimestamp); 29787db96d56Sopenharmony_ci 29797db96d56Sopenharmony_ci time = time_time(); 29807db96d56Sopenharmony_ci if (time == NULL) 29817db96d56Sopenharmony_ci return NULL; 29827db96d56Sopenharmony_ci 29837db96d56Sopenharmony_ci /* Note well: today() is a class method, so this may not call 29847db96d56Sopenharmony_ci * date.fromtimestamp. For example, it may call 29857db96d56Sopenharmony_ci * datetime.fromtimestamp. That's why we need all the accuracy 29867db96d56Sopenharmony_ci * time.time() delivers; if someone were gonzo about optimization, 29877db96d56Sopenharmony_ci * date.today() could get away with plain C time(). 29887db96d56Sopenharmony_ci */ 29897db96d56Sopenharmony_ci result = _PyObject_CallMethodIdOneArg(cls, &PyId_fromtimestamp, time); 29907db96d56Sopenharmony_ci Py_DECREF(time); 29917db96d56Sopenharmony_ci return result; 29927db96d56Sopenharmony_ci} 29937db96d56Sopenharmony_ci 29947db96d56Sopenharmony_ci/*[clinic input] 29957db96d56Sopenharmony_ci@classmethod 29967db96d56Sopenharmony_cidatetime.date.fromtimestamp 29977db96d56Sopenharmony_ci 29987db96d56Sopenharmony_ci timestamp: object 29997db96d56Sopenharmony_ci / 30007db96d56Sopenharmony_ci 30017db96d56Sopenharmony_ciCreate a date from a POSIX timestamp. 30027db96d56Sopenharmony_ci 30037db96d56Sopenharmony_ciThe timestamp is a number, e.g. created via time.time(), that is interpreted 30047db96d56Sopenharmony_cias local time. 30057db96d56Sopenharmony_ci[clinic start generated code]*/ 30067db96d56Sopenharmony_ci 30077db96d56Sopenharmony_cistatic PyObject * 30087db96d56Sopenharmony_cidatetime_date_fromtimestamp(PyTypeObject *type, PyObject *timestamp) 30097db96d56Sopenharmony_ci/*[clinic end generated code: output=fd045fda58168869 input=eabb3fe7f40491fe]*/ 30107db96d56Sopenharmony_ci{ 30117db96d56Sopenharmony_ci return date_fromtimestamp((PyObject *) type, timestamp); 30127db96d56Sopenharmony_ci} 30137db96d56Sopenharmony_ci 30147db96d56Sopenharmony_ci/* bpo-36025: This is a wrapper for API compatibility with the public C API, 30157db96d56Sopenharmony_ci * which expects a function that takes an *args tuple, whereas the argument 30167db96d56Sopenharmony_ci * clinic generates code that takes METH_O. 30177db96d56Sopenharmony_ci */ 30187db96d56Sopenharmony_cistatic PyObject * 30197db96d56Sopenharmony_cidatetime_date_fromtimestamp_capi(PyObject *cls, PyObject *args) 30207db96d56Sopenharmony_ci{ 30217db96d56Sopenharmony_ci PyObject *timestamp; 30227db96d56Sopenharmony_ci PyObject *result = NULL; 30237db96d56Sopenharmony_ci 30247db96d56Sopenharmony_ci if (PyArg_UnpackTuple(args, "fromtimestamp", 1, 1, ×tamp)) { 30257db96d56Sopenharmony_ci result = date_fromtimestamp(cls, timestamp); 30267db96d56Sopenharmony_ci } 30277db96d56Sopenharmony_ci 30287db96d56Sopenharmony_ci return result; 30297db96d56Sopenharmony_ci} 30307db96d56Sopenharmony_ci 30317db96d56Sopenharmony_ci/* Return new date from proleptic Gregorian ordinal. Raises ValueError if 30327db96d56Sopenharmony_ci * the ordinal is out of range. 30337db96d56Sopenharmony_ci */ 30347db96d56Sopenharmony_cistatic PyObject * 30357db96d56Sopenharmony_cidate_fromordinal(PyObject *cls, PyObject *args) 30367db96d56Sopenharmony_ci{ 30377db96d56Sopenharmony_ci PyObject *result = NULL; 30387db96d56Sopenharmony_ci int ordinal; 30397db96d56Sopenharmony_ci 30407db96d56Sopenharmony_ci if (PyArg_ParseTuple(args, "i:fromordinal", &ordinal)) { 30417db96d56Sopenharmony_ci int year; 30427db96d56Sopenharmony_ci int month; 30437db96d56Sopenharmony_ci int day; 30447db96d56Sopenharmony_ci 30457db96d56Sopenharmony_ci if (ordinal < 1) 30467db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "ordinal must be " 30477db96d56Sopenharmony_ci ">= 1"); 30487db96d56Sopenharmony_ci else { 30497db96d56Sopenharmony_ci ord_to_ymd(ordinal, &year, &month, &day); 30507db96d56Sopenharmony_ci result = new_date_subclass_ex(year, month, day, cls); 30517db96d56Sopenharmony_ci } 30527db96d56Sopenharmony_ci } 30537db96d56Sopenharmony_ci return result; 30547db96d56Sopenharmony_ci} 30557db96d56Sopenharmony_ci 30567db96d56Sopenharmony_ci/* Return the new date from a string as generated by date.isoformat() */ 30577db96d56Sopenharmony_cistatic PyObject * 30587db96d56Sopenharmony_cidate_fromisoformat(PyObject *cls, PyObject *dtstr) 30597db96d56Sopenharmony_ci{ 30607db96d56Sopenharmony_ci assert(dtstr != NULL); 30617db96d56Sopenharmony_ci 30627db96d56Sopenharmony_ci if (!PyUnicode_Check(dtstr)) { 30637db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 30647db96d56Sopenharmony_ci "fromisoformat: argument must be str"); 30657db96d56Sopenharmony_ci return NULL; 30667db96d56Sopenharmony_ci } 30677db96d56Sopenharmony_ci 30687db96d56Sopenharmony_ci Py_ssize_t len; 30697db96d56Sopenharmony_ci 30707db96d56Sopenharmony_ci const char *dt_ptr = PyUnicode_AsUTF8AndSize(dtstr, &len); 30717db96d56Sopenharmony_ci if (dt_ptr == NULL) { 30727db96d56Sopenharmony_ci goto invalid_string_error; 30737db96d56Sopenharmony_ci } 30747db96d56Sopenharmony_ci 30757db96d56Sopenharmony_ci int year = 0, month = 0, day = 0; 30767db96d56Sopenharmony_ci 30777db96d56Sopenharmony_ci int rv; 30787db96d56Sopenharmony_ci if (len == 7 || len == 8 || len == 10) { 30797db96d56Sopenharmony_ci rv = parse_isoformat_date(dt_ptr, len, &year, &month, &day); 30807db96d56Sopenharmony_ci } 30817db96d56Sopenharmony_ci else { 30827db96d56Sopenharmony_ci rv = -1; 30837db96d56Sopenharmony_ci } 30847db96d56Sopenharmony_ci 30857db96d56Sopenharmony_ci if (rv < 0) { 30867db96d56Sopenharmony_ci goto invalid_string_error; 30877db96d56Sopenharmony_ci } 30887db96d56Sopenharmony_ci 30897db96d56Sopenharmony_ci return new_date_subclass_ex(year, month, day, cls); 30907db96d56Sopenharmony_ci 30917db96d56Sopenharmony_ciinvalid_string_error: 30927db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %R", dtstr); 30937db96d56Sopenharmony_ci return NULL; 30947db96d56Sopenharmony_ci} 30957db96d56Sopenharmony_ci 30967db96d56Sopenharmony_ci 30977db96d56Sopenharmony_cistatic PyObject * 30987db96d56Sopenharmony_cidate_fromisocalendar(PyObject *cls, PyObject *args, PyObject *kw) 30997db96d56Sopenharmony_ci{ 31007db96d56Sopenharmony_ci static char *keywords[] = { 31017db96d56Sopenharmony_ci "year", "week", "day", NULL 31027db96d56Sopenharmony_ci }; 31037db96d56Sopenharmony_ci 31047db96d56Sopenharmony_ci int year, week, day; 31057db96d56Sopenharmony_ci if (PyArg_ParseTupleAndKeywords(args, kw, "iii:fromisocalendar", 31067db96d56Sopenharmony_ci keywords, 31077db96d56Sopenharmony_ci &year, &week, &day) == 0) { 31087db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_OverflowError)) { 31097db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, 31107db96d56Sopenharmony_ci "ISO calendar component out of range"); 31117db96d56Sopenharmony_ci 31127db96d56Sopenharmony_ci } 31137db96d56Sopenharmony_ci return NULL; 31147db96d56Sopenharmony_ci } 31157db96d56Sopenharmony_ci 31167db96d56Sopenharmony_ci // Year is bounded to 0 < year < 10000 because 9999-12-31 is (9999, 52, 5) 31177db96d56Sopenharmony_ci if (year < MINYEAR || year > MAXYEAR) { 31187db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "Year is out of range: %d", year); 31197db96d56Sopenharmony_ci return NULL; 31207db96d56Sopenharmony_ci } 31217db96d56Sopenharmony_ci 31227db96d56Sopenharmony_ci int month; 31237db96d56Sopenharmony_ci int rv = iso_to_ymd(year, week, day, &year, &month, &day); 31247db96d56Sopenharmony_ci 31257db96d56Sopenharmony_ci 31267db96d56Sopenharmony_ci if (rv == -2) { 31277db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "Invalid week: %d", week); 31287db96d56Sopenharmony_ci return NULL; 31297db96d56Sopenharmony_ci } 31307db96d56Sopenharmony_ci 31317db96d56Sopenharmony_ci if (rv == -3) { 31327db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "Invalid day: %d (range is [1, 7])", 31337db96d56Sopenharmony_ci day); 31347db96d56Sopenharmony_ci return NULL; 31357db96d56Sopenharmony_ci } 31367db96d56Sopenharmony_ci 31377db96d56Sopenharmony_ci return new_date_subclass_ex(year, month, day, cls); 31387db96d56Sopenharmony_ci} 31397db96d56Sopenharmony_ci 31407db96d56Sopenharmony_ci 31417db96d56Sopenharmony_ci/* 31427db96d56Sopenharmony_ci * Date arithmetic. 31437db96d56Sopenharmony_ci */ 31447db96d56Sopenharmony_ci 31457db96d56Sopenharmony_ci/* date + timedelta -> date. If arg negate is true, subtract the timedelta 31467db96d56Sopenharmony_ci * instead. 31477db96d56Sopenharmony_ci */ 31487db96d56Sopenharmony_cistatic PyObject * 31497db96d56Sopenharmony_ciadd_date_timedelta(PyDateTime_Date *date, PyDateTime_Delta *delta, int negate) 31507db96d56Sopenharmony_ci{ 31517db96d56Sopenharmony_ci PyObject *result = NULL; 31527db96d56Sopenharmony_ci int year = GET_YEAR(date); 31537db96d56Sopenharmony_ci int month = GET_MONTH(date); 31547db96d56Sopenharmony_ci int deltadays = GET_TD_DAYS(delta); 31557db96d56Sopenharmony_ci /* C-level overflow is impossible because |deltadays| < 1e9. */ 31567db96d56Sopenharmony_ci int day = GET_DAY(date) + (negate ? -deltadays : deltadays); 31577db96d56Sopenharmony_ci 31587db96d56Sopenharmony_ci if (normalize_date(&year, &month, &day) >= 0) 31597db96d56Sopenharmony_ci result = new_date_subclass_ex(year, month, day, 31607db96d56Sopenharmony_ci (PyObject* )Py_TYPE(date)); 31617db96d56Sopenharmony_ci return result; 31627db96d56Sopenharmony_ci} 31637db96d56Sopenharmony_ci 31647db96d56Sopenharmony_cistatic PyObject * 31657db96d56Sopenharmony_cidate_add(PyObject *left, PyObject *right) 31667db96d56Sopenharmony_ci{ 31677db96d56Sopenharmony_ci if (PyDateTime_Check(left) || PyDateTime_Check(right)) 31687db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 31697db96d56Sopenharmony_ci 31707db96d56Sopenharmony_ci if (PyDate_Check(left)) { 31717db96d56Sopenharmony_ci /* date + ??? */ 31727db96d56Sopenharmony_ci if (PyDelta_Check(right)) 31737db96d56Sopenharmony_ci /* date + delta */ 31747db96d56Sopenharmony_ci return add_date_timedelta((PyDateTime_Date *) left, 31757db96d56Sopenharmony_ci (PyDateTime_Delta *) right, 31767db96d56Sopenharmony_ci 0); 31777db96d56Sopenharmony_ci } 31787db96d56Sopenharmony_ci else { 31797db96d56Sopenharmony_ci /* ??? + date 31807db96d56Sopenharmony_ci * 'right' must be one of us, or we wouldn't have been called 31817db96d56Sopenharmony_ci */ 31827db96d56Sopenharmony_ci if (PyDelta_Check(left)) 31837db96d56Sopenharmony_ci /* delta + date */ 31847db96d56Sopenharmony_ci return add_date_timedelta((PyDateTime_Date *) right, 31857db96d56Sopenharmony_ci (PyDateTime_Delta *) left, 31867db96d56Sopenharmony_ci 0); 31877db96d56Sopenharmony_ci } 31887db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 31897db96d56Sopenharmony_ci} 31907db96d56Sopenharmony_ci 31917db96d56Sopenharmony_cistatic PyObject * 31927db96d56Sopenharmony_cidate_subtract(PyObject *left, PyObject *right) 31937db96d56Sopenharmony_ci{ 31947db96d56Sopenharmony_ci if (PyDateTime_Check(left) || PyDateTime_Check(right)) 31957db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 31967db96d56Sopenharmony_ci 31977db96d56Sopenharmony_ci if (PyDate_Check(left)) { 31987db96d56Sopenharmony_ci if (PyDate_Check(right)) { 31997db96d56Sopenharmony_ci /* date - date */ 32007db96d56Sopenharmony_ci int left_ord = ymd_to_ord(GET_YEAR(left), 32017db96d56Sopenharmony_ci GET_MONTH(left), 32027db96d56Sopenharmony_ci GET_DAY(left)); 32037db96d56Sopenharmony_ci int right_ord = ymd_to_ord(GET_YEAR(right), 32047db96d56Sopenharmony_ci GET_MONTH(right), 32057db96d56Sopenharmony_ci GET_DAY(right)); 32067db96d56Sopenharmony_ci return new_delta(left_ord - right_ord, 0, 0, 0); 32077db96d56Sopenharmony_ci } 32087db96d56Sopenharmony_ci if (PyDelta_Check(right)) { 32097db96d56Sopenharmony_ci /* date - delta */ 32107db96d56Sopenharmony_ci return add_date_timedelta((PyDateTime_Date *) left, 32117db96d56Sopenharmony_ci (PyDateTime_Delta *) right, 32127db96d56Sopenharmony_ci 1); 32137db96d56Sopenharmony_ci } 32147db96d56Sopenharmony_ci } 32157db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 32167db96d56Sopenharmony_ci} 32177db96d56Sopenharmony_ci 32187db96d56Sopenharmony_ci 32197db96d56Sopenharmony_ci/* Various ways to turn a date into a string. */ 32207db96d56Sopenharmony_ci 32217db96d56Sopenharmony_cistatic PyObject * 32227db96d56Sopenharmony_cidate_repr(PyDateTime_Date *self) 32237db96d56Sopenharmony_ci{ 32247db96d56Sopenharmony_ci return PyUnicode_FromFormat("%s(%d, %d, %d)", 32257db96d56Sopenharmony_ci Py_TYPE(self)->tp_name, 32267db96d56Sopenharmony_ci GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); 32277db96d56Sopenharmony_ci} 32287db96d56Sopenharmony_ci 32297db96d56Sopenharmony_cistatic PyObject * 32307db96d56Sopenharmony_cidate_isoformat(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) 32317db96d56Sopenharmony_ci{ 32327db96d56Sopenharmony_ci return PyUnicode_FromFormat("%04d-%02d-%02d", 32337db96d56Sopenharmony_ci GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); 32347db96d56Sopenharmony_ci} 32357db96d56Sopenharmony_ci 32367db96d56Sopenharmony_ci/* str() calls the appropriate isoformat() method. */ 32377db96d56Sopenharmony_cistatic PyObject * 32387db96d56Sopenharmony_cidate_str(PyDateTime_Date *self) 32397db96d56Sopenharmony_ci{ 32407db96d56Sopenharmony_ci return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat); 32417db96d56Sopenharmony_ci} 32427db96d56Sopenharmony_ci 32437db96d56Sopenharmony_ci 32447db96d56Sopenharmony_cistatic PyObject * 32457db96d56Sopenharmony_cidate_ctime(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) 32467db96d56Sopenharmony_ci{ 32477db96d56Sopenharmony_ci return format_ctime(self, 0, 0, 0); 32487db96d56Sopenharmony_ci} 32497db96d56Sopenharmony_ci 32507db96d56Sopenharmony_cistatic PyObject * 32517db96d56Sopenharmony_cidate_strftime(PyDateTime_Date *self, PyObject *args, PyObject *kw) 32527db96d56Sopenharmony_ci{ 32537db96d56Sopenharmony_ci /* This method can be inherited, and needs to call the 32547db96d56Sopenharmony_ci * timetuple() method appropriate to self's class. 32557db96d56Sopenharmony_ci */ 32567db96d56Sopenharmony_ci PyObject *result; 32577db96d56Sopenharmony_ci PyObject *tuple; 32587db96d56Sopenharmony_ci PyObject *format; 32597db96d56Sopenharmony_ci _Py_IDENTIFIER(timetuple); 32607db96d56Sopenharmony_ci static char *keywords[] = {"format", NULL}; 32617db96d56Sopenharmony_ci 32627db96d56Sopenharmony_ci if (! PyArg_ParseTupleAndKeywords(args, kw, "U:strftime", keywords, 32637db96d56Sopenharmony_ci &format)) 32647db96d56Sopenharmony_ci return NULL; 32657db96d56Sopenharmony_ci 32667db96d56Sopenharmony_ci tuple = _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_timetuple); 32677db96d56Sopenharmony_ci if (tuple == NULL) 32687db96d56Sopenharmony_ci return NULL; 32697db96d56Sopenharmony_ci result = wrap_strftime((PyObject *)self, format, tuple, 32707db96d56Sopenharmony_ci (PyObject *)self); 32717db96d56Sopenharmony_ci Py_DECREF(tuple); 32727db96d56Sopenharmony_ci return result; 32737db96d56Sopenharmony_ci} 32747db96d56Sopenharmony_ci 32757db96d56Sopenharmony_cistatic PyObject * 32767db96d56Sopenharmony_cidate_format(PyDateTime_Date *self, PyObject *args) 32777db96d56Sopenharmony_ci{ 32787db96d56Sopenharmony_ci PyObject *format; 32797db96d56Sopenharmony_ci 32807db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "U:__format__", &format)) 32817db96d56Sopenharmony_ci return NULL; 32827db96d56Sopenharmony_ci 32837db96d56Sopenharmony_ci /* if the format is zero length, return str(self) */ 32847db96d56Sopenharmony_ci if (PyUnicode_GetLength(format) == 0) 32857db96d56Sopenharmony_ci return PyObject_Str((PyObject *)self); 32867db96d56Sopenharmony_ci 32877db96d56Sopenharmony_ci return _PyObject_CallMethodIdOneArg((PyObject *)self, &PyId_strftime, 32887db96d56Sopenharmony_ci format); 32897db96d56Sopenharmony_ci} 32907db96d56Sopenharmony_ci 32917db96d56Sopenharmony_ci/* ISO methods. */ 32927db96d56Sopenharmony_ci 32937db96d56Sopenharmony_cistatic PyObject * 32947db96d56Sopenharmony_cidate_isoweekday(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) 32957db96d56Sopenharmony_ci{ 32967db96d56Sopenharmony_ci int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); 32977db96d56Sopenharmony_ci 32987db96d56Sopenharmony_ci return PyLong_FromLong(dow + 1); 32997db96d56Sopenharmony_ci} 33007db96d56Sopenharmony_ci 33017db96d56Sopenharmony_ciPyDoc_STRVAR(iso_calendar_date__doc__, 33027db96d56Sopenharmony_ci"The result of date.isocalendar() or datetime.isocalendar()\n\n\ 33037db96d56Sopenharmony_ciThis object may be accessed either as a tuple of\n\ 33047db96d56Sopenharmony_ci ((year, week, weekday)\n\ 33057db96d56Sopenharmony_cior via the object attributes as named in the above tuple."); 33067db96d56Sopenharmony_ci 33077db96d56Sopenharmony_citypedef struct { 33087db96d56Sopenharmony_ci PyTupleObject tuple; 33097db96d56Sopenharmony_ci} PyDateTime_IsoCalendarDate; 33107db96d56Sopenharmony_ci 33117db96d56Sopenharmony_cistatic PyObject * 33127db96d56Sopenharmony_ciiso_calendar_date_repr(PyDateTime_IsoCalendarDate *self) 33137db96d56Sopenharmony_ci{ 33147db96d56Sopenharmony_ci PyObject* year = PyTuple_GetItem((PyObject *)self, 0); 33157db96d56Sopenharmony_ci if (year == NULL) { 33167db96d56Sopenharmony_ci return NULL; 33177db96d56Sopenharmony_ci } 33187db96d56Sopenharmony_ci PyObject* week = PyTuple_GetItem((PyObject *)self, 1); 33197db96d56Sopenharmony_ci if (week == NULL) { 33207db96d56Sopenharmony_ci return NULL; 33217db96d56Sopenharmony_ci } 33227db96d56Sopenharmony_ci PyObject* weekday = PyTuple_GetItem((PyObject *)self, 2); 33237db96d56Sopenharmony_ci if (weekday == NULL) { 33247db96d56Sopenharmony_ci return NULL; 33257db96d56Sopenharmony_ci } 33267db96d56Sopenharmony_ci 33277db96d56Sopenharmony_ci return PyUnicode_FromFormat("%.200s(year=%S, week=%S, weekday=%S)", 33287db96d56Sopenharmony_ci Py_TYPE(self)->tp_name, year, week, weekday); 33297db96d56Sopenharmony_ci} 33307db96d56Sopenharmony_ci 33317db96d56Sopenharmony_cistatic PyObject * 33327db96d56Sopenharmony_ciiso_calendar_date_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) 33337db96d56Sopenharmony_ci{ 33347db96d56Sopenharmony_ci // Construct the tuple that this reduces to 33357db96d56Sopenharmony_ci PyObject * reduce_tuple = Py_BuildValue( 33367db96d56Sopenharmony_ci "O((OOO))", &PyTuple_Type, 33377db96d56Sopenharmony_ci PyTuple_GET_ITEM(self, 0), 33387db96d56Sopenharmony_ci PyTuple_GET_ITEM(self, 1), 33397db96d56Sopenharmony_ci PyTuple_GET_ITEM(self, 2) 33407db96d56Sopenharmony_ci ); 33417db96d56Sopenharmony_ci 33427db96d56Sopenharmony_ci return reduce_tuple; 33437db96d56Sopenharmony_ci} 33447db96d56Sopenharmony_ci 33457db96d56Sopenharmony_cistatic PyObject * 33467db96d56Sopenharmony_ciiso_calendar_date_year(PyDateTime_IsoCalendarDate *self, void *unused) 33477db96d56Sopenharmony_ci{ 33487db96d56Sopenharmony_ci PyObject *year = PyTuple_GetItem((PyObject *)self, 0); 33497db96d56Sopenharmony_ci if (year == NULL) { 33507db96d56Sopenharmony_ci return NULL; 33517db96d56Sopenharmony_ci } 33527db96d56Sopenharmony_ci Py_INCREF(year); 33537db96d56Sopenharmony_ci return year; 33547db96d56Sopenharmony_ci} 33557db96d56Sopenharmony_ci 33567db96d56Sopenharmony_cistatic PyObject * 33577db96d56Sopenharmony_ciiso_calendar_date_week(PyDateTime_IsoCalendarDate *self, void *unused) 33587db96d56Sopenharmony_ci{ 33597db96d56Sopenharmony_ci PyObject *week = PyTuple_GetItem((PyObject *)self, 1); 33607db96d56Sopenharmony_ci if (week == NULL) { 33617db96d56Sopenharmony_ci return NULL; 33627db96d56Sopenharmony_ci } 33637db96d56Sopenharmony_ci Py_INCREF(week); 33647db96d56Sopenharmony_ci return week; 33657db96d56Sopenharmony_ci} 33667db96d56Sopenharmony_ci 33677db96d56Sopenharmony_cistatic PyObject * 33687db96d56Sopenharmony_ciiso_calendar_date_weekday(PyDateTime_IsoCalendarDate *self, void *unused) 33697db96d56Sopenharmony_ci{ 33707db96d56Sopenharmony_ci PyObject *weekday = PyTuple_GetItem((PyObject *)self, 2); 33717db96d56Sopenharmony_ci if (weekday == NULL) { 33727db96d56Sopenharmony_ci return NULL; 33737db96d56Sopenharmony_ci } 33747db96d56Sopenharmony_ci Py_INCREF(weekday); 33757db96d56Sopenharmony_ci return weekday; 33767db96d56Sopenharmony_ci} 33777db96d56Sopenharmony_ci 33787db96d56Sopenharmony_cistatic PyGetSetDef iso_calendar_date_getset[] = { 33797db96d56Sopenharmony_ci {"year", (getter)iso_calendar_date_year}, 33807db96d56Sopenharmony_ci {"week", (getter)iso_calendar_date_week}, 33817db96d56Sopenharmony_ci {"weekday", (getter)iso_calendar_date_weekday}, 33827db96d56Sopenharmony_ci {NULL} 33837db96d56Sopenharmony_ci}; 33847db96d56Sopenharmony_ci 33857db96d56Sopenharmony_cistatic PyMethodDef iso_calendar_date_methods[] = { 33867db96d56Sopenharmony_ci {"__reduce__", (PyCFunction)iso_calendar_date_reduce, METH_NOARGS, 33877db96d56Sopenharmony_ci PyDoc_STR("__reduce__() -> (cls, state)")}, 33887db96d56Sopenharmony_ci {NULL, NULL}, 33897db96d56Sopenharmony_ci}; 33907db96d56Sopenharmony_ci 33917db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_IsoCalendarDateType = { 33927db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 33937db96d56Sopenharmony_ci .tp_name = "datetime.IsoCalendarDate", 33947db96d56Sopenharmony_ci .tp_basicsize = sizeof(PyDateTime_IsoCalendarDate), 33957db96d56Sopenharmony_ci .tp_repr = (reprfunc) iso_calendar_date_repr, 33967db96d56Sopenharmony_ci .tp_flags = Py_TPFLAGS_DEFAULT, 33977db96d56Sopenharmony_ci .tp_doc = iso_calendar_date__doc__, 33987db96d56Sopenharmony_ci .tp_methods = iso_calendar_date_methods, 33997db96d56Sopenharmony_ci .tp_getset = iso_calendar_date_getset, 34007db96d56Sopenharmony_ci // .tp_base = &PyTuple_Type, // filled in PyInit__datetime 34017db96d56Sopenharmony_ci .tp_new = iso_calendar_date_new, 34027db96d56Sopenharmony_ci}; 34037db96d56Sopenharmony_ci 34047db96d56Sopenharmony_ci/*[clinic input] 34057db96d56Sopenharmony_ci@classmethod 34067db96d56Sopenharmony_cidatetime.IsoCalendarDate.__new__ as iso_calendar_date_new 34077db96d56Sopenharmony_ci year: int 34087db96d56Sopenharmony_ci week: int 34097db96d56Sopenharmony_ci weekday: int 34107db96d56Sopenharmony_ci[clinic start generated code]*/ 34117db96d56Sopenharmony_ci 34127db96d56Sopenharmony_cistatic PyObject * 34137db96d56Sopenharmony_ciiso_calendar_date_new_impl(PyTypeObject *type, int year, int week, 34147db96d56Sopenharmony_ci int weekday) 34157db96d56Sopenharmony_ci/*[clinic end generated code: output=383d33d8dc7183a2 input=4f2c663c9d19c4ee]*/ 34167db96d56Sopenharmony_ci 34177db96d56Sopenharmony_ci{ 34187db96d56Sopenharmony_ci PyDateTime_IsoCalendarDate *self; 34197db96d56Sopenharmony_ci self = (PyDateTime_IsoCalendarDate *) type->tp_alloc(type, 3); 34207db96d56Sopenharmony_ci if (self == NULL) { 34217db96d56Sopenharmony_ci return NULL; 34227db96d56Sopenharmony_ci } 34237db96d56Sopenharmony_ci 34247db96d56Sopenharmony_ci PyTuple_SET_ITEM(self, 0, PyLong_FromLong(year)); 34257db96d56Sopenharmony_ci PyTuple_SET_ITEM(self, 1, PyLong_FromLong(week)); 34267db96d56Sopenharmony_ci PyTuple_SET_ITEM(self, 2, PyLong_FromLong(weekday)); 34277db96d56Sopenharmony_ci 34287db96d56Sopenharmony_ci return (PyObject *)self; 34297db96d56Sopenharmony_ci} 34307db96d56Sopenharmony_ci 34317db96d56Sopenharmony_cistatic PyObject * 34327db96d56Sopenharmony_cidate_isocalendar(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) 34337db96d56Sopenharmony_ci{ 34347db96d56Sopenharmony_ci int year = GET_YEAR(self); 34357db96d56Sopenharmony_ci int week1_monday = iso_week1_monday(year); 34367db96d56Sopenharmony_ci int today = ymd_to_ord(year, GET_MONTH(self), GET_DAY(self)); 34377db96d56Sopenharmony_ci int week; 34387db96d56Sopenharmony_ci int day; 34397db96d56Sopenharmony_ci 34407db96d56Sopenharmony_ci week = divmod(today - week1_monday, 7, &day); 34417db96d56Sopenharmony_ci if (week < 0) { 34427db96d56Sopenharmony_ci --year; 34437db96d56Sopenharmony_ci week1_monday = iso_week1_monday(year); 34447db96d56Sopenharmony_ci week = divmod(today - week1_monday, 7, &day); 34457db96d56Sopenharmony_ci } 34467db96d56Sopenharmony_ci else if (week >= 52 && today >= iso_week1_monday(year + 1)) { 34477db96d56Sopenharmony_ci ++year; 34487db96d56Sopenharmony_ci week = 0; 34497db96d56Sopenharmony_ci } 34507db96d56Sopenharmony_ci 34517db96d56Sopenharmony_ci PyObject* v = iso_calendar_date_new_impl(&PyDateTime_IsoCalendarDateType, 34527db96d56Sopenharmony_ci year, week + 1, day + 1); 34537db96d56Sopenharmony_ci if (v == NULL) { 34547db96d56Sopenharmony_ci return NULL; 34557db96d56Sopenharmony_ci } 34567db96d56Sopenharmony_ci return v; 34577db96d56Sopenharmony_ci} 34587db96d56Sopenharmony_ci 34597db96d56Sopenharmony_ci/* Miscellaneous methods. */ 34607db96d56Sopenharmony_ci 34617db96d56Sopenharmony_cistatic PyObject * 34627db96d56Sopenharmony_cidate_richcompare(PyObject *self, PyObject *other, int op) 34637db96d56Sopenharmony_ci{ 34647db96d56Sopenharmony_ci if (PyDate_Check(other)) { 34657db96d56Sopenharmony_ci int diff = memcmp(((PyDateTime_Date *)self)->data, 34667db96d56Sopenharmony_ci ((PyDateTime_Date *)other)->data, 34677db96d56Sopenharmony_ci _PyDateTime_DATE_DATASIZE); 34687db96d56Sopenharmony_ci return diff_to_bool(diff, op); 34697db96d56Sopenharmony_ci } 34707db96d56Sopenharmony_ci else 34717db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 34727db96d56Sopenharmony_ci} 34737db96d56Sopenharmony_ci 34747db96d56Sopenharmony_cistatic PyObject * 34757db96d56Sopenharmony_cidate_timetuple(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) 34767db96d56Sopenharmony_ci{ 34777db96d56Sopenharmony_ci return build_struct_time(GET_YEAR(self), 34787db96d56Sopenharmony_ci GET_MONTH(self), 34797db96d56Sopenharmony_ci GET_DAY(self), 34807db96d56Sopenharmony_ci 0, 0, 0, -1); 34817db96d56Sopenharmony_ci} 34827db96d56Sopenharmony_ci 34837db96d56Sopenharmony_cistatic PyObject * 34847db96d56Sopenharmony_cidate_replace(PyDateTime_Date *self, PyObject *args, PyObject *kw) 34857db96d56Sopenharmony_ci{ 34867db96d56Sopenharmony_ci PyObject *clone; 34877db96d56Sopenharmony_ci PyObject *tuple; 34887db96d56Sopenharmony_ci int year = GET_YEAR(self); 34897db96d56Sopenharmony_ci int month = GET_MONTH(self); 34907db96d56Sopenharmony_ci int day = GET_DAY(self); 34917db96d56Sopenharmony_ci 34927db96d56Sopenharmony_ci if (! PyArg_ParseTupleAndKeywords(args, kw, "|iii:replace", date_kws, 34937db96d56Sopenharmony_ci &year, &month, &day)) 34947db96d56Sopenharmony_ci return NULL; 34957db96d56Sopenharmony_ci tuple = Py_BuildValue("iii", year, month, day); 34967db96d56Sopenharmony_ci if (tuple == NULL) 34977db96d56Sopenharmony_ci return NULL; 34987db96d56Sopenharmony_ci clone = date_new(Py_TYPE(self), tuple, NULL); 34997db96d56Sopenharmony_ci Py_DECREF(tuple); 35007db96d56Sopenharmony_ci return clone; 35017db96d56Sopenharmony_ci} 35027db96d56Sopenharmony_ci 35037db96d56Sopenharmony_cistatic Py_hash_t 35047db96d56Sopenharmony_cigeneric_hash(unsigned char *data, int len) 35057db96d56Sopenharmony_ci{ 35067db96d56Sopenharmony_ci return _Py_HashBytes(data, len); 35077db96d56Sopenharmony_ci} 35087db96d56Sopenharmony_ci 35097db96d56Sopenharmony_ci 35107db96d56Sopenharmony_cistatic PyObject *date_getstate(PyDateTime_Date *self); 35117db96d56Sopenharmony_ci 35127db96d56Sopenharmony_cistatic Py_hash_t 35137db96d56Sopenharmony_cidate_hash(PyDateTime_Date *self) 35147db96d56Sopenharmony_ci{ 35157db96d56Sopenharmony_ci if (self->hashcode == -1) { 35167db96d56Sopenharmony_ci self->hashcode = generic_hash( 35177db96d56Sopenharmony_ci (unsigned char *)self->data, _PyDateTime_DATE_DATASIZE); 35187db96d56Sopenharmony_ci } 35197db96d56Sopenharmony_ci 35207db96d56Sopenharmony_ci return self->hashcode; 35217db96d56Sopenharmony_ci} 35227db96d56Sopenharmony_ci 35237db96d56Sopenharmony_cistatic PyObject * 35247db96d56Sopenharmony_cidate_toordinal(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) 35257db96d56Sopenharmony_ci{ 35267db96d56Sopenharmony_ci return PyLong_FromLong(ymd_to_ord(GET_YEAR(self), GET_MONTH(self), 35277db96d56Sopenharmony_ci GET_DAY(self))); 35287db96d56Sopenharmony_ci} 35297db96d56Sopenharmony_ci 35307db96d56Sopenharmony_cistatic PyObject * 35317db96d56Sopenharmony_cidate_weekday(PyDateTime_Date *self, PyObject *Py_UNUSED(ignored)) 35327db96d56Sopenharmony_ci{ 35337db96d56Sopenharmony_ci int dow = weekday(GET_YEAR(self), GET_MONTH(self), GET_DAY(self)); 35347db96d56Sopenharmony_ci 35357db96d56Sopenharmony_ci return PyLong_FromLong(dow); 35367db96d56Sopenharmony_ci} 35377db96d56Sopenharmony_ci 35387db96d56Sopenharmony_ci/* Pickle support, a simple use of __reduce__. */ 35397db96d56Sopenharmony_ci 35407db96d56Sopenharmony_ci/* __getstate__ isn't exposed */ 35417db96d56Sopenharmony_cistatic PyObject * 35427db96d56Sopenharmony_cidate_getstate(PyDateTime_Date *self) 35437db96d56Sopenharmony_ci{ 35447db96d56Sopenharmony_ci PyObject* field; 35457db96d56Sopenharmony_ci field = PyBytes_FromStringAndSize((char*)self->data, 35467db96d56Sopenharmony_ci _PyDateTime_DATE_DATASIZE); 35477db96d56Sopenharmony_ci return Py_BuildValue("(N)", field); 35487db96d56Sopenharmony_ci} 35497db96d56Sopenharmony_ci 35507db96d56Sopenharmony_cistatic PyObject * 35517db96d56Sopenharmony_cidate_reduce(PyDateTime_Date *self, PyObject *arg) 35527db96d56Sopenharmony_ci{ 35537db96d56Sopenharmony_ci return Py_BuildValue("(ON)", Py_TYPE(self), date_getstate(self)); 35547db96d56Sopenharmony_ci} 35557db96d56Sopenharmony_ci 35567db96d56Sopenharmony_cistatic PyMethodDef date_methods[] = { 35577db96d56Sopenharmony_ci 35587db96d56Sopenharmony_ci /* Class methods: */ 35597db96d56Sopenharmony_ci DATETIME_DATE_FROMTIMESTAMP_METHODDEF 35607db96d56Sopenharmony_ci 35617db96d56Sopenharmony_ci {"fromordinal", (PyCFunction)date_fromordinal, METH_VARARGS | 35627db96d56Sopenharmony_ci METH_CLASS, 35637db96d56Sopenharmony_ci PyDoc_STR("int -> date corresponding to a proleptic Gregorian " 35647db96d56Sopenharmony_ci "ordinal.")}, 35657db96d56Sopenharmony_ci 35667db96d56Sopenharmony_ci {"fromisoformat", (PyCFunction)date_fromisoformat, METH_O | 35677db96d56Sopenharmony_ci METH_CLASS, 35687db96d56Sopenharmony_ci PyDoc_STR("str -> Construct a date from a string in ISO 8601 format.")}, 35697db96d56Sopenharmony_ci 35707db96d56Sopenharmony_ci {"fromisocalendar", _PyCFunction_CAST(date_fromisocalendar), 35717db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS | METH_CLASS, 35727db96d56Sopenharmony_ci PyDoc_STR("int, int, int -> Construct a date from the ISO year, week " 35737db96d56Sopenharmony_ci "number and weekday.\n\n" 35747db96d56Sopenharmony_ci "This is the inverse of the date.isocalendar() function")}, 35757db96d56Sopenharmony_ci 35767db96d56Sopenharmony_ci {"today", (PyCFunction)date_today, METH_NOARGS | METH_CLASS, 35777db96d56Sopenharmony_ci PyDoc_STR("Current date or datetime: same as " 35787db96d56Sopenharmony_ci "self.__class__.fromtimestamp(time.time()).")}, 35797db96d56Sopenharmony_ci 35807db96d56Sopenharmony_ci /* Instance methods: */ 35817db96d56Sopenharmony_ci 35827db96d56Sopenharmony_ci {"ctime", (PyCFunction)date_ctime, METH_NOARGS, 35837db96d56Sopenharmony_ci PyDoc_STR("Return ctime() style string.")}, 35847db96d56Sopenharmony_ci 35857db96d56Sopenharmony_ci {"strftime", _PyCFunction_CAST(date_strftime), METH_VARARGS | METH_KEYWORDS, 35867db96d56Sopenharmony_ci PyDoc_STR("format -> strftime() style string.")}, 35877db96d56Sopenharmony_ci 35887db96d56Sopenharmony_ci {"__format__", (PyCFunction)date_format, METH_VARARGS, 35897db96d56Sopenharmony_ci PyDoc_STR("Formats self with strftime.")}, 35907db96d56Sopenharmony_ci 35917db96d56Sopenharmony_ci {"timetuple", (PyCFunction)date_timetuple, METH_NOARGS, 35927db96d56Sopenharmony_ci PyDoc_STR("Return time tuple, compatible with time.localtime().")}, 35937db96d56Sopenharmony_ci 35947db96d56Sopenharmony_ci {"isocalendar", (PyCFunction)date_isocalendar, METH_NOARGS, 35957db96d56Sopenharmony_ci PyDoc_STR("Return a named tuple containing ISO year, week number, and " 35967db96d56Sopenharmony_ci "weekday.")}, 35977db96d56Sopenharmony_ci 35987db96d56Sopenharmony_ci {"isoformat", (PyCFunction)date_isoformat, METH_NOARGS, 35997db96d56Sopenharmony_ci PyDoc_STR("Return string in ISO 8601 format, YYYY-MM-DD.")}, 36007db96d56Sopenharmony_ci 36017db96d56Sopenharmony_ci {"isoweekday", (PyCFunction)date_isoweekday, METH_NOARGS, 36027db96d56Sopenharmony_ci PyDoc_STR("Return the day of the week represented by the date.\n" 36037db96d56Sopenharmony_ci "Monday == 1 ... Sunday == 7")}, 36047db96d56Sopenharmony_ci 36057db96d56Sopenharmony_ci {"toordinal", (PyCFunction)date_toordinal, METH_NOARGS, 36067db96d56Sopenharmony_ci PyDoc_STR("Return proleptic Gregorian ordinal. January 1 of year " 36077db96d56Sopenharmony_ci "1 is day 1.")}, 36087db96d56Sopenharmony_ci 36097db96d56Sopenharmony_ci {"weekday", (PyCFunction)date_weekday, METH_NOARGS, 36107db96d56Sopenharmony_ci PyDoc_STR("Return the day of the week represented by the date.\n" 36117db96d56Sopenharmony_ci "Monday == 0 ... Sunday == 6")}, 36127db96d56Sopenharmony_ci 36137db96d56Sopenharmony_ci {"replace", _PyCFunction_CAST(date_replace), METH_VARARGS | METH_KEYWORDS, 36147db96d56Sopenharmony_ci PyDoc_STR("Return date with new specified fields.")}, 36157db96d56Sopenharmony_ci 36167db96d56Sopenharmony_ci {"__reduce__", (PyCFunction)date_reduce, METH_NOARGS, 36177db96d56Sopenharmony_ci PyDoc_STR("__reduce__() -> (cls, state)")}, 36187db96d56Sopenharmony_ci 36197db96d56Sopenharmony_ci {NULL, NULL} 36207db96d56Sopenharmony_ci}; 36217db96d56Sopenharmony_ci 36227db96d56Sopenharmony_cistatic const char date_doc[] = 36237db96d56Sopenharmony_ciPyDoc_STR("date(year, month, day) --> date object"); 36247db96d56Sopenharmony_ci 36257db96d56Sopenharmony_cistatic PyNumberMethods date_as_number = { 36267db96d56Sopenharmony_ci date_add, /* nb_add */ 36277db96d56Sopenharmony_ci date_subtract, /* nb_subtract */ 36287db96d56Sopenharmony_ci 0, /* nb_multiply */ 36297db96d56Sopenharmony_ci 0, /* nb_remainder */ 36307db96d56Sopenharmony_ci 0, /* nb_divmod */ 36317db96d56Sopenharmony_ci 0, /* nb_power */ 36327db96d56Sopenharmony_ci 0, /* nb_negative */ 36337db96d56Sopenharmony_ci 0, /* nb_positive */ 36347db96d56Sopenharmony_ci 0, /* nb_absolute */ 36357db96d56Sopenharmony_ci 0, /* nb_bool */ 36367db96d56Sopenharmony_ci}; 36377db96d56Sopenharmony_ci 36387db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_DateType = { 36397db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 36407db96d56Sopenharmony_ci "datetime.date", /* tp_name */ 36417db96d56Sopenharmony_ci sizeof(PyDateTime_Date), /* tp_basicsize */ 36427db96d56Sopenharmony_ci 0, /* tp_itemsize */ 36437db96d56Sopenharmony_ci 0, /* tp_dealloc */ 36447db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 36457db96d56Sopenharmony_ci 0, /* tp_getattr */ 36467db96d56Sopenharmony_ci 0, /* tp_setattr */ 36477db96d56Sopenharmony_ci 0, /* tp_as_async */ 36487db96d56Sopenharmony_ci (reprfunc)date_repr, /* tp_repr */ 36497db96d56Sopenharmony_ci &date_as_number, /* tp_as_number */ 36507db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 36517db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 36527db96d56Sopenharmony_ci (hashfunc)date_hash, /* tp_hash */ 36537db96d56Sopenharmony_ci 0, /* tp_call */ 36547db96d56Sopenharmony_ci (reprfunc)date_str, /* tp_str */ 36557db96d56Sopenharmony_ci PyObject_GenericGetAttr, /* tp_getattro */ 36567db96d56Sopenharmony_ci 0, /* tp_setattro */ 36577db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 36587db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 36597db96d56Sopenharmony_ci date_doc, /* tp_doc */ 36607db96d56Sopenharmony_ci 0, /* tp_traverse */ 36617db96d56Sopenharmony_ci 0, /* tp_clear */ 36627db96d56Sopenharmony_ci date_richcompare, /* tp_richcompare */ 36637db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 36647db96d56Sopenharmony_ci 0, /* tp_iter */ 36657db96d56Sopenharmony_ci 0, /* tp_iternext */ 36667db96d56Sopenharmony_ci date_methods, /* tp_methods */ 36677db96d56Sopenharmony_ci 0, /* tp_members */ 36687db96d56Sopenharmony_ci date_getset, /* tp_getset */ 36697db96d56Sopenharmony_ci 0, /* tp_base */ 36707db96d56Sopenharmony_ci 0, /* tp_dict */ 36717db96d56Sopenharmony_ci 0, /* tp_descr_get */ 36727db96d56Sopenharmony_ci 0, /* tp_descr_set */ 36737db96d56Sopenharmony_ci 0, /* tp_dictoffset */ 36747db96d56Sopenharmony_ci 0, /* tp_init */ 36757db96d56Sopenharmony_ci 0, /* tp_alloc */ 36767db96d56Sopenharmony_ci date_new, /* tp_new */ 36777db96d56Sopenharmony_ci 0, /* tp_free */ 36787db96d56Sopenharmony_ci}; 36797db96d56Sopenharmony_ci 36807db96d56Sopenharmony_ci/* 36817db96d56Sopenharmony_ci * PyDateTime_TZInfo implementation. 36827db96d56Sopenharmony_ci */ 36837db96d56Sopenharmony_ci 36847db96d56Sopenharmony_ci/* This is a pure abstract base class, so doesn't do anything beyond 36857db96d56Sopenharmony_ci * raising NotImplemented exceptions. Real tzinfo classes need 36867db96d56Sopenharmony_ci * to derive from this. This is mostly for clarity, and for efficiency in 36877db96d56Sopenharmony_ci * datetime and time constructors (their tzinfo arguments need to 36887db96d56Sopenharmony_ci * be subclasses of this tzinfo class, which is easy and quick to check). 36897db96d56Sopenharmony_ci * 36907db96d56Sopenharmony_ci * Note: For reasons having to do with pickling of subclasses, we have 36917db96d56Sopenharmony_ci * to allow tzinfo objects to be instantiated. This wasn't an issue 36927db96d56Sopenharmony_ci * in the Python implementation (__init__() could raise NotImplementedError 36937db96d56Sopenharmony_ci * there without ill effect), but doing so in the C implementation hit a 36947db96d56Sopenharmony_ci * brick wall. 36957db96d56Sopenharmony_ci */ 36967db96d56Sopenharmony_ci 36977db96d56Sopenharmony_cistatic PyObject * 36987db96d56Sopenharmony_citzinfo_nogo(const char* methodname) 36997db96d56Sopenharmony_ci{ 37007db96d56Sopenharmony_ci PyErr_Format(PyExc_NotImplementedError, 37017db96d56Sopenharmony_ci "a tzinfo subclass must implement %s()", 37027db96d56Sopenharmony_ci methodname); 37037db96d56Sopenharmony_ci return NULL; 37047db96d56Sopenharmony_ci} 37057db96d56Sopenharmony_ci 37067db96d56Sopenharmony_ci/* Methods. A subclass must implement these. */ 37077db96d56Sopenharmony_ci 37087db96d56Sopenharmony_cistatic PyObject * 37097db96d56Sopenharmony_citzinfo_tzname(PyDateTime_TZInfo *self, PyObject *dt) 37107db96d56Sopenharmony_ci{ 37117db96d56Sopenharmony_ci return tzinfo_nogo("tzname"); 37127db96d56Sopenharmony_ci} 37137db96d56Sopenharmony_ci 37147db96d56Sopenharmony_cistatic PyObject * 37157db96d56Sopenharmony_citzinfo_utcoffset(PyDateTime_TZInfo *self, PyObject *dt) 37167db96d56Sopenharmony_ci{ 37177db96d56Sopenharmony_ci return tzinfo_nogo("utcoffset"); 37187db96d56Sopenharmony_ci} 37197db96d56Sopenharmony_ci 37207db96d56Sopenharmony_cistatic PyObject * 37217db96d56Sopenharmony_citzinfo_dst(PyDateTime_TZInfo *self, PyObject *dt) 37227db96d56Sopenharmony_ci{ 37237db96d56Sopenharmony_ci return tzinfo_nogo("dst"); 37247db96d56Sopenharmony_ci} 37257db96d56Sopenharmony_ci 37267db96d56Sopenharmony_ci 37277db96d56Sopenharmony_cistatic PyObject *add_datetime_timedelta(PyDateTime_DateTime *date, 37287db96d56Sopenharmony_ci PyDateTime_Delta *delta, 37297db96d56Sopenharmony_ci int factor); 37307db96d56Sopenharmony_cistatic PyObject *datetime_utcoffset(PyObject *self, PyObject *); 37317db96d56Sopenharmony_cistatic PyObject *datetime_dst(PyObject *self, PyObject *); 37327db96d56Sopenharmony_ci 37337db96d56Sopenharmony_cistatic PyObject * 37347db96d56Sopenharmony_citzinfo_fromutc(PyDateTime_TZInfo *self, PyObject *dt) 37357db96d56Sopenharmony_ci{ 37367db96d56Sopenharmony_ci PyObject *result = NULL; 37377db96d56Sopenharmony_ci PyObject *off = NULL, *dst = NULL; 37387db96d56Sopenharmony_ci PyDateTime_Delta *delta = NULL; 37397db96d56Sopenharmony_ci 37407db96d56Sopenharmony_ci if (!PyDateTime_Check(dt)) { 37417db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 37427db96d56Sopenharmony_ci "fromutc: argument must be a datetime"); 37437db96d56Sopenharmony_ci return NULL; 37447db96d56Sopenharmony_ci } 37457db96d56Sopenharmony_ci if (GET_DT_TZINFO(dt) != (PyObject *)self) { 37467db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo " 37477db96d56Sopenharmony_ci "is not self"); 37487db96d56Sopenharmony_ci return NULL; 37497db96d56Sopenharmony_ci } 37507db96d56Sopenharmony_ci 37517db96d56Sopenharmony_ci off = datetime_utcoffset(dt, NULL); 37527db96d56Sopenharmony_ci if (off == NULL) 37537db96d56Sopenharmony_ci return NULL; 37547db96d56Sopenharmony_ci if (off == Py_None) { 37557db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "fromutc: non-None " 37567db96d56Sopenharmony_ci "utcoffset() result required"); 37577db96d56Sopenharmony_ci goto Fail; 37587db96d56Sopenharmony_ci } 37597db96d56Sopenharmony_ci 37607db96d56Sopenharmony_ci dst = datetime_dst(dt, NULL); 37617db96d56Sopenharmony_ci if (dst == NULL) 37627db96d56Sopenharmony_ci goto Fail; 37637db96d56Sopenharmony_ci if (dst == Py_None) { 37647db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "fromutc: non-None " 37657db96d56Sopenharmony_ci "dst() result required"); 37667db96d56Sopenharmony_ci goto Fail; 37677db96d56Sopenharmony_ci } 37687db96d56Sopenharmony_ci 37697db96d56Sopenharmony_ci delta = (PyDateTime_Delta *)delta_subtract(off, dst); 37707db96d56Sopenharmony_ci if (delta == NULL) 37717db96d56Sopenharmony_ci goto Fail; 37727db96d56Sopenharmony_ci result = add_datetime_timedelta((PyDateTime_DateTime *)dt, delta, 1); 37737db96d56Sopenharmony_ci if (result == NULL) 37747db96d56Sopenharmony_ci goto Fail; 37757db96d56Sopenharmony_ci 37767db96d56Sopenharmony_ci Py_DECREF(dst); 37777db96d56Sopenharmony_ci dst = call_dst(GET_DT_TZINFO(dt), result); 37787db96d56Sopenharmony_ci if (dst == NULL) 37797db96d56Sopenharmony_ci goto Fail; 37807db96d56Sopenharmony_ci if (dst == Py_None) 37817db96d56Sopenharmony_ci goto Inconsistent; 37827db96d56Sopenharmony_ci if (delta_bool((PyDateTime_Delta *)dst) != 0) { 37837db96d56Sopenharmony_ci Py_SETREF(result, add_datetime_timedelta((PyDateTime_DateTime *)result, 37847db96d56Sopenharmony_ci (PyDateTime_Delta *)dst, 1)); 37857db96d56Sopenharmony_ci if (result == NULL) 37867db96d56Sopenharmony_ci goto Fail; 37877db96d56Sopenharmony_ci } 37887db96d56Sopenharmony_ci Py_DECREF(delta); 37897db96d56Sopenharmony_ci Py_DECREF(dst); 37907db96d56Sopenharmony_ci Py_DECREF(off); 37917db96d56Sopenharmony_ci return result; 37927db96d56Sopenharmony_ci 37937db96d56Sopenharmony_ciInconsistent: 37947db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "fromutc: tz.dst() gave " 37957db96d56Sopenharmony_ci "inconsistent results; cannot convert"); 37967db96d56Sopenharmony_ci 37977db96d56Sopenharmony_ci /* fall through to failure */ 37987db96d56Sopenharmony_ciFail: 37997db96d56Sopenharmony_ci Py_XDECREF(off); 38007db96d56Sopenharmony_ci Py_XDECREF(dst); 38017db96d56Sopenharmony_ci Py_XDECREF(delta); 38027db96d56Sopenharmony_ci Py_XDECREF(result); 38037db96d56Sopenharmony_ci return NULL; 38047db96d56Sopenharmony_ci} 38057db96d56Sopenharmony_ci 38067db96d56Sopenharmony_ci/* 38077db96d56Sopenharmony_ci * Pickle support. This is solely so that tzinfo subclasses can use 38087db96d56Sopenharmony_ci * pickling -- tzinfo itself is supposed to be uninstantiable. 38097db96d56Sopenharmony_ci */ 38107db96d56Sopenharmony_ci 38117db96d56Sopenharmony_cistatic PyObject * 38127db96d56Sopenharmony_citzinfo_reduce(PyObject *self, PyObject *Py_UNUSED(ignored)) 38137db96d56Sopenharmony_ci{ 38147db96d56Sopenharmony_ci PyObject *args, *state; 38157db96d56Sopenharmony_ci PyObject *getinitargs; 38167db96d56Sopenharmony_ci _Py_IDENTIFIER(__getinitargs__); 38177db96d56Sopenharmony_ci 38187db96d56Sopenharmony_ci if (_PyObject_LookupAttrId(self, &PyId___getinitargs__, &getinitargs) < 0) { 38197db96d56Sopenharmony_ci return NULL; 38207db96d56Sopenharmony_ci } 38217db96d56Sopenharmony_ci if (getinitargs != NULL) { 38227db96d56Sopenharmony_ci args = PyObject_CallNoArgs(getinitargs); 38237db96d56Sopenharmony_ci Py_DECREF(getinitargs); 38247db96d56Sopenharmony_ci } 38257db96d56Sopenharmony_ci else { 38267db96d56Sopenharmony_ci args = PyTuple_New(0); 38277db96d56Sopenharmony_ci } 38287db96d56Sopenharmony_ci if (args == NULL) { 38297db96d56Sopenharmony_ci return NULL; 38307db96d56Sopenharmony_ci } 38317db96d56Sopenharmony_ci 38327db96d56Sopenharmony_ci state = _PyObject_GetState(self); 38337db96d56Sopenharmony_ci if (state == NULL) { 38347db96d56Sopenharmony_ci Py_DECREF(args); 38357db96d56Sopenharmony_ci return NULL; 38367db96d56Sopenharmony_ci } 38377db96d56Sopenharmony_ci 38387db96d56Sopenharmony_ci return Py_BuildValue("(ONN)", Py_TYPE(self), args, state); 38397db96d56Sopenharmony_ci} 38407db96d56Sopenharmony_ci 38417db96d56Sopenharmony_cistatic PyMethodDef tzinfo_methods[] = { 38427db96d56Sopenharmony_ci 38437db96d56Sopenharmony_ci {"tzname", (PyCFunction)tzinfo_tzname, METH_O, 38447db96d56Sopenharmony_ci PyDoc_STR("datetime -> string name of time zone.")}, 38457db96d56Sopenharmony_ci 38467db96d56Sopenharmony_ci {"utcoffset", (PyCFunction)tzinfo_utcoffset, METH_O, 38477db96d56Sopenharmony_ci PyDoc_STR("datetime -> timedelta showing offset from UTC, negative " 38487db96d56Sopenharmony_ci "values indicating West of UTC")}, 38497db96d56Sopenharmony_ci 38507db96d56Sopenharmony_ci {"dst", (PyCFunction)tzinfo_dst, METH_O, 38517db96d56Sopenharmony_ci PyDoc_STR("datetime -> DST offset as timedelta positive east of UTC.")}, 38527db96d56Sopenharmony_ci 38537db96d56Sopenharmony_ci {"fromutc", (PyCFunction)tzinfo_fromutc, METH_O, 38547db96d56Sopenharmony_ci PyDoc_STR("datetime in UTC -> datetime in local time.")}, 38557db96d56Sopenharmony_ci 38567db96d56Sopenharmony_ci {"__reduce__", tzinfo_reduce, METH_NOARGS, 38577db96d56Sopenharmony_ci PyDoc_STR("-> (cls, state)")}, 38587db96d56Sopenharmony_ci 38597db96d56Sopenharmony_ci {NULL, NULL} 38607db96d56Sopenharmony_ci}; 38617db96d56Sopenharmony_ci 38627db96d56Sopenharmony_cistatic const char tzinfo_doc[] = 38637db96d56Sopenharmony_ciPyDoc_STR("Abstract base class for time zone info objects."); 38647db96d56Sopenharmony_ci 38657db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_TZInfoType = { 38667db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 38677db96d56Sopenharmony_ci "datetime.tzinfo", /* tp_name */ 38687db96d56Sopenharmony_ci sizeof(PyDateTime_TZInfo), /* tp_basicsize */ 38697db96d56Sopenharmony_ci 0, /* tp_itemsize */ 38707db96d56Sopenharmony_ci 0, /* tp_dealloc */ 38717db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 38727db96d56Sopenharmony_ci 0, /* tp_getattr */ 38737db96d56Sopenharmony_ci 0, /* tp_setattr */ 38747db96d56Sopenharmony_ci 0, /* tp_as_async */ 38757db96d56Sopenharmony_ci 0, /* tp_repr */ 38767db96d56Sopenharmony_ci 0, /* tp_as_number */ 38777db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 38787db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 38797db96d56Sopenharmony_ci 0, /* tp_hash */ 38807db96d56Sopenharmony_ci 0, /* tp_call */ 38817db96d56Sopenharmony_ci 0, /* tp_str */ 38827db96d56Sopenharmony_ci PyObject_GenericGetAttr, /* tp_getattro */ 38837db96d56Sopenharmony_ci 0, /* tp_setattro */ 38847db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 38857db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 38867db96d56Sopenharmony_ci tzinfo_doc, /* tp_doc */ 38877db96d56Sopenharmony_ci 0, /* tp_traverse */ 38887db96d56Sopenharmony_ci 0, /* tp_clear */ 38897db96d56Sopenharmony_ci 0, /* tp_richcompare */ 38907db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 38917db96d56Sopenharmony_ci 0, /* tp_iter */ 38927db96d56Sopenharmony_ci 0, /* tp_iternext */ 38937db96d56Sopenharmony_ci tzinfo_methods, /* tp_methods */ 38947db96d56Sopenharmony_ci 0, /* tp_members */ 38957db96d56Sopenharmony_ci 0, /* tp_getset */ 38967db96d56Sopenharmony_ci 0, /* tp_base */ 38977db96d56Sopenharmony_ci 0, /* tp_dict */ 38987db96d56Sopenharmony_ci 0, /* tp_descr_get */ 38997db96d56Sopenharmony_ci 0, /* tp_descr_set */ 39007db96d56Sopenharmony_ci 0, /* tp_dictoffset */ 39017db96d56Sopenharmony_ci 0, /* tp_init */ 39027db96d56Sopenharmony_ci 0, /* tp_alloc */ 39037db96d56Sopenharmony_ci PyType_GenericNew, /* tp_new */ 39047db96d56Sopenharmony_ci 0, /* tp_free */ 39057db96d56Sopenharmony_ci}; 39067db96d56Sopenharmony_ci 39077db96d56Sopenharmony_cistatic char *timezone_kws[] = {"offset", "name", NULL}; 39087db96d56Sopenharmony_ci 39097db96d56Sopenharmony_cistatic PyObject * 39107db96d56Sopenharmony_citimezone_new(PyTypeObject *type, PyObject *args, PyObject *kw) 39117db96d56Sopenharmony_ci{ 39127db96d56Sopenharmony_ci PyObject *offset; 39137db96d56Sopenharmony_ci PyObject *name = NULL; 39147db96d56Sopenharmony_ci if (PyArg_ParseTupleAndKeywords(args, kw, "O!|U:timezone", timezone_kws, 39157db96d56Sopenharmony_ci &PyDateTime_DeltaType, &offset, &name)) 39167db96d56Sopenharmony_ci return new_timezone(offset, name); 39177db96d56Sopenharmony_ci 39187db96d56Sopenharmony_ci return NULL; 39197db96d56Sopenharmony_ci} 39207db96d56Sopenharmony_ci 39217db96d56Sopenharmony_cistatic void 39227db96d56Sopenharmony_citimezone_dealloc(PyDateTime_TimeZone *self) 39237db96d56Sopenharmony_ci{ 39247db96d56Sopenharmony_ci Py_CLEAR(self->offset); 39257db96d56Sopenharmony_ci Py_CLEAR(self->name); 39267db96d56Sopenharmony_ci Py_TYPE(self)->tp_free((PyObject *)self); 39277db96d56Sopenharmony_ci} 39287db96d56Sopenharmony_ci 39297db96d56Sopenharmony_cistatic PyObject * 39307db96d56Sopenharmony_citimezone_richcompare(PyDateTime_TimeZone *self, 39317db96d56Sopenharmony_ci PyDateTime_TimeZone *other, int op) 39327db96d56Sopenharmony_ci{ 39337db96d56Sopenharmony_ci if (op != Py_EQ && op != Py_NE) 39347db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 39357db96d56Sopenharmony_ci if (!PyTimezone_Check(other)) { 39367db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 39377db96d56Sopenharmony_ci } 39387db96d56Sopenharmony_ci return delta_richcompare(self->offset, other->offset, op); 39397db96d56Sopenharmony_ci} 39407db96d56Sopenharmony_ci 39417db96d56Sopenharmony_cistatic Py_hash_t 39427db96d56Sopenharmony_citimezone_hash(PyDateTime_TimeZone *self) 39437db96d56Sopenharmony_ci{ 39447db96d56Sopenharmony_ci return delta_hash((PyDateTime_Delta *)self->offset); 39457db96d56Sopenharmony_ci} 39467db96d56Sopenharmony_ci 39477db96d56Sopenharmony_ci/* Check argument type passed to tzname, utcoffset, or dst methods. 39487db96d56Sopenharmony_ci Returns 0 for good argument. Returns -1 and sets exception info 39497db96d56Sopenharmony_ci otherwise. 39507db96d56Sopenharmony_ci */ 39517db96d56Sopenharmony_cistatic int 39527db96d56Sopenharmony_ci_timezone_check_argument(PyObject *dt, const char *meth) 39537db96d56Sopenharmony_ci{ 39547db96d56Sopenharmony_ci if (dt == Py_None || PyDateTime_Check(dt)) 39557db96d56Sopenharmony_ci return 0; 39567db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, "%s(dt) argument must be a datetime instance" 39577db96d56Sopenharmony_ci " or None, not %.200s", meth, Py_TYPE(dt)->tp_name); 39587db96d56Sopenharmony_ci return -1; 39597db96d56Sopenharmony_ci} 39607db96d56Sopenharmony_ci 39617db96d56Sopenharmony_cistatic PyObject * 39627db96d56Sopenharmony_citimezone_repr(PyDateTime_TimeZone *self) 39637db96d56Sopenharmony_ci{ 39647db96d56Sopenharmony_ci /* Note that although timezone is not subclassable, it is convenient 39657db96d56Sopenharmony_ci to use Py_TYPE(self)->tp_name here. */ 39667db96d56Sopenharmony_ci const char *type_name = Py_TYPE(self)->tp_name; 39677db96d56Sopenharmony_ci 39687db96d56Sopenharmony_ci if (((PyObject *)self) == PyDateTime_TimeZone_UTC) 39697db96d56Sopenharmony_ci return PyUnicode_FromFormat("%s.utc", type_name); 39707db96d56Sopenharmony_ci 39717db96d56Sopenharmony_ci if (self->name == NULL) 39727db96d56Sopenharmony_ci return PyUnicode_FromFormat("%s(%R)", type_name, self->offset); 39737db96d56Sopenharmony_ci 39747db96d56Sopenharmony_ci return PyUnicode_FromFormat("%s(%R, %R)", type_name, self->offset, 39757db96d56Sopenharmony_ci self->name); 39767db96d56Sopenharmony_ci} 39777db96d56Sopenharmony_ci 39787db96d56Sopenharmony_ci 39797db96d56Sopenharmony_cistatic PyObject * 39807db96d56Sopenharmony_citimezone_str(PyDateTime_TimeZone *self) 39817db96d56Sopenharmony_ci{ 39827db96d56Sopenharmony_ci int hours, minutes, seconds, microseconds; 39837db96d56Sopenharmony_ci PyObject *offset; 39847db96d56Sopenharmony_ci char sign; 39857db96d56Sopenharmony_ci 39867db96d56Sopenharmony_ci if (self->name != NULL) { 39877db96d56Sopenharmony_ci Py_INCREF(self->name); 39887db96d56Sopenharmony_ci return self->name; 39897db96d56Sopenharmony_ci } 39907db96d56Sopenharmony_ci if ((PyObject *)self == PyDateTime_TimeZone_UTC || 39917db96d56Sopenharmony_ci (GET_TD_DAYS(self->offset) == 0 && 39927db96d56Sopenharmony_ci GET_TD_SECONDS(self->offset) == 0 && 39937db96d56Sopenharmony_ci GET_TD_MICROSECONDS(self->offset) == 0)) 39947db96d56Sopenharmony_ci return PyUnicode_FromString("UTC"); 39957db96d56Sopenharmony_ci /* Offset is normalized, so it is negative if days < 0 */ 39967db96d56Sopenharmony_ci if (GET_TD_DAYS(self->offset) < 0) { 39977db96d56Sopenharmony_ci sign = '-'; 39987db96d56Sopenharmony_ci offset = delta_negative((PyDateTime_Delta *)self->offset); 39997db96d56Sopenharmony_ci if (offset == NULL) 40007db96d56Sopenharmony_ci return NULL; 40017db96d56Sopenharmony_ci } 40027db96d56Sopenharmony_ci else { 40037db96d56Sopenharmony_ci sign = '+'; 40047db96d56Sopenharmony_ci offset = self->offset; 40057db96d56Sopenharmony_ci Py_INCREF(offset); 40067db96d56Sopenharmony_ci } 40077db96d56Sopenharmony_ci /* Offset is not negative here. */ 40087db96d56Sopenharmony_ci microseconds = GET_TD_MICROSECONDS(offset); 40097db96d56Sopenharmony_ci seconds = GET_TD_SECONDS(offset); 40107db96d56Sopenharmony_ci Py_DECREF(offset); 40117db96d56Sopenharmony_ci minutes = divmod(seconds, 60, &seconds); 40127db96d56Sopenharmony_ci hours = divmod(minutes, 60, &minutes); 40137db96d56Sopenharmony_ci if (microseconds != 0) { 40147db96d56Sopenharmony_ci return PyUnicode_FromFormat("UTC%c%02d:%02d:%02d.%06d", 40157db96d56Sopenharmony_ci sign, hours, minutes, 40167db96d56Sopenharmony_ci seconds, microseconds); 40177db96d56Sopenharmony_ci } 40187db96d56Sopenharmony_ci if (seconds != 0) { 40197db96d56Sopenharmony_ci return PyUnicode_FromFormat("UTC%c%02d:%02d:%02d", 40207db96d56Sopenharmony_ci sign, hours, minutes, seconds); 40217db96d56Sopenharmony_ci } 40227db96d56Sopenharmony_ci return PyUnicode_FromFormat("UTC%c%02d:%02d", sign, hours, minutes); 40237db96d56Sopenharmony_ci} 40247db96d56Sopenharmony_ci 40257db96d56Sopenharmony_cistatic PyObject * 40267db96d56Sopenharmony_citimezone_tzname(PyDateTime_TimeZone *self, PyObject *dt) 40277db96d56Sopenharmony_ci{ 40287db96d56Sopenharmony_ci if (_timezone_check_argument(dt, "tzname") == -1) 40297db96d56Sopenharmony_ci return NULL; 40307db96d56Sopenharmony_ci 40317db96d56Sopenharmony_ci return timezone_str(self); 40327db96d56Sopenharmony_ci} 40337db96d56Sopenharmony_ci 40347db96d56Sopenharmony_cistatic PyObject * 40357db96d56Sopenharmony_citimezone_utcoffset(PyDateTime_TimeZone *self, PyObject *dt) 40367db96d56Sopenharmony_ci{ 40377db96d56Sopenharmony_ci if (_timezone_check_argument(dt, "utcoffset") == -1) 40387db96d56Sopenharmony_ci return NULL; 40397db96d56Sopenharmony_ci 40407db96d56Sopenharmony_ci Py_INCREF(self->offset); 40417db96d56Sopenharmony_ci return self->offset; 40427db96d56Sopenharmony_ci} 40437db96d56Sopenharmony_ci 40447db96d56Sopenharmony_cistatic PyObject * 40457db96d56Sopenharmony_citimezone_dst(PyObject *self, PyObject *dt) 40467db96d56Sopenharmony_ci{ 40477db96d56Sopenharmony_ci if (_timezone_check_argument(dt, "dst") == -1) 40487db96d56Sopenharmony_ci return NULL; 40497db96d56Sopenharmony_ci 40507db96d56Sopenharmony_ci Py_RETURN_NONE; 40517db96d56Sopenharmony_ci} 40527db96d56Sopenharmony_ci 40537db96d56Sopenharmony_cistatic PyObject * 40547db96d56Sopenharmony_citimezone_fromutc(PyDateTime_TimeZone *self, PyDateTime_DateTime *dt) 40557db96d56Sopenharmony_ci{ 40567db96d56Sopenharmony_ci if (!PyDateTime_Check(dt)) { 40577db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 40587db96d56Sopenharmony_ci "fromutc: argument must be a datetime"); 40597db96d56Sopenharmony_ci return NULL; 40607db96d56Sopenharmony_ci } 40617db96d56Sopenharmony_ci if (!HASTZINFO(dt) || dt->tzinfo != (PyObject *)self) { 40627db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "fromutc: dt.tzinfo " 40637db96d56Sopenharmony_ci "is not self"); 40647db96d56Sopenharmony_ci return NULL; 40657db96d56Sopenharmony_ci } 40667db96d56Sopenharmony_ci 40677db96d56Sopenharmony_ci return add_datetime_timedelta(dt, (PyDateTime_Delta *)self->offset, 1); 40687db96d56Sopenharmony_ci} 40697db96d56Sopenharmony_ci 40707db96d56Sopenharmony_cistatic PyObject * 40717db96d56Sopenharmony_citimezone_getinitargs(PyDateTime_TimeZone *self, PyObject *Py_UNUSED(ignored)) 40727db96d56Sopenharmony_ci{ 40737db96d56Sopenharmony_ci if (self->name == NULL) 40747db96d56Sopenharmony_ci return Py_BuildValue("(O)", self->offset); 40757db96d56Sopenharmony_ci return Py_BuildValue("(OO)", self->offset, self->name); 40767db96d56Sopenharmony_ci} 40777db96d56Sopenharmony_ci 40787db96d56Sopenharmony_cistatic PyMethodDef timezone_methods[] = { 40797db96d56Sopenharmony_ci {"tzname", (PyCFunction)timezone_tzname, METH_O, 40807db96d56Sopenharmony_ci PyDoc_STR("If name is specified when timezone is created, returns the name." 40817db96d56Sopenharmony_ci " Otherwise returns offset as 'UTC(+|-)HH:MM'.")}, 40827db96d56Sopenharmony_ci 40837db96d56Sopenharmony_ci {"utcoffset", (PyCFunction)timezone_utcoffset, METH_O, 40847db96d56Sopenharmony_ci PyDoc_STR("Return fixed offset.")}, 40857db96d56Sopenharmony_ci 40867db96d56Sopenharmony_ci {"dst", (PyCFunction)timezone_dst, METH_O, 40877db96d56Sopenharmony_ci PyDoc_STR("Return None.")}, 40887db96d56Sopenharmony_ci 40897db96d56Sopenharmony_ci {"fromutc", (PyCFunction)timezone_fromutc, METH_O, 40907db96d56Sopenharmony_ci PyDoc_STR("datetime in UTC -> datetime in local time.")}, 40917db96d56Sopenharmony_ci 40927db96d56Sopenharmony_ci {"__getinitargs__", (PyCFunction)timezone_getinitargs, METH_NOARGS, 40937db96d56Sopenharmony_ci PyDoc_STR("pickle support")}, 40947db96d56Sopenharmony_ci 40957db96d56Sopenharmony_ci {NULL, NULL} 40967db96d56Sopenharmony_ci}; 40977db96d56Sopenharmony_ci 40987db96d56Sopenharmony_cistatic const char timezone_doc[] = 40997db96d56Sopenharmony_ciPyDoc_STR("Fixed offset from UTC implementation of tzinfo."); 41007db96d56Sopenharmony_ci 41017db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_TimeZoneType = { 41027db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 41037db96d56Sopenharmony_ci "datetime.timezone", /* tp_name */ 41047db96d56Sopenharmony_ci sizeof(PyDateTime_TimeZone), /* tp_basicsize */ 41057db96d56Sopenharmony_ci 0, /* tp_itemsize */ 41067db96d56Sopenharmony_ci (destructor)timezone_dealloc, /* tp_dealloc */ 41077db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 41087db96d56Sopenharmony_ci 0, /* tp_getattr */ 41097db96d56Sopenharmony_ci 0, /* tp_setattr */ 41107db96d56Sopenharmony_ci 0, /* tp_as_async */ 41117db96d56Sopenharmony_ci (reprfunc)timezone_repr, /* tp_repr */ 41127db96d56Sopenharmony_ci 0, /* tp_as_number */ 41137db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 41147db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 41157db96d56Sopenharmony_ci (hashfunc)timezone_hash, /* tp_hash */ 41167db96d56Sopenharmony_ci 0, /* tp_call */ 41177db96d56Sopenharmony_ci (reprfunc)timezone_str, /* tp_str */ 41187db96d56Sopenharmony_ci 0, /* tp_getattro */ 41197db96d56Sopenharmony_ci 0, /* tp_setattro */ 41207db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 41217db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT, /* tp_flags */ 41227db96d56Sopenharmony_ci timezone_doc, /* tp_doc */ 41237db96d56Sopenharmony_ci 0, /* tp_traverse */ 41247db96d56Sopenharmony_ci 0, /* tp_clear */ 41257db96d56Sopenharmony_ci (richcmpfunc)timezone_richcompare,/* tp_richcompare */ 41267db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 41277db96d56Sopenharmony_ci 0, /* tp_iter */ 41287db96d56Sopenharmony_ci 0, /* tp_iternext */ 41297db96d56Sopenharmony_ci timezone_methods, /* tp_methods */ 41307db96d56Sopenharmony_ci 0, /* tp_members */ 41317db96d56Sopenharmony_ci 0, /* tp_getset */ 41327db96d56Sopenharmony_ci 0, /* tp_base; filled in PyInit__datetime */ 41337db96d56Sopenharmony_ci 0, /* tp_dict */ 41347db96d56Sopenharmony_ci 0, /* tp_descr_get */ 41357db96d56Sopenharmony_ci 0, /* tp_descr_set */ 41367db96d56Sopenharmony_ci 0, /* tp_dictoffset */ 41377db96d56Sopenharmony_ci 0, /* tp_init */ 41387db96d56Sopenharmony_ci 0, /* tp_alloc */ 41397db96d56Sopenharmony_ci timezone_new, /* tp_new */ 41407db96d56Sopenharmony_ci}; 41417db96d56Sopenharmony_ci 41427db96d56Sopenharmony_ci/* 41437db96d56Sopenharmony_ci * PyDateTime_Time implementation. 41447db96d56Sopenharmony_ci */ 41457db96d56Sopenharmony_ci 41467db96d56Sopenharmony_ci/* Accessor properties. 41477db96d56Sopenharmony_ci */ 41487db96d56Sopenharmony_ci 41497db96d56Sopenharmony_cistatic PyObject * 41507db96d56Sopenharmony_citime_hour(PyDateTime_Time *self, void *unused) 41517db96d56Sopenharmony_ci{ 41527db96d56Sopenharmony_ci return PyLong_FromLong(TIME_GET_HOUR(self)); 41537db96d56Sopenharmony_ci} 41547db96d56Sopenharmony_ci 41557db96d56Sopenharmony_cistatic PyObject * 41567db96d56Sopenharmony_citime_minute(PyDateTime_Time *self, void *unused) 41577db96d56Sopenharmony_ci{ 41587db96d56Sopenharmony_ci return PyLong_FromLong(TIME_GET_MINUTE(self)); 41597db96d56Sopenharmony_ci} 41607db96d56Sopenharmony_ci 41617db96d56Sopenharmony_ci/* The name time_second conflicted with some platform header file. */ 41627db96d56Sopenharmony_cistatic PyObject * 41637db96d56Sopenharmony_cipy_time_second(PyDateTime_Time *self, void *unused) 41647db96d56Sopenharmony_ci{ 41657db96d56Sopenharmony_ci return PyLong_FromLong(TIME_GET_SECOND(self)); 41667db96d56Sopenharmony_ci} 41677db96d56Sopenharmony_ci 41687db96d56Sopenharmony_cistatic PyObject * 41697db96d56Sopenharmony_citime_microsecond(PyDateTime_Time *self, void *unused) 41707db96d56Sopenharmony_ci{ 41717db96d56Sopenharmony_ci return PyLong_FromLong(TIME_GET_MICROSECOND(self)); 41727db96d56Sopenharmony_ci} 41737db96d56Sopenharmony_ci 41747db96d56Sopenharmony_cistatic PyObject * 41757db96d56Sopenharmony_citime_tzinfo(PyDateTime_Time *self, void *unused) 41767db96d56Sopenharmony_ci{ 41777db96d56Sopenharmony_ci PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None; 41787db96d56Sopenharmony_ci Py_INCREF(result); 41797db96d56Sopenharmony_ci return result; 41807db96d56Sopenharmony_ci} 41817db96d56Sopenharmony_ci 41827db96d56Sopenharmony_cistatic PyObject * 41837db96d56Sopenharmony_citime_fold(PyDateTime_Time *self, void *unused) 41847db96d56Sopenharmony_ci{ 41857db96d56Sopenharmony_ci return PyLong_FromLong(TIME_GET_FOLD(self)); 41867db96d56Sopenharmony_ci} 41877db96d56Sopenharmony_ci 41887db96d56Sopenharmony_cistatic PyGetSetDef time_getset[] = { 41897db96d56Sopenharmony_ci {"hour", (getter)time_hour}, 41907db96d56Sopenharmony_ci {"minute", (getter)time_minute}, 41917db96d56Sopenharmony_ci {"second", (getter)py_time_second}, 41927db96d56Sopenharmony_ci {"microsecond", (getter)time_microsecond}, 41937db96d56Sopenharmony_ci {"tzinfo", (getter)time_tzinfo}, 41947db96d56Sopenharmony_ci {"fold", (getter)time_fold}, 41957db96d56Sopenharmony_ci {NULL} 41967db96d56Sopenharmony_ci}; 41977db96d56Sopenharmony_ci 41987db96d56Sopenharmony_ci/* 41997db96d56Sopenharmony_ci * Constructors. 42007db96d56Sopenharmony_ci */ 42017db96d56Sopenharmony_ci 42027db96d56Sopenharmony_cistatic char *time_kws[] = {"hour", "minute", "second", "microsecond", 42037db96d56Sopenharmony_ci "tzinfo", "fold", NULL}; 42047db96d56Sopenharmony_ci 42057db96d56Sopenharmony_cistatic PyObject * 42067db96d56Sopenharmony_citime_from_pickle(PyTypeObject *type, PyObject *state, PyObject *tzinfo) 42077db96d56Sopenharmony_ci{ 42087db96d56Sopenharmony_ci PyDateTime_Time *me; 42097db96d56Sopenharmony_ci char aware = (char)(tzinfo != Py_None); 42107db96d56Sopenharmony_ci 42117db96d56Sopenharmony_ci if (aware && check_tzinfo_subclass(tzinfo) < 0) { 42127db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, "bad tzinfo state arg"); 42137db96d56Sopenharmony_ci return NULL; 42147db96d56Sopenharmony_ci } 42157db96d56Sopenharmony_ci 42167db96d56Sopenharmony_ci me = (PyDateTime_Time *) (type->tp_alloc(type, aware)); 42177db96d56Sopenharmony_ci if (me != NULL) { 42187db96d56Sopenharmony_ci const char *pdata = PyBytes_AS_STRING(state); 42197db96d56Sopenharmony_ci 42207db96d56Sopenharmony_ci memcpy(me->data, pdata, _PyDateTime_TIME_DATASIZE); 42217db96d56Sopenharmony_ci me->hashcode = -1; 42227db96d56Sopenharmony_ci me->hastzinfo = aware; 42237db96d56Sopenharmony_ci if (aware) { 42247db96d56Sopenharmony_ci Py_INCREF(tzinfo); 42257db96d56Sopenharmony_ci me->tzinfo = tzinfo; 42267db96d56Sopenharmony_ci } 42277db96d56Sopenharmony_ci if (pdata[0] & (1 << 7)) { 42287db96d56Sopenharmony_ci me->data[0] -= 128; 42297db96d56Sopenharmony_ci me->fold = 1; 42307db96d56Sopenharmony_ci } 42317db96d56Sopenharmony_ci else { 42327db96d56Sopenharmony_ci me->fold = 0; 42337db96d56Sopenharmony_ci } 42347db96d56Sopenharmony_ci } 42357db96d56Sopenharmony_ci return (PyObject *)me; 42367db96d56Sopenharmony_ci} 42377db96d56Sopenharmony_ci 42387db96d56Sopenharmony_cistatic PyObject * 42397db96d56Sopenharmony_citime_new(PyTypeObject *type, PyObject *args, PyObject *kw) 42407db96d56Sopenharmony_ci{ 42417db96d56Sopenharmony_ci PyObject *self = NULL; 42427db96d56Sopenharmony_ci int hour = 0; 42437db96d56Sopenharmony_ci int minute = 0; 42447db96d56Sopenharmony_ci int second = 0; 42457db96d56Sopenharmony_ci int usecond = 0; 42467db96d56Sopenharmony_ci PyObject *tzinfo = Py_None; 42477db96d56Sopenharmony_ci int fold = 0; 42487db96d56Sopenharmony_ci 42497db96d56Sopenharmony_ci /* Check for invocation from pickle with __getstate__ state */ 42507db96d56Sopenharmony_ci if (PyTuple_GET_SIZE(args) >= 1 && PyTuple_GET_SIZE(args) <= 2) { 42517db96d56Sopenharmony_ci PyObject *state = PyTuple_GET_ITEM(args, 0); 42527db96d56Sopenharmony_ci if (PyTuple_GET_SIZE(args) == 2) { 42537db96d56Sopenharmony_ci tzinfo = PyTuple_GET_ITEM(args, 1); 42547db96d56Sopenharmony_ci } 42557db96d56Sopenharmony_ci if (PyBytes_Check(state)) { 42567db96d56Sopenharmony_ci if (PyBytes_GET_SIZE(state) == _PyDateTime_TIME_DATASIZE && 42577db96d56Sopenharmony_ci (0x7F & ((unsigned char) (PyBytes_AS_STRING(state)[0]))) < 24) 42587db96d56Sopenharmony_ci { 42597db96d56Sopenharmony_ci return time_from_pickle(type, state, tzinfo); 42607db96d56Sopenharmony_ci } 42617db96d56Sopenharmony_ci } 42627db96d56Sopenharmony_ci else if (PyUnicode_Check(state)) { 42637db96d56Sopenharmony_ci if (PyUnicode_READY(state)) { 42647db96d56Sopenharmony_ci return NULL; 42657db96d56Sopenharmony_ci } 42667db96d56Sopenharmony_ci if (PyUnicode_GET_LENGTH(state) == _PyDateTime_TIME_DATASIZE && 42677db96d56Sopenharmony_ci (0x7F & PyUnicode_READ_CHAR(state, 0)) < 24) 42687db96d56Sopenharmony_ci { 42697db96d56Sopenharmony_ci state = PyUnicode_AsLatin1String(state); 42707db96d56Sopenharmony_ci if (state == NULL) { 42717db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) { 42727db96d56Sopenharmony_ci /* More informative error message. */ 42737db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 42747db96d56Sopenharmony_ci "Failed to encode latin1 string when unpickling " 42757db96d56Sopenharmony_ci "a time object. " 42767db96d56Sopenharmony_ci "pickle.load(data, encoding='latin1') is assumed."); 42777db96d56Sopenharmony_ci } 42787db96d56Sopenharmony_ci return NULL; 42797db96d56Sopenharmony_ci } 42807db96d56Sopenharmony_ci self = time_from_pickle(type, state, tzinfo); 42817db96d56Sopenharmony_ci Py_DECREF(state); 42827db96d56Sopenharmony_ci return self; 42837db96d56Sopenharmony_ci } 42847db96d56Sopenharmony_ci } 42857db96d56Sopenharmony_ci tzinfo = Py_None; 42867db96d56Sopenharmony_ci } 42877db96d56Sopenharmony_ci 42887db96d56Sopenharmony_ci if (PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO$i", time_kws, 42897db96d56Sopenharmony_ci &hour, &minute, &second, &usecond, 42907db96d56Sopenharmony_ci &tzinfo, &fold)) { 42917db96d56Sopenharmony_ci self = new_time_ex2(hour, minute, second, usecond, tzinfo, fold, 42927db96d56Sopenharmony_ci type); 42937db96d56Sopenharmony_ci } 42947db96d56Sopenharmony_ci return self; 42957db96d56Sopenharmony_ci} 42967db96d56Sopenharmony_ci 42977db96d56Sopenharmony_ci/* 42987db96d56Sopenharmony_ci * Destructor. 42997db96d56Sopenharmony_ci */ 43007db96d56Sopenharmony_ci 43017db96d56Sopenharmony_cistatic void 43027db96d56Sopenharmony_citime_dealloc(PyDateTime_Time *self) 43037db96d56Sopenharmony_ci{ 43047db96d56Sopenharmony_ci if (HASTZINFO(self)) { 43057db96d56Sopenharmony_ci Py_XDECREF(self->tzinfo); 43067db96d56Sopenharmony_ci } 43077db96d56Sopenharmony_ci Py_TYPE(self)->tp_free((PyObject *)self); 43087db96d56Sopenharmony_ci} 43097db96d56Sopenharmony_ci 43107db96d56Sopenharmony_ci/* 43117db96d56Sopenharmony_ci * Indirect access to tzinfo methods. 43127db96d56Sopenharmony_ci */ 43137db96d56Sopenharmony_ci 43147db96d56Sopenharmony_ci/* These are all METH_NOARGS, so don't need to check the arglist. */ 43157db96d56Sopenharmony_cistatic PyObject * 43167db96d56Sopenharmony_citime_utcoffset(PyObject *self, PyObject *unused) { 43177db96d56Sopenharmony_ci return call_utcoffset(GET_TIME_TZINFO(self), Py_None); 43187db96d56Sopenharmony_ci} 43197db96d56Sopenharmony_ci 43207db96d56Sopenharmony_cistatic PyObject * 43217db96d56Sopenharmony_citime_dst(PyObject *self, PyObject *unused) { 43227db96d56Sopenharmony_ci return call_dst(GET_TIME_TZINFO(self), Py_None); 43237db96d56Sopenharmony_ci} 43247db96d56Sopenharmony_ci 43257db96d56Sopenharmony_cistatic PyObject * 43267db96d56Sopenharmony_citime_tzname(PyDateTime_Time *self, PyObject *unused) { 43277db96d56Sopenharmony_ci return call_tzname(GET_TIME_TZINFO(self), Py_None); 43287db96d56Sopenharmony_ci} 43297db96d56Sopenharmony_ci 43307db96d56Sopenharmony_ci/* 43317db96d56Sopenharmony_ci * Various ways to turn a time into a string. 43327db96d56Sopenharmony_ci */ 43337db96d56Sopenharmony_ci 43347db96d56Sopenharmony_cistatic PyObject * 43357db96d56Sopenharmony_citime_repr(PyDateTime_Time *self) 43367db96d56Sopenharmony_ci{ 43377db96d56Sopenharmony_ci const char *type_name = Py_TYPE(self)->tp_name; 43387db96d56Sopenharmony_ci int h = TIME_GET_HOUR(self); 43397db96d56Sopenharmony_ci int m = TIME_GET_MINUTE(self); 43407db96d56Sopenharmony_ci int s = TIME_GET_SECOND(self); 43417db96d56Sopenharmony_ci int us = TIME_GET_MICROSECOND(self); 43427db96d56Sopenharmony_ci int fold = TIME_GET_FOLD(self); 43437db96d56Sopenharmony_ci PyObject *result = NULL; 43447db96d56Sopenharmony_ci 43457db96d56Sopenharmony_ci if (us) 43467db96d56Sopenharmony_ci result = PyUnicode_FromFormat("%s(%d, %d, %d, %d)", 43477db96d56Sopenharmony_ci type_name, h, m, s, us); 43487db96d56Sopenharmony_ci else if (s) 43497db96d56Sopenharmony_ci result = PyUnicode_FromFormat("%s(%d, %d, %d)", 43507db96d56Sopenharmony_ci type_name, h, m, s); 43517db96d56Sopenharmony_ci else 43527db96d56Sopenharmony_ci result = PyUnicode_FromFormat("%s(%d, %d)", type_name, h, m); 43537db96d56Sopenharmony_ci if (result != NULL && HASTZINFO(self)) 43547db96d56Sopenharmony_ci result = append_keyword_tzinfo(result, self->tzinfo); 43557db96d56Sopenharmony_ci if (result != NULL && fold) 43567db96d56Sopenharmony_ci result = append_keyword_fold(result, fold); 43577db96d56Sopenharmony_ci return result; 43587db96d56Sopenharmony_ci} 43597db96d56Sopenharmony_ci 43607db96d56Sopenharmony_cistatic PyObject * 43617db96d56Sopenharmony_citime_str(PyDateTime_Time *self) 43627db96d56Sopenharmony_ci{ 43637db96d56Sopenharmony_ci return _PyObject_CallMethodIdNoArgs((PyObject *)self, &PyId_isoformat); 43647db96d56Sopenharmony_ci} 43657db96d56Sopenharmony_ci 43667db96d56Sopenharmony_cistatic PyObject * 43677db96d56Sopenharmony_citime_isoformat(PyDateTime_Time *self, PyObject *args, PyObject *kw) 43687db96d56Sopenharmony_ci{ 43697db96d56Sopenharmony_ci char buf[100]; 43707db96d56Sopenharmony_ci const char *timespec = NULL; 43717db96d56Sopenharmony_ci static char *keywords[] = {"timespec", NULL}; 43727db96d56Sopenharmony_ci PyObject *result; 43737db96d56Sopenharmony_ci int us = TIME_GET_MICROSECOND(self); 43747db96d56Sopenharmony_ci static const char *specs[][2] = { 43757db96d56Sopenharmony_ci {"hours", "%02d"}, 43767db96d56Sopenharmony_ci {"minutes", "%02d:%02d"}, 43777db96d56Sopenharmony_ci {"seconds", "%02d:%02d:%02d"}, 43787db96d56Sopenharmony_ci {"milliseconds", "%02d:%02d:%02d.%03d"}, 43797db96d56Sopenharmony_ci {"microseconds", "%02d:%02d:%02d.%06d"}, 43807db96d56Sopenharmony_ci }; 43817db96d56Sopenharmony_ci size_t given_spec; 43827db96d56Sopenharmony_ci 43837db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kw, "|s:isoformat", keywords, ×pec)) 43847db96d56Sopenharmony_ci return NULL; 43857db96d56Sopenharmony_ci 43867db96d56Sopenharmony_ci if (timespec == NULL || strcmp(timespec, "auto") == 0) { 43877db96d56Sopenharmony_ci if (us == 0) { 43887db96d56Sopenharmony_ci /* seconds */ 43897db96d56Sopenharmony_ci given_spec = 2; 43907db96d56Sopenharmony_ci } 43917db96d56Sopenharmony_ci else { 43927db96d56Sopenharmony_ci /* microseconds */ 43937db96d56Sopenharmony_ci given_spec = 4; 43947db96d56Sopenharmony_ci } 43957db96d56Sopenharmony_ci } 43967db96d56Sopenharmony_ci else { 43977db96d56Sopenharmony_ci for (given_spec = 0; given_spec < Py_ARRAY_LENGTH(specs); given_spec++) { 43987db96d56Sopenharmony_ci if (strcmp(timespec, specs[given_spec][0]) == 0) { 43997db96d56Sopenharmony_ci if (given_spec == 3) { 44007db96d56Sopenharmony_ci /* milliseconds */ 44017db96d56Sopenharmony_ci us = us / 1000; 44027db96d56Sopenharmony_ci } 44037db96d56Sopenharmony_ci break; 44047db96d56Sopenharmony_ci } 44057db96d56Sopenharmony_ci } 44067db96d56Sopenharmony_ci } 44077db96d56Sopenharmony_ci 44087db96d56Sopenharmony_ci if (given_spec == Py_ARRAY_LENGTH(specs)) { 44097db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "Unknown timespec value"); 44107db96d56Sopenharmony_ci return NULL; 44117db96d56Sopenharmony_ci } 44127db96d56Sopenharmony_ci else { 44137db96d56Sopenharmony_ci result = PyUnicode_FromFormat(specs[given_spec][1], 44147db96d56Sopenharmony_ci TIME_GET_HOUR(self), TIME_GET_MINUTE(self), 44157db96d56Sopenharmony_ci TIME_GET_SECOND(self), us); 44167db96d56Sopenharmony_ci } 44177db96d56Sopenharmony_ci 44187db96d56Sopenharmony_ci if (result == NULL || !HASTZINFO(self) || self->tzinfo == Py_None) 44197db96d56Sopenharmony_ci return result; 44207db96d56Sopenharmony_ci 44217db96d56Sopenharmony_ci /* We need to append the UTC offset. */ 44227db96d56Sopenharmony_ci if (format_utcoffset(buf, sizeof(buf), ":", self->tzinfo, 44237db96d56Sopenharmony_ci Py_None) < 0) { 44247db96d56Sopenharmony_ci Py_DECREF(result); 44257db96d56Sopenharmony_ci return NULL; 44267db96d56Sopenharmony_ci } 44277db96d56Sopenharmony_ci PyUnicode_AppendAndDel(&result, PyUnicode_FromString(buf)); 44287db96d56Sopenharmony_ci return result; 44297db96d56Sopenharmony_ci} 44307db96d56Sopenharmony_ci 44317db96d56Sopenharmony_cistatic PyObject * 44327db96d56Sopenharmony_citime_strftime(PyDateTime_Time *self, PyObject *args, PyObject *kw) 44337db96d56Sopenharmony_ci{ 44347db96d56Sopenharmony_ci PyObject *result; 44357db96d56Sopenharmony_ci PyObject *tuple; 44367db96d56Sopenharmony_ci PyObject *format; 44377db96d56Sopenharmony_ci static char *keywords[] = {"format", NULL}; 44387db96d56Sopenharmony_ci 44397db96d56Sopenharmony_ci if (! PyArg_ParseTupleAndKeywords(args, kw, "U:strftime", keywords, 44407db96d56Sopenharmony_ci &format)) 44417db96d56Sopenharmony_ci return NULL; 44427db96d56Sopenharmony_ci 44437db96d56Sopenharmony_ci /* Python's strftime does insane things with the year part of the 44447db96d56Sopenharmony_ci * timetuple. The year is forced to (the otherwise nonsensical) 44457db96d56Sopenharmony_ci * 1900 to work around that. 44467db96d56Sopenharmony_ci */ 44477db96d56Sopenharmony_ci tuple = Py_BuildValue("iiiiiiiii", 44487db96d56Sopenharmony_ci 1900, 1, 1, /* year, month, day */ 44497db96d56Sopenharmony_ci TIME_GET_HOUR(self), 44507db96d56Sopenharmony_ci TIME_GET_MINUTE(self), 44517db96d56Sopenharmony_ci TIME_GET_SECOND(self), 44527db96d56Sopenharmony_ci 0, 1, -1); /* weekday, daynum, dst */ 44537db96d56Sopenharmony_ci if (tuple == NULL) 44547db96d56Sopenharmony_ci return NULL; 44557db96d56Sopenharmony_ci assert(PyTuple_Size(tuple) == 9); 44567db96d56Sopenharmony_ci result = wrap_strftime((PyObject *)self, format, tuple, 44577db96d56Sopenharmony_ci Py_None); 44587db96d56Sopenharmony_ci Py_DECREF(tuple); 44597db96d56Sopenharmony_ci return result; 44607db96d56Sopenharmony_ci} 44617db96d56Sopenharmony_ci 44627db96d56Sopenharmony_ci/* 44637db96d56Sopenharmony_ci * Miscellaneous methods. 44647db96d56Sopenharmony_ci */ 44657db96d56Sopenharmony_ci 44667db96d56Sopenharmony_cistatic PyObject * 44677db96d56Sopenharmony_citime_richcompare(PyObject *self, PyObject *other, int op) 44687db96d56Sopenharmony_ci{ 44697db96d56Sopenharmony_ci PyObject *result = NULL; 44707db96d56Sopenharmony_ci PyObject *offset1, *offset2; 44717db96d56Sopenharmony_ci int diff; 44727db96d56Sopenharmony_ci 44737db96d56Sopenharmony_ci if (! PyTime_Check(other)) 44747db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 44757db96d56Sopenharmony_ci 44767db96d56Sopenharmony_ci if (GET_TIME_TZINFO(self) == GET_TIME_TZINFO(other)) { 44777db96d56Sopenharmony_ci diff = memcmp(((PyDateTime_Time *)self)->data, 44787db96d56Sopenharmony_ci ((PyDateTime_Time *)other)->data, 44797db96d56Sopenharmony_ci _PyDateTime_TIME_DATASIZE); 44807db96d56Sopenharmony_ci return diff_to_bool(diff, op); 44817db96d56Sopenharmony_ci } 44827db96d56Sopenharmony_ci offset1 = time_utcoffset(self, NULL); 44837db96d56Sopenharmony_ci if (offset1 == NULL) 44847db96d56Sopenharmony_ci return NULL; 44857db96d56Sopenharmony_ci offset2 = time_utcoffset(other, NULL); 44867db96d56Sopenharmony_ci if (offset2 == NULL) 44877db96d56Sopenharmony_ci goto done; 44887db96d56Sopenharmony_ci /* If they're both naive, or both aware and have the same offsets, 44897db96d56Sopenharmony_ci * we get off cheap. Note that if they're both naive, offset1 == 44907db96d56Sopenharmony_ci * offset2 == Py_None at this point. 44917db96d56Sopenharmony_ci */ 44927db96d56Sopenharmony_ci if ((offset1 == offset2) || 44937db96d56Sopenharmony_ci (PyDelta_Check(offset1) && PyDelta_Check(offset2) && 44947db96d56Sopenharmony_ci delta_cmp(offset1, offset2) == 0)) { 44957db96d56Sopenharmony_ci diff = memcmp(((PyDateTime_Time *)self)->data, 44967db96d56Sopenharmony_ci ((PyDateTime_Time *)other)->data, 44977db96d56Sopenharmony_ci _PyDateTime_TIME_DATASIZE); 44987db96d56Sopenharmony_ci result = diff_to_bool(diff, op); 44997db96d56Sopenharmony_ci } 45007db96d56Sopenharmony_ci /* The hard case: both aware with different UTC offsets */ 45017db96d56Sopenharmony_ci else if (offset1 != Py_None && offset2 != Py_None) { 45027db96d56Sopenharmony_ci int offsecs1, offsecs2; 45037db96d56Sopenharmony_ci assert(offset1 != offset2); /* else last "if" handled it */ 45047db96d56Sopenharmony_ci offsecs1 = TIME_GET_HOUR(self) * 3600 + 45057db96d56Sopenharmony_ci TIME_GET_MINUTE(self) * 60 + 45067db96d56Sopenharmony_ci TIME_GET_SECOND(self) - 45077db96d56Sopenharmony_ci GET_TD_DAYS(offset1) * 86400 - 45087db96d56Sopenharmony_ci GET_TD_SECONDS(offset1); 45097db96d56Sopenharmony_ci offsecs2 = TIME_GET_HOUR(other) * 3600 + 45107db96d56Sopenharmony_ci TIME_GET_MINUTE(other) * 60 + 45117db96d56Sopenharmony_ci TIME_GET_SECOND(other) - 45127db96d56Sopenharmony_ci GET_TD_DAYS(offset2) * 86400 - 45137db96d56Sopenharmony_ci GET_TD_SECONDS(offset2); 45147db96d56Sopenharmony_ci diff = offsecs1 - offsecs2; 45157db96d56Sopenharmony_ci if (diff == 0) 45167db96d56Sopenharmony_ci diff = TIME_GET_MICROSECOND(self) - 45177db96d56Sopenharmony_ci TIME_GET_MICROSECOND(other); 45187db96d56Sopenharmony_ci result = diff_to_bool(diff, op); 45197db96d56Sopenharmony_ci } 45207db96d56Sopenharmony_ci else if (op == Py_EQ) { 45217db96d56Sopenharmony_ci result = Py_False; 45227db96d56Sopenharmony_ci Py_INCREF(result); 45237db96d56Sopenharmony_ci } 45247db96d56Sopenharmony_ci else if (op == Py_NE) { 45257db96d56Sopenharmony_ci result = Py_True; 45267db96d56Sopenharmony_ci Py_INCREF(result); 45277db96d56Sopenharmony_ci } 45287db96d56Sopenharmony_ci else { 45297db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 45307db96d56Sopenharmony_ci "can't compare offset-naive and " 45317db96d56Sopenharmony_ci "offset-aware times"); 45327db96d56Sopenharmony_ci } 45337db96d56Sopenharmony_ci done: 45347db96d56Sopenharmony_ci Py_DECREF(offset1); 45357db96d56Sopenharmony_ci Py_XDECREF(offset2); 45367db96d56Sopenharmony_ci return result; 45377db96d56Sopenharmony_ci} 45387db96d56Sopenharmony_ci 45397db96d56Sopenharmony_cistatic Py_hash_t 45407db96d56Sopenharmony_citime_hash(PyDateTime_Time *self) 45417db96d56Sopenharmony_ci{ 45427db96d56Sopenharmony_ci if (self->hashcode == -1) { 45437db96d56Sopenharmony_ci PyObject *offset, *self0; 45447db96d56Sopenharmony_ci if (TIME_GET_FOLD(self)) { 45457db96d56Sopenharmony_ci self0 = new_time_ex2(TIME_GET_HOUR(self), 45467db96d56Sopenharmony_ci TIME_GET_MINUTE(self), 45477db96d56Sopenharmony_ci TIME_GET_SECOND(self), 45487db96d56Sopenharmony_ci TIME_GET_MICROSECOND(self), 45497db96d56Sopenharmony_ci HASTZINFO(self) ? self->tzinfo : Py_None, 45507db96d56Sopenharmony_ci 0, Py_TYPE(self)); 45517db96d56Sopenharmony_ci if (self0 == NULL) 45527db96d56Sopenharmony_ci return -1; 45537db96d56Sopenharmony_ci } 45547db96d56Sopenharmony_ci else { 45557db96d56Sopenharmony_ci self0 = (PyObject *)self; 45567db96d56Sopenharmony_ci Py_INCREF(self0); 45577db96d56Sopenharmony_ci } 45587db96d56Sopenharmony_ci offset = time_utcoffset(self0, NULL); 45597db96d56Sopenharmony_ci Py_DECREF(self0); 45607db96d56Sopenharmony_ci 45617db96d56Sopenharmony_ci if (offset == NULL) 45627db96d56Sopenharmony_ci return -1; 45637db96d56Sopenharmony_ci 45647db96d56Sopenharmony_ci /* Reduce this to a hash of another object. */ 45657db96d56Sopenharmony_ci if (offset == Py_None) 45667db96d56Sopenharmony_ci self->hashcode = generic_hash( 45677db96d56Sopenharmony_ci (unsigned char *)self->data, _PyDateTime_TIME_DATASIZE); 45687db96d56Sopenharmony_ci else { 45697db96d56Sopenharmony_ci PyObject *temp1, *temp2; 45707db96d56Sopenharmony_ci int seconds, microseconds; 45717db96d56Sopenharmony_ci assert(HASTZINFO(self)); 45727db96d56Sopenharmony_ci seconds = TIME_GET_HOUR(self) * 3600 + 45737db96d56Sopenharmony_ci TIME_GET_MINUTE(self) * 60 + 45747db96d56Sopenharmony_ci TIME_GET_SECOND(self); 45757db96d56Sopenharmony_ci microseconds = TIME_GET_MICROSECOND(self); 45767db96d56Sopenharmony_ci temp1 = new_delta(0, seconds, microseconds, 1); 45777db96d56Sopenharmony_ci if (temp1 == NULL) { 45787db96d56Sopenharmony_ci Py_DECREF(offset); 45797db96d56Sopenharmony_ci return -1; 45807db96d56Sopenharmony_ci } 45817db96d56Sopenharmony_ci temp2 = delta_subtract(temp1, offset); 45827db96d56Sopenharmony_ci Py_DECREF(temp1); 45837db96d56Sopenharmony_ci if (temp2 == NULL) { 45847db96d56Sopenharmony_ci Py_DECREF(offset); 45857db96d56Sopenharmony_ci return -1; 45867db96d56Sopenharmony_ci } 45877db96d56Sopenharmony_ci self->hashcode = PyObject_Hash(temp2); 45887db96d56Sopenharmony_ci Py_DECREF(temp2); 45897db96d56Sopenharmony_ci } 45907db96d56Sopenharmony_ci Py_DECREF(offset); 45917db96d56Sopenharmony_ci } 45927db96d56Sopenharmony_ci return self->hashcode; 45937db96d56Sopenharmony_ci} 45947db96d56Sopenharmony_ci 45957db96d56Sopenharmony_cistatic PyObject * 45967db96d56Sopenharmony_citime_replace(PyDateTime_Time *self, PyObject *args, PyObject *kw) 45977db96d56Sopenharmony_ci{ 45987db96d56Sopenharmony_ci PyObject *clone; 45997db96d56Sopenharmony_ci PyObject *tuple; 46007db96d56Sopenharmony_ci int hh = TIME_GET_HOUR(self); 46017db96d56Sopenharmony_ci int mm = TIME_GET_MINUTE(self); 46027db96d56Sopenharmony_ci int ss = TIME_GET_SECOND(self); 46037db96d56Sopenharmony_ci int us = TIME_GET_MICROSECOND(self); 46047db96d56Sopenharmony_ci PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None; 46057db96d56Sopenharmony_ci int fold = TIME_GET_FOLD(self); 46067db96d56Sopenharmony_ci 46077db96d56Sopenharmony_ci if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO$i:replace", 46087db96d56Sopenharmony_ci time_kws, 46097db96d56Sopenharmony_ci &hh, &mm, &ss, &us, &tzinfo, &fold)) 46107db96d56Sopenharmony_ci return NULL; 46117db96d56Sopenharmony_ci if (fold != 0 && fold != 1) { 46127db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 46137db96d56Sopenharmony_ci "fold must be either 0 or 1"); 46147db96d56Sopenharmony_ci return NULL; 46157db96d56Sopenharmony_ci } 46167db96d56Sopenharmony_ci tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo); 46177db96d56Sopenharmony_ci if (tuple == NULL) 46187db96d56Sopenharmony_ci return NULL; 46197db96d56Sopenharmony_ci clone = time_new(Py_TYPE(self), tuple, NULL); 46207db96d56Sopenharmony_ci if (clone != NULL) { 46217db96d56Sopenharmony_ci TIME_SET_FOLD(clone, fold); 46227db96d56Sopenharmony_ci } 46237db96d56Sopenharmony_ci Py_DECREF(tuple); 46247db96d56Sopenharmony_ci return clone; 46257db96d56Sopenharmony_ci} 46267db96d56Sopenharmony_ci 46277db96d56Sopenharmony_cistatic PyObject * 46287db96d56Sopenharmony_citime_fromisoformat(PyObject *cls, PyObject *tstr) { 46297db96d56Sopenharmony_ci assert(tstr != NULL); 46307db96d56Sopenharmony_ci 46317db96d56Sopenharmony_ci if (!PyUnicode_Check(tstr)) { 46327db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, "fromisoformat: argument must be str"); 46337db96d56Sopenharmony_ci return NULL; 46347db96d56Sopenharmony_ci } 46357db96d56Sopenharmony_ci 46367db96d56Sopenharmony_ci Py_ssize_t len; 46377db96d56Sopenharmony_ci const char *p = PyUnicode_AsUTF8AndSize(tstr, &len); 46387db96d56Sopenharmony_ci 46397db96d56Sopenharmony_ci if (p == NULL) { 46407db96d56Sopenharmony_ci goto invalid_string_error; 46417db96d56Sopenharmony_ci } 46427db96d56Sopenharmony_ci 46437db96d56Sopenharmony_ci // The spec actually requires that time-only ISO 8601 strings start with 46447db96d56Sopenharmony_ci // T, but the extended format allows this to be omitted as long as there 46457db96d56Sopenharmony_ci // is no ambiguity with date strings. 46467db96d56Sopenharmony_ci if (*p == 'T') { 46477db96d56Sopenharmony_ci ++p; 46487db96d56Sopenharmony_ci len -= 1; 46497db96d56Sopenharmony_ci } 46507db96d56Sopenharmony_ci 46517db96d56Sopenharmony_ci int hour = 0, minute = 0, second = 0, microsecond = 0; 46527db96d56Sopenharmony_ci int tzoffset, tzimicrosecond = 0; 46537db96d56Sopenharmony_ci int rv = parse_isoformat_time(p, len, 46547db96d56Sopenharmony_ci &hour, &minute, &second, µsecond, 46557db96d56Sopenharmony_ci &tzoffset, &tzimicrosecond); 46567db96d56Sopenharmony_ci 46577db96d56Sopenharmony_ci if (rv < 0) { 46587db96d56Sopenharmony_ci goto invalid_string_error; 46597db96d56Sopenharmony_ci } 46607db96d56Sopenharmony_ci 46617db96d56Sopenharmony_ci PyObject *tzinfo = tzinfo_from_isoformat_results(rv, tzoffset, 46627db96d56Sopenharmony_ci tzimicrosecond); 46637db96d56Sopenharmony_ci 46647db96d56Sopenharmony_ci if (tzinfo == NULL) { 46657db96d56Sopenharmony_ci return NULL; 46667db96d56Sopenharmony_ci } 46677db96d56Sopenharmony_ci 46687db96d56Sopenharmony_ci PyObject *t; 46697db96d56Sopenharmony_ci if ( (PyTypeObject *)cls == &PyDateTime_TimeType ) { 46707db96d56Sopenharmony_ci t = new_time(hour, minute, second, microsecond, tzinfo, 0); 46717db96d56Sopenharmony_ci } else { 46727db96d56Sopenharmony_ci t = PyObject_CallFunction(cls, "iiiiO", 46737db96d56Sopenharmony_ci hour, minute, second, microsecond, tzinfo); 46747db96d56Sopenharmony_ci } 46757db96d56Sopenharmony_ci 46767db96d56Sopenharmony_ci Py_DECREF(tzinfo); 46777db96d56Sopenharmony_ci return t; 46787db96d56Sopenharmony_ci 46797db96d56Sopenharmony_ciinvalid_string_error: 46807db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %R", tstr); 46817db96d56Sopenharmony_ci return NULL; 46827db96d56Sopenharmony_ci} 46837db96d56Sopenharmony_ci 46847db96d56Sopenharmony_ci 46857db96d56Sopenharmony_ci/* Pickle support, a simple use of __reduce__. */ 46867db96d56Sopenharmony_ci 46877db96d56Sopenharmony_ci/* Let basestate be the non-tzinfo data string. 46887db96d56Sopenharmony_ci * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo). 46897db96d56Sopenharmony_ci * So it's a tuple in any (non-error) case. 46907db96d56Sopenharmony_ci * __getstate__ isn't exposed. 46917db96d56Sopenharmony_ci */ 46927db96d56Sopenharmony_cistatic PyObject * 46937db96d56Sopenharmony_citime_getstate(PyDateTime_Time *self, int proto) 46947db96d56Sopenharmony_ci{ 46957db96d56Sopenharmony_ci PyObject *basestate; 46967db96d56Sopenharmony_ci PyObject *result = NULL; 46977db96d56Sopenharmony_ci 46987db96d56Sopenharmony_ci basestate = PyBytes_FromStringAndSize((char *)self->data, 46997db96d56Sopenharmony_ci _PyDateTime_TIME_DATASIZE); 47007db96d56Sopenharmony_ci if (basestate != NULL) { 47017db96d56Sopenharmony_ci if (proto > 3 && TIME_GET_FOLD(self)) 47027db96d56Sopenharmony_ci /* Set the first bit of the first byte */ 47037db96d56Sopenharmony_ci PyBytes_AS_STRING(basestate)[0] |= (1 << 7); 47047db96d56Sopenharmony_ci if (! HASTZINFO(self) || self->tzinfo == Py_None) 47057db96d56Sopenharmony_ci result = PyTuple_Pack(1, basestate); 47067db96d56Sopenharmony_ci else 47077db96d56Sopenharmony_ci result = PyTuple_Pack(2, basestate, self->tzinfo); 47087db96d56Sopenharmony_ci Py_DECREF(basestate); 47097db96d56Sopenharmony_ci } 47107db96d56Sopenharmony_ci return result; 47117db96d56Sopenharmony_ci} 47127db96d56Sopenharmony_ci 47137db96d56Sopenharmony_cistatic PyObject * 47147db96d56Sopenharmony_citime_reduce_ex(PyDateTime_Time *self, PyObject *args) 47157db96d56Sopenharmony_ci{ 47167db96d56Sopenharmony_ci int proto; 47177db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "i:__reduce_ex__", &proto)) 47187db96d56Sopenharmony_ci return NULL; 47197db96d56Sopenharmony_ci 47207db96d56Sopenharmony_ci return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self, proto)); 47217db96d56Sopenharmony_ci} 47227db96d56Sopenharmony_ci 47237db96d56Sopenharmony_cistatic PyObject * 47247db96d56Sopenharmony_citime_reduce(PyDateTime_Time *self, PyObject *arg) 47257db96d56Sopenharmony_ci{ 47267db96d56Sopenharmony_ci return Py_BuildValue("(ON)", Py_TYPE(self), time_getstate(self, 2)); 47277db96d56Sopenharmony_ci} 47287db96d56Sopenharmony_ci 47297db96d56Sopenharmony_cistatic PyMethodDef time_methods[] = { 47307db96d56Sopenharmony_ci 47317db96d56Sopenharmony_ci {"isoformat", _PyCFunction_CAST(time_isoformat), METH_VARARGS | METH_KEYWORDS, 47327db96d56Sopenharmony_ci PyDoc_STR("Return string in ISO 8601 format, [HH[:MM[:SS[.mmm[uuu]]]]]" 47337db96d56Sopenharmony_ci "[+HH:MM].\n\n" 47347db96d56Sopenharmony_ci "The optional argument timespec specifies the number " 47357db96d56Sopenharmony_ci "of additional terms\nof the time to include. Valid " 47367db96d56Sopenharmony_ci "options are 'auto', 'hours', 'minutes',\n'seconds', " 47377db96d56Sopenharmony_ci "'milliseconds' and 'microseconds'.\n")}, 47387db96d56Sopenharmony_ci 47397db96d56Sopenharmony_ci {"strftime", _PyCFunction_CAST(time_strftime), METH_VARARGS | METH_KEYWORDS, 47407db96d56Sopenharmony_ci PyDoc_STR("format -> strftime() style string.")}, 47417db96d56Sopenharmony_ci 47427db96d56Sopenharmony_ci {"__format__", (PyCFunction)date_format, METH_VARARGS, 47437db96d56Sopenharmony_ci PyDoc_STR("Formats self with strftime.")}, 47447db96d56Sopenharmony_ci 47457db96d56Sopenharmony_ci {"utcoffset", (PyCFunction)time_utcoffset, METH_NOARGS, 47467db96d56Sopenharmony_ci PyDoc_STR("Return self.tzinfo.utcoffset(self).")}, 47477db96d56Sopenharmony_ci 47487db96d56Sopenharmony_ci {"tzname", (PyCFunction)time_tzname, METH_NOARGS, 47497db96d56Sopenharmony_ci PyDoc_STR("Return self.tzinfo.tzname(self).")}, 47507db96d56Sopenharmony_ci 47517db96d56Sopenharmony_ci {"dst", (PyCFunction)time_dst, METH_NOARGS, 47527db96d56Sopenharmony_ci PyDoc_STR("Return self.tzinfo.dst(self).")}, 47537db96d56Sopenharmony_ci 47547db96d56Sopenharmony_ci {"replace", _PyCFunction_CAST(time_replace), METH_VARARGS | METH_KEYWORDS, 47557db96d56Sopenharmony_ci PyDoc_STR("Return time with new specified fields.")}, 47567db96d56Sopenharmony_ci 47577db96d56Sopenharmony_ci {"fromisoformat", (PyCFunction)time_fromisoformat, METH_O | METH_CLASS, 47587db96d56Sopenharmony_ci PyDoc_STR("string -> time from a string in ISO 8601 format")}, 47597db96d56Sopenharmony_ci 47607db96d56Sopenharmony_ci {"__reduce_ex__", (PyCFunction)time_reduce_ex, METH_VARARGS, 47617db96d56Sopenharmony_ci PyDoc_STR("__reduce_ex__(proto) -> (cls, state)")}, 47627db96d56Sopenharmony_ci 47637db96d56Sopenharmony_ci {"__reduce__", (PyCFunction)time_reduce, METH_NOARGS, 47647db96d56Sopenharmony_ci PyDoc_STR("__reduce__() -> (cls, state)")}, 47657db96d56Sopenharmony_ci 47667db96d56Sopenharmony_ci {NULL, NULL} 47677db96d56Sopenharmony_ci}; 47687db96d56Sopenharmony_ci 47697db96d56Sopenharmony_cistatic const char time_doc[] = 47707db96d56Sopenharmony_ciPyDoc_STR("time([hour[, minute[, second[, microsecond[, tzinfo]]]]]) --> a time object\n\ 47717db96d56Sopenharmony_ci\n\ 47727db96d56Sopenharmony_ciAll arguments are optional. tzinfo may be None, or an instance of\n\ 47737db96d56Sopenharmony_cia tzinfo subclass. The remaining arguments may be ints.\n"); 47747db96d56Sopenharmony_ci 47757db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_TimeType = { 47767db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 47777db96d56Sopenharmony_ci "datetime.time", /* tp_name */ 47787db96d56Sopenharmony_ci sizeof(PyDateTime_Time), /* tp_basicsize */ 47797db96d56Sopenharmony_ci 0, /* tp_itemsize */ 47807db96d56Sopenharmony_ci (destructor)time_dealloc, /* tp_dealloc */ 47817db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 47827db96d56Sopenharmony_ci 0, /* tp_getattr */ 47837db96d56Sopenharmony_ci 0, /* tp_setattr */ 47847db96d56Sopenharmony_ci 0, /* tp_as_async */ 47857db96d56Sopenharmony_ci (reprfunc)time_repr, /* tp_repr */ 47867db96d56Sopenharmony_ci 0, /* tp_as_number */ 47877db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 47887db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 47897db96d56Sopenharmony_ci (hashfunc)time_hash, /* tp_hash */ 47907db96d56Sopenharmony_ci 0, /* tp_call */ 47917db96d56Sopenharmony_ci (reprfunc)time_str, /* tp_str */ 47927db96d56Sopenharmony_ci PyObject_GenericGetAttr, /* tp_getattro */ 47937db96d56Sopenharmony_ci 0, /* tp_setattro */ 47947db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 47957db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 47967db96d56Sopenharmony_ci time_doc, /* tp_doc */ 47977db96d56Sopenharmony_ci 0, /* tp_traverse */ 47987db96d56Sopenharmony_ci 0, /* tp_clear */ 47997db96d56Sopenharmony_ci time_richcompare, /* tp_richcompare */ 48007db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 48017db96d56Sopenharmony_ci 0, /* tp_iter */ 48027db96d56Sopenharmony_ci 0, /* tp_iternext */ 48037db96d56Sopenharmony_ci time_methods, /* tp_methods */ 48047db96d56Sopenharmony_ci 0, /* tp_members */ 48057db96d56Sopenharmony_ci time_getset, /* tp_getset */ 48067db96d56Sopenharmony_ci 0, /* tp_base */ 48077db96d56Sopenharmony_ci 0, /* tp_dict */ 48087db96d56Sopenharmony_ci 0, /* tp_descr_get */ 48097db96d56Sopenharmony_ci 0, /* tp_descr_set */ 48107db96d56Sopenharmony_ci 0, /* tp_dictoffset */ 48117db96d56Sopenharmony_ci 0, /* tp_init */ 48127db96d56Sopenharmony_ci time_alloc, /* tp_alloc */ 48137db96d56Sopenharmony_ci time_new, /* tp_new */ 48147db96d56Sopenharmony_ci 0, /* tp_free */ 48157db96d56Sopenharmony_ci}; 48167db96d56Sopenharmony_ci 48177db96d56Sopenharmony_ci/* 48187db96d56Sopenharmony_ci * PyDateTime_DateTime implementation. 48197db96d56Sopenharmony_ci */ 48207db96d56Sopenharmony_ci 48217db96d56Sopenharmony_ci/* Accessor properties. Properties for day, month, and year are inherited 48227db96d56Sopenharmony_ci * from date. 48237db96d56Sopenharmony_ci */ 48247db96d56Sopenharmony_ci 48257db96d56Sopenharmony_cistatic PyObject * 48267db96d56Sopenharmony_cidatetime_hour(PyDateTime_DateTime *self, void *unused) 48277db96d56Sopenharmony_ci{ 48287db96d56Sopenharmony_ci return PyLong_FromLong(DATE_GET_HOUR(self)); 48297db96d56Sopenharmony_ci} 48307db96d56Sopenharmony_ci 48317db96d56Sopenharmony_cistatic PyObject * 48327db96d56Sopenharmony_cidatetime_minute(PyDateTime_DateTime *self, void *unused) 48337db96d56Sopenharmony_ci{ 48347db96d56Sopenharmony_ci return PyLong_FromLong(DATE_GET_MINUTE(self)); 48357db96d56Sopenharmony_ci} 48367db96d56Sopenharmony_ci 48377db96d56Sopenharmony_cistatic PyObject * 48387db96d56Sopenharmony_cidatetime_second(PyDateTime_DateTime *self, void *unused) 48397db96d56Sopenharmony_ci{ 48407db96d56Sopenharmony_ci return PyLong_FromLong(DATE_GET_SECOND(self)); 48417db96d56Sopenharmony_ci} 48427db96d56Sopenharmony_ci 48437db96d56Sopenharmony_cistatic PyObject * 48447db96d56Sopenharmony_cidatetime_microsecond(PyDateTime_DateTime *self, void *unused) 48457db96d56Sopenharmony_ci{ 48467db96d56Sopenharmony_ci return PyLong_FromLong(DATE_GET_MICROSECOND(self)); 48477db96d56Sopenharmony_ci} 48487db96d56Sopenharmony_ci 48497db96d56Sopenharmony_cistatic PyObject * 48507db96d56Sopenharmony_cidatetime_tzinfo(PyDateTime_DateTime *self, void *unused) 48517db96d56Sopenharmony_ci{ 48527db96d56Sopenharmony_ci PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None; 48537db96d56Sopenharmony_ci Py_INCREF(result); 48547db96d56Sopenharmony_ci return result; 48557db96d56Sopenharmony_ci} 48567db96d56Sopenharmony_ci 48577db96d56Sopenharmony_cistatic PyObject * 48587db96d56Sopenharmony_cidatetime_fold(PyDateTime_DateTime *self, void *unused) 48597db96d56Sopenharmony_ci{ 48607db96d56Sopenharmony_ci return PyLong_FromLong(DATE_GET_FOLD(self)); 48617db96d56Sopenharmony_ci} 48627db96d56Sopenharmony_ci 48637db96d56Sopenharmony_cistatic PyGetSetDef datetime_getset[] = { 48647db96d56Sopenharmony_ci {"hour", (getter)datetime_hour}, 48657db96d56Sopenharmony_ci {"minute", (getter)datetime_minute}, 48667db96d56Sopenharmony_ci {"second", (getter)datetime_second}, 48677db96d56Sopenharmony_ci {"microsecond", (getter)datetime_microsecond}, 48687db96d56Sopenharmony_ci {"tzinfo", (getter)datetime_tzinfo}, 48697db96d56Sopenharmony_ci {"fold", (getter)datetime_fold}, 48707db96d56Sopenharmony_ci {NULL} 48717db96d56Sopenharmony_ci}; 48727db96d56Sopenharmony_ci 48737db96d56Sopenharmony_ci/* 48747db96d56Sopenharmony_ci * Constructors. 48757db96d56Sopenharmony_ci */ 48767db96d56Sopenharmony_ci 48777db96d56Sopenharmony_cistatic char *datetime_kws[] = { 48787db96d56Sopenharmony_ci "year", "month", "day", "hour", "minute", "second", 48797db96d56Sopenharmony_ci "microsecond", "tzinfo", "fold", NULL 48807db96d56Sopenharmony_ci}; 48817db96d56Sopenharmony_ci 48827db96d56Sopenharmony_cistatic PyObject * 48837db96d56Sopenharmony_cidatetime_from_pickle(PyTypeObject *type, PyObject *state, PyObject *tzinfo) 48847db96d56Sopenharmony_ci{ 48857db96d56Sopenharmony_ci PyDateTime_DateTime *me; 48867db96d56Sopenharmony_ci char aware = (char)(tzinfo != Py_None); 48877db96d56Sopenharmony_ci 48887db96d56Sopenharmony_ci if (aware && check_tzinfo_subclass(tzinfo) < 0) { 48897db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, "bad tzinfo state arg"); 48907db96d56Sopenharmony_ci return NULL; 48917db96d56Sopenharmony_ci } 48927db96d56Sopenharmony_ci 48937db96d56Sopenharmony_ci me = (PyDateTime_DateTime *) (type->tp_alloc(type , aware)); 48947db96d56Sopenharmony_ci if (me != NULL) { 48957db96d56Sopenharmony_ci const char *pdata = PyBytes_AS_STRING(state); 48967db96d56Sopenharmony_ci 48977db96d56Sopenharmony_ci memcpy(me->data, pdata, _PyDateTime_DATETIME_DATASIZE); 48987db96d56Sopenharmony_ci me->hashcode = -1; 48997db96d56Sopenharmony_ci me->hastzinfo = aware; 49007db96d56Sopenharmony_ci if (aware) { 49017db96d56Sopenharmony_ci Py_INCREF(tzinfo); 49027db96d56Sopenharmony_ci me->tzinfo = tzinfo; 49037db96d56Sopenharmony_ci } 49047db96d56Sopenharmony_ci if (pdata[2] & (1 << 7)) { 49057db96d56Sopenharmony_ci me->data[2] -= 128; 49067db96d56Sopenharmony_ci me->fold = 1; 49077db96d56Sopenharmony_ci } 49087db96d56Sopenharmony_ci else { 49097db96d56Sopenharmony_ci me->fold = 0; 49107db96d56Sopenharmony_ci } 49117db96d56Sopenharmony_ci } 49127db96d56Sopenharmony_ci return (PyObject *)me; 49137db96d56Sopenharmony_ci} 49147db96d56Sopenharmony_ci 49157db96d56Sopenharmony_cistatic PyObject * 49167db96d56Sopenharmony_cidatetime_new(PyTypeObject *type, PyObject *args, PyObject *kw) 49177db96d56Sopenharmony_ci{ 49187db96d56Sopenharmony_ci PyObject *self = NULL; 49197db96d56Sopenharmony_ci int year; 49207db96d56Sopenharmony_ci int month; 49217db96d56Sopenharmony_ci int day; 49227db96d56Sopenharmony_ci int hour = 0; 49237db96d56Sopenharmony_ci int minute = 0; 49247db96d56Sopenharmony_ci int second = 0; 49257db96d56Sopenharmony_ci int usecond = 0; 49267db96d56Sopenharmony_ci int fold = 0; 49277db96d56Sopenharmony_ci PyObject *tzinfo = Py_None; 49287db96d56Sopenharmony_ci 49297db96d56Sopenharmony_ci /* Check for invocation from pickle with __getstate__ state */ 49307db96d56Sopenharmony_ci if (PyTuple_GET_SIZE(args) >= 1 && PyTuple_GET_SIZE(args) <= 2) { 49317db96d56Sopenharmony_ci PyObject *state = PyTuple_GET_ITEM(args, 0); 49327db96d56Sopenharmony_ci if (PyTuple_GET_SIZE(args) == 2) { 49337db96d56Sopenharmony_ci tzinfo = PyTuple_GET_ITEM(args, 1); 49347db96d56Sopenharmony_ci } 49357db96d56Sopenharmony_ci if (PyBytes_Check(state)) { 49367db96d56Sopenharmony_ci if (PyBytes_GET_SIZE(state) == _PyDateTime_DATETIME_DATASIZE && 49377db96d56Sopenharmony_ci MONTH_IS_SANE(PyBytes_AS_STRING(state)[2] & 0x7F)) 49387db96d56Sopenharmony_ci { 49397db96d56Sopenharmony_ci return datetime_from_pickle(type, state, tzinfo); 49407db96d56Sopenharmony_ci } 49417db96d56Sopenharmony_ci } 49427db96d56Sopenharmony_ci else if (PyUnicode_Check(state)) { 49437db96d56Sopenharmony_ci if (PyUnicode_READY(state)) { 49447db96d56Sopenharmony_ci return NULL; 49457db96d56Sopenharmony_ci } 49467db96d56Sopenharmony_ci if (PyUnicode_GET_LENGTH(state) == _PyDateTime_DATETIME_DATASIZE && 49477db96d56Sopenharmony_ci MONTH_IS_SANE(PyUnicode_READ_CHAR(state, 2) & 0x7F)) 49487db96d56Sopenharmony_ci { 49497db96d56Sopenharmony_ci state = PyUnicode_AsLatin1String(state); 49507db96d56Sopenharmony_ci if (state == NULL) { 49517db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) { 49527db96d56Sopenharmony_ci /* More informative error message. */ 49537db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 49547db96d56Sopenharmony_ci "Failed to encode latin1 string when unpickling " 49557db96d56Sopenharmony_ci "a datetime object. " 49567db96d56Sopenharmony_ci "pickle.load(data, encoding='latin1') is assumed."); 49577db96d56Sopenharmony_ci } 49587db96d56Sopenharmony_ci return NULL; 49597db96d56Sopenharmony_ci } 49607db96d56Sopenharmony_ci self = datetime_from_pickle(type, state, tzinfo); 49617db96d56Sopenharmony_ci Py_DECREF(state); 49627db96d56Sopenharmony_ci return self; 49637db96d56Sopenharmony_ci } 49647db96d56Sopenharmony_ci } 49657db96d56Sopenharmony_ci tzinfo = Py_None; 49667db96d56Sopenharmony_ci } 49677db96d56Sopenharmony_ci 49687db96d56Sopenharmony_ci if (PyArg_ParseTupleAndKeywords(args, kw, "iii|iiiiO$i", datetime_kws, 49697db96d56Sopenharmony_ci &year, &month, &day, &hour, &minute, 49707db96d56Sopenharmony_ci &second, &usecond, &tzinfo, &fold)) { 49717db96d56Sopenharmony_ci self = new_datetime_ex2(year, month, day, 49727db96d56Sopenharmony_ci hour, minute, second, usecond, 49737db96d56Sopenharmony_ci tzinfo, fold, type); 49747db96d56Sopenharmony_ci } 49757db96d56Sopenharmony_ci return self; 49767db96d56Sopenharmony_ci} 49777db96d56Sopenharmony_ci 49787db96d56Sopenharmony_ci/* TM_FUNC is the shared type of _PyTime_localtime() and 49797db96d56Sopenharmony_ci * _PyTime_gmtime(). */ 49807db96d56Sopenharmony_citypedef int (*TM_FUNC)(time_t timer, struct tm*); 49817db96d56Sopenharmony_ci 49827db96d56Sopenharmony_ci/* As of version 2015f max fold in IANA database is 49837db96d56Sopenharmony_ci * 23 hours at 1969-09-30 13:00:00 in Kwajalein. */ 49847db96d56Sopenharmony_cistatic long long max_fold_seconds = 24 * 3600; 49857db96d56Sopenharmony_ci/* NB: date(1970,1,1).toordinal() == 719163 */ 49867db96d56Sopenharmony_cistatic long long epoch = 719163LL * 24 * 60 * 60; 49877db96d56Sopenharmony_ci 49887db96d56Sopenharmony_cistatic long long 49897db96d56Sopenharmony_ciutc_to_seconds(int year, int month, int day, 49907db96d56Sopenharmony_ci int hour, int minute, int second) 49917db96d56Sopenharmony_ci{ 49927db96d56Sopenharmony_ci long long ordinal; 49937db96d56Sopenharmony_ci 49947db96d56Sopenharmony_ci /* ymd_to_ord() doesn't support year <= 0 */ 49957db96d56Sopenharmony_ci if (year < MINYEAR || year > MAXYEAR) { 49967db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "year %i is out of range", year); 49977db96d56Sopenharmony_ci return -1; 49987db96d56Sopenharmony_ci } 49997db96d56Sopenharmony_ci 50007db96d56Sopenharmony_ci ordinal = ymd_to_ord(year, month, day); 50017db96d56Sopenharmony_ci return ((ordinal * 24 + hour) * 60 + minute) * 60 + second; 50027db96d56Sopenharmony_ci} 50037db96d56Sopenharmony_ci 50047db96d56Sopenharmony_cistatic long long 50057db96d56Sopenharmony_cilocal(long long u) 50067db96d56Sopenharmony_ci{ 50077db96d56Sopenharmony_ci struct tm local_time; 50087db96d56Sopenharmony_ci time_t t; 50097db96d56Sopenharmony_ci u -= epoch; 50107db96d56Sopenharmony_ci t = u; 50117db96d56Sopenharmony_ci if (t != u) { 50127db96d56Sopenharmony_ci PyErr_SetString(PyExc_OverflowError, 50137db96d56Sopenharmony_ci "timestamp out of range for platform time_t"); 50147db96d56Sopenharmony_ci return -1; 50157db96d56Sopenharmony_ci } 50167db96d56Sopenharmony_ci if (_PyTime_localtime(t, &local_time) != 0) 50177db96d56Sopenharmony_ci return -1; 50187db96d56Sopenharmony_ci return utc_to_seconds(local_time.tm_year + 1900, 50197db96d56Sopenharmony_ci local_time.tm_mon + 1, 50207db96d56Sopenharmony_ci local_time.tm_mday, 50217db96d56Sopenharmony_ci local_time.tm_hour, 50227db96d56Sopenharmony_ci local_time.tm_min, 50237db96d56Sopenharmony_ci local_time.tm_sec); 50247db96d56Sopenharmony_ci} 50257db96d56Sopenharmony_ci 50267db96d56Sopenharmony_ci/* Internal helper. 50277db96d56Sopenharmony_ci * Build datetime from a time_t and a distinct count of microseconds. 50287db96d56Sopenharmony_ci * Pass localtime or gmtime for f, to control the interpretation of timet. 50297db96d56Sopenharmony_ci */ 50307db96d56Sopenharmony_cistatic PyObject * 50317db96d56Sopenharmony_cidatetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us, 50327db96d56Sopenharmony_ci PyObject *tzinfo) 50337db96d56Sopenharmony_ci{ 50347db96d56Sopenharmony_ci struct tm tm; 50357db96d56Sopenharmony_ci int year, month, day, hour, minute, second, fold = 0; 50367db96d56Sopenharmony_ci 50377db96d56Sopenharmony_ci if (f(timet, &tm) != 0) 50387db96d56Sopenharmony_ci return NULL; 50397db96d56Sopenharmony_ci 50407db96d56Sopenharmony_ci year = tm.tm_year + 1900; 50417db96d56Sopenharmony_ci month = tm.tm_mon + 1; 50427db96d56Sopenharmony_ci day = tm.tm_mday; 50437db96d56Sopenharmony_ci hour = tm.tm_hour; 50447db96d56Sopenharmony_ci minute = tm.tm_min; 50457db96d56Sopenharmony_ci /* The platform localtime/gmtime may insert leap seconds, 50467db96d56Sopenharmony_ci * indicated by tm.tm_sec > 59. We don't care about them, 50477db96d56Sopenharmony_ci * except to the extent that passing them on to the datetime 50487db96d56Sopenharmony_ci * constructor would raise ValueError for a reason that 50497db96d56Sopenharmony_ci * made no sense to the user. 50507db96d56Sopenharmony_ci */ 50517db96d56Sopenharmony_ci second = Py_MIN(59, tm.tm_sec); 50527db96d56Sopenharmony_ci 50537db96d56Sopenharmony_ci /* local timezone requires to compute fold */ 50547db96d56Sopenharmony_ci if (tzinfo == Py_None && f == _PyTime_localtime 50557db96d56Sopenharmony_ci /* On Windows, passing a negative value to local results 50567db96d56Sopenharmony_ci * in an OSError because localtime_s on Windows does 50577db96d56Sopenharmony_ci * not support negative timestamps. Unfortunately this 50587db96d56Sopenharmony_ci * means that fold detection for time values between 50597db96d56Sopenharmony_ci * 0 and max_fold_seconds will result in an identical 50607db96d56Sopenharmony_ci * error since we subtract max_fold_seconds to detect a 50617db96d56Sopenharmony_ci * fold. However, since we know there haven't been any 50627db96d56Sopenharmony_ci * folds in the interval [0, max_fold_seconds) in any 50637db96d56Sopenharmony_ci * timezone, we can hackily just forego fold detection 50647db96d56Sopenharmony_ci * for this time range. 50657db96d56Sopenharmony_ci */ 50667db96d56Sopenharmony_ci#ifdef MS_WINDOWS 50677db96d56Sopenharmony_ci && (timet - max_fold_seconds > 0) 50687db96d56Sopenharmony_ci#endif 50697db96d56Sopenharmony_ci ) { 50707db96d56Sopenharmony_ci long long probe_seconds, result_seconds, transition; 50717db96d56Sopenharmony_ci 50727db96d56Sopenharmony_ci result_seconds = utc_to_seconds(year, month, day, 50737db96d56Sopenharmony_ci hour, minute, second); 50747db96d56Sopenharmony_ci if (result_seconds == -1 && PyErr_Occurred()) { 50757db96d56Sopenharmony_ci return NULL; 50767db96d56Sopenharmony_ci } 50777db96d56Sopenharmony_ci 50787db96d56Sopenharmony_ci /* Probe max_fold_seconds to detect a fold. */ 50797db96d56Sopenharmony_ci probe_seconds = local(epoch + timet - max_fold_seconds); 50807db96d56Sopenharmony_ci if (probe_seconds == -1) 50817db96d56Sopenharmony_ci return NULL; 50827db96d56Sopenharmony_ci transition = result_seconds - probe_seconds - max_fold_seconds; 50837db96d56Sopenharmony_ci if (transition < 0) { 50847db96d56Sopenharmony_ci probe_seconds = local(epoch + timet + transition); 50857db96d56Sopenharmony_ci if (probe_seconds == -1) 50867db96d56Sopenharmony_ci return NULL; 50877db96d56Sopenharmony_ci if (probe_seconds == result_seconds) 50887db96d56Sopenharmony_ci fold = 1; 50897db96d56Sopenharmony_ci } 50907db96d56Sopenharmony_ci } 50917db96d56Sopenharmony_ci return new_datetime_subclass_fold_ex(year, month, day, hour, minute, 50927db96d56Sopenharmony_ci second, us, tzinfo, fold, cls); 50937db96d56Sopenharmony_ci} 50947db96d56Sopenharmony_ci 50957db96d56Sopenharmony_ci/* Internal helper. 50967db96d56Sopenharmony_ci * Build datetime from a Python timestamp. Pass localtime or gmtime for f, 50977db96d56Sopenharmony_ci * to control the interpretation of the timestamp. Since a double doesn't 50987db96d56Sopenharmony_ci * have enough bits to cover a datetime's full range of precision, it's 50997db96d56Sopenharmony_ci * better to call datetime_from_timet_and_us provided you have a way 51007db96d56Sopenharmony_ci * to get that much precision (e.g., C time() isn't good enough). 51017db96d56Sopenharmony_ci */ 51027db96d56Sopenharmony_cistatic PyObject * 51037db96d56Sopenharmony_cidatetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp, 51047db96d56Sopenharmony_ci PyObject *tzinfo) 51057db96d56Sopenharmony_ci{ 51067db96d56Sopenharmony_ci time_t timet; 51077db96d56Sopenharmony_ci long us; 51087db96d56Sopenharmony_ci 51097db96d56Sopenharmony_ci if (_PyTime_ObjectToTimeval(timestamp, 51107db96d56Sopenharmony_ci &timet, &us, _PyTime_ROUND_HALF_EVEN) == -1) 51117db96d56Sopenharmony_ci return NULL; 51127db96d56Sopenharmony_ci 51137db96d56Sopenharmony_ci return datetime_from_timet_and_us(cls, f, timet, (int)us, tzinfo); 51147db96d56Sopenharmony_ci} 51157db96d56Sopenharmony_ci 51167db96d56Sopenharmony_ci/* Internal helper. 51177db96d56Sopenharmony_ci * Build most accurate possible datetime for current time. Pass localtime or 51187db96d56Sopenharmony_ci * gmtime for f as appropriate. 51197db96d56Sopenharmony_ci */ 51207db96d56Sopenharmony_cistatic PyObject * 51217db96d56Sopenharmony_cidatetime_best_possible(PyObject *cls, TM_FUNC f, PyObject *tzinfo) 51227db96d56Sopenharmony_ci{ 51237db96d56Sopenharmony_ci _PyTime_t ts = _PyTime_GetSystemClock(); 51247db96d56Sopenharmony_ci time_t secs; 51257db96d56Sopenharmony_ci int us; 51267db96d56Sopenharmony_ci 51277db96d56Sopenharmony_ci if (_PyTime_AsTimevalTime_t(ts, &secs, &us, _PyTime_ROUND_FLOOR) < 0) 51287db96d56Sopenharmony_ci return NULL; 51297db96d56Sopenharmony_ci assert(0 <= us && us <= 999999); 51307db96d56Sopenharmony_ci 51317db96d56Sopenharmony_ci return datetime_from_timet_and_us(cls, f, secs, us, tzinfo); 51327db96d56Sopenharmony_ci} 51337db96d56Sopenharmony_ci 51347db96d56Sopenharmony_ci/*[clinic input] 51357db96d56Sopenharmony_ci 51367db96d56Sopenharmony_ci@classmethod 51377db96d56Sopenharmony_cidatetime.datetime.now 51387db96d56Sopenharmony_ci 51397db96d56Sopenharmony_ci tz: object = None 51407db96d56Sopenharmony_ci Timezone object. 51417db96d56Sopenharmony_ci 51427db96d56Sopenharmony_ciReturns new datetime object representing current time local to tz. 51437db96d56Sopenharmony_ci 51447db96d56Sopenharmony_ciIf no tz is specified, uses local timezone. 51457db96d56Sopenharmony_ci[clinic start generated code]*/ 51467db96d56Sopenharmony_ci 51477db96d56Sopenharmony_cistatic PyObject * 51487db96d56Sopenharmony_cidatetime_datetime_now_impl(PyTypeObject *type, PyObject *tz) 51497db96d56Sopenharmony_ci/*[clinic end generated code: output=b3386e5345e2b47a input=80d09869c5267d00]*/ 51507db96d56Sopenharmony_ci{ 51517db96d56Sopenharmony_ci PyObject *self; 51527db96d56Sopenharmony_ci 51537db96d56Sopenharmony_ci /* Return best possible local time -- this isn't constrained by the 51547db96d56Sopenharmony_ci * precision of a timestamp. 51557db96d56Sopenharmony_ci */ 51567db96d56Sopenharmony_ci if (check_tzinfo_subclass(tz) < 0) 51577db96d56Sopenharmony_ci return NULL; 51587db96d56Sopenharmony_ci 51597db96d56Sopenharmony_ci self = datetime_best_possible((PyObject *)type, 51607db96d56Sopenharmony_ci tz == Py_None ? _PyTime_localtime : 51617db96d56Sopenharmony_ci _PyTime_gmtime, 51627db96d56Sopenharmony_ci tz); 51637db96d56Sopenharmony_ci if (self != NULL && tz != Py_None) { 51647db96d56Sopenharmony_ci /* Convert UTC to tzinfo's zone. */ 51657db96d56Sopenharmony_ci self = _PyObject_CallMethodId(tz, &PyId_fromutc, "N", self); 51667db96d56Sopenharmony_ci } 51677db96d56Sopenharmony_ci return self; 51687db96d56Sopenharmony_ci} 51697db96d56Sopenharmony_ci 51707db96d56Sopenharmony_ci/* Return best possible UTC time -- this isn't constrained by the 51717db96d56Sopenharmony_ci * precision of a timestamp. 51727db96d56Sopenharmony_ci */ 51737db96d56Sopenharmony_cistatic PyObject * 51747db96d56Sopenharmony_cidatetime_utcnow(PyObject *cls, PyObject *dummy) 51757db96d56Sopenharmony_ci{ 51767db96d56Sopenharmony_ci return datetime_best_possible(cls, _PyTime_gmtime, Py_None); 51777db96d56Sopenharmony_ci} 51787db96d56Sopenharmony_ci 51797db96d56Sopenharmony_ci/* Return new local datetime from timestamp (Python timestamp -- a double). */ 51807db96d56Sopenharmony_cistatic PyObject * 51817db96d56Sopenharmony_cidatetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw) 51827db96d56Sopenharmony_ci{ 51837db96d56Sopenharmony_ci PyObject *self; 51847db96d56Sopenharmony_ci PyObject *timestamp; 51857db96d56Sopenharmony_ci PyObject *tzinfo = Py_None; 51867db96d56Sopenharmony_ci static char *keywords[] = {"timestamp", "tz", NULL}; 51877db96d56Sopenharmony_ci 51887db96d56Sopenharmony_ci if (! PyArg_ParseTupleAndKeywords(args, kw, "O|O:fromtimestamp", 51897db96d56Sopenharmony_ci keywords, ×tamp, &tzinfo)) 51907db96d56Sopenharmony_ci return NULL; 51917db96d56Sopenharmony_ci if (check_tzinfo_subclass(tzinfo) < 0) 51927db96d56Sopenharmony_ci return NULL; 51937db96d56Sopenharmony_ci 51947db96d56Sopenharmony_ci self = datetime_from_timestamp(cls, 51957db96d56Sopenharmony_ci tzinfo == Py_None ? _PyTime_localtime : 51967db96d56Sopenharmony_ci _PyTime_gmtime, 51977db96d56Sopenharmony_ci timestamp, 51987db96d56Sopenharmony_ci tzinfo); 51997db96d56Sopenharmony_ci if (self != NULL && tzinfo != Py_None) { 52007db96d56Sopenharmony_ci /* Convert UTC to tzinfo's zone. */ 52017db96d56Sopenharmony_ci self = _PyObject_CallMethodId(tzinfo, &PyId_fromutc, "N", self); 52027db96d56Sopenharmony_ci } 52037db96d56Sopenharmony_ci return self; 52047db96d56Sopenharmony_ci} 52057db96d56Sopenharmony_ci 52067db96d56Sopenharmony_ci/* Return new UTC datetime from timestamp (Python timestamp -- a double). */ 52077db96d56Sopenharmony_cistatic PyObject * 52087db96d56Sopenharmony_cidatetime_utcfromtimestamp(PyObject *cls, PyObject *args) 52097db96d56Sopenharmony_ci{ 52107db96d56Sopenharmony_ci PyObject *timestamp; 52117db96d56Sopenharmony_ci PyObject *result = NULL; 52127db96d56Sopenharmony_ci 52137db96d56Sopenharmony_ci if (PyArg_ParseTuple(args, "O:utcfromtimestamp", ×tamp)) 52147db96d56Sopenharmony_ci result = datetime_from_timestamp(cls, _PyTime_gmtime, timestamp, 52157db96d56Sopenharmony_ci Py_None); 52167db96d56Sopenharmony_ci return result; 52177db96d56Sopenharmony_ci} 52187db96d56Sopenharmony_ci 52197db96d56Sopenharmony_ci/* Return new datetime from _strptime.strptime_datetime(). */ 52207db96d56Sopenharmony_cistatic PyObject * 52217db96d56Sopenharmony_cidatetime_strptime(PyObject *cls, PyObject *args) 52227db96d56Sopenharmony_ci{ 52237db96d56Sopenharmony_ci static PyObject *module = NULL; 52247db96d56Sopenharmony_ci PyObject *string, *format; 52257db96d56Sopenharmony_ci _Py_IDENTIFIER(_strptime_datetime); 52267db96d56Sopenharmony_ci 52277db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "UU:strptime", &string, &format)) 52287db96d56Sopenharmony_ci return NULL; 52297db96d56Sopenharmony_ci 52307db96d56Sopenharmony_ci if (module == NULL) { 52317db96d56Sopenharmony_ci module = PyImport_ImportModule("_strptime"); 52327db96d56Sopenharmony_ci if (module == NULL) 52337db96d56Sopenharmony_ci return NULL; 52347db96d56Sopenharmony_ci } 52357db96d56Sopenharmony_ci return _PyObject_CallMethodIdObjArgs(module, &PyId__strptime_datetime, 52367db96d56Sopenharmony_ci cls, string, format, NULL); 52377db96d56Sopenharmony_ci} 52387db96d56Sopenharmony_ci 52397db96d56Sopenharmony_ci/* Return new datetime from date/datetime and time arguments. */ 52407db96d56Sopenharmony_cistatic PyObject * 52417db96d56Sopenharmony_cidatetime_combine(PyObject *cls, PyObject *args, PyObject *kw) 52427db96d56Sopenharmony_ci{ 52437db96d56Sopenharmony_ci static char *keywords[] = {"date", "time", "tzinfo", NULL}; 52447db96d56Sopenharmony_ci PyObject *date; 52457db96d56Sopenharmony_ci PyObject *time; 52467db96d56Sopenharmony_ci PyObject *tzinfo = NULL; 52477db96d56Sopenharmony_ci PyObject *result = NULL; 52487db96d56Sopenharmony_ci 52497db96d56Sopenharmony_ci if (PyArg_ParseTupleAndKeywords(args, kw, "O!O!|O:combine", keywords, 52507db96d56Sopenharmony_ci &PyDateTime_DateType, &date, 52517db96d56Sopenharmony_ci &PyDateTime_TimeType, &time, &tzinfo)) { 52527db96d56Sopenharmony_ci if (tzinfo == NULL) { 52537db96d56Sopenharmony_ci if (HASTZINFO(time)) 52547db96d56Sopenharmony_ci tzinfo = ((PyDateTime_Time *)time)->tzinfo; 52557db96d56Sopenharmony_ci else 52567db96d56Sopenharmony_ci tzinfo = Py_None; 52577db96d56Sopenharmony_ci } 52587db96d56Sopenharmony_ci result = new_datetime_subclass_fold_ex(GET_YEAR(date), 52597db96d56Sopenharmony_ci GET_MONTH(date), 52607db96d56Sopenharmony_ci GET_DAY(date), 52617db96d56Sopenharmony_ci TIME_GET_HOUR(time), 52627db96d56Sopenharmony_ci TIME_GET_MINUTE(time), 52637db96d56Sopenharmony_ci TIME_GET_SECOND(time), 52647db96d56Sopenharmony_ci TIME_GET_MICROSECOND(time), 52657db96d56Sopenharmony_ci tzinfo, 52667db96d56Sopenharmony_ci TIME_GET_FOLD(time), 52677db96d56Sopenharmony_ci cls); 52687db96d56Sopenharmony_ci } 52697db96d56Sopenharmony_ci return result; 52707db96d56Sopenharmony_ci} 52717db96d56Sopenharmony_ci 52727db96d56Sopenharmony_cistatic PyObject * 52737db96d56Sopenharmony_ci_sanitize_isoformat_str(PyObject *dtstr) 52747db96d56Sopenharmony_ci{ 52757db96d56Sopenharmony_ci Py_ssize_t len = PyUnicode_GetLength(dtstr); 52767db96d56Sopenharmony_ci if (len < 7) { // All valid ISO 8601 strings are at least 7 characters long 52777db96d56Sopenharmony_ci return NULL; 52787db96d56Sopenharmony_ci } 52797db96d56Sopenharmony_ci 52807db96d56Sopenharmony_ci // `fromisoformat` allows surrogate characters in exactly one position, 52817db96d56Sopenharmony_ci // the separator; to allow datetime_fromisoformat to make the simplifying 52827db96d56Sopenharmony_ci // assumption that all valid strings can be encoded in UTF-8, this function 52837db96d56Sopenharmony_ci // replaces any surrogate character separators with `T`. 52847db96d56Sopenharmony_ci // 52857db96d56Sopenharmony_ci // The result of this, if not NULL, returns a new reference 52867db96d56Sopenharmony_ci const void* const unicode_data = PyUnicode_DATA(dtstr); 52877db96d56Sopenharmony_ci const unsigned int kind = PyUnicode_KIND(dtstr); 52887db96d56Sopenharmony_ci 52897db96d56Sopenharmony_ci // Depending on the format of the string, the separator can only ever be 52907db96d56Sopenharmony_ci // in positions 7, 8 or 10. We'll check each of these for a surrogate and 52917db96d56Sopenharmony_ci // if we find one, replace it with `T`. If there is more than one surrogate, 52927db96d56Sopenharmony_ci // we don't have to bother sanitizing it, because the function will later 52937db96d56Sopenharmony_ci // fail when we try to encode the string as ASCII. 52947db96d56Sopenharmony_ci static const size_t potential_separators[3] = {7, 8, 10}; 52957db96d56Sopenharmony_ci size_t surrogate_separator = 0; 52967db96d56Sopenharmony_ci for(size_t idx = 0; 52977db96d56Sopenharmony_ci idx < sizeof(potential_separators) / sizeof(*potential_separators); 52987db96d56Sopenharmony_ci ++idx) { 52997db96d56Sopenharmony_ci size_t pos = potential_separators[idx]; 53007db96d56Sopenharmony_ci if (pos > (size_t)len) { 53017db96d56Sopenharmony_ci break; 53027db96d56Sopenharmony_ci } 53037db96d56Sopenharmony_ci 53047db96d56Sopenharmony_ci if(Py_UNICODE_IS_SURROGATE(PyUnicode_READ(kind, unicode_data, pos))) { 53057db96d56Sopenharmony_ci surrogate_separator = pos; 53067db96d56Sopenharmony_ci break; 53077db96d56Sopenharmony_ci } 53087db96d56Sopenharmony_ci } 53097db96d56Sopenharmony_ci 53107db96d56Sopenharmony_ci if (surrogate_separator == 0) { 53117db96d56Sopenharmony_ci Py_INCREF(dtstr); 53127db96d56Sopenharmony_ci return dtstr; 53137db96d56Sopenharmony_ci } 53147db96d56Sopenharmony_ci 53157db96d56Sopenharmony_ci PyObject *str_out = _PyUnicode_Copy(dtstr); 53167db96d56Sopenharmony_ci if (str_out == NULL) { 53177db96d56Sopenharmony_ci return NULL; 53187db96d56Sopenharmony_ci } 53197db96d56Sopenharmony_ci 53207db96d56Sopenharmony_ci if (PyUnicode_WriteChar(str_out, surrogate_separator, (Py_UCS4)'T')) { 53217db96d56Sopenharmony_ci Py_DECREF(str_out); 53227db96d56Sopenharmony_ci return NULL; 53237db96d56Sopenharmony_ci } 53247db96d56Sopenharmony_ci 53257db96d56Sopenharmony_ci return str_out; 53267db96d56Sopenharmony_ci} 53277db96d56Sopenharmony_ci 53287db96d56Sopenharmony_ci 53297db96d56Sopenharmony_cistatic Py_ssize_t 53307db96d56Sopenharmony_ci_find_isoformat_datetime_separator(const char *dtstr, Py_ssize_t len) { 53317db96d56Sopenharmony_ci // The valid date formats can all be distinguished by characters 4 and 5 53327db96d56Sopenharmony_ci // and further narrowed down by character 53337db96d56Sopenharmony_ci // which tells us where to look for the separator character. 53347db96d56Sopenharmony_ci // Format | As-rendered | Position 53357db96d56Sopenharmony_ci // --------------------------------------- 53367db96d56Sopenharmony_ci // %Y-%m-%d | YYYY-MM-DD | 10 53377db96d56Sopenharmony_ci // %Y%m%d | YYYYMMDD | 8 53387db96d56Sopenharmony_ci // %Y-W%V | YYYY-Www | 8 53397db96d56Sopenharmony_ci // %YW%V | YYYYWww | 7 53407db96d56Sopenharmony_ci // %Y-W%V-%u | YYYY-Www-d | 10 53417db96d56Sopenharmony_ci // %YW%V%u | YYYYWwwd | 8 53427db96d56Sopenharmony_ci // %Y-%j | YYYY-DDD | 8 53437db96d56Sopenharmony_ci // %Y%j | YYYYDDD | 7 53447db96d56Sopenharmony_ci // 53457db96d56Sopenharmony_ci // Note that because we allow *any* character for the separator, in the 53467db96d56Sopenharmony_ci // case where character 4 is W, it's not straightforward to determine where 53477db96d56Sopenharmony_ci // the separator is — in the case of YYYY-Www-d, you have actual ambiguity, 53487db96d56Sopenharmony_ci // e.g. 2020-W01-0000 could be YYYY-Www-D0HH or YYYY-Www-HHMM, when the 53497db96d56Sopenharmony_ci // separator character is a number in the former case or a hyphen in the 53507db96d56Sopenharmony_ci // latter case. 53517db96d56Sopenharmony_ci // 53527db96d56Sopenharmony_ci // The case of YYYYWww can be distinguished from YYYYWwwd by tracking ahead 53537db96d56Sopenharmony_ci // to either the end of the string or the first non-numeric character — 53547db96d56Sopenharmony_ci // since the time components all come in pairs YYYYWww#HH can be 53557db96d56Sopenharmony_ci // distinguished from YYYYWwwd#HH by the fact that there will always be an 53567db96d56Sopenharmony_ci // odd number of digits before the first non-digit character in the former 53577db96d56Sopenharmony_ci // case. 53587db96d56Sopenharmony_ci static const char date_separator = '-'; 53597db96d56Sopenharmony_ci static const char week_indicator = 'W'; 53607db96d56Sopenharmony_ci 53617db96d56Sopenharmony_ci if (len == 7) { 53627db96d56Sopenharmony_ci return 7; 53637db96d56Sopenharmony_ci } 53647db96d56Sopenharmony_ci 53657db96d56Sopenharmony_ci if (dtstr[4] == date_separator) { 53667db96d56Sopenharmony_ci // YYYY-??? 53677db96d56Sopenharmony_ci 53687db96d56Sopenharmony_ci if (dtstr[5] == week_indicator) { 53697db96d56Sopenharmony_ci // YYYY-W?? 53707db96d56Sopenharmony_ci 53717db96d56Sopenharmony_ci if (len < 8) { 53727db96d56Sopenharmony_ci return -1; 53737db96d56Sopenharmony_ci } 53747db96d56Sopenharmony_ci 53757db96d56Sopenharmony_ci if (len > 8 && dtstr[8] == date_separator) { 53767db96d56Sopenharmony_ci // YYYY-Www-D (10) or YYYY-Www-HH (8) 53777db96d56Sopenharmony_ci if (len == 9) { return -1; } 53787db96d56Sopenharmony_ci if (len > 10 && is_digit(dtstr[10])) { 53797db96d56Sopenharmony_ci // This is as far as we'll try to go to resolve the 53807db96d56Sopenharmony_ci // ambiguity for the moment — if we have YYYY-Www-##, the 53817db96d56Sopenharmony_ci // separator is either a hyphen at 8 or a number at 10. 53827db96d56Sopenharmony_ci // 53837db96d56Sopenharmony_ci // We'll assume it's a hyphen at 8 because it's way more 53847db96d56Sopenharmony_ci // likely that someone will use a hyphen as a separator 53857db96d56Sopenharmony_ci // than a number, but at this point it's really best effort 53867db96d56Sopenharmony_ci // because this is an extension of the spec anyway. 53877db96d56Sopenharmony_ci return 8; 53887db96d56Sopenharmony_ci } 53897db96d56Sopenharmony_ci 53907db96d56Sopenharmony_ci return 10; 53917db96d56Sopenharmony_ci } else { 53927db96d56Sopenharmony_ci // YYYY-Www (8) 53937db96d56Sopenharmony_ci return 8; 53947db96d56Sopenharmony_ci } 53957db96d56Sopenharmony_ci } else { 53967db96d56Sopenharmony_ci // YYYY-MM-DD (10) 53977db96d56Sopenharmony_ci return 10; 53987db96d56Sopenharmony_ci } 53997db96d56Sopenharmony_ci } else { 54007db96d56Sopenharmony_ci // YYYY??? 54017db96d56Sopenharmony_ci if (dtstr[4] == week_indicator) { 54027db96d56Sopenharmony_ci // YYYYWww (7) or YYYYWwwd (8) 54037db96d56Sopenharmony_ci size_t idx = 7; 54047db96d56Sopenharmony_ci for (; idx < (size_t)len; ++idx) { 54057db96d56Sopenharmony_ci // Keep going until we run out of digits. 54067db96d56Sopenharmony_ci if (!is_digit(dtstr[idx])) { 54077db96d56Sopenharmony_ci break; 54087db96d56Sopenharmony_ci } 54097db96d56Sopenharmony_ci } 54107db96d56Sopenharmony_ci 54117db96d56Sopenharmony_ci if (idx < 9) { 54127db96d56Sopenharmony_ci return idx; 54137db96d56Sopenharmony_ci } 54147db96d56Sopenharmony_ci 54157db96d56Sopenharmony_ci if (idx % 2 == 0) { 54167db96d56Sopenharmony_ci // If the index of the last number is even, it's YYYYWww 54177db96d56Sopenharmony_ci return 7; 54187db96d56Sopenharmony_ci } else { 54197db96d56Sopenharmony_ci return 8; 54207db96d56Sopenharmony_ci } 54217db96d56Sopenharmony_ci } else { 54227db96d56Sopenharmony_ci // YYYYMMDD (8) 54237db96d56Sopenharmony_ci return 8; 54247db96d56Sopenharmony_ci } 54257db96d56Sopenharmony_ci } 54267db96d56Sopenharmony_ci} 54277db96d56Sopenharmony_ci 54287db96d56Sopenharmony_cistatic PyObject * 54297db96d56Sopenharmony_cidatetime_fromisoformat(PyObject *cls, PyObject *dtstr) 54307db96d56Sopenharmony_ci{ 54317db96d56Sopenharmony_ci assert(dtstr != NULL); 54327db96d56Sopenharmony_ci 54337db96d56Sopenharmony_ci if (!PyUnicode_Check(dtstr)) { 54347db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 54357db96d56Sopenharmony_ci "fromisoformat: argument must be str"); 54367db96d56Sopenharmony_ci return NULL; 54377db96d56Sopenharmony_ci } 54387db96d56Sopenharmony_ci 54397db96d56Sopenharmony_ci // We only need to sanitize this string if the separator is a surrogate 54407db96d56Sopenharmony_ci // character. In the situation where the separator location is ambiguous, 54417db96d56Sopenharmony_ci // we don't have to sanitize it anything because that can only happen when 54427db96d56Sopenharmony_ci // the separator is either '-' or a number. This should mostly be a noop 54437db96d56Sopenharmony_ci // but it makes the reference counting easier if we still sanitize. 54447db96d56Sopenharmony_ci PyObject *dtstr_clean = _sanitize_isoformat_str(dtstr); 54457db96d56Sopenharmony_ci if (dtstr_clean == NULL) { 54467db96d56Sopenharmony_ci goto invalid_string_error; 54477db96d56Sopenharmony_ci } 54487db96d56Sopenharmony_ci 54497db96d56Sopenharmony_ci Py_ssize_t len; 54507db96d56Sopenharmony_ci const char *dt_ptr = PyUnicode_AsUTF8AndSize(dtstr_clean, &len); 54517db96d56Sopenharmony_ci 54527db96d56Sopenharmony_ci if (dt_ptr == NULL) { 54537db96d56Sopenharmony_ci if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) { 54547db96d56Sopenharmony_ci // Encoding errors are invalid string errors at this point 54557db96d56Sopenharmony_ci goto invalid_string_error; 54567db96d56Sopenharmony_ci } 54577db96d56Sopenharmony_ci else { 54587db96d56Sopenharmony_ci goto error; 54597db96d56Sopenharmony_ci } 54607db96d56Sopenharmony_ci } 54617db96d56Sopenharmony_ci 54627db96d56Sopenharmony_ci const Py_ssize_t separator_location = _find_isoformat_datetime_separator( 54637db96d56Sopenharmony_ci dt_ptr, len); 54647db96d56Sopenharmony_ci 54657db96d56Sopenharmony_ci 54667db96d56Sopenharmony_ci const char *p = dt_ptr; 54677db96d56Sopenharmony_ci 54687db96d56Sopenharmony_ci int year = 0, month = 0, day = 0; 54697db96d56Sopenharmony_ci int hour = 0, minute = 0, second = 0, microsecond = 0; 54707db96d56Sopenharmony_ci int tzoffset = 0, tzusec = 0; 54717db96d56Sopenharmony_ci 54727db96d56Sopenharmony_ci // date runs up to separator_location 54737db96d56Sopenharmony_ci int rv = parse_isoformat_date(p, separator_location, &year, &month, &day); 54747db96d56Sopenharmony_ci 54757db96d56Sopenharmony_ci if (!rv && len > separator_location) { 54767db96d56Sopenharmony_ci // In UTF-8, the length of multi-byte characters is encoded in the MSB 54777db96d56Sopenharmony_ci p += separator_location; 54787db96d56Sopenharmony_ci if ((p[0] & 0x80) == 0) { 54797db96d56Sopenharmony_ci p += 1; 54807db96d56Sopenharmony_ci } 54817db96d56Sopenharmony_ci else { 54827db96d56Sopenharmony_ci switch (p[0] & 0xf0) { 54837db96d56Sopenharmony_ci case 0xe0: 54847db96d56Sopenharmony_ci p += 3; 54857db96d56Sopenharmony_ci break; 54867db96d56Sopenharmony_ci case 0xf0: 54877db96d56Sopenharmony_ci p += 4; 54887db96d56Sopenharmony_ci break; 54897db96d56Sopenharmony_ci default: 54907db96d56Sopenharmony_ci p += 2; 54917db96d56Sopenharmony_ci break; 54927db96d56Sopenharmony_ci } 54937db96d56Sopenharmony_ci } 54947db96d56Sopenharmony_ci 54957db96d56Sopenharmony_ci len -= (p - dt_ptr); 54967db96d56Sopenharmony_ci rv = parse_isoformat_time(p, len, &hour, &minute, &second, 54977db96d56Sopenharmony_ci µsecond, &tzoffset, &tzusec); 54987db96d56Sopenharmony_ci } 54997db96d56Sopenharmony_ci if (rv < 0) { 55007db96d56Sopenharmony_ci goto invalid_string_error; 55017db96d56Sopenharmony_ci } 55027db96d56Sopenharmony_ci 55037db96d56Sopenharmony_ci PyObject *tzinfo = tzinfo_from_isoformat_results(rv, tzoffset, tzusec); 55047db96d56Sopenharmony_ci if (tzinfo == NULL) { 55057db96d56Sopenharmony_ci goto error; 55067db96d56Sopenharmony_ci } 55077db96d56Sopenharmony_ci 55087db96d56Sopenharmony_ci PyObject *dt = new_datetime_subclass_ex(year, month, day, hour, minute, 55097db96d56Sopenharmony_ci second, microsecond, tzinfo, cls); 55107db96d56Sopenharmony_ci 55117db96d56Sopenharmony_ci Py_DECREF(tzinfo); 55127db96d56Sopenharmony_ci Py_DECREF(dtstr_clean); 55137db96d56Sopenharmony_ci return dt; 55147db96d56Sopenharmony_ci 55157db96d56Sopenharmony_ciinvalid_string_error: 55167db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "Invalid isoformat string: %R", dtstr); 55177db96d56Sopenharmony_ci 55187db96d56Sopenharmony_cierror: 55197db96d56Sopenharmony_ci Py_XDECREF(dtstr_clean); 55207db96d56Sopenharmony_ci 55217db96d56Sopenharmony_ci return NULL; 55227db96d56Sopenharmony_ci} 55237db96d56Sopenharmony_ci 55247db96d56Sopenharmony_ci/* 55257db96d56Sopenharmony_ci * Destructor. 55267db96d56Sopenharmony_ci */ 55277db96d56Sopenharmony_ci 55287db96d56Sopenharmony_cistatic void 55297db96d56Sopenharmony_cidatetime_dealloc(PyDateTime_DateTime *self) 55307db96d56Sopenharmony_ci{ 55317db96d56Sopenharmony_ci if (HASTZINFO(self)) { 55327db96d56Sopenharmony_ci Py_XDECREF(self->tzinfo); 55337db96d56Sopenharmony_ci } 55347db96d56Sopenharmony_ci Py_TYPE(self)->tp_free((PyObject *)self); 55357db96d56Sopenharmony_ci} 55367db96d56Sopenharmony_ci 55377db96d56Sopenharmony_ci/* 55387db96d56Sopenharmony_ci * Indirect access to tzinfo methods. 55397db96d56Sopenharmony_ci */ 55407db96d56Sopenharmony_ci 55417db96d56Sopenharmony_ci/* These are all METH_NOARGS, so don't need to check the arglist. */ 55427db96d56Sopenharmony_cistatic PyObject * 55437db96d56Sopenharmony_cidatetime_utcoffset(PyObject *self, PyObject *unused) { 55447db96d56Sopenharmony_ci return call_utcoffset(GET_DT_TZINFO(self), self); 55457db96d56Sopenharmony_ci} 55467db96d56Sopenharmony_ci 55477db96d56Sopenharmony_cistatic PyObject * 55487db96d56Sopenharmony_cidatetime_dst(PyObject *self, PyObject *unused) { 55497db96d56Sopenharmony_ci return call_dst(GET_DT_TZINFO(self), self); 55507db96d56Sopenharmony_ci} 55517db96d56Sopenharmony_ci 55527db96d56Sopenharmony_cistatic PyObject * 55537db96d56Sopenharmony_cidatetime_tzname(PyObject *self, PyObject *unused) { 55547db96d56Sopenharmony_ci return call_tzname(GET_DT_TZINFO(self), self); 55557db96d56Sopenharmony_ci} 55567db96d56Sopenharmony_ci 55577db96d56Sopenharmony_ci/* 55587db96d56Sopenharmony_ci * datetime arithmetic. 55597db96d56Sopenharmony_ci */ 55607db96d56Sopenharmony_ci 55617db96d56Sopenharmony_ci/* factor must be 1 (to add) or -1 (to subtract). The result inherits 55627db96d56Sopenharmony_ci * the tzinfo state of date. 55637db96d56Sopenharmony_ci */ 55647db96d56Sopenharmony_cistatic PyObject * 55657db96d56Sopenharmony_ciadd_datetime_timedelta(PyDateTime_DateTime *date, PyDateTime_Delta *delta, 55667db96d56Sopenharmony_ci int factor) 55677db96d56Sopenharmony_ci{ 55687db96d56Sopenharmony_ci /* Note that the C-level additions can't overflow, because of 55697db96d56Sopenharmony_ci * invariant bounds on the member values. 55707db96d56Sopenharmony_ci */ 55717db96d56Sopenharmony_ci int year = GET_YEAR(date); 55727db96d56Sopenharmony_ci int month = GET_MONTH(date); 55737db96d56Sopenharmony_ci int day = GET_DAY(date) + GET_TD_DAYS(delta) * factor; 55747db96d56Sopenharmony_ci int hour = DATE_GET_HOUR(date); 55757db96d56Sopenharmony_ci int minute = DATE_GET_MINUTE(date); 55767db96d56Sopenharmony_ci int second = DATE_GET_SECOND(date) + GET_TD_SECONDS(delta) * factor; 55777db96d56Sopenharmony_ci int microsecond = DATE_GET_MICROSECOND(date) + 55787db96d56Sopenharmony_ci GET_TD_MICROSECONDS(delta) * factor; 55797db96d56Sopenharmony_ci 55807db96d56Sopenharmony_ci assert(factor == 1 || factor == -1); 55817db96d56Sopenharmony_ci if (normalize_datetime(&year, &month, &day, 55827db96d56Sopenharmony_ci &hour, &minute, &second, µsecond) < 0) { 55837db96d56Sopenharmony_ci return NULL; 55847db96d56Sopenharmony_ci } 55857db96d56Sopenharmony_ci 55867db96d56Sopenharmony_ci return new_datetime_subclass_ex(year, month, day, 55877db96d56Sopenharmony_ci hour, minute, second, microsecond, 55887db96d56Sopenharmony_ci HASTZINFO(date) ? date->tzinfo : Py_None, 55897db96d56Sopenharmony_ci (PyObject *)Py_TYPE(date)); 55907db96d56Sopenharmony_ci} 55917db96d56Sopenharmony_ci 55927db96d56Sopenharmony_cistatic PyObject * 55937db96d56Sopenharmony_cidatetime_add(PyObject *left, PyObject *right) 55947db96d56Sopenharmony_ci{ 55957db96d56Sopenharmony_ci if (PyDateTime_Check(left)) { 55967db96d56Sopenharmony_ci /* datetime + ??? */ 55977db96d56Sopenharmony_ci if (PyDelta_Check(right)) 55987db96d56Sopenharmony_ci /* datetime + delta */ 55997db96d56Sopenharmony_ci return add_datetime_timedelta( 56007db96d56Sopenharmony_ci (PyDateTime_DateTime *)left, 56017db96d56Sopenharmony_ci (PyDateTime_Delta *)right, 56027db96d56Sopenharmony_ci 1); 56037db96d56Sopenharmony_ci } 56047db96d56Sopenharmony_ci else if (PyDelta_Check(left)) { 56057db96d56Sopenharmony_ci /* delta + datetime */ 56067db96d56Sopenharmony_ci return add_datetime_timedelta((PyDateTime_DateTime *) right, 56077db96d56Sopenharmony_ci (PyDateTime_Delta *) left, 56087db96d56Sopenharmony_ci 1); 56097db96d56Sopenharmony_ci } 56107db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 56117db96d56Sopenharmony_ci} 56127db96d56Sopenharmony_ci 56137db96d56Sopenharmony_cistatic PyObject * 56147db96d56Sopenharmony_cidatetime_subtract(PyObject *left, PyObject *right) 56157db96d56Sopenharmony_ci{ 56167db96d56Sopenharmony_ci PyObject *result = Py_NotImplemented; 56177db96d56Sopenharmony_ci 56187db96d56Sopenharmony_ci if (PyDateTime_Check(left)) { 56197db96d56Sopenharmony_ci /* datetime - ??? */ 56207db96d56Sopenharmony_ci if (PyDateTime_Check(right)) { 56217db96d56Sopenharmony_ci /* datetime - datetime */ 56227db96d56Sopenharmony_ci PyObject *offset1, *offset2, *offdiff = NULL; 56237db96d56Sopenharmony_ci int delta_d, delta_s, delta_us; 56247db96d56Sopenharmony_ci 56257db96d56Sopenharmony_ci if (GET_DT_TZINFO(left) == GET_DT_TZINFO(right)) { 56267db96d56Sopenharmony_ci offset2 = offset1 = Py_None; 56277db96d56Sopenharmony_ci Py_INCREF(offset1); 56287db96d56Sopenharmony_ci Py_INCREF(offset2); 56297db96d56Sopenharmony_ci } 56307db96d56Sopenharmony_ci else { 56317db96d56Sopenharmony_ci offset1 = datetime_utcoffset(left, NULL); 56327db96d56Sopenharmony_ci if (offset1 == NULL) 56337db96d56Sopenharmony_ci return NULL; 56347db96d56Sopenharmony_ci offset2 = datetime_utcoffset(right, NULL); 56357db96d56Sopenharmony_ci if (offset2 == NULL) { 56367db96d56Sopenharmony_ci Py_DECREF(offset1); 56377db96d56Sopenharmony_ci return NULL; 56387db96d56Sopenharmony_ci } 56397db96d56Sopenharmony_ci if ((offset1 != Py_None) != (offset2 != Py_None)) { 56407db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 56417db96d56Sopenharmony_ci "can't subtract offset-naive and " 56427db96d56Sopenharmony_ci "offset-aware datetimes"); 56437db96d56Sopenharmony_ci Py_DECREF(offset1); 56447db96d56Sopenharmony_ci Py_DECREF(offset2); 56457db96d56Sopenharmony_ci return NULL; 56467db96d56Sopenharmony_ci } 56477db96d56Sopenharmony_ci } 56487db96d56Sopenharmony_ci if ((offset1 != offset2) && 56497db96d56Sopenharmony_ci delta_cmp(offset1, offset2) != 0) { 56507db96d56Sopenharmony_ci offdiff = delta_subtract(offset1, offset2); 56517db96d56Sopenharmony_ci if (offdiff == NULL) { 56527db96d56Sopenharmony_ci Py_DECREF(offset1); 56537db96d56Sopenharmony_ci Py_DECREF(offset2); 56547db96d56Sopenharmony_ci return NULL; 56557db96d56Sopenharmony_ci } 56567db96d56Sopenharmony_ci } 56577db96d56Sopenharmony_ci Py_DECREF(offset1); 56587db96d56Sopenharmony_ci Py_DECREF(offset2); 56597db96d56Sopenharmony_ci delta_d = ymd_to_ord(GET_YEAR(left), 56607db96d56Sopenharmony_ci GET_MONTH(left), 56617db96d56Sopenharmony_ci GET_DAY(left)) - 56627db96d56Sopenharmony_ci ymd_to_ord(GET_YEAR(right), 56637db96d56Sopenharmony_ci GET_MONTH(right), 56647db96d56Sopenharmony_ci GET_DAY(right)); 56657db96d56Sopenharmony_ci /* These can't overflow, since the values are 56667db96d56Sopenharmony_ci * normalized. At most this gives the number of 56677db96d56Sopenharmony_ci * seconds in one day. 56687db96d56Sopenharmony_ci */ 56697db96d56Sopenharmony_ci delta_s = (DATE_GET_HOUR(left) - 56707db96d56Sopenharmony_ci DATE_GET_HOUR(right)) * 3600 + 56717db96d56Sopenharmony_ci (DATE_GET_MINUTE(left) - 56727db96d56Sopenharmony_ci DATE_GET_MINUTE(right)) * 60 + 56737db96d56Sopenharmony_ci (DATE_GET_SECOND(left) - 56747db96d56Sopenharmony_ci DATE_GET_SECOND(right)); 56757db96d56Sopenharmony_ci delta_us = DATE_GET_MICROSECOND(left) - 56767db96d56Sopenharmony_ci DATE_GET_MICROSECOND(right); 56777db96d56Sopenharmony_ci result = new_delta(delta_d, delta_s, delta_us, 1); 56787db96d56Sopenharmony_ci if (result == NULL) 56797db96d56Sopenharmony_ci return NULL; 56807db96d56Sopenharmony_ci 56817db96d56Sopenharmony_ci if (offdiff != NULL) { 56827db96d56Sopenharmony_ci Py_SETREF(result, delta_subtract(result, offdiff)); 56837db96d56Sopenharmony_ci Py_DECREF(offdiff); 56847db96d56Sopenharmony_ci } 56857db96d56Sopenharmony_ci } 56867db96d56Sopenharmony_ci else if (PyDelta_Check(right)) { 56877db96d56Sopenharmony_ci /* datetime - delta */ 56887db96d56Sopenharmony_ci result = add_datetime_timedelta( 56897db96d56Sopenharmony_ci (PyDateTime_DateTime *)left, 56907db96d56Sopenharmony_ci (PyDateTime_Delta *)right, 56917db96d56Sopenharmony_ci -1); 56927db96d56Sopenharmony_ci } 56937db96d56Sopenharmony_ci } 56947db96d56Sopenharmony_ci 56957db96d56Sopenharmony_ci if (result == Py_NotImplemented) 56967db96d56Sopenharmony_ci Py_INCREF(result); 56977db96d56Sopenharmony_ci return result; 56987db96d56Sopenharmony_ci} 56997db96d56Sopenharmony_ci 57007db96d56Sopenharmony_ci/* Various ways to turn a datetime into a string. */ 57017db96d56Sopenharmony_ci 57027db96d56Sopenharmony_cistatic PyObject * 57037db96d56Sopenharmony_cidatetime_repr(PyDateTime_DateTime *self) 57047db96d56Sopenharmony_ci{ 57057db96d56Sopenharmony_ci const char *type_name = Py_TYPE(self)->tp_name; 57067db96d56Sopenharmony_ci PyObject *baserepr; 57077db96d56Sopenharmony_ci 57087db96d56Sopenharmony_ci if (DATE_GET_MICROSECOND(self)) { 57097db96d56Sopenharmony_ci baserepr = PyUnicode_FromFormat( 57107db96d56Sopenharmony_ci "%s(%d, %d, %d, %d, %d, %d, %d)", 57117db96d56Sopenharmony_ci type_name, 57127db96d56Sopenharmony_ci GET_YEAR(self), GET_MONTH(self), GET_DAY(self), 57137db96d56Sopenharmony_ci DATE_GET_HOUR(self), DATE_GET_MINUTE(self), 57147db96d56Sopenharmony_ci DATE_GET_SECOND(self), 57157db96d56Sopenharmony_ci DATE_GET_MICROSECOND(self)); 57167db96d56Sopenharmony_ci } 57177db96d56Sopenharmony_ci else if (DATE_GET_SECOND(self)) { 57187db96d56Sopenharmony_ci baserepr = PyUnicode_FromFormat( 57197db96d56Sopenharmony_ci "%s(%d, %d, %d, %d, %d, %d)", 57207db96d56Sopenharmony_ci type_name, 57217db96d56Sopenharmony_ci GET_YEAR(self), GET_MONTH(self), GET_DAY(self), 57227db96d56Sopenharmony_ci DATE_GET_HOUR(self), DATE_GET_MINUTE(self), 57237db96d56Sopenharmony_ci DATE_GET_SECOND(self)); 57247db96d56Sopenharmony_ci } 57257db96d56Sopenharmony_ci else { 57267db96d56Sopenharmony_ci baserepr = PyUnicode_FromFormat( 57277db96d56Sopenharmony_ci "%s(%d, %d, %d, %d, %d)", 57287db96d56Sopenharmony_ci type_name, 57297db96d56Sopenharmony_ci GET_YEAR(self), GET_MONTH(self), GET_DAY(self), 57307db96d56Sopenharmony_ci DATE_GET_HOUR(self), DATE_GET_MINUTE(self)); 57317db96d56Sopenharmony_ci } 57327db96d56Sopenharmony_ci if (baserepr != NULL && DATE_GET_FOLD(self) != 0) 57337db96d56Sopenharmony_ci baserepr = append_keyword_fold(baserepr, DATE_GET_FOLD(self)); 57347db96d56Sopenharmony_ci if (baserepr == NULL || ! HASTZINFO(self)) 57357db96d56Sopenharmony_ci return baserepr; 57367db96d56Sopenharmony_ci return append_keyword_tzinfo(baserepr, self->tzinfo); 57377db96d56Sopenharmony_ci} 57387db96d56Sopenharmony_ci 57397db96d56Sopenharmony_cistatic PyObject * 57407db96d56Sopenharmony_cidatetime_str(PyDateTime_DateTime *self) 57417db96d56Sopenharmony_ci{ 57427db96d56Sopenharmony_ci return _PyObject_CallMethodId((PyObject *)self, &PyId_isoformat, "s", " "); 57437db96d56Sopenharmony_ci} 57447db96d56Sopenharmony_ci 57457db96d56Sopenharmony_cistatic PyObject * 57467db96d56Sopenharmony_cidatetime_isoformat(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) 57477db96d56Sopenharmony_ci{ 57487db96d56Sopenharmony_ci int sep = 'T'; 57497db96d56Sopenharmony_ci char *timespec = NULL; 57507db96d56Sopenharmony_ci static char *keywords[] = {"sep", "timespec", NULL}; 57517db96d56Sopenharmony_ci char buffer[100]; 57527db96d56Sopenharmony_ci PyObject *result = NULL; 57537db96d56Sopenharmony_ci int us = DATE_GET_MICROSECOND(self); 57547db96d56Sopenharmony_ci static const char *specs[][2] = { 57557db96d56Sopenharmony_ci {"hours", "%04d-%02d-%02d%c%02d"}, 57567db96d56Sopenharmony_ci {"minutes", "%04d-%02d-%02d%c%02d:%02d"}, 57577db96d56Sopenharmony_ci {"seconds", "%04d-%02d-%02d%c%02d:%02d:%02d"}, 57587db96d56Sopenharmony_ci {"milliseconds", "%04d-%02d-%02d%c%02d:%02d:%02d.%03d"}, 57597db96d56Sopenharmony_ci {"microseconds", "%04d-%02d-%02d%c%02d:%02d:%02d.%06d"}, 57607db96d56Sopenharmony_ci }; 57617db96d56Sopenharmony_ci size_t given_spec; 57627db96d56Sopenharmony_ci 57637db96d56Sopenharmony_ci if (!PyArg_ParseTupleAndKeywords(args, kw, "|Cs:isoformat", keywords, &sep, ×pec)) 57647db96d56Sopenharmony_ci return NULL; 57657db96d56Sopenharmony_ci 57667db96d56Sopenharmony_ci if (timespec == NULL || strcmp(timespec, "auto") == 0) { 57677db96d56Sopenharmony_ci if (us == 0) { 57687db96d56Sopenharmony_ci /* seconds */ 57697db96d56Sopenharmony_ci given_spec = 2; 57707db96d56Sopenharmony_ci } 57717db96d56Sopenharmony_ci else { 57727db96d56Sopenharmony_ci /* microseconds */ 57737db96d56Sopenharmony_ci given_spec = 4; 57747db96d56Sopenharmony_ci } 57757db96d56Sopenharmony_ci } 57767db96d56Sopenharmony_ci else { 57777db96d56Sopenharmony_ci for (given_spec = 0; given_spec < Py_ARRAY_LENGTH(specs); given_spec++) { 57787db96d56Sopenharmony_ci if (strcmp(timespec, specs[given_spec][0]) == 0) { 57797db96d56Sopenharmony_ci if (given_spec == 3) { 57807db96d56Sopenharmony_ci us = us / 1000; 57817db96d56Sopenharmony_ci } 57827db96d56Sopenharmony_ci break; 57837db96d56Sopenharmony_ci } 57847db96d56Sopenharmony_ci } 57857db96d56Sopenharmony_ci } 57867db96d56Sopenharmony_ci 57877db96d56Sopenharmony_ci if (given_spec == Py_ARRAY_LENGTH(specs)) { 57887db96d56Sopenharmony_ci PyErr_Format(PyExc_ValueError, "Unknown timespec value"); 57897db96d56Sopenharmony_ci return NULL; 57907db96d56Sopenharmony_ci } 57917db96d56Sopenharmony_ci else { 57927db96d56Sopenharmony_ci result = PyUnicode_FromFormat(specs[given_spec][1], 57937db96d56Sopenharmony_ci GET_YEAR(self), GET_MONTH(self), 57947db96d56Sopenharmony_ci GET_DAY(self), (int)sep, 57957db96d56Sopenharmony_ci DATE_GET_HOUR(self), DATE_GET_MINUTE(self), 57967db96d56Sopenharmony_ci DATE_GET_SECOND(self), us); 57977db96d56Sopenharmony_ci } 57987db96d56Sopenharmony_ci 57997db96d56Sopenharmony_ci if (!result || !HASTZINFO(self)) 58007db96d56Sopenharmony_ci return result; 58017db96d56Sopenharmony_ci 58027db96d56Sopenharmony_ci /* We need to append the UTC offset. */ 58037db96d56Sopenharmony_ci if (format_utcoffset(buffer, sizeof(buffer), ":", self->tzinfo, 58047db96d56Sopenharmony_ci (PyObject *)self) < 0) { 58057db96d56Sopenharmony_ci Py_DECREF(result); 58067db96d56Sopenharmony_ci return NULL; 58077db96d56Sopenharmony_ci } 58087db96d56Sopenharmony_ci PyUnicode_AppendAndDel(&result, PyUnicode_FromString(buffer)); 58097db96d56Sopenharmony_ci return result; 58107db96d56Sopenharmony_ci} 58117db96d56Sopenharmony_ci 58127db96d56Sopenharmony_cistatic PyObject * 58137db96d56Sopenharmony_cidatetime_ctime(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) 58147db96d56Sopenharmony_ci{ 58157db96d56Sopenharmony_ci return format_ctime((PyDateTime_Date *)self, 58167db96d56Sopenharmony_ci DATE_GET_HOUR(self), 58177db96d56Sopenharmony_ci DATE_GET_MINUTE(self), 58187db96d56Sopenharmony_ci DATE_GET_SECOND(self)); 58197db96d56Sopenharmony_ci} 58207db96d56Sopenharmony_ci 58217db96d56Sopenharmony_ci/* Miscellaneous methods. */ 58227db96d56Sopenharmony_ci 58237db96d56Sopenharmony_cistatic PyObject * 58247db96d56Sopenharmony_ciflip_fold(PyObject *dt) 58257db96d56Sopenharmony_ci{ 58267db96d56Sopenharmony_ci return new_datetime_ex2(GET_YEAR(dt), 58277db96d56Sopenharmony_ci GET_MONTH(dt), 58287db96d56Sopenharmony_ci GET_DAY(dt), 58297db96d56Sopenharmony_ci DATE_GET_HOUR(dt), 58307db96d56Sopenharmony_ci DATE_GET_MINUTE(dt), 58317db96d56Sopenharmony_ci DATE_GET_SECOND(dt), 58327db96d56Sopenharmony_ci DATE_GET_MICROSECOND(dt), 58337db96d56Sopenharmony_ci HASTZINFO(dt) ? 58347db96d56Sopenharmony_ci ((PyDateTime_DateTime *)dt)->tzinfo : Py_None, 58357db96d56Sopenharmony_ci !DATE_GET_FOLD(dt), 58367db96d56Sopenharmony_ci Py_TYPE(dt)); 58377db96d56Sopenharmony_ci} 58387db96d56Sopenharmony_ci 58397db96d56Sopenharmony_cistatic PyObject * 58407db96d56Sopenharmony_ciget_flip_fold_offset(PyObject *dt) 58417db96d56Sopenharmony_ci{ 58427db96d56Sopenharmony_ci PyObject *result, *flip_dt; 58437db96d56Sopenharmony_ci 58447db96d56Sopenharmony_ci flip_dt = flip_fold(dt); 58457db96d56Sopenharmony_ci if (flip_dt == NULL) 58467db96d56Sopenharmony_ci return NULL; 58477db96d56Sopenharmony_ci result = datetime_utcoffset(flip_dt, NULL); 58487db96d56Sopenharmony_ci Py_DECREF(flip_dt); 58497db96d56Sopenharmony_ci return result; 58507db96d56Sopenharmony_ci} 58517db96d56Sopenharmony_ci 58527db96d56Sopenharmony_ci/* PEP 495 exception: Whenever one or both of the operands in 58537db96d56Sopenharmony_ci * inter-zone comparison is such that its utcoffset() depends 58547db96d56Sopenharmony_ci * on the value of its fold attribute, the result is False. 58557db96d56Sopenharmony_ci * 58567db96d56Sopenharmony_ci * Return 1 if exception applies, 0 if not, and -1 on error. 58577db96d56Sopenharmony_ci */ 58587db96d56Sopenharmony_cistatic int 58597db96d56Sopenharmony_cipep495_eq_exception(PyObject *self, PyObject *other, 58607db96d56Sopenharmony_ci PyObject *offset_self, PyObject *offset_other) 58617db96d56Sopenharmony_ci{ 58627db96d56Sopenharmony_ci int result = 0; 58637db96d56Sopenharmony_ci PyObject *flip_offset; 58647db96d56Sopenharmony_ci 58657db96d56Sopenharmony_ci flip_offset = get_flip_fold_offset(self); 58667db96d56Sopenharmony_ci if (flip_offset == NULL) 58677db96d56Sopenharmony_ci return -1; 58687db96d56Sopenharmony_ci if (flip_offset != offset_self && 58697db96d56Sopenharmony_ci delta_cmp(flip_offset, offset_self)) 58707db96d56Sopenharmony_ci { 58717db96d56Sopenharmony_ci result = 1; 58727db96d56Sopenharmony_ci goto done; 58737db96d56Sopenharmony_ci } 58747db96d56Sopenharmony_ci Py_DECREF(flip_offset); 58757db96d56Sopenharmony_ci 58767db96d56Sopenharmony_ci flip_offset = get_flip_fold_offset(other); 58777db96d56Sopenharmony_ci if (flip_offset == NULL) 58787db96d56Sopenharmony_ci return -1; 58797db96d56Sopenharmony_ci if (flip_offset != offset_other && 58807db96d56Sopenharmony_ci delta_cmp(flip_offset, offset_other)) 58817db96d56Sopenharmony_ci result = 1; 58827db96d56Sopenharmony_ci done: 58837db96d56Sopenharmony_ci Py_DECREF(flip_offset); 58847db96d56Sopenharmony_ci return result; 58857db96d56Sopenharmony_ci} 58867db96d56Sopenharmony_ci 58877db96d56Sopenharmony_cistatic PyObject * 58887db96d56Sopenharmony_cidatetime_richcompare(PyObject *self, PyObject *other, int op) 58897db96d56Sopenharmony_ci{ 58907db96d56Sopenharmony_ci PyObject *result = NULL; 58917db96d56Sopenharmony_ci PyObject *offset1, *offset2; 58927db96d56Sopenharmony_ci int diff; 58937db96d56Sopenharmony_ci 58947db96d56Sopenharmony_ci if (! PyDateTime_Check(other)) { 58957db96d56Sopenharmony_ci if (PyDate_Check(other)) { 58967db96d56Sopenharmony_ci /* Prevent invocation of date_richcompare. We want to 58977db96d56Sopenharmony_ci return NotImplemented here to give the other object 58987db96d56Sopenharmony_ci a chance. But since DateTime is a subclass of 58997db96d56Sopenharmony_ci Date, if the other object is a Date, it would 59007db96d56Sopenharmony_ci compute an ordering based on the date part alone, 59017db96d56Sopenharmony_ci and we don't want that. So force unequal or 59027db96d56Sopenharmony_ci uncomparable here in that case. */ 59037db96d56Sopenharmony_ci if (op == Py_EQ) 59047db96d56Sopenharmony_ci Py_RETURN_FALSE; 59057db96d56Sopenharmony_ci if (op == Py_NE) 59067db96d56Sopenharmony_ci Py_RETURN_TRUE; 59077db96d56Sopenharmony_ci return cmperror(self, other); 59087db96d56Sopenharmony_ci } 59097db96d56Sopenharmony_ci Py_RETURN_NOTIMPLEMENTED; 59107db96d56Sopenharmony_ci } 59117db96d56Sopenharmony_ci 59127db96d56Sopenharmony_ci if (GET_DT_TZINFO(self) == GET_DT_TZINFO(other)) { 59137db96d56Sopenharmony_ci diff = memcmp(((PyDateTime_DateTime *)self)->data, 59147db96d56Sopenharmony_ci ((PyDateTime_DateTime *)other)->data, 59157db96d56Sopenharmony_ci _PyDateTime_DATETIME_DATASIZE); 59167db96d56Sopenharmony_ci return diff_to_bool(diff, op); 59177db96d56Sopenharmony_ci } 59187db96d56Sopenharmony_ci offset1 = datetime_utcoffset(self, NULL); 59197db96d56Sopenharmony_ci if (offset1 == NULL) 59207db96d56Sopenharmony_ci return NULL; 59217db96d56Sopenharmony_ci offset2 = datetime_utcoffset(other, NULL); 59227db96d56Sopenharmony_ci if (offset2 == NULL) 59237db96d56Sopenharmony_ci goto done; 59247db96d56Sopenharmony_ci /* If they're both naive, or both aware and have the same offsets, 59257db96d56Sopenharmony_ci * we get off cheap. Note that if they're both naive, offset1 == 59267db96d56Sopenharmony_ci * offset2 == Py_None at this point. 59277db96d56Sopenharmony_ci */ 59287db96d56Sopenharmony_ci if ((offset1 == offset2) || 59297db96d56Sopenharmony_ci (PyDelta_Check(offset1) && PyDelta_Check(offset2) && 59307db96d56Sopenharmony_ci delta_cmp(offset1, offset2) == 0)) { 59317db96d56Sopenharmony_ci diff = memcmp(((PyDateTime_DateTime *)self)->data, 59327db96d56Sopenharmony_ci ((PyDateTime_DateTime *)other)->data, 59337db96d56Sopenharmony_ci _PyDateTime_DATETIME_DATASIZE); 59347db96d56Sopenharmony_ci if ((op == Py_EQ || op == Py_NE) && diff == 0) { 59357db96d56Sopenharmony_ci int ex = pep495_eq_exception(self, other, offset1, offset2); 59367db96d56Sopenharmony_ci if (ex == -1) 59377db96d56Sopenharmony_ci goto done; 59387db96d56Sopenharmony_ci if (ex) 59397db96d56Sopenharmony_ci diff = 1; 59407db96d56Sopenharmony_ci } 59417db96d56Sopenharmony_ci result = diff_to_bool(diff, op); 59427db96d56Sopenharmony_ci } 59437db96d56Sopenharmony_ci else if (offset1 != Py_None && offset2 != Py_None) { 59447db96d56Sopenharmony_ci PyDateTime_Delta *delta; 59457db96d56Sopenharmony_ci 59467db96d56Sopenharmony_ci assert(offset1 != offset2); /* else last "if" handled it */ 59477db96d56Sopenharmony_ci delta = (PyDateTime_Delta *)datetime_subtract((PyObject *)self, 59487db96d56Sopenharmony_ci other); 59497db96d56Sopenharmony_ci if (delta == NULL) 59507db96d56Sopenharmony_ci goto done; 59517db96d56Sopenharmony_ci diff = GET_TD_DAYS(delta); 59527db96d56Sopenharmony_ci if (diff == 0) 59537db96d56Sopenharmony_ci diff = GET_TD_SECONDS(delta) | 59547db96d56Sopenharmony_ci GET_TD_MICROSECONDS(delta); 59557db96d56Sopenharmony_ci Py_DECREF(delta); 59567db96d56Sopenharmony_ci if ((op == Py_EQ || op == Py_NE) && diff == 0) { 59577db96d56Sopenharmony_ci int ex = pep495_eq_exception(self, other, offset1, offset2); 59587db96d56Sopenharmony_ci if (ex == -1) 59597db96d56Sopenharmony_ci goto done; 59607db96d56Sopenharmony_ci if (ex) 59617db96d56Sopenharmony_ci diff = 1; 59627db96d56Sopenharmony_ci } 59637db96d56Sopenharmony_ci result = diff_to_bool(diff, op); 59647db96d56Sopenharmony_ci } 59657db96d56Sopenharmony_ci else if (op == Py_EQ) { 59667db96d56Sopenharmony_ci result = Py_False; 59677db96d56Sopenharmony_ci Py_INCREF(result); 59687db96d56Sopenharmony_ci } 59697db96d56Sopenharmony_ci else if (op == Py_NE) { 59707db96d56Sopenharmony_ci result = Py_True; 59717db96d56Sopenharmony_ci Py_INCREF(result); 59727db96d56Sopenharmony_ci } 59737db96d56Sopenharmony_ci else { 59747db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 59757db96d56Sopenharmony_ci "can't compare offset-naive and " 59767db96d56Sopenharmony_ci "offset-aware datetimes"); 59777db96d56Sopenharmony_ci } 59787db96d56Sopenharmony_ci done: 59797db96d56Sopenharmony_ci Py_DECREF(offset1); 59807db96d56Sopenharmony_ci Py_XDECREF(offset2); 59817db96d56Sopenharmony_ci return result; 59827db96d56Sopenharmony_ci} 59837db96d56Sopenharmony_ci 59847db96d56Sopenharmony_cistatic Py_hash_t 59857db96d56Sopenharmony_cidatetime_hash(PyDateTime_DateTime *self) 59867db96d56Sopenharmony_ci{ 59877db96d56Sopenharmony_ci if (self->hashcode == -1) { 59887db96d56Sopenharmony_ci PyObject *offset, *self0; 59897db96d56Sopenharmony_ci if (DATE_GET_FOLD(self)) { 59907db96d56Sopenharmony_ci self0 = new_datetime_ex2(GET_YEAR(self), 59917db96d56Sopenharmony_ci GET_MONTH(self), 59927db96d56Sopenharmony_ci GET_DAY(self), 59937db96d56Sopenharmony_ci DATE_GET_HOUR(self), 59947db96d56Sopenharmony_ci DATE_GET_MINUTE(self), 59957db96d56Sopenharmony_ci DATE_GET_SECOND(self), 59967db96d56Sopenharmony_ci DATE_GET_MICROSECOND(self), 59977db96d56Sopenharmony_ci HASTZINFO(self) ? self->tzinfo : Py_None, 59987db96d56Sopenharmony_ci 0, Py_TYPE(self)); 59997db96d56Sopenharmony_ci if (self0 == NULL) 60007db96d56Sopenharmony_ci return -1; 60017db96d56Sopenharmony_ci } 60027db96d56Sopenharmony_ci else { 60037db96d56Sopenharmony_ci self0 = (PyObject *)self; 60047db96d56Sopenharmony_ci Py_INCREF(self0); 60057db96d56Sopenharmony_ci } 60067db96d56Sopenharmony_ci offset = datetime_utcoffset(self0, NULL); 60077db96d56Sopenharmony_ci Py_DECREF(self0); 60087db96d56Sopenharmony_ci 60097db96d56Sopenharmony_ci if (offset == NULL) 60107db96d56Sopenharmony_ci return -1; 60117db96d56Sopenharmony_ci 60127db96d56Sopenharmony_ci /* Reduce this to a hash of another object. */ 60137db96d56Sopenharmony_ci if (offset == Py_None) 60147db96d56Sopenharmony_ci self->hashcode = generic_hash( 60157db96d56Sopenharmony_ci (unsigned char *)self->data, _PyDateTime_DATETIME_DATASIZE); 60167db96d56Sopenharmony_ci else { 60177db96d56Sopenharmony_ci PyObject *temp1, *temp2; 60187db96d56Sopenharmony_ci int days, seconds; 60197db96d56Sopenharmony_ci 60207db96d56Sopenharmony_ci assert(HASTZINFO(self)); 60217db96d56Sopenharmony_ci days = ymd_to_ord(GET_YEAR(self), 60227db96d56Sopenharmony_ci GET_MONTH(self), 60237db96d56Sopenharmony_ci GET_DAY(self)); 60247db96d56Sopenharmony_ci seconds = DATE_GET_HOUR(self) * 3600 + 60257db96d56Sopenharmony_ci DATE_GET_MINUTE(self) * 60 + 60267db96d56Sopenharmony_ci DATE_GET_SECOND(self); 60277db96d56Sopenharmony_ci temp1 = new_delta(days, seconds, 60287db96d56Sopenharmony_ci DATE_GET_MICROSECOND(self), 60297db96d56Sopenharmony_ci 1); 60307db96d56Sopenharmony_ci if (temp1 == NULL) { 60317db96d56Sopenharmony_ci Py_DECREF(offset); 60327db96d56Sopenharmony_ci return -1; 60337db96d56Sopenharmony_ci } 60347db96d56Sopenharmony_ci temp2 = delta_subtract(temp1, offset); 60357db96d56Sopenharmony_ci Py_DECREF(temp1); 60367db96d56Sopenharmony_ci if (temp2 == NULL) { 60377db96d56Sopenharmony_ci Py_DECREF(offset); 60387db96d56Sopenharmony_ci return -1; 60397db96d56Sopenharmony_ci } 60407db96d56Sopenharmony_ci self->hashcode = PyObject_Hash(temp2); 60417db96d56Sopenharmony_ci Py_DECREF(temp2); 60427db96d56Sopenharmony_ci } 60437db96d56Sopenharmony_ci Py_DECREF(offset); 60447db96d56Sopenharmony_ci } 60457db96d56Sopenharmony_ci return self->hashcode; 60467db96d56Sopenharmony_ci} 60477db96d56Sopenharmony_ci 60487db96d56Sopenharmony_cistatic PyObject * 60497db96d56Sopenharmony_cidatetime_replace(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) 60507db96d56Sopenharmony_ci{ 60517db96d56Sopenharmony_ci PyObject *clone; 60527db96d56Sopenharmony_ci PyObject *tuple; 60537db96d56Sopenharmony_ci int y = GET_YEAR(self); 60547db96d56Sopenharmony_ci int m = GET_MONTH(self); 60557db96d56Sopenharmony_ci int d = GET_DAY(self); 60567db96d56Sopenharmony_ci int hh = DATE_GET_HOUR(self); 60577db96d56Sopenharmony_ci int mm = DATE_GET_MINUTE(self); 60587db96d56Sopenharmony_ci int ss = DATE_GET_SECOND(self); 60597db96d56Sopenharmony_ci int us = DATE_GET_MICROSECOND(self); 60607db96d56Sopenharmony_ci PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None; 60617db96d56Sopenharmony_ci int fold = DATE_GET_FOLD(self); 60627db96d56Sopenharmony_ci 60637db96d56Sopenharmony_ci if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO$i:replace", 60647db96d56Sopenharmony_ci datetime_kws, 60657db96d56Sopenharmony_ci &y, &m, &d, &hh, &mm, &ss, &us, 60667db96d56Sopenharmony_ci &tzinfo, &fold)) 60677db96d56Sopenharmony_ci return NULL; 60687db96d56Sopenharmony_ci if (fold != 0 && fold != 1) { 60697db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 60707db96d56Sopenharmony_ci "fold must be either 0 or 1"); 60717db96d56Sopenharmony_ci return NULL; 60727db96d56Sopenharmony_ci } 60737db96d56Sopenharmony_ci tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo); 60747db96d56Sopenharmony_ci if (tuple == NULL) 60757db96d56Sopenharmony_ci return NULL; 60767db96d56Sopenharmony_ci clone = datetime_new(Py_TYPE(self), tuple, NULL); 60777db96d56Sopenharmony_ci if (clone != NULL) { 60787db96d56Sopenharmony_ci DATE_SET_FOLD(clone, fold); 60797db96d56Sopenharmony_ci } 60807db96d56Sopenharmony_ci Py_DECREF(tuple); 60817db96d56Sopenharmony_ci return clone; 60827db96d56Sopenharmony_ci} 60837db96d56Sopenharmony_ci 60847db96d56Sopenharmony_cistatic PyObject * 60857db96d56Sopenharmony_cilocal_timezone_from_timestamp(time_t timestamp) 60867db96d56Sopenharmony_ci{ 60877db96d56Sopenharmony_ci PyObject *result = NULL; 60887db96d56Sopenharmony_ci PyObject *delta; 60897db96d56Sopenharmony_ci struct tm local_time_tm; 60907db96d56Sopenharmony_ci PyObject *nameo = NULL; 60917db96d56Sopenharmony_ci const char *zone = NULL; 60927db96d56Sopenharmony_ci 60937db96d56Sopenharmony_ci if (_PyTime_localtime(timestamp, &local_time_tm) != 0) 60947db96d56Sopenharmony_ci return NULL; 60957db96d56Sopenharmony_ci#ifdef HAVE_STRUCT_TM_TM_ZONE 60967db96d56Sopenharmony_ci zone = local_time_tm.tm_zone; 60977db96d56Sopenharmony_ci delta = new_delta(0, local_time_tm.tm_gmtoff, 0, 1); 60987db96d56Sopenharmony_ci#else /* HAVE_STRUCT_TM_TM_ZONE */ 60997db96d56Sopenharmony_ci { 61007db96d56Sopenharmony_ci PyObject *local_time, *utc_time; 61017db96d56Sopenharmony_ci struct tm utc_time_tm; 61027db96d56Sopenharmony_ci char buf[100]; 61037db96d56Sopenharmony_ci strftime(buf, sizeof(buf), "%Z", &local_time_tm); 61047db96d56Sopenharmony_ci zone = buf; 61057db96d56Sopenharmony_ci local_time = new_datetime(local_time_tm.tm_year + 1900, 61067db96d56Sopenharmony_ci local_time_tm.tm_mon + 1, 61077db96d56Sopenharmony_ci local_time_tm.tm_mday, 61087db96d56Sopenharmony_ci local_time_tm.tm_hour, 61097db96d56Sopenharmony_ci local_time_tm.tm_min, 61107db96d56Sopenharmony_ci local_time_tm.tm_sec, 0, Py_None, 0); 61117db96d56Sopenharmony_ci if (local_time == NULL) { 61127db96d56Sopenharmony_ci return NULL; 61137db96d56Sopenharmony_ci } 61147db96d56Sopenharmony_ci if (_PyTime_gmtime(timestamp, &utc_time_tm) != 0) 61157db96d56Sopenharmony_ci return NULL; 61167db96d56Sopenharmony_ci utc_time = new_datetime(utc_time_tm.tm_year + 1900, 61177db96d56Sopenharmony_ci utc_time_tm.tm_mon + 1, 61187db96d56Sopenharmony_ci utc_time_tm.tm_mday, 61197db96d56Sopenharmony_ci utc_time_tm.tm_hour, 61207db96d56Sopenharmony_ci utc_time_tm.tm_min, 61217db96d56Sopenharmony_ci utc_time_tm.tm_sec, 0, Py_None, 0); 61227db96d56Sopenharmony_ci if (utc_time == NULL) { 61237db96d56Sopenharmony_ci Py_DECREF(local_time); 61247db96d56Sopenharmony_ci return NULL; 61257db96d56Sopenharmony_ci } 61267db96d56Sopenharmony_ci delta = datetime_subtract(local_time, utc_time); 61277db96d56Sopenharmony_ci Py_DECREF(local_time); 61287db96d56Sopenharmony_ci Py_DECREF(utc_time); 61297db96d56Sopenharmony_ci } 61307db96d56Sopenharmony_ci#endif /* HAVE_STRUCT_TM_TM_ZONE */ 61317db96d56Sopenharmony_ci if (delta == NULL) { 61327db96d56Sopenharmony_ci return NULL; 61337db96d56Sopenharmony_ci } 61347db96d56Sopenharmony_ci if (zone != NULL) { 61357db96d56Sopenharmony_ci nameo = PyUnicode_DecodeLocale(zone, "surrogateescape"); 61367db96d56Sopenharmony_ci if (nameo == NULL) 61377db96d56Sopenharmony_ci goto error; 61387db96d56Sopenharmony_ci } 61397db96d56Sopenharmony_ci result = new_timezone(delta, nameo); 61407db96d56Sopenharmony_ci Py_XDECREF(nameo); 61417db96d56Sopenharmony_ci error: 61427db96d56Sopenharmony_ci Py_DECREF(delta); 61437db96d56Sopenharmony_ci return result; 61447db96d56Sopenharmony_ci} 61457db96d56Sopenharmony_ci 61467db96d56Sopenharmony_cistatic PyObject * 61477db96d56Sopenharmony_cilocal_timezone(PyDateTime_DateTime *utc_time) 61487db96d56Sopenharmony_ci{ 61497db96d56Sopenharmony_ci time_t timestamp; 61507db96d56Sopenharmony_ci PyObject *delta; 61517db96d56Sopenharmony_ci PyObject *one_second; 61527db96d56Sopenharmony_ci PyObject *seconds; 61537db96d56Sopenharmony_ci 61547db96d56Sopenharmony_ci delta = datetime_subtract((PyObject *)utc_time, PyDateTime_Epoch); 61557db96d56Sopenharmony_ci if (delta == NULL) 61567db96d56Sopenharmony_ci return NULL; 61577db96d56Sopenharmony_ci one_second = new_delta(0, 1, 0, 0); 61587db96d56Sopenharmony_ci if (one_second == NULL) { 61597db96d56Sopenharmony_ci Py_DECREF(delta); 61607db96d56Sopenharmony_ci return NULL; 61617db96d56Sopenharmony_ci } 61627db96d56Sopenharmony_ci seconds = divide_timedelta_timedelta((PyDateTime_Delta *)delta, 61637db96d56Sopenharmony_ci (PyDateTime_Delta *)one_second); 61647db96d56Sopenharmony_ci Py_DECREF(one_second); 61657db96d56Sopenharmony_ci Py_DECREF(delta); 61667db96d56Sopenharmony_ci if (seconds == NULL) 61677db96d56Sopenharmony_ci return NULL; 61687db96d56Sopenharmony_ci timestamp = _PyLong_AsTime_t(seconds); 61697db96d56Sopenharmony_ci Py_DECREF(seconds); 61707db96d56Sopenharmony_ci if (timestamp == -1 && PyErr_Occurred()) 61717db96d56Sopenharmony_ci return NULL; 61727db96d56Sopenharmony_ci return local_timezone_from_timestamp(timestamp); 61737db96d56Sopenharmony_ci} 61747db96d56Sopenharmony_ci 61757db96d56Sopenharmony_cistatic long long 61767db96d56Sopenharmony_cilocal_to_seconds(int year, int month, int day, 61777db96d56Sopenharmony_ci int hour, int minute, int second, int fold); 61787db96d56Sopenharmony_ci 61797db96d56Sopenharmony_cistatic PyObject * 61807db96d56Sopenharmony_cilocal_timezone_from_local(PyDateTime_DateTime *local_dt) 61817db96d56Sopenharmony_ci{ 61827db96d56Sopenharmony_ci long long seconds; 61837db96d56Sopenharmony_ci time_t timestamp; 61847db96d56Sopenharmony_ci seconds = local_to_seconds(GET_YEAR(local_dt), 61857db96d56Sopenharmony_ci GET_MONTH(local_dt), 61867db96d56Sopenharmony_ci GET_DAY(local_dt), 61877db96d56Sopenharmony_ci DATE_GET_HOUR(local_dt), 61887db96d56Sopenharmony_ci DATE_GET_MINUTE(local_dt), 61897db96d56Sopenharmony_ci DATE_GET_SECOND(local_dt), 61907db96d56Sopenharmony_ci DATE_GET_FOLD(local_dt)); 61917db96d56Sopenharmony_ci if (seconds == -1) 61927db96d56Sopenharmony_ci return NULL; 61937db96d56Sopenharmony_ci /* XXX: add bounds check */ 61947db96d56Sopenharmony_ci timestamp = seconds - epoch; 61957db96d56Sopenharmony_ci return local_timezone_from_timestamp(timestamp); 61967db96d56Sopenharmony_ci} 61977db96d56Sopenharmony_ci 61987db96d56Sopenharmony_cistatic PyDateTime_DateTime * 61997db96d56Sopenharmony_cidatetime_astimezone(PyDateTime_DateTime *self, PyObject *args, PyObject *kw) 62007db96d56Sopenharmony_ci{ 62017db96d56Sopenharmony_ci PyDateTime_DateTime *result; 62027db96d56Sopenharmony_ci PyObject *offset; 62037db96d56Sopenharmony_ci PyObject *temp; 62047db96d56Sopenharmony_ci PyObject *self_tzinfo; 62057db96d56Sopenharmony_ci PyObject *tzinfo = Py_None; 62067db96d56Sopenharmony_ci static char *keywords[] = {"tz", NULL}; 62077db96d56Sopenharmony_ci 62087db96d56Sopenharmony_ci if (! PyArg_ParseTupleAndKeywords(args, kw, "|O:astimezone", keywords, 62097db96d56Sopenharmony_ci &tzinfo)) 62107db96d56Sopenharmony_ci return NULL; 62117db96d56Sopenharmony_ci 62127db96d56Sopenharmony_ci if (check_tzinfo_subclass(tzinfo) == -1) 62137db96d56Sopenharmony_ci return NULL; 62147db96d56Sopenharmony_ci 62157db96d56Sopenharmony_ci if (!HASTZINFO(self) || self->tzinfo == Py_None) { 62167db96d56Sopenharmony_ci naive: 62177db96d56Sopenharmony_ci self_tzinfo = local_timezone_from_local(self); 62187db96d56Sopenharmony_ci if (self_tzinfo == NULL) 62197db96d56Sopenharmony_ci return NULL; 62207db96d56Sopenharmony_ci } else { 62217db96d56Sopenharmony_ci self_tzinfo = self->tzinfo; 62227db96d56Sopenharmony_ci Py_INCREF(self_tzinfo); 62237db96d56Sopenharmony_ci } 62247db96d56Sopenharmony_ci 62257db96d56Sopenharmony_ci /* Conversion to self's own time zone is a NOP. */ 62267db96d56Sopenharmony_ci if (self_tzinfo == tzinfo) { 62277db96d56Sopenharmony_ci Py_DECREF(self_tzinfo); 62287db96d56Sopenharmony_ci Py_INCREF(self); 62297db96d56Sopenharmony_ci return self; 62307db96d56Sopenharmony_ci } 62317db96d56Sopenharmony_ci 62327db96d56Sopenharmony_ci /* Convert self to UTC. */ 62337db96d56Sopenharmony_ci offset = call_utcoffset(self_tzinfo, (PyObject *)self); 62347db96d56Sopenharmony_ci Py_DECREF(self_tzinfo); 62357db96d56Sopenharmony_ci if (offset == NULL) 62367db96d56Sopenharmony_ci return NULL; 62377db96d56Sopenharmony_ci else if(offset == Py_None) { 62387db96d56Sopenharmony_ci Py_DECREF(offset); 62397db96d56Sopenharmony_ci goto naive; 62407db96d56Sopenharmony_ci } 62417db96d56Sopenharmony_ci else if (!PyDelta_Check(offset)) { 62427db96d56Sopenharmony_ci Py_DECREF(offset); 62437db96d56Sopenharmony_ci PyErr_Format(PyExc_TypeError, "utcoffset() returned %.200s," 62447db96d56Sopenharmony_ci " expected timedelta or None", Py_TYPE(offset)->tp_name); 62457db96d56Sopenharmony_ci return NULL; 62467db96d56Sopenharmony_ci } 62477db96d56Sopenharmony_ci /* result = self - offset */ 62487db96d56Sopenharmony_ci result = (PyDateTime_DateTime *)add_datetime_timedelta(self, 62497db96d56Sopenharmony_ci (PyDateTime_Delta *)offset, -1); 62507db96d56Sopenharmony_ci Py_DECREF(offset); 62517db96d56Sopenharmony_ci if (result == NULL) 62527db96d56Sopenharmony_ci return NULL; 62537db96d56Sopenharmony_ci 62547db96d56Sopenharmony_ci /* Make sure result is aware and UTC. */ 62557db96d56Sopenharmony_ci if (!HASTZINFO(result)) { 62567db96d56Sopenharmony_ci temp = (PyObject *)result; 62577db96d56Sopenharmony_ci result = (PyDateTime_DateTime *) 62587db96d56Sopenharmony_ci new_datetime_ex2(GET_YEAR(result), 62597db96d56Sopenharmony_ci GET_MONTH(result), 62607db96d56Sopenharmony_ci GET_DAY(result), 62617db96d56Sopenharmony_ci DATE_GET_HOUR(result), 62627db96d56Sopenharmony_ci DATE_GET_MINUTE(result), 62637db96d56Sopenharmony_ci DATE_GET_SECOND(result), 62647db96d56Sopenharmony_ci DATE_GET_MICROSECOND(result), 62657db96d56Sopenharmony_ci PyDateTime_TimeZone_UTC, 62667db96d56Sopenharmony_ci DATE_GET_FOLD(result), 62677db96d56Sopenharmony_ci Py_TYPE(result)); 62687db96d56Sopenharmony_ci Py_DECREF(temp); 62697db96d56Sopenharmony_ci if (result == NULL) 62707db96d56Sopenharmony_ci return NULL; 62717db96d56Sopenharmony_ci } 62727db96d56Sopenharmony_ci else { 62737db96d56Sopenharmony_ci /* Result is already aware - just replace tzinfo. */ 62747db96d56Sopenharmony_ci temp = result->tzinfo; 62757db96d56Sopenharmony_ci result->tzinfo = PyDateTime_TimeZone_UTC; 62767db96d56Sopenharmony_ci Py_INCREF(result->tzinfo); 62777db96d56Sopenharmony_ci Py_DECREF(temp); 62787db96d56Sopenharmony_ci } 62797db96d56Sopenharmony_ci 62807db96d56Sopenharmony_ci /* Attach new tzinfo and let fromutc() do the rest. */ 62817db96d56Sopenharmony_ci temp = result->tzinfo; 62827db96d56Sopenharmony_ci if (tzinfo == Py_None) { 62837db96d56Sopenharmony_ci tzinfo = local_timezone(result); 62847db96d56Sopenharmony_ci if (tzinfo == NULL) { 62857db96d56Sopenharmony_ci Py_DECREF(result); 62867db96d56Sopenharmony_ci return NULL; 62877db96d56Sopenharmony_ci } 62887db96d56Sopenharmony_ci } 62897db96d56Sopenharmony_ci else 62907db96d56Sopenharmony_ci Py_INCREF(tzinfo); 62917db96d56Sopenharmony_ci result->tzinfo = tzinfo; 62927db96d56Sopenharmony_ci Py_DECREF(temp); 62937db96d56Sopenharmony_ci 62947db96d56Sopenharmony_ci temp = (PyObject *)result; 62957db96d56Sopenharmony_ci result = (PyDateTime_DateTime *) 62967db96d56Sopenharmony_ci _PyObject_CallMethodIdOneArg(tzinfo, &PyId_fromutc, temp); 62977db96d56Sopenharmony_ci Py_DECREF(temp); 62987db96d56Sopenharmony_ci 62997db96d56Sopenharmony_ci return result; 63007db96d56Sopenharmony_ci} 63017db96d56Sopenharmony_ci 63027db96d56Sopenharmony_cistatic PyObject * 63037db96d56Sopenharmony_cidatetime_timetuple(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) 63047db96d56Sopenharmony_ci{ 63057db96d56Sopenharmony_ci int dstflag = -1; 63067db96d56Sopenharmony_ci 63077db96d56Sopenharmony_ci if (HASTZINFO(self) && self->tzinfo != Py_None) { 63087db96d56Sopenharmony_ci PyObject * dst; 63097db96d56Sopenharmony_ci 63107db96d56Sopenharmony_ci dst = call_dst(self->tzinfo, (PyObject *)self); 63117db96d56Sopenharmony_ci if (dst == NULL) 63127db96d56Sopenharmony_ci return NULL; 63137db96d56Sopenharmony_ci 63147db96d56Sopenharmony_ci if (dst != Py_None) 63157db96d56Sopenharmony_ci dstflag = delta_bool((PyDateTime_Delta *)dst); 63167db96d56Sopenharmony_ci Py_DECREF(dst); 63177db96d56Sopenharmony_ci } 63187db96d56Sopenharmony_ci return build_struct_time(GET_YEAR(self), 63197db96d56Sopenharmony_ci GET_MONTH(self), 63207db96d56Sopenharmony_ci GET_DAY(self), 63217db96d56Sopenharmony_ci DATE_GET_HOUR(self), 63227db96d56Sopenharmony_ci DATE_GET_MINUTE(self), 63237db96d56Sopenharmony_ci DATE_GET_SECOND(self), 63247db96d56Sopenharmony_ci dstflag); 63257db96d56Sopenharmony_ci} 63267db96d56Sopenharmony_ci 63277db96d56Sopenharmony_cistatic long long 63287db96d56Sopenharmony_cilocal_to_seconds(int year, int month, int day, 63297db96d56Sopenharmony_ci int hour, int minute, int second, int fold) 63307db96d56Sopenharmony_ci{ 63317db96d56Sopenharmony_ci long long t, a, b, u1, u2, t1, t2, lt; 63327db96d56Sopenharmony_ci t = utc_to_seconds(year, month, day, hour, minute, second); 63337db96d56Sopenharmony_ci /* Our goal is to solve t = local(u) for u. */ 63347db96d56Sopenharmony_ci lt = local(t); 63357db96d56Sopenharmony_ci if (lt == -1) 63367db96d56Sopenharmony_ci return -1; 63377db96d56Sopenharmony_ci a = lt - t; 63387db96d56Sopenharmony_ci u1 = t - a; 63397db96d56Sopenharmony_ci t1 = local(u1); 63407db96d56Sopenharmony_ci if (t1 == -1) 63417db96d56Sopenharmony_ci return -1; 63427db96d56Sopenharmony_ci if (t1 == t) { 63437db96d56Sopenharmony_ci /* We found one solution, but it may not be the one we need. 63447db96d56Sopenharmony_ci * Look for an earlier solution (if `fold` is 0), or a 63457db96d56Sopenharmony_ci * later one (if `fold` is 1). */ 63467db96d56Sopenharmony_ci if (fold) 63477db96d56Sopenharmony_ci u2 = u1 + max_fold_seconds; 63487db96d56Sopenharmony_ci else 63497db96d56Sopenharmony_ci u2 = u1 - max_fold_seconds; 63507db96d56Sopenharmony_ci lt = local(u2); 63517db96d56Sopenharmony_ci if (lt == -1) 63527db96d56Sopenharmony_ci return -1; 63537db96d56Sopenharmony_ci b = lt - u2; 63547db96d56Sopenharmony_ci if (a == b) 63557db96d56Sopenharmony_ci return u1; 63567db96d56Sopenharmony_ci } 63577db96d56Sopenharmony_ci else { 63587db96d56Sopenharmony_ci b = t1 - u1; 63597db96d56Sopenharmony_ci assert(a != b); 63607db96d56Sopenharmony_ci } 63617db96d56Sopenharmony_ci u2 = t - b; 63627db96d56Sopenharmony_ci t2 = local(u2); 63637db96d56Sopenharmony_ci if (t2 == -1) 63647db96d56Sopenharmony_ci return -1; 63657db96d56Sopenharmony_ci if (t2 == t) 63667db96d56Sopenharmony_ci return u2; 63677db96d56Sopenharmony_ci if (t1 == t) 63687db96d56Sopenharmony_ci return u1; 63697db96d56Sopenharmony_ci /* We have found both offsets a and b, but neither t - a nor t - b is 63707db96d56Sopenharmony_ci * a solution. This means t is in the gap. */ 63717db96d56Sopenharmony_ci return fold?Py_MIN(u1, u2):Py_MAX(u1, u2); 63727db96d56Sopenharmony_ci} 63737db96d56Sopenharmony_ci 63747db96d56Sopenharmony_ci/* date(1970,1,1).toordinal() == 719163 */ 63757db96d56Sopenharmony_ci#define EPOCH_SECONDS (719163LL * 24 * 60 * 60) 63767db96d56Sopenharmony_ci 63777db96d56Sopenharmony_cistatic PyObject * 63787db96d56Sopenharmony_cidatetime_timestamp(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) 63797db96d56Sopenharmony_ci{ 63807db96d56Sopenharmony_ci PyObject *result; 63817db96d56Sopenharmony_ci 63827db96d56Sopenharmony_ci if (HASTZINFO(self) && self->tzinfo != Py_None) { 63837db96d56Sopenharmony_ci PyObject *delta; 63847db96d56Sopenharmony_ci delta = datetime_subtract((PyObject *)self, PyDateTime_Epoch); 63857db96d56Sopenharmony_ci if (delta == NULL) 63867db96d56Sopenharmony_ci return NULL; 63877db96d56Sopenharmony_ci result = delta_total_seconds(delta, NULL); 63887db96d56Sopenharmony_ci Py_DECREF(delta); 63897db96d56Sopenharmony_ci } 63907db96d56Sopenharmony_ci else { 63917db96d56Sopenharmony_ci long long seconds; 63927db96d56Sopenharmony_ci seconds = local_to_seconds(GET_YEAR(self), 63937db96d56Sopenharmony_ci GET_MONTH(self), 63947db96d56Sopenharmony_ci GET_DAY(self), 63957db96d56Sopenharmony_ci DATE_GET_HOUR(self), 63967db96d56Sopenharmony_ci DATE_GET_MINUTE(self), 63977db96d56Sopenharmony_ci DATE_GET_SECOND(self), 63987db96d56Sopenharmony_ci DATE_GET_FOLD(self)); 63997db96d56Sopenharmony_ci if (seconds == -1) 64007db96d56Sopenharmony_ci return NULL; 64017db96d56Sopenharmony_ci result = PyFloat_FromDouble(seconds - EPOCH_SECONDS + 64027db96d56Sopenharmony_ci DATE_GET_MICROSECOND(self) / 1e6); 64037db96d56Sopenharmony_ci } 64047db96d56Sopenharmony_ci return result; 64057db96d56Sopenharmony_ci} 64067db96d56Sopenharmony_ci 64077db96d56Sopenharmony_cistatic PyObject * 64087db96d56Sopenharmony_cidatetime_getdate(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) 64097db96d56Sopenharmony_ci{ 64107db96d56Sopenharmony_ci return new_date(GET_YEAR(self), 64117db96d56Sopenharmony_ci GET_MONTH(self), 64127db96d56Sopenharmony_ci GET_DAY(self)); 64137db96d56Sopenharmony_ci} 64147db96d56Sopenharmony_ci 64157db96d56Sopenharmony_cistatic PyObject * 64167db96d56Sopenharmony_cidatetime_gettime(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) 64177db96d56Sopenharmony_ci{ 64187db96d56Sopenharmony_ci return new_time(DATE_GET_HOUR(self), 64197db96d56Sopenharmony_ci DATE_GET_MINUTE(self), 64207db96d56Sopenharmony_ci DATE_GET_SECOND(self), 64217db96d56Sopenharmony_ci DATE_GET_MICROSECOND(self), 64227db96d56Sopenharmony_ci Py_None, 64237db96d56Sopenharmony_ci DATE_GET_FOLD(self)); 64247db96d56Sopenharmony_ci} 64257db96d56Sopenharmony_ci 64267db96d56Sopenharmony_cistatic PyObject * 64277db96d56Sopenharmony_cidatetime_gettimetz(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) 64287db96d56Sopenharmony_ci{ 64297db96d56Sopenharmony_ci return new_time(DATE_GET_HOUR(self), 64307db96d56Sopenharmony_ci DATE_GET_MINUTE(self), 64317db96d56Sopenharmony_ci DATE_GET_SECOND(self), 64327db96d56Sopenharmony_ci DATE_GET_MICROSECOND(self), 64337db96d56Sopenharmony_ci GET_DT_TZINFO(self), 64347db96d56Sopenharmony_ci DATE_GET_FOLD(self)); 64357db96d56Sopenharmony_ci} 64367db96d56Sopenharmony_ci 64377db96d56Sopenharmony_cistatic PyObject * 64387db96d56Sopenharmony_cidatetime_utctimetuple(PyDateTime_DateTime *self, PyObject *Py_UNUSED(ignored)) 64397db96d56Sopenharmony_ci{ 64407db96d56Sopenharmony_ci int y, m, d, hh, mm, ss; 64417db96d56Sopenharmony_ci PyObject *tzinfo; 64427db96d56Sopenharmony_ci PyDateTime_DateTime *utcself; 64437db96d56Sopenharmony_ci 64447db96d56Sopenharmony_ci tzinfo = GET_DT_TZINFO(self); 64457db96d56Sopenharmony_ci if (tzinfo == Py_None) { 64467db96d56Sopenharmony_ci utcself = self; 64477db96d56Sopenharmony_ci Py_INCREF(utcself); 64487db96d56Sopenharmony_ci } 64497db96d56Sopenharmony_ci else { 64507db96d56Sopenharmony_ci PyObject *offset; 64517db96d56Sopenharmony_ci offset = call_utcoffset(tzinfo, (PyObject *)self); 64527db96d56Sopenharmony_ci if (offset == NULL) 64537db96d56Sopenharmony_ci return NULL; 64547db96d56Sopenharmony_ci if (offset == Py_None) { 64557db96d56Sopenharmony_ci Py_DECREF(offset); 64567db96d56Sopenharmony_ci utcself = self; 64577db96d56Sopenharmony_ci Py_INCREF(utcself); 64587db96d56Sopenharmony_ci } 64597db96d56Sopenharmony_ci else { 64607db96d56Sopenharmony_ci utcself = (PyDateTime_DateTime *)add_datetime_timedelta(self, 64617db96d56Sopenharmony_ci (PyDateTime_Delta *)offset, -1); 64627db96d56Sopenharmony_ci Py_DECREF(offset); 64637db96d56Sopenharmony_ci if (utcself == NULL) 64647db96d56Sopenharmony_ci return NULL; 64657db96d56Sopenharmony_ci } 64667db96d56Sopenharmony_ci } 64677db96d56Sopenharmony_ci y = GET_YEAR(utcself); 64687db96d56Sopenharmony_ci m = GET_MONTH(utcself); 64697db96d56Sopenharmony_ci d = GET_DAY(utcself); 64707db96d56Sopenharmony_ci hh = DATE_GET_HOUR(utcself); 64717db96d56Sopenharmony_ci mm = DATE_GET_MINUTE(utcself); 64727db96d56Sopenharmony_ci ss = DATE_GET_SECOND(utcself); 64737db96d56Sopenharmony_ci 64747db96d56Sopenharmony_ci Py_DECREF(utcself); 64757db96d56Sopenharmony_ci return build_struct_time(y, m, d, hh, mm, ss, 0); 64767db96d56Sopenharmony_ci} 64777db96d56Sopenharmony_ci 64787db96d56Sopenharmony_ci/* Pickle support, a simple use of __reduce__. */ 64797db96d56Sopenharmony_ci 64807db96d56Sopenharmony_ci/* Let basestate be the non-tzinfo data string. 64817db96d56Sopenharmony_ci * If tzinfo is None, this returns (basestate,), else (basestate, tzinfo). 64827db96d56Sopenharmony_ci * So it's a tuple in any (non-error) case. 64837db96d56Sopenharmony_ci * __getstate__ isn't exposed. 64847db96d56Sopenharmony_ci */ 64857db96d56Sopenharmony_cistatic PyObject * 64867db96d56Sopenharmony_cidatetime_getstate(PyDateTime_DateTime *self, int proto) 64877db96d56Sopenharmony_ci{ 64887db96d56Sopenharmony_ci PyObject *basestate; 64897db96d56Sopenharmony_ci PyObject *result = NULL; 64907db96d56Sopenharmony_ci 64917db96d56Sopenharmony_ci basestate = PyBytes_FromStringAndSize((char *)self->data, 64927db96d56Sopenharmony_ci _PyDateTime_DATETIME_DATASIZE); 64937db96d56Sopenharmony_ci if (basestate != NULL) { 64947db96d56Sopenharmony_ci if (proto > 3 && DATE_GET_FOLD(self)) 64957db96d56Sopenharmony_ci /* Set the first bit of the third byte */ 64967db96d56Sopenharmony_ci PyBytes_AS_STRING(basestate)[2] |= (1 << 7); 64977db96d56Sopenharmony_ci if (! HASTZINFO(self) || self->tzinfo == Py_None) 64987db96d56Sopenharmony_ci result = PyTuple_Pack(1, basestate); 64997db96d56Sopenharmony_ci else 65007db96d56Sopenharmony_ci result = PyTuple_Pack(2, basestate, self->tzinfo); 65017db96d56Sopenharmony_ci Py_DECREF(basestate); 65027db96d56Sopenharmony_ci } 65037db96d56Sopenharmony_ci return result; 65047db96d56Sopenharmony_ci} 65057db96d56Sopenharmony_ci 65067db96d56Sopenharmony_cistatic PyObject * 65077db96d56Sopenharmony_cidatetime_reduce_ex(PyDateTime_DateTime *self, PyObject *args) 65087db96d56Sopenharmony_ci{ 65097db96d56Sopenharmony_ci int proto; 65107db96d56Sopenharmony_ci if (!PyArg_ParseTuple(args, "i:__reduce_ex__", &proto)) 65117db96d56Sopenharmony_ci return NULL; 65127db96d56Sopenharmony_ci 65137db96d56Sopenharmony_ci return Py_BuildValue("(ON)", Py_TYPE(self), datetime_getstate(self, proto)); 65147db96d56Sopenharmony_ci} 65157db96d56Sopenharmony_ci 65167db96d56Sopenharmony_cistatic PyObject * 65177db96d56Sopenharmony_cidatetime_reduce(PyDateTime_DateTime *self, PyObject *arg) 65187db96d56Sopenharmony_ci{ 65197db96d56Sopenharmony_ci return Py_BuildValue("(ON)", Py_TYPE(self), datetime_getstate(self, 2)); 65207db96d56Sopenharmony_ci} 65217db96d56Sopenharmony_ci 65227db96d56Sopenharmony_cistatic PyMethodDef datetime_methods[] = { 65237db96d56Sopenharmony_ci 65247db96d56Sopenharmony_ci /* Class methods: */ 65257db96d56Sopenharmony_ci 65267db96d56Sopenharmony_ci DATETIME_DATETIME_NOW_METHODDEF 65277db96d56Sopenharmony_ci 65287db96d56Sopenharmony_ci {"utcnow", (PyCFunction)datetime_utcnow, 65297db96d56Sopenharmony_ci METH_NOARGS | METH_CLASS, 65307db96d56Sopenharmony_ci PyDoc_STR("Return a new datetime representing UTC day and time.")}, 65317db96d56Sopenharmony_ci 65327db96d56Sopenharmony_ci {"fromtimestamp", _PyCFunction_CAST(datetime_fromtimestamp), 65337db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS | METH_CLASS, 65347db96d56Sopenharmony_ci PyDoc_STR("timestamp[, tz] -> tz's local time from POSIX timestamp.")}, 65357db96d56Sopenharmony_ci 65367db96d56Sopenharmony_ci {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp, 65377db96d56Sopenharmony_ci METH_VARARGS | METH_CLASS, 65387db96d56Sopenharmony_ci PyDoc_STR("Construct a naive UTC datetime from a POSIX timestamp.")}, 65397db96d56Sopenharmony_ci 65407db96d56Sopenharmony_ci {"strptime", (PyCFunction)datetime_strptime, 65417db96d56Sopenharmony_ci METH_VARARGS | METH_CLASS, 65427db96d56Sopenharmony_ci PyDoc_STR("string, format -> new datetime parsed from a string " 65437db96d56Sopenharmony_ci "(like time.strptime()).")}, 65447db96d56Sopenharmony_ci 65457db96d56Sopenharmony_ci {"combine", _PyCFunction_CAST(datetime_combine), 65467db96d56Sopenharmony_ci METH_VARARGS | METH_KEYWORDS | METH_CLASS, 65477db96d56Sopenharmony_ci PyDoc_STR("date, time -> datetime with same date and time fields")}, 65487db96d56Sopenharmony_ci 65497db96d56Sopenharmony_ci {"fromisoformat", (PyCFunction)datetime_fromisoformat, 65507db96d56Sopenharmony_ci METH_O | METH_CLASS, 65517db96d56Sopenharmony_ci PyDoc_STR("string -> datetime from a string in most ISO 8601 formats")}, 65527db96d56Sopenharmony_ci 65537db96d56Sopenharmony_ci /* Instance methods: */ 65547db96d56Sopenharmony_ci 65557db96d56Sopenharmony_ci {"date", (PyCFunction)datetime_getdate, METH_NOARGS, 65567db96d56Sopenharmony_ci PyDoc_STR("Return date object with same year, month and day.")}, 65577db96d56Sopenharmony_ci 65587db96d56Sopenharmony_ci {"time", (PyCFunction)datetime_gettime, METH_NOARGS, 65597db96d56Sopenharmony_ci PyDoc_STR("Return time object with same time but with tzinfo=None.")}, 65607db96d56Sopenharmony_ci 65617db96d56Sopenharmony_ci {"timetz", (PyCFunction)datetime_gettimetz, METH_NOARGS, 65627db96d56Sopenharmony_ci PyDoc_STR("Return time object with same time and tzinfo.")}, 65637db96d56Sopenharmony_ci 65647db96d56Sopenharmony_ci {"ctime", (PyCFunction)datetime_ctime, METH_NOARGS, 65657db96d56Sopenharmony_ci PyDoc_STR("Return ctime() style string.")}, 65667db96d56Sopenharmony_ci 65677db96d56Sopenharmony_ci {"timetuple", (PyCFunction)datetime_timetuple, METH_NOARGS, 65687db96d56Sopenharmony_ci PyDoc_STR("Return time tuple, compatible with time.localtime().")}, 65697db96d56Sopenharmony_ci 65707db96d56Sopenharmony_ci {"timestamp", (PyCFunction)datetime_timestamp, METH_NOARGS, 65717db96d56Sopenharmony_ci PyDoc_STR("Return POSIX timestamp as float.")}, 65727db96d56Sopenharmony_ci 65737db96d56Sopenharmony_ci {"utctimetuple", (PyCFunction)datetime_utctimetuple, METH_NOARGS, 65747db96d56Sopenharmony_ci PyDoc_STR("Return UTC time tuple, compatible with time.localtime().")}, 65757db96d56Sopenharmony_ci 65767db96d56Sopenharmony_ci {"isoformat", _PyCFunction_CAST(datetime_isoformat), METH_VARARGS | METH_KEYWORDS, 65777db96d56Sopenharmony_ci PyDoc_STR("[sep] -> string in ISO 8601 format, " 65787db96d56Sopenharmony_ci "YYYY-MM-DDT[HH[:MM[:SS[.mmm[uuu]]]]][+HH:MM].\n" 65797db96d56Sopenharmony_ci "sep is used to separate the year from the time, and " 65807db96d56Sopenharmony_ci "defaults to 'T'.\n" 65817db96d56Sopenharmony_ci "The optional argument timespec specifies the number " 65827db96d56Sopenharmony_ci "of additional terms\nof the time to include. Valid " 65837db96d56Sopenharmony_ci "options are 'auto', 'hours', 'minutes',\n'seconds', " 65847db96d56Sopenharmony_ci "'milliseconds' and 'microseconds'.\n")}, 65857db96d56Sopenharmony_ci 65867db96d56Sopenharmony_ci {"utcoffset", (PyCFunction)datetime_utcoffset, METH_NOARGS, 65877db96d56Sopenharmony_ci PyDoc_STR("Return self.tzinfo.utcoffset(self).")}, 65887db96d56Sopenharmony_ci 65897db96d56Sopenharmony_ci {"tzname", (PyCFunction)datetime_tzname, METH_NOARGS, 65907db96d56Sopenharmony_ci PyDoc_STR("Return self.tzinfo.tzname(self).")}, 65917db96d56Sopenharmony_ci 65927db96d56Sopenharmony_ci {"dst", (PyCFunction)datetime_dst, METH_NOARGS, 65937db96d56Sopenharmony_ci PyDoc_STR("Return self.tzinfo.dst(self).")}, 65947db96d56Sopenharmony_ci 65957db96d56Sopenharmony_ci {"replace", _PyCFunction_CAST(datetime_replace), METH_VARARGS | METH_KEYWORDS, 65967db96d56Sopenharmony_ci PyDoc_STR("Return datetime with new specified fields.")}, 65977db96d56Sopenharmony_ci 65987db96d56Sopenharmony_ci {"astimezone", _PyCFunction_CAST(datetime_astimezone), METH_VARARGS | METH_KEYWORDS, 65997db96d56Sopenharmony_ci PyDoc_STR("tz -> convert to local time in new timezone tz\n")}, 66007db96d56Sopenharmony_ci 66017db96d56Sopenharmony_ci {"__reduce_ex__", (PyCFunction)datetime_reduce_ex, METH_VARARGS, 66027db96d56Sopenharmony_ci PyDoc_STR("__reduce_ex__(proto) -> (cls, state)")}, 66037db96d56Sopenharmony_ci 66047db96d56Sopenharmony_ci {"__reduce__", (PyCFunction)datetime_reduce, METH_NOARGS, 66057db96d56Sopenharmony_ci PyDoc_STR("__reduce__() -> (cls, state)")}, 66067db96d56Sopenharmony_ci 66077db96d56Sopenharmony_ci {NULL, NULL} 66087db96d56Sopenharmony_ci}; 66097db96d56Sopenharmony_ci 66107db96d56Sopenharmony_cistatic const char datetime_doc[] = 66117db96d56Sopenharmony_ciPyDoc_STR("datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])\n\ 66127db96d56Sopenharmony_ci\n\ 66137db96d56Sopenharmony_ciThe year, month and day arguments are required. tzinfo may be None, or an\n\ 66147db96d56Sopenharmony_ciinstance of a tzinfo subclass. The remaining arguments may be ints.\n"); 66157db96d56Sopenharmony_ci 66167db96d56Sopenharmony_cistatic PyNumberMethods datetime_as_number = { 66177db96d56Sopenharmony_ci datetime_add, /* nb_add */ 66187db96d56Sopenharmony_ci datetime_subtract, /* nb_subtract */ 66197db96d56Sopenharmony_ci 0, /* nb_multiply */ 66207db96d56Sopenharmony_ci 0, /* nb_remainder */ 66217db96d56Sopenharmony_ci 0, /* nb_divmod */ 66227db96d56Sopenharmony_ci 0, /* nb_power */ 66237db96d56Sopenharmony_ci 0, /* nb_negative */ 66247db96d56Sopenharmony_ci 0, /* nb_positive */ 66257db96d56Sopenharmony_ci 0, /* nb_absolute */ 66267db96d56Sopenharmony_ci 0, /* nb_bool */ 66277db96d56Sopenharmony_ci}; 66287db96d56Sopenharmony_ci 66297db96d56Sopenharmony_cistatic PyTypeObject PyDateTime_DateTimeType = { 66307db96d56Sopenharmony_ci PyVarObject_HEAD_INIT(NULL, 0) 66317db96d56Sopenharmony_ci "datetime.datetime", /* tp_name */ 66327db96d56Sopenharmony_ci sizeof(PyDateTime_DateTime), /* tp_basicsize */ 66337db96d56Sopenharmony_ci 0, /* tp_itemsize */ 66347db96d56Sopenharmony_ci (destructor)datetime_dealloc, /* tp_dealloc */ 66357db96d56Sopenharmony_ci 0, /* tp_vectorcall_offset */ 66367db96d56Sopenharmony_ci 0, /* tp_getattr */ 66377db96d56Sopenharmony_ci 0, /* tp_setattr */ 66387db96d56Sopenharmony_ci 0, /* tp_as_async */ 66397db96d56Sopenharmony_ci (reprfunc)datetime_repr, /* tp_repr */ 66407db96d56Sopenharmony_ci &datetime_as_number, /* tp_as_number */ 66417db96d56Sopenharmony_ci 0, /* tp_as_sequence */ 66427db96d56Sopenharmony_ci 0, /* tp_as_mapping */ 66437db96d56Sopenharmony_ci (hashfunc)datetime_hash, /* tp_hash */ 66447db96d56Sopenharmony_ci 0, /* tp_call */ 66457db96d56Sopenharmony_ci (reprfunc)datetime_str, /* tp_str */ 66467db96d56Sopenharmony_ci PyObject_GenericGetAttr, /* tp_getattro */ 66477db96d56Sopenharmony_ci 0, /* tp_setattro */ 66487db96d56Sopenharmony_ci 0, /* tp_as_buffer */ 66497db96d56Sopenharmony_ci Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ 66507db96d56Sopenharmony_ci datetime_doc, /* tp_doc */ 66517db96d56Sopenharmony_ci 0, /* tp_traverse */ 66527db96d56Sopenharmony_ci 0, /* tp_clear */ 66537db96d56Sopenharmony_ci datetime_richcompare, /* tp_richcompare */ 66547db96d56Sopenharmony_ci 0, /* tp_weaklistoffset */ 66557db96d56Sopenharmony_ci 0, /* tp_iter */ 66567db96d56Sopenharmony_ci 0, /* tp_iternext */ 66577db96d56Sopenharmony_ci datetime_methods, /* tp_methods */ 66587db96d56Sopenharmony_ci 0, /* tp_members */ 66597db96d56Sopenharmony_ci datetime_getset, /* tp_getset */ 66607db96d56Sopenharmony_ci 0, /* tp_base; filled in 66617db96d56Sopenharmony_ci PyInit__datetime */ 66627db96d56Sopenharmony_ci 0, /* tp_dict */ 66637db96d56Sopenharmony_ci 0, /* tp_descr_get */ 66647db96d56Sopenharmony_ci 0, /* tp_descr_set */ 66657db96d56Sopenharmony_ci 0, /* tp_dictoffset */ 66667db96d56Sopenharmony_ci 0, /* tp_init */ 66677db96d56Sopenharmony_ci datetime_alloc, /* tp_alloc */ 66687db96d56Sopenharmony_ci datetime_new, /* tp_new */ 66697db96d56Sopenharmony_ci 0, /* tp_free */ 66707db96d56Sopenharmony_ci}; 66717db96d56Sopenharmony_ci 66727db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 66737db96d56Sopenharmony_ci * Module methods and initialization. 66747db96d56Sopenharmony_ci */ 66757db96d56Sopenharmony_ci 66767db96d56Sopenharmony_cistatic PyMethodDef module_methods[] = { 66777db96d56Sopenharmony_ci {NULL, NULL} 66787db96d56Sopenharmony_ci}; 66797db96d56Sopenharmony_ci 66807db96d56Sopenharmony_ci/* Get a new C API by calling this function. 66817db96d56Sopenharmony_ci * Clients get at C API via PyDateTime_IMPORT, defined in datetime.h. 66827db96d56Sopenharmony_ci */ 66837db96d56Sopenharmony_cistatic inline PyDateTime_CAPI * 66847db96d56Sopenharmony_ciget_datetime_capi(void) 66857db96d56Sopenharmony_ci{ 66867db96d56Sopenharmony_ci PyDateTime_CAPI *capi = PyMem_Malloc(sizeof(PyDateTime_CAPI)); 66877db96d56Sopenharmony_ci if (capi == NULL) { 66887db96d56Sopenharmony_ci PyErr_NoMemory(); 66897db96d56Sopenharmony_ci return NULL; 66907db96d56Sopenharmony_ci } 66917db96d56Sopenharmony_ci capi->DateType = &PyDateTime_DateType; 66927db96d56Sopenharmony_ci capi->DateTimeType = &PyDateTime_DateTimeType; 66937db96d56Sopenharmony_ci capi->TimeType = &PyDateTime_TimeType; 66947db96d56Sopenharmony_ci capi->DeltaType = &PyDateTime_DeltaType; 66957db96d56Sopenharmony_ci capi->TZInfoType = &PyDateTime_TZInfoType; 66967db96d56Sopenharmony_ci capi->Date_FromDate = new_date_ex; 66977db96d56Sopenharmony_ci capi->DateTime_FromDateAndTime = new_datetime_ex; 66987db96d56Sopenharmony_ci capi->Time_FromTime = new_time_ex; 66997db96d56Sopenharmony_ci capi->Delta_FromDelta = new_delta_ex; 67007db96d56Sopenharmony_ci capi->TimeZone_FromTimeZone = new_timezone; 67017db96d56Sopenharmony_ci capi->DateTime_FromTimestamp = datetime_fromtimestamp; 67027db96d56Sopenharmony_ci capi->Date_FromTimestamp = datetime_date_fromtimestamp_capi; 67037db96d56Sopenharmony_ci capi->DateTime_FromDateAndTimeAndFold = new_datetime_ex2; 67047db96d56Sopenharmony_ci capi->Time_FromTimeAndFold = new_time_ex2; 67057db96d56Sopenharmony_ci // Make sure this function is called after PyDateTime_TimeZone_UTC has 67067db96d56Sopenharmony_ci // been initialized. 67077db96d56Sopenharmony_ci assert(PyDateTime_TimeZone_UTC != NULL); 67087db96d56Sopenharmony_ci capi->TimeZone_UTC = PyDateTime_TimeZone_UTC; // borrowed ref 67097db96d56Sopenharmony_ci return capi; 67107db96d56Sopenharmony_ci} 67117db96d56Sopenharmony_ci 67127db96d56Sopenharmony_cistatic void 67137db96d56Sopenharmony_cidatetime_destructor(PyObject *op) 67147db96d56Sopenharmony_ci{ 67157db96d56Sopenharmony_ci void *ptr = PyCapsule_GetPointer(op, PyDateTime_CAPSULE_NAME); 67167db96d56Sopenharmony_ci PyMem_Free(ptr); 67177db96d56Sopenharmony_ci} 67187db96d56Sopenharmony_ci 67197db96d56Sopenharmony_cistatic int 67207db96d56Sopenharmony_ci_datetime_exec(PyObject *module) 67217db96d56Sopenharmony_ci{ 67227db96d56Sopenharmony_ci // `&...` is not a constant expression according to a strict reading 67237db96d56Sopenharmony_ci // of C standards. Fill tp_base at run-time rather than statically. 67247db96d56Sopenharmony_ci // See https://bugs.python.org/issue40777 67257db96d56Sopenharmony_ci PyDateTime_IsoCalendarDateType.tp_base = &PyTuple_Type; 67267db96d56Sopenharmony_ci PyDateTime_TimeZoneType.tp_base = &PyDateTime_TZInfoType; 67277db96d56Sopenharmony_ci PyDateTime_DateTimeType.tp_base = &PyDateTime_DateType; 67287db96d56Sopenharmony_ci 67297db96d56Sopenharmony_ci PyTypeObject *types[] = { 67307db96d56Sopenharmony_ci &PyDateTime_DateType, 67317db96d56Sopenharmony_ci &PyDateTime_DateTimeType, 67327db96d56Sopenharmony_ci &PyDateTime_TimeType, 67337db96d56Sopenharmony_ci &PyDateTime_DeltaType, 67347db96d56Sopenharmony_ci &PyDateTime_TZInfoType, 67357db96d56Sopenharmony_ci &PyDateTime_TimeZoneType, 67367db96d56Sopenharmony_ci }; 67377db96d56Sopenharmony_ci 67387db96d56Sopenharmony_ci for (size_t i = 0; i < Py_ARRAY_LENGTH(types); i++) { 67397db96d56Sopenharmony_ci if (PyModule_AddType(module, types[i]) < 0) { 67407db96d56Sopenharmony_ci return -1; 67417db96d56Sopenharmony_ci } 67427db96d56Sopenharmony_ci } 67437db96d56Sopenharmony_ci 67447db96d56Sopenharmony_ci if (PyType_Ready(&PyDateTime_IsoCalendarDateType) < 0) { 67457db96d56Sopenharmony_ci return -1; 67467db96d56Sopenharmony_ci } 67477db96d56Sopenharmony_ci 67487db96d56Sopenharmony_ci#define DATETIME_ADD_MACRO(dict, c, value_expr) \ 67497db96d56Sopenharmony_ci do { \ 67507db96d56Sopenharmony_ci PyObject *value = (value_expr); \ 67517db96d56Sopenharmony_ci if (value == NULL) { \ 67527db96d56Sopenharmony_ci return -1; \ 67537db96d56Sopenharmony_ci } \ 67547db96d56Sopenharmony_ci if (PyDict_SetItemString(dict, c, value) < 0) { \ 67557db96d56Sopenharmony_ci Py_DECREF(value); \ 67567db96d56Sopenharmony_ci return -1; \ 67577db96d56Sopenharmony_ci } \ 67587db96d56Sopenharmony_ci Py_DECREF(value); \ 67597db96d56Sopenharmony_ci } while(0) 67607db96d56Sopenharmony_ci 67617db96d56Sopenharmony_ci /* timedelta values */ 67627db96d56Sopenharmony_ci PyObject *d = PyDateTime_DeltaType.tp_dict; 67637db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0)); 67647db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "min", new_delta(-MAX_DELTA_DAYS, 0, 0, 0)); 67657db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "max", 67667db96d56Sopenharmony_ci new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0)); 67677db96d56Sopenharmony_ci 67687db96d56Sopenharmony_ci /* date values */ 67697db96d56Sopenharmony_ci d = PyDateTime_DateType.tp_dict; 67707db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "min", new_date(1, 1, 1)); 67717db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "max", new_date(MAXYEAR, 12, 31)); 67727db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "resolution", new_delta(1, 0, 0, 0)); 67737db96d56Sopenharmony_ci 67747db96d56Sopenharmony_ci /* time values */ 67757db96d56Sopenharmony_ci d = PyDateTime_TimeType.tp_dict; 67767db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "min", new_time(0, 0, 0, 0, Py_None, 0)); 67777db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "max", new_time(23, 59, 59, 999999, Py_None, 0)); 67787db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0)); 67797db96d56Sopenharmony_ci 67807db96d56Sopenharmony_ci /* datetime values */ 67817db96d56Sopenharmony_ci d = PyDateTime_DateTimeType.tp_dict; 67827db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "min", 67837db96d56Sopenharmony_ci new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None, 0)); 67847db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "max", new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 67857db96d56Sopenharmony_ci 999999, Py_None, 0)); 67867db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "resolution", new_delta(0, 0, 1, 0)); 67877db96d56Sopenharmony_ci 67887db96d56Sopenharmony_ci /* timezone values */ 67897db96d56Sopenharmony_ci d = PyDateTime_TimeZoneType.tp_dict; 67907db96d56Sopenharmony_ci PyObject *delta = new_delta(0, 0, 0, 0); 67917db96d56Sopenharmony_ci if (delta == NULL) { 67927db96d56Sopenharmony_ci return -1; 67937db96d56Sopenharmony_ci } 67947db96d56Sopenharmony_ci 67957db96d56Sopenharmony_ci PyObject *x = create_timezone(delta, NULL); 67967db96d56Sopenharmony_ci Py_DECREF(delta); 67977db96d56Sopenharmony_ci if (x == NULL) { 67987db96d56Sopenharmony_ci return -1; 67997db96d56Sopenharmony_ci } 68007db96d56Sopenharmony_ci if (PyDict_SetItemString(d, "utc", x) < 0) { 68017db96d56Sopenharmony_ci Py_DECREF(x); 68027db96d56Sopenharmony_ci return -1; 68037db96d56Sopenharmony_ci } 68047db96d56Sopenharmony_ci 68057db96d56Sopenharmony_ci PyDateTime_TimeZone_UTC = x; 68067db96d56Sopenharmony_ci 68077db96d56Sopenharmony_ci /* bpo-37642: These attributes are rounded to the nearest minute for backwards 68087db96d56Sopenharmony_ci * compatibility, even though the constructor will accept a wider range of 68097db96d56Sopenharmony_ci * values. This may change in the future.*/ 68107db96d56Sopenharmony_ci delta = new_delta(-1, 60, 0, 1); /* -23:59 */ 68117db96d56Sopenharmony_ci if (delta == NULL) { 68127db96d56Sopenharmony_ci return -1; 68137db96d56Sopenharmony_ci } 68147db96d56Sopenharmony_ci 68157db96d56Sopenharmony_ci x = create_timezone(delta, NULL); 68167db96d56Sopenharmony_ci Py_DECREF(delta); 68177db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "min", x); 68187db96d56Sopenharmony_ci 68197db96d56Sopenharmony_ci delta = new_delta(0, (23 * 60 + 59) * 60, 0, 0); /* +23:59 */ 68207db96d56Sopenharmony_ci if (delta == NULL) { 68217db96d56Sopenharmony_ci return -1; 68227db96d56Sopenharmony_ci } 68237db96d56Sopenharmony_ci 68247db96d56Sopenharmony_ci x = create_timezone(delta, NULL); 68257db96d56Sopenharmony_ci Py_DECREF(delta); 68267db96d56Sopenharmony_ci DATETIME_ADD_MACRO(d, "max", x); 68277db96d56Sopenharmony_ci 68287db96d56Sopenharmony_ci /* Epoch */ 68297db96d56Sopenharmony_ci PyDateTime_Epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0, 68307db96d56Sopenharmony_ci PyDateTime_TimeZone_UTC, 0); 68317db96d56Sopenharmony_ci if (PyDateTime_Epoch == NULL) { 68327db96d56Sopenharmony_ci return -1; 68337db96d56Sopenharmony_ci } 68347db96d56Sopenharmony_ci 68357db96d56Sopenharmony_ci /* module initialization */ 68367db96d56Sopenharmony_ci if (PyModule_AddIntMacro(module, MINYEAR) < 0) { 68377db96d56Sopenharmony_ci return -1; 68387db96d56Sopenharmony_ci } 68397db96d56Sopenharmony_ci if (PyModule_AddIntMacro(module, MAXYEAR) < 0) { 68407db96d56Sopenharmony_ci return -1; 68417db96d56Sopenharmony_ci } 68427db96d56Sopenharmony_ci 68437db96d56Sopenharmony_ci PyDateTime_CAPI *capi = get_datetime_capi(); 68447db96d56Sopenharmony_ci if (capi == NULL) { 68457db96d56Sopenharmony_ci return -1; 68467db96d56Sopenharmony_ci } 68477db96d56Sopenharmony_ci x = PyCapsule_New(capi, PyDateTime_CAPSULE_NAME, datetime_destructor); 68487db96d56Sopenharmony_ci if (x == NULL) { 68497db96d56Sopenharmony_ci PyMem_Free(capi); 68507db96d56Sopenharmony_ci return -1; 68517db96d56Sopenharmony_ci } 68527db96d56Sopenharmony_ci 68537db96d56Sopenharmony_ci if (PyModule_AddObject(module, "datetime_CAPI", x) < 0) { 68547db96d56Sopenharmony_ci Py_DECREF(x); 68557db96d56Sopenharmony_ci return -1; 68567db96d56Sopenharmony_ci } 68577db96d56Sopenharmony_ci 68587db96d56Sopenharmony_ci if (PyModule_AddObjectRef(module, "UTC", PyDateTime_TimeZone_UTC) < 0) { 68597db96d56Sopenharmony_ci return -1; 68607db96d56Sopenharmony_ci } 68617db96d56Sopenharmony_ci 68627db96d56Sopenharmony_ci /* A 4-year cycle has an extra leap day over what we'd get from 68637db96d56Sopenharmony_ci * pasting together 4 single years. 68647db96d56Sopenharmony_ci */ 68657db96d56Sopenharmony_ci static_assert(DI4Y == 4 * 365 + 1, "DI4Y"); 68667db96d56Sopenharmony_ci assert(DI4Y == days_before_year(4+1)); 68677db96d56Sopenharmony_ci 68687db96d56Sopenharmony_ci /* Similarly, a 400-year cycle has an extra leap day over what we'd 68697db96d56Sopenharmony_ci * get from pasting together 4 100-year cycles. 68707db96d56Sopenharmony_ci */ 68717db96d56Sopenharmony_ci static_assert(DI400Y == 4 * DI100Y + 1, "DI400Y"); 68727db96d56Sopenharmony_ci assert(DI400Y == days_before_year(400+1)); 68737db96d56Sopenharmony_ci 68747db96d56Sopenharmony_ci /* OTOH, a 100-year cycle has one fewer leap day than we'd get from 68757db96d56Sopenharmony_ci * pasting together 25 4-year cycles. 68767db96d56Sopenharmony_ci */ 68777db96d56Sopenharmony_ci static_assert(DI100Y == 25 * DI4Y - 1, "DI100Y"); 68787db96d56Sopenharmony_ci assert(DI100Y == days_before_year(100+1)); 68797db96d56Sopenharmony_ci 68807db96d56Sopenharmony_ci us_per_ms = PyLong_FromLong(1000); 68817db96d56Sopenharmony_ci us_per_second = PyLong_FromLong(1000000); 68827db96d56Sopenharmony_ci us_per_minute = PyLong_FromLong(60000000); 68837db96d56Sopenharmony_ci seconds_per_day = PyLong_FromLong(24 * 3600); 68847db96d56Sopenharmony_ci if (us_per_ms == NULL || us_per_second == NULL || 68857db96d56Sopenharmony_ci us_per_minute == NULL || seconds_per_day == NULL) { 68867db96d56Sopenharmony_ci return -1; 68877db96d56Sopenharmony_ci } 68887db96d56Sopenharmony_ci 68897db96d56Sopenharmony_ci /* The rest are too big for 32-bit ints, but even 68907db96d56Sopenharmony_ci * us_per_week fits in 40 bits, so doubles should be exact. 68917db96d56Sopenharmony_ci */ 68927db96d56Sopenharmony_ci us_per_hour = PyLong_FromDouble(3600000000.0); 68937db96d56Sopenharmony_ci us_per_day = PyLong_FromDouble(86400000000.0); 68947db96d56Sopenharmony_ci us_per_week = PyLong_FromDouble(604800000000.0); 68957db96d56Sopenharmony_ci if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL) { 68967db96d56Sopenharmony_ci return -1; 68977db96d56Sopenharmony_ci } 68987db96d56Sopenharmony_ci return 0; 68997db96d56Sopenharmony_ci} 69007db96d56Sopenharmony_ci 69017db96d56Sopenharmony_cistatic struct PyModuleDef datetimemodule = { 69027db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 69037db96d56Sopenharmony_ci .m_name = "_datetime", 69047db96d56Sopenharmony_ci .m_doc = "Fast implementation of the datetime type.", 69057db96d56Sopenharmony_ci .m_size = -1, 69067db96d56Sopenharmony_ci .m_methods = module_methods, 69077db96d56Sopenharmony_ci}; 69087db96d56Sopenharmony_ci 69097db96d56Sopenharmony_ciPyMODINIT_FUNC 69107db96d56Sopenharmony_ciPyInit__datetime(void) 69117db96d56Sopenharmony_ci{ 69127db96d56Sopenharmony_ci PyObject *mod = PyModule_Create(&datetimemodule); 69137db96d56Sopenharmony_ci if (mod == NULL) 69147db96d56Sopenharmony_ci return NULL; 69157db96d56Sopenharmony_ci 69167db96d56Sopenharmony_ci if (_datetime_exec(mod) < 0) { 69177db96d56Sopenharmony_ci Py_DECREF(mod); 69187db96d56Sopenharmony_ci return NULL; 69197db96d56Sopenharmony_ci } 69207db96d56Sopenharmony_ci 69217db96d56Sopenharmony_ci return mod; 69227db96d56Sopenharmony_ci} 69237db96d56Sopenharmony_ci 69247db96d56Sopenharmony_ci/* --------------------------------------------------------------------------- 69257db96d56Sopenharmony_ciSome time zone algebra. For a datetime x, let 69267db96d56Sopenharmony_ci x.n = x stripped of its timezone -- its naive time. 69277db96d56Sopenharmony_ci x.o = x.utcoffset(), and assuming that doesn't raise an exception or 69287db96d56Sopenharmony_ci return None 69297db96d56Sopenharmony_ci x.d = x.dst(), and assuming that doesn't raise an exception or 69307db96d56Sopenharmony_ci return None 69317db96d56Sopenharmony_ci x.s = x's standard offset, x.o - x.d 69327db96d56Sopenharmony_ci 69337db96d56Sopenharmony_ciNow some derived rules, where k is a duration (timedelta). 69347db96d56Sopenharmony_ci 69357db96d56Sopenharmony_ci1. x.o = x.s + x.d 69367db96d56Sopenharmony_ci This follows from the definition of x.s. 69377db96d56Sopenharmony_ci 69387db96d56Sopenharmony_ci2. If x and y have the same tzinfo member, x.s = y.s. 69397db96d56Sopenharmony_ci This is actually a requirement, an assumption we need to make about 69407db96d56Sopenharmony_ci sane tzinfo classes. 69417db96d56Sopenharmony_ci 69427db96d56Sopenharmony_ci3. The naive UTC time corresponding to x is x.n - x.o. 69437db96d56Sopenharmony_ci This is again a requirement for a sane tzinfo class. 69447db96d56Sopenharmony_ci 69457db96d56Sopenharmony_ci4. (x+k).s = x.s 69467db96d56Sopenharmony_ci This follows from #2, and that datimetimetz+timedelta preserves tzinfo. 69477db96d56Sopenharmony_ci 69487db96d56Sopenharmony_ci5. (x+k).n = x.n + k 69497db96d56Sopenharmony_ci Again follows from how arithmetic is defined. 69507db96d56Sopenharmony_ci 69517db96d56Sopenharmony_ciNow we can explain tz.fromutc(x). Let's assume it's an interesting case 69527db96d56Sopenharmony_ci(meaning that the various tzinfo methods exist, and don't blow up or return 69537db96d56Sopenharmony_ciNone when called). 69547db96d56Sopenharmony_ci 69557db96d56Sopenharmony_ciThe function wants to return a datetime y with timezone tz, equivalent to x. 69567db96d56Sopenharmony_cix is already in UTC. 69577db96d56Sopenharmony_ci 69587db96d56Sopenharmony_ciBy #3, we want 69597db96d56Sopenharmony_ci 69607db96d56Sopenharmony_ci y.n - y.o = x.n [1] 69617db96d56Sopenharmony_ci 69627db96d56Sopenharmony_ciThe algorithm starts by attaching tz to x.n, and calling that y. So 69637db96d56Sopenharmony_cix.n = y.n at the start. Then it wants to add a duration k to y, so that [1] 69647db96d56Sopenharmony_cibecomes true; in effect, we want to solve [2] for k: 69657db96d56Sopenharmony_ci 69667db96d56Sopenharmony_ci (y+k).n - (y+k).o = x.n [2] 69677db96d56Sopenharmony_ci 69687db96d56Sopenharmony_ciBy #1, this is the same as 69697db96d56Sopenharmony_ci 69707db96d56Sopenharmony_ci (y+k).n - ((y+k).s + (y+k).d) = x.n [3] 69717db96d56Sopenharmony_ci 69727db96d56Sopenharmony_ciBy #5, (y+k).n = y.n + k, which equals x.n + k because x.n=y.n at the start. 69737db96d56Sopenharmony_ciSubstituting that into [3], 69747db96d56Sopenharmony_ci 69757db96d56Sopenharmony_ci x.n + k - (y+k).s - (y+k).d = x.n; the x.n terms cancel, leaving 69767db96d56Sopenharmony_ci k - (y+k).s - (y+k).d = 0; rearranging, 69777db96d56Sopenharmony_ci k = (y+k).s - (y+k).d; by #4, (y+k).s == y.s, so 69787db96d56Sopenharmony_ci k = y.s - (y+k).d 69797db96d56Sopenharmony_ci 69807db96d56Sopenharmony_ciOn the RHS, (y+k).d can't be computed directly, but y.s can be, and we 69817db96d56Sopenharmony_ciapproximate k by ignoring the (y+k).d term at first. Note that k can't be 69827db96d56Sopenharmony_civery large, since all offset-returning methods return a duration of magnitude 69837db96d56Sopenharmony_ciless than 24 hours. For that reason, if y is firmly in std time, (y+k).d must 69847db96d56Sopenharmony_cibe 0, so ignoring it has no consequence then. 69857db96d56Sopenharmony_ci 69867db96d56Sopenharmony_ciIn any case, the new value is 69877db96d56Sopenharmony_ci 69887db96d56Sopenharmony_ci z = y + y.s [4] 69897db96d56Sopenharmony_ci 69907db96d56Sopenharmony_ciIt's helpful to step back at look at [4] from a higher level: it's simply 69917db96d56Sopenharmony_cimapping from UTC to tz's standard time. 69927db96d56Sopenharmony_ci 69937db96d56Sopenharmony_ciAt this point, if 69947db96d56Sopenharmony_ci 69957db96d56Sopenharmony_ci z.n - z.o = x.n [5] 69967db96d56Sopenharmony_ci 69977db96d56Sopenharmony_ciwe have an equivalent time, and are almost done. The insecurity here is 69987db96d56Sopenharmony_ciat the start of daylight time. Picture US Eastern for concreteness. The wall 69997db96d56Sopenharmony_citime jumps from 1:59 to 3:00, and wall hours of the form 2:MM don't make good 70007db96d56Sopenharmony_cisense then. The docs ask that an Eastern tzinfo class consider such a time to 70017db96d56Sopenharmony_cibe EDT (because it's "after 2"), which is a redundant spelling of 1:MM EST 70027db96d56Sopenharmony_cion the day DST starts. We want to return the 1:MM EST spelling because that's 70037db96d56Sopenharmony_cithe only spelling that makes sense on the local wall clock. 70047db96d56Sopenharmony_ci 70057db96d56Sopenharmony_ciIn fact, if [5] holds at this point, we do have the standard-time spelling, 70067db96d56Sopenharmony_cibut that takes a bit of proof. We first prove a stronger result. What's the 70077db96d56Sopenharmony_cidifference between the LHS and RHS of [5]? Let 70087db96d56Sopenharmony_ci 70097db96d56Sopenharmony_ci diff = x.n - (z.n - z.o) [6] 70107db96d56Sopenharmony_ci 70117db96d56Sopenharmony_ciNow 70127db96d56Sopenharmony_ci z.n = by [4] 70137db96d56Sopenharmony_ci (y + y.s).n = by #5 70147db96d56Sopenharmony_ci y.n + y.s = since y.n = x.n 70157db96d56Sopenharmony_ci x.n + y.s = since z and y are have the same tzinfo member, 70167db96d56Sopenharmony_ci y.s = z.s by #2 70177db96d56Sopenharmony_ci x.n + z.s 70187db96d56Sopenharmony_ci 70197db96d56Sopenharmony_ciPlugging that back into [6] gives 70207db96d56Sopenharmony_ci 70217db96d56Sopenharmony_ci diff = 70227db96d56Sopenharmony_ci x.n - ((x.n + z.s) - z.o) = expanding 70237db96d56Sopenharmony_ci x.n - x.n - z.s + z.o = cancelling 70247db96d56Sopenharmony_ci - z.s + z.o = by #2 70257db96d56Sopenharmony_ci z.d 70267db96d56Sopenharmony_ci 70277db96d56Sopenharmony_ciSo diff = z.d. 70287db96d56Sopenharmony_ci 70297db96d56Sopenharmony_ciIf [5] is true now, diff = 0, so z.d = 0 too, and we have the standard-time 70307db96d56Sopenharmony_cispelling we wanted in the endcase described above. We're done. Contrarily, 70317db96d56Sopenharmony_ciif z.d = 0, then we have a UTC equivalent, and are also done. 70327db96d56Sopenharmony_ci 70337db96d56Sopenharmony_ciIf [5] is not true now, diff = z.d != 0, and z.d is the offset we need to 70347db96d56Sopenharmony_ciadd to z (in effect, z is in tz's standard time, and we need to shift the 70357db96d56Sopenharmony_cilocal clock into tz's daylight time). 70367db96d56Sopenharmony_ci 70377db96d56Sopenharmony_ciLet 70387db96d56Sopenharmony_ci 70397db96d56Sopenharmony_ci z' = z + z.d = z + diff [7] 70407db96d56Sopenharmony_ci 70417db96d56Sopenharmony_ciand we can again ask whether 70427db96d56Sopenharmony_ci 70437db96d56Sopenharmony_ci z'.n - z'.o = x.n [8] 70447db96d56Sopenharmony_ci 70457db96d56Sopenharmony_ciIf so, we're done. If not, the tzinfo class is insane, according to the 70467db96d56Sopenharmony_ciassumptions we've made. This also requires a bit of proof. As before, let's 70477db96d56Sopenharmony_cicompute the difference between the LHS and RHS of [8] (and skipping some of 70487db96d56Sopenharmony_cithe justifications for the kinds of substitutions we've done several times 70497db96d56Sopenharmony_cialready): 70507db96d56Sopenharmony_ci 70517db96d56Sopenharmony_ci diff' = x.n - (z'.n - z'.o) = replacing z'.n via [7] 70527db96d56Sopenharmony_ci x.n - (z.n + diff - z'.o) = replacing diff via [6] 70537db96d56Sopenharmony_ci x.n - (z.n + x.n - (z.n - z.o) - z'.o) = 70547db96d56Sopenharmony_ci x.n - z.n - x.n + z.n - z.o + z'.o = cancel x.n 70557db96d56Sopenharmony_ci - z.n + z.n - z.o + z'.o = cancel z.n 70567db96d56Sopenharmony_ci - z.o + z'.o = #1 twice 70577db96d56Sopenharmony_ci -z.s - z.d + z'.s + z'.d = z and z' have same tzinfo 70587db96d56Sopenharmony_ci z'.d - z.d 70597db96d56Sopenharmony_ci 70607db96d56Sopenharmony_ciSo z' is UTC-equivalent to x iff z'.d = z.d at this point. If they are equal, 70617db96d56Sopenharmony_ciwe've found the UTC-equivalent so are done. In fact, we stop with [7] and 70627db96d56Sopenharmony_cireturn z', not bothering to compute z'.d. 70637db96d56Sopenharmony_ci 70647db96d56Sopenharmony_ciHow could z.d and z'd differ? z' = z + z.d [7], so merely moving z' by 70657db96d56Sopenharmony_cia dst() offset, and starting *from* a time already in DST (we know z.d != 0), 70667db96d56Sopenharmony_ciwould have to change the result dst() returns: we start in DST, and moving 70677db96d56Sopenharmony_cia little further into it takes us out of DST. 70687db96d56Sopenharmony_ci 70697db96d56Sopenharmony_ciThere isn't a sane case where this can happen. The closest it gets is at 70707db96d56Sopenharmony_cithe end of DST, where there's an hour in UTC with no spelling in a hybrid 70717db96d56Sopenharmony_citzinfo class. In US Eastern, that's 5:MM UTC = 0:MM EST = 1:MM EDT. During 70727db96d56Sopenharmony_cithat hour, on an Eastern clock 1:MM is taken as being in standard time (6:MM 70737db96d56Sopenharmony_ciUTC) because the docs insist on that, but 0:MM is taken as being in daylight 70747db96d56Sopenharmony_citime (4:MM UTC). There is no local time mapping to 5:MM UTC. The local 70757db96d56Sopenharmony_ciclock jumps from 1:59 back to 1:00 again, and repeats the 1:MM hour in 70767db96d56Sopenharmony_cistandard time. Since that's what the local clock *does*, we want to map both 70777db96d56Sopenharmony_ciUTC hours 5:MM and 6:MM to 1:MM Eastern. The result is ambiguous 70787db96d56Sopenharmony_ciin local time, but so it goes -- it's the way the local clock works. 70797db96d56Sopenharmony_ci 70807db96d56Sopenharmony_ciWhen x = 5:MM UTC is the input to this algorithm, x.o=0, y.o=-5 and y.d=0, 70817db96d56Sopenharmony_ciso z=0:MM. z.d=60 (minutes) then, so [5] doesn't hold and we keep going. 70827db96d56Sopenharmony_ciz' = z + z.d = 1:MM then, and z'.d=0, and z'.d - z.d = -60 != 0 so [8] 70837db96d56Sopenharmony_ci(correctly) concludes that z' is not UTC-equivalent to x. 70847db96d56Sopenharmony_ci 70857db96d56Sopenharmony_ciBecause we know z.d said z was in daylight time (else [5] would have held and 70867db96d56Sopenharmony_ciwe would have stopped then), and we know z.d != z'.d (else [8] would have held 70877db96d56Sopenharmony_ciand we would have stopped then), and there are only 2 possible values dst() can 70887db96d56Sopenharmony_cireturn in Eastern, it follows that z'.d must be 0 (which it is in the example, 70897db96d56Sopenharmony_cibut the reasoning doesn't depend on the example -- it depends on there being 70907db96d56Sopenharmony_citwo possible dst() outcomes, one zero and the other non-zero). Therefore 70917db96d56Sopenharmony_ciz' must be in standard time, and is the spelling we want in this case. 70927db96d56Sopenharmony_ci 70937db96d56Sopenharmony_ciNote again that z' is not UTC-equivalent as far as the hybrid tzinfo class is 70947db96d56Sopenharmony_ciconcerned (because it takes z' as being in standard time rather than the 70957db96d56Sopenharmony_cidaylight time we intend here), but returning it gives the real-life "local 70967db96d56Sopenharmony_ciclock repeats an hour" behavior when mapping the "unspellable" UTC hour into 70977db96d56Sopenharmony_citz. 70987db96d56Sopenharmony_ci 70997db96d56Sopenharmony_ciWhen the input is 6:MM, z=1:MM and z.d=0, and we stop at once, again with 71007db96d56Sopenharmony_cithe 1:MM standard time spelling we want. 71017db96d56Sopenharmony_ci 71027db96d56Sopenharmony_ciSo how can this break? One of the assumptions must be violated. Two 71037db96d56Sopenharmony_cipossibilities: 71047db96d56Sopenharmony_ci 71057db96d56Sopenharmony_ci1) [2] effectively says that y.s is invariant across all y belong to a given 71067db96d56Sopenharmony_ci time zone. This isn't true if, for political reasons or continental drift, 71077db96d56Sopenharmony_ci a region decides to change its base offset from UTC. 71087db96d56Sopenharmony_ci 71097db96d56Sopenharmony_ci2) There may be versions of "double daylight" time where the tail end of 71107db96d56Sopenharmony_ci the analysis gives up a step too early. I haven't thought about that 71117db96d56Sopenharmony_ci enough to say. 71127db96d56Sopenharmony_ci 71137db96d56Sopenharmony_ciIn any case, it's clear that the default fromutc() is strong enough to handle 71147db96d56Sopenharmony_ci"almost all" time zones: so long as the standard offset is invariant, it 71157db96d56Sopenharmony_cidoesn't matter if daylight time transition points change from year to year, or 71167db96d56Sopenharmony_ciif daylight time is skipped in some years; it doesn't matter how large or 71177db96d56Sopenharmony_cismall dst() may get within its bounds; and it doesn't even matter if some 71187db96d56Sopenharmony_ciperverse time zone returns a negative dst()). So a breaking case must be 71197db96d56Sopenharmony_cipretty bizarre, and a tzinfo subclass can override fromutc() if it is. 71207db96d56Sopenharmony_ci--------------------------------------------------------------------------- */ 7121