Mercurial > cpython-lru_cache-weakref
annotate Python/pytime.c @ 74832:f8409b3d6449
PEP 410
| author | Victor Stinner <victor.stinner@haypocalc.com> |
|---|---|
| date | Wed, 08 Feb 2012 14:31:50 +0100 |
| parents | bee7943d38c6 |
| children | 90eda29a8e03 |
| rev | line source |
|---|---|
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
1 #include "Python.h" |
|
74821
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
2 #ifdef MS_WINDOWS |
|
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
3 #include <windows.h> |
|
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
4 #endif |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
5 |
|
74821
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
6 #if defined(__APPLE__) && defined(HAVE_GETTIMEOFDAY) && defined(HAVE_FTIME) |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
7 /* |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
8 * _PyTime_gettimeofday falls back to ftime when getttimeofday fails because the latter |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
9 * might fail on some platforms. This fallback is unwanted on MacOSX because |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
10 * that makes it impossible to use a binary build on OSX 10.4 on earlier |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
11 * releases of the OS. Therefore claim we don't support ftime. |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
12 */ |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
13 # undef HAVE_FTIME |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
14 #endif |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
15 |
|
74821
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
16 #if defined(HAVE_FTIME) && !defined(MS_WINDOWS) |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
17 #include <sys/timeb.h> |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
18 extern int ftime(struct timeb *); |
|
74821
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
19 #endif |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
20 |
| 74832 | 21 #define MICROSECONDS 1000000 |
| 22 | |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
23 void |
| 74832 | 24 _PyTime_get(_PyTime_t *ts) |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
25 { |
|
74821
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
26 #ifdef MS_WINDOWS |
|
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
27 FILETIME system_time; |
|
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
28 ULARGE_INTEGER large; |
| 74832 | 29 ULONGLONG value; |
|
74821
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
30 |
|
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
31 GetSystemTimeAsFileTime(&system_time); |
|
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
32 large.u.LowPart = system_time.dwLowDateTime; |
|
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
33 large.u.HighPart = system_time.dwHighDateTime; |
| 74832 | 34 /* 116,444,736,000,000,000: number of 100 ns between |
|
74821
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
35 the 1st january 1601 and the 1st january 1970 (369 years + 89 leap |
|
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
36 days). */ |
| 74832 | 37 value = large.QuadPart - 116444736000000000; |
| 38 ts->seconds = 0; | |
| 39 ts->numerator = value; | |
| 40 ts->denominator = (_PyTime_fraction_t)10000000; | |
|
74821
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
41 #else |
| 74832 | 42 |
| 43 #ifdef HAVE_GETTIMEOFDAY | |
| 44 struct timeval tv; | |
| 45 int err; | |
| 46 #endif | |
| 47 #if defined(HAVE_FTIME) | |
| 48 struct timeb t; | |
| 49 #endif | |
| 50 | |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
51 /* There are three ways to get the time: |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
52 (1) gettimeofday() -- resolution in microseconds |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
53 (2) ftime() -- resolution in milliseconds |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
54 (3) time() -- resolution in seconds |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
55 In all cases the return value in a timeval struct. |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
56 Since on some systems (e.g. SCO ODT 3.0) gettimeofday() may |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
57 fail, so we fall back on ftime() or time(). |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
58 Note: clock resolution does not imply clock accuracy! */ |
|
74821
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
59 |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
60 #ifdef HAVE_GETTIMEOFDAY |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
61 #ifdef GETTIMEOFDAY_NO_TZ |
| 74832 | 62 err = gettimeofday(&tv); |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
63 #else /* !GETTIMEOFDAY_NO_TZ */ |
| 74832 | 64 err = gettimeofday(&tv, (struct timezone *)NULL); |
| 65 #endif /* !GETTIMEOFDAY_NO_TZ */ | |
| 66 if (err == 0) | |
| 67 { | |
| 68 ts->seconds = tv.tv_sec; | |
| 69 ts->numerator = tv.tv_usec; | |
| 70 ts->denominator = MICROSECONDS; | |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
71 return; |
| 74832 | 72 } |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
73 #endif /* !HAVE_GETTIMEOFDAY */ |
|
74821
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
74 |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
75 #if defined(HAVE_FTIME) |
| 74832 | 76 ftime(&t); |
| 77 ts->seconds = t.time; | |
| 78 ts->numerator = t.millitm; | |
| 79 ts->denominator = 1000; | |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
80 #else /* !HAVE_FTIME */ |
| 74832 | 81 ts->seconds = time(NULL); |
| 82 ts->numerator = 0; | |
| 83 ts->denominator = 1; | |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
84 #endif /* !HAVE_FTIME */ |
|
74821
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
85 |
|
bee7943d38c6
Issue #13845: time.time() now uses GetSystemTimeAsFileTime() instead of ftime()
Victor Stinner <victor.stinner@haypocalc.com>
parents:
63757
diff
changeset
|
86 #endif /* MS_WINDOWS */ |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
87 } |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
88 |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
89 void |
| 74832 | 90 _PyTime_gettimeofday(_PyTime_timeval *tv) |
| 91 { | |
| 92 _PyTime_t ts; | |
| 93 _PyTime_fraction_t k; | |
| 94 time_t sec; | |
| 95 | |
| 96 _PyTime_get(&ts); | |
| 97 tv->tv_sec = ts.seconds; | |
| 98 if (ts.numerator) { | |
| 99 if (ts.numerator > ts.denominator) { | |
| 100 sec = Py_SAFE_DOWNCAST(ts.numerator / ts.denominator, | |
| 101 _PyTime_fraction_t, time_t); | |
| 102 /* ignore integer overflow because _PyTime_gettimeofday() has | |
| 103 no return value */ | |
| 104 tv->tv_sec += sec; | |
| 105 ts.numerator = ts.numerator % ts.denominator; | |
| 106 } | |
| 107 if (MICROSECONDS >= ts.denominator) { | |
| 108 k = (_PyTime_fraction_t)MICROSECONDS / ts.denominator; | |
| 109 tv->tv_usec = (long)(ts.numerator * k); | |
| 110 } | |
| 111 else { | |
| 112 k = ts.denominator / (_PyTime_fraction_t)MICROSECONDS; | |
| 113 tv->tv_usec = (long)(ts.numerator / k); | |
| 114 } | |
| 115 } | |
| 116 else { | |
| 117 tv->tv_usec = 0; | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 static PyObject* | |
| 122 _PyLong_FromTime_t(time_t value) | |
| 123 { | |
| 124 #if SIZEOF_TIME_T <= SIZEOF_LONG | |
| 125 return PyLong_FromLong(value); | |
| 126 #else | |
| 127 assert(sizeof(time_t) <= sizeof(PY_LONG_LONG)); | |
| 128 return PyLong_FromLongLong(value); | |
| 129 #endif | |
| 130 } | |
| 131 | |
| 132 #if defined(HAVE_LONG_LONG) | |
| 133 # define _PyLong_FromTimeFraction_t PyLong_FromLongLong | |
| 134 #else | |
| 135 # define _PyLong_FromTimeFraction_t PyLong_FromSize_t | |
| 136 #endif | |
| 137 | |
| 138 /* Convert a timestamp to a PyFloat object */ | |
| 139 static PyObject* | |
| 140 _PyTime_AsFloat(_PyTime_t *ts) | |
| 141 { | |
| 142 double d; | |
| 143 d = (double)ts->seconds; | |
| 144 d += (double)ts->numerator / (double)ts->denominator; | |
| 145 return PyFloat_FromDouble(d); | |
| 146 } | |
| 147 | |
| 148 /* Convert a timestamp to a PyLong object */ | |
| 149 static PyObject* | |
| 150 _PyTime_AsLong(_PyTime_t *ts) | |
| 151 { | |
| 152 PyObject *a, *b, *c; | |
| 153 | |
| 154 a = _PyLong_FromTime_t(ts->seconds); | |
| 155 if (a == NULL) | |
| 156 return NULL; | |
| 157 b = _PyLong_FromTimeFraction_t(ts->numerator / ts->denominator); | |
| 158 if (b == NULL) | |
| 159 { | |
| 160 Py_DECREF(a); | |
| 161 return NULL; | |
| 162 } | |
| 163 c = PyNumber_Add(a, b); | |
| 164 Py_DECREF(a); | |
| 165 Py_DECREF(b); | |
| 166 return c; | |
| 167 } | |
| 168 | |
| 169 /* Convert a timestamp to a decimal.Decimal object */ | |
| 170 static PyObject* | |
| 171 _PyTime_AsDecimal(_PyTime_t *ts) | |
| 172 { | |
| 173 static PyObject* module = NULL; | |
| 174 static PyObject* decimal = NULL; | |
| 175 static PyObject* exponent_context = NULL; | |
| 176 static PyObject* context = NULL; | |
| 177 /* exponent cache, dictionary of: | |
| 178 int (denominator) => Decimal (1/denominator) */ | |
| 179 static PyObject* exponent_cache = NULL; | |
| 180 PyObject *t = NULL; | |
| 181 PyObject *key, *exponent, *quantized; | |
| 182 _Py_IDENTIFIER(quantize); | |
| 183 _Py_IDENTIFIER(__truediv__); | |
| 184 | |
| 185 if (!module) { | |
| 186 module = PyImport_ImportModuleNoBlock("decimal"); | |
| 187 if (module == NULL) | |
| 188 return NULL; | |
| 189 } | |
| 190 | |
| 191 if (!decimal) { | |
| 192 decimal = PyObject_GetAttrString(module, "Decimal"); | |
| 193 if (decimal == NULL) | |
| 194 return NULL; | |
| 195 } | |
| 196 | |
| 197 if (context == NULL) | |
| 198 { | |
| 199 /* Use 12 decimal digits to store 10,000 years in seconds + 9 | |
| 200 decimal digits for the floating part in nanoseconds + 1 decimal | |
| 201 digit to round correctly. | |
| 202 | |
| 203 context = decimal.Context(22, rounding=decimal.ROUND_HALF_EVEN) | |
| 204 exponent_context = decimal.Context(1, rounding=decimal.ROUND_HALF_EVEN) | |
| 205 */ | |
| 206 PyObject *context_class, *rounding; | |
| 207 context_class = PyObject_GetAttrString(module, "Context"); | |
| 208 if (context_class == NULL) | |
| 209 return NULL; | |
| 210 rounding = PyObject_GetAttrString(module, "ROUND_HALF_EVEN"); | |
| 211 if (rounding == NULL) | |
| 212 { | |
| 213 Py_DECREF(context_class); | |
| 214 return NULL; | |
| 215 } | |
| 216 context = PyObject_CallFunction(context_class, "iO", 22, rounding); | |
| 217 if (context == NULL) | |
| 218 { | |
| 219 Py_DECREF(context_class); | |
| 220 Py_DECREF(rounding); | |
| 221 return NULL; | |
| 222 } | |
| 223 | |
| 224 exponent_context = PyObject_CallFunction(context_class, "iO", 1, rounding); | |
| 225 Py_DECREF(context_class); | |
| 226 Py_DECREF(rounding); | |
| 227 if (exponent_context == NULL) | |
| 228 { | |
| 229 Py_CLEAR(context); | |
| 230 return NULL; | |
| 231 } | |
| 232 } | |
| 233 | |
| 234 /* t = decimal.Decimal(value) */ | |
| 235 if (ts->seconds) { | |
| 236 PyObject *f = _PyLong_FromTime_t(ts->seconds); | |
| 237 t = PyObject_CallFunction(decimal, "O", f); | |
| 238 Py_CLEAR(f); | |
| 239 } | |
| 240 else { | |
| 241 t = PyObject_CallFunction(decimal, "iO", 0, context); | |
| 242 } | |
| 243 if (t == NULL) | |
| 244 return NULL; | |
| 245 | |
| 246 if (ts->numerator) | |
| 247 { | |
| 248 /* t += decimal.Decimal(numerator, ctx) / decimal.Decimal(denominator, ctx) */ | |
| 249 PyObject *a, *b, *c, *d, *x; | |
| 250 | |
| 251 x = _PyLong_FromTimeFraction_t(ts->numerator); | |
| 252 if (x == NULL) | |
| 253 goto error; | |
| 254 a = PyObject_CallFunction(decimal, "OO", x, context); | |
| 255 Py_CLEAR(x); | |
| 256 if (a == NULL) | |
| 257 goto error; | |
| 258 | |
| 259 x = _PyLong_FromTimeFraction_t(ts->denominator); | |
| 260 if (x == NULL) | |
| 261 { | |
| 262 Py_DECREF(a); | |
| 263 goto error; | |
| 264 } | |
| 265 b = PyObject_CallFunction(decimal, "OO", x, context); | |
| 266 Py_CLEAR(x); | |
| 267 if (b == NULL) | |
| 268 { | |
| 269 Py_DECREF(a); | |
| 270 goto error; | |
| 271 } | |
| 272 | |
| 273 c = _PyObject_CallMethodId(a, &PyId___truediv__, "OO", | |
| 274 b, context); | |
| 275 Py_DECREF(a); | |
| 276 Py_DECREF(b); | |
| 277 if (c == NULL) | |
| 278 goto error; | |
| 279 | |
| 280 d = PyNumber_Add(t, c); | |
| 281 Py_DECREF(c); | |
| 282 if (d == NULL) | |
| 283 goto error; | |
| 284 Py_DECREF(t); | |
| 285 t = d; | |
| 286 } | |
| 287 | |
| 288 if (exponent_cache == NULL) { | |
| 289 exponent_cache = PyDict_New(); | |
| 290 if (exponent_cache == NULL) | |
| 291 goto error; | |
| 292 } | |
| 293 | |
| 294 key = _PyLong_FromTimeFraction_t(ts->denominator); | |
| 295 if (key == NULL) | |
| 296 goto error; | |
| 297 exponent = PyDict_GetItem(exponent_cache, key); | |
| 298 if (exponent == NULL) { | |
| 299 /* exponent = decimal.Decimal(1) / decimal.Decimal(resolution) */ | |
| 300 PyObject *one, *denominator; | |
| 301 | |
| 302 one = PyObject_CallFunction(decimal, "i", 1); | |
| 303 if (one == NULL) { | |
| 304 Py_DECREF(key); | |
| 305 goto error; | |
| 306 } | |
| 307 | |
| 308 denominator = PyObject_CallFunction(decimal, "O", key); | |
| 309 if (denominator == NULL) { | |
| 310 Py_DECREF(key); | |
| 311 Py_DECREF(one); | |
| 312 goto error; | |
| 313 } | |
| 314 | |
| 315 exponent = _PyObject_CallMethodId(one, &PyId___truediv__, "OO", | |
| 316 denominator, exponent_context); | |
| 317 Py_DECREF(one); | |
| 318 Py_DECREF(denominator); | |
| 319 if (exponent == NULL) { | |
| 320 Py_DECREF(key); | |
| 321 goto error; | |
| 322 } | |
| 323 | |
| 324 if (PyDict_SetItem(exponent_cache, key, exponent) < 0) { | |
| 325 Py_DECREF(key); | |
| 326 Py_DECREF(exponent); | |
| 327 goto error; | |
| 328 } | |
| 329 Py_DECREF(key); | |
| 330 } | |
| 331 | |
| 332 /* t = t.quantize(exponent, None, context) */ | |
| 333 quantized = _PyObject_CallMethodId(t, &PyId_quantize, "OOO", | |
| 334 exponent, Py_None, context); | |
| 335 if (quantized == NULL) | |
| 336 goto error; | |
| 337 Py_DECREF(t); | |
| 338 t = quantized; | |
| 339 | |
| 340 return t; | |
| 341 | |
| 342 error: | |
| 343 Py_XDECREF(t); | |
| 344 return NULL; | |
| 345 } | |
| 346 | |
| 347 PyObject* | |
| 348 _PyTime_Convert(_PyTime_t *ts, PyObject *format) | |
| 349 { | |
| 350 assert(ts->denominator != 0); | |
| 351 | |
| 352 if (format == NULL || (PyTypeObject *)format == &PyFloat_Type) | |
| 353 return _PyTime_AsFloat(ts); | |
| 354 if ((PyTypeObject *)format == &PyLong_Type) | |
| 355 return _PyTime_AsLong(ts); | |
| 356 | |
| 357 if (PyType_Check(format)) | |
| 358 { | |
| 359 PyObject *module, *name; | |
| 360 _Py_IDENTIFIER(__name__); | |
| 361 _Py_IDENTIFIER(__module__); | |
| 362 | |
| 363 module = _PyObject_GetAttrId(format, &PyId___module__); | |
| 364 name = _PyObject_GetAttrId(format, &PyId___name__); | |
| 365 if (module != NULL && PyUnicode_Check(module) | |
| 366 && name != NULL && PyUnicode_Check(name)) | |
| 367 { | |
| 368 if (PyUnicode_CompareWithASCIIString(module, "decimal") == 0 | |
| 369 && PyUnicode_CompareWithASCIIString(name, "Decimal") == 0) | |
| 370 return _PyTime_AsDecimal(ts); | |
| 371 } | |
| 372 else | |
| 373 PyErr_Clear(); | |
| 374 } | |
| 375 | |
| 376 PyErr_Format(PyExc_ValueError, "Unknown timestamp format: %R", format); | |
| 377 return NULL; | |
| 378 } | |
| 379 | |
| 380 void | |
|
63757
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
381 _PyTime_Init() |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
382 { |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
383 /* Do nothing. Needed to force linking. */ |
|
c16803bbd790
Issue #9079: Added _PyTime_gettimeofday(_PyTime_timeval *tp) to C API
Alexander Belopolsky <alexander.belopolsky@gmail.com>
parents:
diff
changeset
|
384 } |
