Coverage Report

Created: 2026-02-26 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython/Python/pytime.c
Line
Count
Source
1
#include "Python.h"
2
#include "pycore_initconfig.h"    // _PyStatus_ERR
3
#include "pycore_pystate.h"       // _Py_AssertHoldsTstate()
4
#include "pycore_runtime.h"       // _PyRuntime
5
#include "pycore_time.h"          // export _PyLong_FromTime_t()
6
7
#include <time.h>                 // gmtime_r()
8
#ifdef HAVE_SYS_TIME_H
9
#  include <sys/time.h>           // gettimeofday()
10
#endif
11
#ifdef MS_WINDOWS
12
#  include <winsock2.h>           // struct timeval
13
#endif
14
15
#if defined(__APPLE__)
16
#  include <mach/mach_time.h>     // mach_absolute_time(), mach_timebase_info()
17
18
#if defined(__APPLE__) && defined(__has_builtin)
19
#  if __has_builtin(__builtin_available)
20
#    define HAVE_CLOCK_GETTIME_RUNTIME __builtin_available(macOS 10.12, iOS 10.0, tvOS 10.0, watchOS 3.0, *)
21
#  endif
22
#endif
23
#endif
24
25
/* To millisecond (10^-3) */
26
439k
#define SEC_TO_MS 1000
27
28
/* To microseconds (10^-6) */
29
439k
#define MS_TO_US 1000
30
0
#define SEC_TO_US (SEC_TO_MS * MS_TO_US)
31
32
/* To nanoseconds (10^-9) */
33
1.17M
#define US_TO_NS 1000
34
439k
#define MS_TO_NS (MS_TO_US * US_TO_NS)
35
439k
#define SEC_TO_NS (SEC_TO_MS * MS_TO_NS)
36
37
/* Conversion from nanoseconds */
38
0
#define NS_TO_MS (1000 * 1000)
39
0
#define NS_TO_US (1000)
40
#define NS_TO_100NS (100)
41
42
#if SIZEOF_TIME_T == SIZEOF_LONG_LONG
43
#  define PY_TIME_T_MAX LLONG_MAX
44
0
#  define PY_TIME_T_MIN LLONG_MIN
45
#elif SIZEOF_TIME_T == SIZEOF_LONG
46
#  define PY_TIME_T_MAX LONG_MAX
47
#  define PY_TIME_T_MIN LONG_MIN
48
#else
49
#  error "unsupported time_t size"
50
#endif
51
52
#if PY_TIME_T_MAX + PY_TIME_T_MIN != -1
53
#  error "time_t is not a two's complement integer type"
54
#endif
55
56
#if PyTime_MIN + PyTime_MAX != -1
57
#  error "PyTime_t is not a two's complement integer type"
58
#endif
59
60
61
static PyTime_t
62
_PyTime_GCD(PyTime_t x, PyTime_t y)
63
64
{
64
    // Euclidean algorithm
65
64
    assert(x >= 1);
66
64
    assert(y >= 1);
67
128
    while (y != 0) {
68
64
        PyTime_t tmp = y;
69
64
        y = x % y;
70
64
        x = tmp;
71
64
    }
72
64
    assert(x >= 1);
73
64
    return x;
74
64
}
75
76
77
int
78
_PyTimeFraction_Set(_PyTimeFraction *frac, PyTime_t numer, PyTime_t denom)
79
64
{
80
64
    if (numer < 1 || denom < 1) {
81
0
        return -1;
82
0
    }
83
84
64
    PyTime_t gcd = _PyTime_GCD(numer, denom);
85
64
    frac->numer = numer / gcd;
86
64
    frac->denom = denom / gcd;
87
64
    return 0;
88
64
}
89
90
91
double
92
_PyTimeFraction_Resolution(const _PyTimeFraction *frac)
93
0
{
94
0
    return (double)frac->numer / (double)frac->denom / 1e9;
95
0
}
96
97
98
static void
99
pytime_time_t_overflow(void)
100
0
{
101
0
    PyErr_SetString(PyExc_OverflowError,
102
0
                    "timestamp out of range for platform time_t");
103
0
}
104
105
106
static void
107
pytime_overflow(void)
108
0
{
109
0
    PyErr_SetString(PyExc_OverflowError,
110
0
                    "timestamp too large to convert to C PyTime_t");
111
0
}
112
113
114
// Compute t1 + t2. Clamp to [PyTime_MIN; PyTime_MAX] on overflow.
115
static inline int
116
pytime_add(PyTime_t *t1, PyTime_t t2)
117
180k
{
118
180k
    if (t2 > 0 && *t1 > PyTime_MAX - t2) {
119
0
        *t1 = PyTime_MAX;
120
0
        return -1;
121
0
    }
122
180k
    else if (t2 < 0 && *t1 < PyTime_MIN - t2) {
123
0
        *t1 = PyTime_MIN;
124
0
        return -1;
125
0
    }
126
180k
    else {
127
180k
        *t1 += t2;
128
180k
        return 0;
129
180k
    }
130
180k
}
131
132
133
PyTime_t
134
_PyTime_Add(PyTime_t t1, PyTime_t t2)
135
0
{
136
0
    (void)pytime_add(&t1, t2);
137
0
    return t1;
138
0
}
139
140
141
static inline int
142
pytime_mul_check_overflow(PyTime_t a, PyTime_t b)
143
913k
{
144
913k
    if (b != 0) {
145
913k
        assert(b > 0);
146
913k
        return ((a < PyTime_MIN / b) || (PyTime_MAX / b < a));
147
913k
    }
148
0
    else {
149
0
        return 0;
150
0
    }
151
913k
}
152
153
154
// Compute t * k. Clamp to [PyTime_MIN; PyTime_MAX] on overflow.
155
static inline int
156
pytime_mul(PyTime_t *t, PyTime_t k)
157
913k
{
158
913k
    assert(k >= 0);
159
913k
    if (pytime_mul_check_overflow(*t, k)) {
160
0
        *t = (*t >= 0) ? PyTime_MAX : PyTime_MIN;
161
0
        return -1;
162
0
    }
163
913k
    else {
164
913k
        *t *= k;
165
913k
        return 0;
166
913k
    }
167
913k
}
168
169
170
// Compute t * k. Clamp to [PyTime_MIN; PyTime_MAX] on overflow.
171
static inline PyTime_t
172
_PyTime_Mul(PyTime_t t, PyTime_t k)
173
732k
{
174
732k
    (void)pytime_mul(&t, k);
175
732k
    return t;
176
732k
}
177
178
179
PyTime_t
180
_PyTimeFraction_Mul(PyTime_t ticks, const _PyTimeFraction *frac)
181
0
{
182
0
    const PyTime_t mul = frac->numer;
183
0
    const PyTime_t div = frac->denom;
184
185
0
    if (div == 1) {
186
        // Fast-path taken by mach_absolute_time() with 1/1 time base.
187
0
        return _PyTime_Mul(ticks, mul);
188
0
    }
189
190
    /* Compute (ticks * mul / div) in two parts to reduce the risk of integer
191
       overflow: compute the integer part, and then the remaining part.
192
193
       (ticks * mul) / div == (ticks / div) * mul + (ticks % div) * mul / div
194
    */
195
0
    PyTime_t intpart, remaining;
196
0
    intpart = ticks / div;
197
0
    ticks %= div;
198
0
    remaining = _PyTime_Mul(ticks, mul) / div;
199
    // intpart * mul + remaining
200
0
    return _PyTime_Add(_PyTime_Mul(intpart, mul), remaining);
201
0
}
202
203
204
time_t
205
_PyLong_AsTime_t(PyObject *obj)
206
0
{
207
0
#if SIZEOF_TIME_T == SIZEOF_LONG_LONG
208
0
    long long val = PyLong_AsLongLong(obj);
209
#elif SIZEOF_TIME_T <= SIZEOF_LONG
210
    long val = PyLong_AsLong(obj);
211
#else
212
#   error "unsupported time_t size"
213
#endif
214
0
    if (val == -1 && PyErr_Occurred()) {
215
0
        if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
216
0
            pytime_time_t_overflow();
217
0
        }
218
0
        return -1;
219
0
    }
220
0
    return (time_t)val;
221
0
}
222
223
224
PyObject *
225
_PyLong_FromTime_t(time_t t)
226
1.30M
{
227
1.30M
#if SIZEOF_TIME_T == SIZEOF_LONG_LONG
228
1.30M
    return PyLong_FromLongLong((long long)t);
229
#elif SIZEOF_TIME_T <= SIZEOF_LONG
230
    return PyLong_FromLong((long)t);
231
#else
232
#   error "unsupported time_t size"
233
#endif
234
1.30M
}
235
236
237
// Convert PyTime_t to time_t.
238
// Return 0 on success. Return -1 and clamp the value on overflow.
239
static int
240
_PyTime_AsTime_t(PyTime_t t, time_t *t2)
241
0
{
242
#if SIZEOF_TIME_T < _SIZEOF_PYTIME_T
243
    if ((PyTime_t)PY_TIME_T_MAX < t) {
244
        *t2 = PY_TIME_T_MAX;
245
        return -1;
246
    }
247
    if (t < (PyTime_t)PY_TIME_T_MIN) {
248
        *t2 = PY_TIME_T_MIN;
249
        return -1;
250
    }
251
#endif
252
0
    *t2 = (time_t)t;
253
0
    return 0;
254
0
}
255
256
257
#ifdef MS_WINDOWS
258
// Convert PyTime_t to long.
259
// Return 0 on success. Return -1 and clamp the value on overflow.
260
static int
261
_PyTime_AsCLong(PyTime_t t, long *t2)
262
{
263
#if SIZEOF_LONG < _SIZEOF_PYTIME_T
264
    if ((PyTime_t)LONG_MAX < t) {
265
        *t2 = LONG_MAX;
266
        return -1;
267
    }
268
    if (t < (PyTime_t)LONG_MIN) {
269
        *t2 = LONG_MIN;
270
        return -1;
271
    }
272
#endif
273
    *t2 = (long)t;
274
    return 0;
275
}
276
277
// Seconds between 1601-01-01 and 1970-01-01:
278
// 369 years + 89 leap days.
279
#define SECS_BETWEEN_EPOCHS 11644473600LL
280
#define HUNDRED_NS_PER_SEC 10000000LL
281
282
// Calculate day of year (0-365) from SYSTEMTIME
283
static int
284
_PyTime_calc_yday(const SYSTEMTIME *st)
285
{
286
    // Cumulative days before each month (non-leap year)
287
    static const int days_before_month[] = {
288
        0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
289
    };
290
    int yday = days_before_month[st->wMonth - 1] + st->wDay - 1;
291
    // Account for leap day if we're past February in a leap year.
292
    if (st->wMonth > 2) {
293
        // Leap year rules (Gregorian calendar):
294
        // - Years divisible by 4 are leap years
295
        // - EXCEPT years divisible by 100 are NOT leap years
296
        // - EXCEPT years divisible by 400 ARE leap years
297
        int year = st->wYear;
298
        int is_leap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
299
        yday += is_leap;
300
    }
301
    return yday;
302
}
303
304
// Convert time_t to struct tm using Windows FILETIME API.
305
// If is_local is true, convert to local time.
306
// Fallback for negative timestamps that localtime_s/gmtime_s cannot handle.
307
// Return 0 on success. Return -1 on error.
308
static int
309
_PyTime_windows_filetime(time_t timer, struct tm *tm, int is_local)
310
{
311
    /* Check for underflow - FILETIME epoch is 1601-01-01 */
312
    if (timer < -SECS_BETWEEN_EPOCHS) {
313
        PyErr_SetString(PyExc_OverflowError, "timestamp out of range for Windows FILETIME");
314
        return -1;
315
    }
316
317
    /* Convert time_t to FILETIME (100-nanosecond intervals since 1601-01-01) */
318
    ULONGLONG ticks = ((ULONGLONG)timer + SECS_BETWEEN_EPOCHS) * HUNDRED_NS_PER_SEC;
319
    FILETIME ft;
320
    ft.dwLowDateTime = (DWORD)(ticks); // cast to DWORD truncates to low 32 bits
321
    ft.dwHighDateTime = (DWORD)(ticks >> 32);
322
323
    /* Convert FILETIME to SYSTEMTIME */
324
    SYSTEMTIME st_result;
325
    if (is_local) {
326
        /* Convert to local time */
327
        FILETIME ft_local;
328
        if (!FileTimeToLocalFileTime(&ft, &ft_local) ||
329
            !FileTimeToSystemTime(&ft_local, &st_result)) {
330
            PyErr_SetFromWindowsErr(0);
331
            return -1;
332
        }
333
    }
334
    else {
335
        /* Convert to UTC */
336
        if (!FileTimeToSystemTime(&ft, &st_result)) {
337
            PyErr_SetFromWindowsErr(0);
338
            return -1;
339
        }
340
    }
341
342
    /* Convert SYSTEMTIME to struct tm */
343
    tm->tm_year = st_result.wYear - 1900;
344
    tm->tm_mon = st_result.wMonth - 1; /* SYSTEMTIME: 1-12, tm: 0-11 */
345
    tm->tm_mday = st_result.wDay;
346
    tm->tm_hour = st_result.wHour;
347
    tm->tm_min = st_result.wMinute;
348
    tm->tm_sec = st_result.wSecond;
349
    tm->tm_wday = st_result.wDayOfWeek; /* 0=Sunday */
350
351
    // `time.gmtime` and `time.localtime` will return `struct_time` containing this
352
    tm->tm_yday = _PyTime_calc_yday(&st_result);
353
354
    /* DST flag: -1 (unknown) for local time on historical dates, 0 for UTC */
355
    tm->tm_isdst = is_local ? -1 : 0;
356
357
    return 0;
358
}
359
#endif
360
361
362
/* Round to nearest with ties going to nearest even integer
363
   (_PyTime_ROUND_HALF_EVEN) */
364
static double
365
pytime_round_half_even(double x)
366
0
{
367
0
    double rounded = round(x);
368
0
    if (fabs(x-rounded) == 0.5) {
369
        /* halfway case: round to even */
370
0
        rounded = 2.0 * round(x / 2.0);
371
0
    }
372
0
    return rounded;
373
0
}
374
375
376
static double
377
pytime_round(double x, _PyTime_round_t round)
378
0
{
379
    /* volatile avoids optimization changing how numbers are rounded */
380
0
    volatile double d;
381
382
0
    d = x;
383
0
    if (round == _PyTime_ROUND_HALF_EVEN) {
384
0
        d = pytime_round_half_even(d);
385
0
    }
386
0
    else if (round == _PyTime_ROUND_CEILING) {
387
0
        d = ceil(d);
388
0
    }
389
0
    else if (round == _PyTime_ROUND_FLOOR) {
390
0
        d = floor(d);
391
0
    }
392
0
    else {
393
0
        assert(round == _PyTime_ROUND_UP);
394
0
        d = (d >= 0.0) ? ceil(d) : floor(d);
395
0
    }
396
0
    return d;
397
0
}
398
399
400
static int
401
pytime_double_to_denominator(double d, time_t *sec, long *numerator,
402
                             long idenominator, _PyTime_round_t round)
403
0
{
404
0
    double denominator = (double)idenominator;
405
0
    double intpart;
406
    /* volatile avoids optimization changing how numbers are rounded */
407
0
    volatile double floatpart;
408
409
0
    floatpart = modf(d, &intpart);
410
411
0
    floatpart *= denominator;
412
0
    floatpart = pytime_round(floatpart, round);
413
0
    if (floatpart >= denominator) {
414
0
        floatpart -= denominator;
415
0
        intpart += 1.0;
416
0
    }
417
0
    else if (floatpart < 0) {
418
0
        floatpart += denominator;
419
0
        intpart -= 1.0;
420
0
    }
421
0
    assert(0.0 <= floatpart && floatpart < denominator);
422
423
    /*
424
       Conversion of an out-of-range value to time_t gives undefined behaviour
425
       (C99 §6.3.1.4p1), so we must guard against it. However, checking that
426
       `intpart` is in range is delicate: the obvious expression `intpart <=
427
       PY_TIME_T_MAX` will first convert the value `PY_TIME_T_MAX` to a double,
428
       potentially changing its value and leading to us failing to catch some
429
       UB-inducing values. The code below works correctly under the mild
430
       assumption that time_t is a two's complement integer type with no trap
431
       representation, and that `PY_TIME_T_MIN` is within the representable
432
       range of a C double.
433
434
       Note: we want the `if` condition below to be true for NaNs; therefore,
435
       resist any temptation to simplify by applying De Morgan's laws.
436
    */
437
0
    if (!((double)PY_TIME_T_MIN <= intpart && intpart < -(double)PY_TIME_T_MIN)) {
438
0
        pytime_time_t_overflow();
439
0
        return -1;
440
0
    }
441
0
    *sec = (time_t)intpart;
442
0
    *numerator = (long)floatpart;
443
0
    assert(0 <= *numerator && *numerator < idenominator);
444
0
    return 0;
445
0
}
446
447
448
static int
449
pytime_object_to_denominator(PyObject *obj, time_t *sec, long *numerator,
450
                             long denominator, _PyTime_round_t round)
451
0
{
452
0
    assert(denominator >= 1);
453
454
0
    if (PyIndex_Check(obj)) {
455
0
        *sec = _PyLong_AsTime_t(obj);
456
0
        *numerator = 0;
457
0
        if (*sec == (time_t)-1 && PyErr_Occurred()) {
458
0
            return -1;
459
0
        }
460
0
        return 0;
461
0
    }
462
0
    else {
463
0
        double d = PyFloat_AsDouble(obj);
464
0
        if (d == -1 && PyErr_Occurred()) {
465
0
            *numerator = 0;
466
0
            return -1;
467
0
        }
468
0
        if (isnan(d)) {
469
0
            *numerator = 0;
470
0
            PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
471
0
            return -1;
472
0
        }
473
0
        return pytime_double_to_denominator(d, sec, numerator,
474
0
                                            denominator, round);
475
0
    }
476
0
}
477
478
479
int
480
_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec, _PyTime_round_t round)
481
0
{
482
0
    if (PyIndex_Check(obj)) {
483
0
        *sec = _PyLong_AsTime_t(obj);
484
0
        if (*sec == (time_t)-1 && PyErr_Occurred()) {
485
0
            return -1;
486
0
        }
487
0
        return 0;
488
0
    }
489
0
    else {
490
0
        double intpart;
491
        /* volatile avoids optimization changing how numbers are rounded */
492
0
        volatile double d;
493
494
0
        d = PyFloat_AsDouble(obj);
495
0
        if (d == -1 && PyErr_Occurred()) {
496
0
            return -1;
497
0
        }
498
0
        if (isnan(d)) {
499
0
            PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
500
0
            return -1;
501
0
        }
502
503
0
        d = pytime_round(d, round);
504
0
        (void)modf(d, &intpart);
505
506
        /* See comments in pytime_double_to_denominator */
507
0
        if (!((double)PY_TIME_T_MIN <= intpart && intpart < -(double)PY_TIME_T_MIN)) {
508
0
            pytime_time_t_overflow();
509
0
            return -1;
510
0
        }
511
0
        *sec = (time_t)intpart;
512
0
        return 0;
513
0
    }
514
0
}
515
516
517
int
518
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec,
519
                         _PyTime_round_t round)
520
0
{
521
0
    return pytime_object_to_denominator(obj, sec, nsec, SEC_TO_NS, round);
522
0
}
523
524
525
int
526
_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec,
527
                        _PyTime_round_t round)
528
0
{
529
0
    return pytime_object_to_denominator(obj, sec, usec, SEC_TO_US, round);
530
0
}
531
532
533
PyTime_t
534
_PyTime_FromSeconds(int seconds)
535
168k
{
536
    /* ensure that integer overflow cannot happen, int type should have 32
537
       bits, whereas PyTime_t type has at least 64 bits (SEC_TO_NS takes 30
538
       bits). */
539
168k
    static_assert(INT_MAX <= PyTime_MAX / SEC_TO_NS, "PyTime_t overflow");
540
168k
    static_assert(INT_MIN >= PyTime_MIN / SEC_TO_NS, "PyTime_t underflow");
541
542
168k
    PyTime_t t = (PyTime_t)seconds;
543
168k
    assert((t >= 0 && t <= PyTime_MAX / SEC_TO_NS)
544
168k
           || (t < 0 && t >= PyTime_MIN / SEC_TO_NS));
545
168k
    t *= SEC_TO_NS;
546
168k
    return t;
547
168k
}
548
549
550
PyTime_t
551
_PyTime_FromMicrosecondsClamp(PyTime_t us)
552
732k
{
553
732k
    PyTime_t ns = _PyTime_Mul(us, US_TO_NS);
554
732k
    return ns;
555
732k
}
556
557
558
#ifdef HAVE_CLOCK_GETTIME
559
static int
560
pytime_fromtimespec(PyTime_t *tp, const struct timespec *ts, int raise_exc)
561
180k
{
562
180k
    PyTime_t t, tv_nsec;
563
564
180k
    static_assert(sizeof(ts->tv_sec) <= sizeof(PyTime_t),
565
180k
                  "timespec.tv_sec is larger than PyTime_t");
566
180k
    t = (PyTime_t)ts->tv_sec;
567
568
180k
    int res1 = pytime_mul(&t, SEC_TO_NS);
569
570
180k
    tv_nsec = ts->tv_nsec;
571
180k
    int res2 = pytime_add(&t, tv_nsec);
572
573
180k
    *tp = t;
574
575
180k
    if (raise_exc && (res1 < 0 || res2 < 0)) {
576
0
        pytime_overflow();
577
0
        return -1;
578
0
    }
579
180k
    return 0;
580
180k
}
581
582
int
583
_PyTime_FromTimespec(PyTime_t *tp, const struct timespec *ts)
584
0
{
585
0
    return pytime_fromtimespec(tp, ts, 1);
586
0
}
587
#endif
588
589
590
#ifndef MS_WINDOWS
591
static int
592
pytime_fromtimeval(PyTime_t *tp, struct timeval *tv, int raise_exc)
593
0
{
594
0
    static_assert(sizeof(tv->tv_sec) <= sizeof(PyTime_t),
595
0
                  "timeval.tv_sec is larger than PyTime_t");
596
0
    PyTime_t t = (PyTime_t)tv->tv_sec;
597
598
0
    int res1 = pytime_mul(&t, SEC_TO_NS);
599
600
0
    PyTime_t usec = (PyTime_t)tv->tv_usec * US_TO_NS;
601
0
    int res2 = pytime_add(&t, usec);
602
603
0
    *tp = t;
604
605
0
    if (raise_exc && (res1 < 0 || res2 < 0)) {
606
0
        pytime_overflow();
607
0
        return -1;
608
0
    }
609
0
    return 0;
610
0
}
611
612
613
int
614
_PyTime_FromTimeval(PyTime_t *tp, struct timeval *tv)
615
0
{
616
0
    return pytime_fromtimeval(tp, tv, 1);
617
0
}
618
#endif
619
620
621
static int
622
pytime_from_double(PyTime_t *tp, double value, _PyTime_round_t round,
623
                   long unit_to_ns)
624
0
{
625
    /* volatile avoids optimization changing how numbers are rounded */
626
0
    volatile double d;
627
628
    /* convert to a number of nanoseconds */
629
0
    d = value;
630
0
    d *= (double)unit_to_ns;
631
0
    d = pytime_round(d, round);
632
633
    /* See comments in pytime_double_to_denominator */
634
0
    if (!((double)PyTime_MIN <= d && d < -(double)PyTime_MIN)) {
635
0
        pytime_time_t_overflow();
636
0
        *tp = 0;
637
0
        return -1;
638
0
    }
639
0
    PyTime_t ns = (PyTime_t)d;
640
641
0
    *tp = ns;
642
0
    return 0;
643
0
}
644
645
646
static int
647
pytime_from_object(PyTime_t *tp, PyObject *obj, _PyTime_round_t round,
648
                   long unit_to_ns)
649
0
{
650
0
    if (PyIndex_Check(obj)) {
651
0
        long long sec = PyLong_AsLongLong(obj);
652
0
        if (sec == -1 && PyErr_Occurred()) {
653
0
            if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
654
0
                pytime_overflow();
655
0
            }
656
0
            return -1;
657
0
        }
658
659
0
        static_assert(sizeof(long long) <= sizeof(PyTime_t),
660
0
                    "PyTime_t is smaller than long long");
661
0
        PyTime_t ns = (PyTime_t)sec;
662
0
        if (pytime_mul(&ns, unit_to_ns) < 0) {
663
0
            pytime_overflow();
664
0
            return -1;
665
0
        }
666
667
0
        *tp = ns;
668
0
        return 0;
669
0
    }
670
0
    else {
671
0
        double d;
672
0
        d = PyFloat_AsDouble(obj);
673
0
        if (d == -1 && PyErr_Occurred()) {
674
0
            return -1;
675
0
        }
676
0
        if (isnan(d)) {
677
0
            PyErr_SetString(PyExc_ValueError, "Invalid value NaN (not a number)");
678
0
            return -1;
679
0
        }
680
0
        return pytime_from_double(tp, d, round, unit_to_ns);
681
0
    }
682
0
}
683
684
685
int
686
_PyTime_FromSecondsObject(PyTime_t *tp, PyObject *obj, _PyTime_round_t round)
687
0
{
688
0
    return pytime_from_object(tp, obj, round, SEC_TO_NS);
689
0
}
690
691
692
int
693
_PyTime_FromMillisecondsObject(PyTime_t *tp, PyObject *obj, _PyTime_round_t round)
694
0
{
695
0
    return pytime_from_object(tp, obj, round, MS_TO_NS);
696
0
}
697
698
699
double
700
PyTime_AsSecondsDouble(PyTime_t ns)
701
90.4k
{
702
    /* volatile avoids optimization changing how numbers are rounded */
703
90.4k
    volatile double d;
704
705
90.4k
    if (ns % SEC_TO_NS == 0) {
706
        /* Divide using integers to avoid rounding issues on the integer part.
707
           1e-9 cannot be stored exactly in IEEE 64-bit. */
708
0
        PyTime_t secs = ns / SEC_TO_NS;
709
0
        d = (double)secs;
710
0
    }
711
90.4k
    else {
712
90.4k
        d = (double)ns;
713
90.4k
        d /= 1e9;
714
90.4k
    }
715
90.4k
    return d;
716
90.4k
}
717
718
719
int
720
_PyTime_FromSecondsDouble(double seconds, _PyTime_round_t round, PyTime_t *result)
721
0
{
722
0
    return pytime_from_double(result, seconds, round, SEC_TO_NS);
723
0
}
724
725
726
static PyTime_t
727
pytime_divide_round_up(const PyTime_t t, const PyTime_t k)
728
0
{
729
0
    assert(k > 1);
730
0
    if (t >= 0) {
731
        // Don't use (t + k - 1) / k to avoid integer overflow
732
        // if t is equal to PyTime_MAX
733
0
        PyTime_t q = t / k;
734
0
        if (t % k) {
735
0
            q += 1;
736
0
        }
737
0
        return q;
738
0
    }
739
0
    else {
740
        // Don't use (t - (k - 1)) / k to avoid integer overflow
741
        // if t is equals to PyTime_MIN.
742
0
        PyTime_t q = t / k;
743
0
        if (t % k) {
744
0
            q -= 1;
745
0
        }
746
0
        return q;
747
0
    }
748
0
}
749
750
751
static PyTime_t
752
pytime_divide(const PyTime_t t, const PyTime_t k,
753
              const _PyTime_round_t round)
754
0
{
755
0
    assert(k > 1);
756
0
    if (round == _PyTime_ROUND_HALF_EVEN) {
757
0
        PyTime_t x = t / k;
758
0
        PyTime_t r = t % k;
759
0
        PyTime_t abs_r = Py_ABS(r);
760
0
        if (abs_r > k / 2 || (abs_r == k / 2 && (Py_ABS(x) & 1))) {
761
0
            if (t >= 0) {
762
0
                x++;
763
0
            }
764
0
            else {
765
0
                x--;
766
0
            }
767
0
        }
768
0
        return x;
769
0
    }
770
0
    else if (round == _PyTime_ROUND_CEILING) {
771
0
        if (t >= 0) {
772
0
            return pytime_divide_round_up(t, k);
773
0
        }
774
0
        else {
775
0
            return t / k;
776
0
        }
777
0
    }
778
0
    else if (round == _PyTime_ROUND_FLOOR){
779
0
        if (t >= 0) {
780
0
            return t / k;
781
0
        }
782
0
        else {
783
0
            return pytime_divide_round_up(t, k);
784
0
        }
785
0
    }
786
0
    else {
787
0
        assert(round == _PyTime_ROUND_UP);
788
0
        return pytime_divide_round_up(t, k);
789
0
    }
790
0
}
791
792
793
// Compute (t / k, t % k) in (pq, pr).
794
// Make sure that 0 <= pr < k.
795
// Return 0 on success.
796
// Return -1 on underflow and store (PyTime_MIN, 0) in (pq, pr).
797
static int
798
pytime_divmod(const PyTime_t t, const PyTime_t k,
799
              PyTime_t *pq, PyTime_t *pr)
800
0
{
801
0
    assert(k > 1);
802
0
    PyTime_t q = t / k;
803
0
    PyTime_t r = t % k;
804
0
    if (r < 0) {
805
0
        if (q == PyTime_MIN) {
806
0
            *pq = PyTime_MIN;
807
0
            *pr = 0;
808
0
            return -1;
809
0
        }
810
0
        r += k;
811
0
        q -= 1;
812
0
    }
813
0
    assert(0 <= r && r < k);
814
815
0
    *pq = q;
816
0
    *pr = r;
817
0
    return 0;
818
0
}
819
820
821
#ifdef MS_WINDOWS
822
PyTime_t
823
_PyTime_As100Nanoseconds(PyTime_t ns, _PyTime_round_t round)
824
{
825
    return pytime_divide(ns, NS_TO_100NS, round);
826
}
827
#endif
828
829
830
PyTime_t
831
_PyTime_AsMicroseconds(PyTime_t ns, _PyTime_round_t round)
832
0
{
833
0
    return pytime_divide(ns, NS_TO_US, round);
834
0
}
835
836
837
PyTime_t
838
_PyTime_AsMilliseconds(PyTime_t ns, _PyTime_round_t round)
839
0
{
840
0
    return pytime_divide(ns, NS_TO_MS, round);
841
0
}
842
843
844
static int
845
pytime_as_timeval(PyTime_t ns, PyTime_t *ptv_sec, int *ptv_usec,
846
                  _PyTime_round_t round)
847
0
{
848
0
    PyTime_t us = pytime_divide(ns, US_TO_NS, round);
849
850
0
    PyTime_t tv_sec, tv_usec;
851
0
    int res = pytime_divmod(us, SEC_TO_US, &tv_sec, &tv_usec);
852
0
    *ptv_sec = tv_sec;
853
0
    *ptv_usec = (int)tv_usec;
854
0
    return res;
855
0
}
856
857
858
static int
859
pytime_as_timeval_struct(PyTime_t t, struct timeval *tv,
860
                         _PyTime_round_t round, int raise_exc)
861
0
{
862
0
    PyTime_t tv_sec;
863
0
    int tv_usec;
864
0
    int res = pytime_as_timeval(t, &tv_sec, &tv_usec, round);
865
0
    int res2;
866
#ifdef MS_WINDOWS
867
    // On Windows, timeval.tv_sec type is long
868
    res2 = _PyTime_AsCLong(tv_sec, &tv->tv_sec);
869
#else
870
0
    res2 = _PyTime_AsTime_t(tv_sec, &tv->tv_sec);
871
0
#endif
872
0
    if (res2 < 0) {
873
0
        tv_usec = 0;
874
0
    }
875
0
    tv->tv_usec = tv_usec;
876
877
0
    if (raise_exc && (res < 0 || res2 < 0)) {
878
0
        pytime_time_t_overflow();
879
0
        return -1;
880
0
    }
881
0
    return 0;
882
0
}
883
884
885
int
886
_PyTime_AsTimeval(PyTime_t t, struct timeval *tv, _PyTime_round_t round)
887
0
{
888
0
    return pytime_as_timeval_struct(t, tv, round, 1);
889
0
}
890
891
892
void
893
_PyTime_AsTimeval_clamp(PyTime_t t, struct timeval *tv, _PyTime_round_t round)
894
0
{
895
0
    (void)pytime_as_timeval_struct(t, tv, round, 0);
896
0
}
897
898
899
int
900
_PyTime_AsTimevalTime_t(PyTime_t t, time_t *p_secs, int *us,
901
                        _PyTime_round_t round)
902
0
{
903
0
    PyTime_t secs;
904
0
    if (pytime_as_timeval(t, &secs, us, round) < 0) {
905
0
        pytime_time_t_overflow();
906
0
        return -1;
907
0
    }
908
909
0
    if (_PyTime_AsTime_t(secs, p_secs) < 0) {
910
0
        pytime_time_t_overflow();
911
0
        return -1;
912
0
    }
913
0
    return 0;
914
0
}
915
916
917
#if defined(HAVE_CLOCK_GETTIME) || defined(HAVE_KQUEUE)
918
static int
919
pytime_as_timespec(PyTime_t ns, struct timespec *ts, int raise_exc)
920
0
{
921
0
    PyTime_t tv_sec, tv_nsec;
922
0
    int res = pytime_divmod(ns, SEC_TO_NS, &tv_sec, &tv_nsec);
923
924
0
    int res2 = _PyTime_AsTime_t(tv_sec, &ts->tv_sec);
925
0
    if (res2 < 0) {
926
0
        tv_nsec = 0;
927
0
    }
928
0
    ts->tv_nsec = tv_nsec;
929
930
0
    if (raise_exc && (res < 0 || res2 < 0)) {
931
0
        pytime_time_t_overflow();
932
0
        return -1;
933
0
    }
934
0
    return 0;
935
0
}
936
937
void
938
_PyTime_AsTimespec_clamp(PyTime_t t, struct timespec *ts)
939
0
{
940
0
    (void)pytime_as_timespec(t, ts, 0);
941
0
}
942
943
int
944
_PyTime_AsTimespec(PyTime_t t, struct timespec *ts)
945
0
{
946
0
    return pytime_as_timespec(t, ts, 1);
947
0
}
948
#endif
949
950
951
// N.B. If raise_exc=0, this may be called without a thread state.
952
static int
953
py_get_system_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
954
8
{
955
8
    assert(info == NULL || raise_exc);
956
8
    if (raise_exc) {
957
        // raise_exc requires to hold a thread state
958
8
        _Py_AssertHoldsTstate();
959
8
    }
960
961
#ifdef MS_WINDOWS
962
    FILETIME system_time;
963
    ULARGE_INTEGER large;
964
965
    GetSystemTimePreciseAsFileTime(&system_time);
966
    large.u.LowPart = system_time.dwLowDateTime;
967
    large.u.HighPart = system_time.dwHighDateTime;
968
969
    PyTime_t ns = (large.QuadPart - SECS_BETWEEN_EPOCHS * HUNDRED_NS_PER_SEC) * 100;
970
    *tp = ns;
971
    if (info) {
972
        // GetSystemTimePreciseAsFileTime() is implemented using
973
        // QueryPerformanceCounter() internally.
974
        info->implementation = "GetSystemTimePreciseAsFileTime()";
975
        info->monotonic = 0;
976
        info->resolution = _PyTimeFraction_Resolution(&_PyRuntime.time.base);
977
        info->adjustable = 1;
978
    }
979
980
#else   /* MS_WINDOWS */
981
8
    int err;
982
8
#if defined(HAVE_CLOCK_GETTIME)
983
8
    struct timespec ts;
984
8
#endif
985
986
#if !defined(HAVE_CLOCK_GETTIME) || defined(__APPLE__)
987
    struct timeval tv;
988
#endif
989
990
8
#ifdef HAVE_CLOCK_GETTIME
991
992
#ifdef HAVE_CLOCK_GETTIME_RUNTIME
993
    if (HAVE_CLOCK_GETTIME_RUNTIME) {
994
#endif
995
996
8
    err = clock_gettime(CLOCK_REALTIME, &ts);
997
8
    if (err) {
998
0
        if (raise_exc) {
999
0
            PyErr_SetFromErrno(PyExc_OSError);
1000
0
        }
1001
0
        return -1;
1002
0
    }
1003
8
    if (pytime_fromtimespec(tp, &ts, raise_exc) < 0) {
1004
0
        return -1;
1005
0
    }
1006
1007
8
    if (info) {
1008
0
        struct timespec res;
1009
0
        info->implementation = "clock_gettime(CLOCK_REALTIME)";
1010
0
        info->monotonic = 0;
1011
0
        info->adjustable = 1;
1012
0
        if (clock_getres(CLOCK_REALTIME, &res) == 0) {
1013
0
            info->resolution = (double)res.tv_sec + (double)res.tv_nsec * 1e-9;
1014
0
        }
1015
0
        else {
1016
0
            info->resolution = 1e-9;
1017
0
        }
1018
0
    }
1019
1020
#ifdef HAVE_CLOCK_GETTIME_RUNTIME
1021
    }
1022
    else {
1023
#endif
1024
1025
8
#endif
1026
1027
#if !defined(HAVE_CLOCK_GETTIME) || defined(HAVE_CLOCK_GETTIME_RUNTIME)
1028
1029
     /* test gettimeofday() */
1030
    err = gettimeofday(&tv, (struct timezone *)NULL);
1031
    if (err) {
1032
        if (raise_exc) {
1033
            PyErr_SetFromErrno(PyExc_OSError);
1034
        }
1035
        return -1;
1036
    }
1037
    if (pytime_fromtimeval(tp, &tv, raise_exc) < 0) {
1038
        return -1;
1039
    }
1040
1041
    if (info) {
1042
        info->implementation = "gettimeofday()";
1043
        info->resolution = 1e-6;
1044
        info->monotonic = 0;
1045
        info->adjustable = 1;
1046
    }
1047
1048
#if defined(HAVE_CLOCK_GETTIME_RUNTIME) && defined(HAVE_CLOCK_GETTIME)
1049
    } /* end of availability block */
1050
#endif
1051
1052
#endif   /* !HAVE_CLOCK_GETTIME */
1053
8
#endif   /* !MS_WINDOWS */
1054
8
    return 0;
1055
8
}
1056
1057
1058
int
1059
PyTime_Time(PyTime_t *result)
1060
8
{
1061
8
    if (py_get_system_clock(result, NULL, 1) < 0) {
1062
0
        *result = 0;
1063
0
        return -1;
1064
0
    }
1065
8
    return 0;
1066
8
}
1067
1068
1069
int
1070
PyTime_TimeRaw(PyTime_t *result)
1071
0
{
1072
0
    if (py_get_system_clock(result, NULL, 0) < 0) {
1073
0
        *result = 0;
1074
0
        return -1;
1075
0
    }
1076
0
    return 0;
1077
0
}
1078
1079
1080
int
1081
_PyTime_TimeWithInfo(PyTime_t *t, _Py_clock_info_t *info)
1082
0
{
1083
0
    return py_get_system_clock(t, info, 1);
1084
0
}
1085
1086
1087
#ifdef MS_WINDOWS
1088
static PyStatus
1089
py_win_perf_counter_frequency(_PyTimeFraction *base)
1090
{
1091
    LARGE_INTEGER freq;
1092
    // Since Windows XP, the function cannot fail.
1093
    (void)QueryPerformanceFrequency(&freq);
1094
    LONGLONG frequency = freq.QuadPart;
1095
1096
    // Since Windows XP, frequency cannot be zero.
1097
    assert(frequency >= 1);
1098
1099
    Py_BUILD_ASSERT(sizeof(PyTime_t) == sizeof(frequency));
1100
    PyTime_t denom = (PyTime_t)frequency;
1101
1102
    // Known QueryPerformanceFrequency() values:
1103
    //
1104
    // * 10,000,000 (10 MHz): 100 ns resolution
1105
    // * 3,579,545 Hz (3.6 MHz): 279 ns resolution
1106
    if (_PyTimeFraction_Set(base, SEC_TO_NS, denom) < 0) {
1107
        return _PyStatus_ERR("invalid QueryPerformanceFrequency");
1108
    }
1109
    return PyStatus_Ok();
1110
}
1111
1112
1113
// N.B. If raise_exc=0, this may be called without the GIL.
1114
static int
1115
py_get_win_perf_counter(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
1116
{
1117
    assert(info == NULL || raise_exc);
1118
1119
    if (info) {
1120
        info->implementation = "QueryPerformanceCounter()";
1121
        info->resolution = _PyTimeFraction_Resolution(&_PyRuntime.time.base);
1122
        info->monotonic = 1;
1123
        info->adjustable = 0;
1124
    }
1125
1126
    LARGE_INTEGER now;
1127
    QueryPerformanceCounter(&now);
1128
    LONGLONG ticksll = now.QuadPart;
1129
1130
    /* Make sure that casting LONGLONG to PyTime_t cannot overflow,
1131
       both types are signed */
1132
    PyTime_t ticks;
1133
    static_assert(sizeof(ticksll) <= sizeof(ticks),
1134
                  "LONGLONG is larger than PyTime_t");
1135
    ticks = (PyTime_t)ticksll;
1136
1137
    *tp = _PyTimeFraction_Mul(ticks, &_PyRuntime.time.base);
1138
    return 0;
1139
}
1140
#endif  // MS_WINDOWS
1141
1142
1143
#ifdef __APPLE__
1144
static PyStatus
1145
py_mach_timebase_info(_PyTimeFraction *base)
1146
{
1147
    mach_timebase_info_data_t timebase;
1148
    // According to the Technical Q&A QA1398, mach_timebase_info() cannot
1149
    // fail: https://developer.apple.com/library/mac/#qa/qa1398/
1150
    (void)mach_timebase_info(&timebase);
1151
1152
    // Check that timebase.numer and timebase.denom can be casted to
1153
    // PyTime_t. In practice, timebase uses uint32_t, so casting cannot
1154
    // overflow. At the end, only make sure that the type is uint32_t
1155
    // (PyTime_t is 64-bit long).
1156
    Py_BUILD_ASSERT(sizeof(timebase.numer) <= sizeof(PyTime_t));
1157
    Py_BUILD_ASSERT(sizeof(timebase.denom) <= sizeof(PyTime_t));
1158
    PyTime_t numer = (PyTime_t)timebase.numer;
1159
    PyTime_t denom = (PyTime_t)timebase.denom;
1160
1161
    // Known time bases:
1162
    //
1163
    // * (1, 1) on Intel: 1 ns
1164
    // * (1000000000, 33333335) on PowerPC: ~30 ns
1165
    // * (1000000000, 25000000) on PowerPC: 40 ns
1166
    if (_PyTimeFraction_Set(base, numer, denom) < 0) {
1167
        return _PyStatus_ERR("invalid mach_timebase_info");
1168
    }
1169
    return PyStatus_Ok();
1170
}
1171
#endif
1172
1173
PyStatus
1174
_PyTime_Init(struct _Py_time_runtime_state *state)
1175
32
{
1176
#ifdef MS_WINDOWS
1177
    return py_win_perf_counter_frequency(&state->base);
1178
#elif defined(__APPLE__)
1179
    return py_mach_timebase_info(&state->base);
1180
#else
1181
32
    return PyStatus_Ok();
1182
32
#endif
1183
32
}
1184
1185
// N.B. If raise_exc=0, this may be called without a thread state.
1186
static int
1187
py_get_monotonic_clock(PyTime_t *tp, _Py_clock_info_t *info, int raise_exc)
1188
180k
{
1189
180k
    assert(info == NULL || raise_exc);
1190
180k
    if (raise_exc) {
1191
        // raise_exc requires to hold a thread state
1192
116
        _Py_AssertHoldsTstate();
1193
116
    }
1194
1195
#if defined(MS_WINDOWS)
1196
    if (py_get_win_perf_counter(tp, info, raise_exc) < 0) {
1197
        return -1;
1198
    }
1199
#elif defined(__APPLE__)
1200
    if (info) {
1201
        info->implementation = "mach_absolute_time()";
1202
        info->resolution = _PyTimeFraction_Resolution(&_PyRuntime.time.base);
1203
        info->monotonic = 1;
1204
        info->adjustable = 0;
1205
    }
1206
1207
    uint64_t uticks = mach_absolute_time();
1208
    // unsigned => signed
1209
    assert(uticks <= (uint64_t)PyTime_MAX);
1210
    PyTime_t ticks = (PyTime_t)uticks;
1211
1212
    PyTime_t ns = _PyTimeFraction_Mul(ticks, &_PyRuntime.time.base);
1213
    *tp = ns;
1214
1215
#elif defined(__hpux)
1216
    hrtime_t time = gethrtime();
1217
    if (time == -1) {
1218
        if (raise_exc) {
1219
            PyErr_SetFromErrno(PyExc_OSError);
1220
        }
1221
        return -1;
1222
    }
1223
1224
    *tp = time;
1225
1226
    if (info) {
1227
        info->implementation = "gethrtime()";
1228
        info->resolution = 1e-9;
1229
        info->monotonic = 1;
1230
        info->adjustable = 0;
1231
    }
1232
1233
#else
1234
1235
#ifdef CLOCK_HIGHRES
1236
    const clockid_t clk_id = CLOCK_HIGHRES;
1237
    const char *implementation = "clock_gettime(CLOCK_HIGHRES)";
1238
#else
1239
180k
    const clockid_t clk_id = CLOCK_MONOTONIC;
1240
180k
    const char *implementation = "clock_gettime(CLOCK_MONOTONIC)";
1241
180k
#endif
1242
1243
180k
    struct timespec ts;
1244
180k
    if (clock_gettime(clk_id, &ts) != 0) {
1245
0
        if (raise_exc) {
1246
0
            PyErr_SetFromErrno(PyExc_OSError);
1247
0
            return -1;
1248
0
        }
1249
0
        return -1;
1250
0
    }
1251
1252
180k
    if (pytime_fromtimespec(tp, &ts, raise_exc) < 0) {
1253
0
        return -1;
1254
0
    }
1255
1256
180k
    if (info) {
1257
0
        info->monotonic = 1;
1258
0
        info->implementation = implementation;
1259
0
        info->adjustable = 0;
1260
0
        struct timespec res;
1261
0
        if (clock_getres(clk_id, &res) != 0) {
1262
0
            PyErr_SetFromErrno(PyExc_OSError);
1263
0
            return -1;
1264
0
        }
1265
0
        info->resolution = res.tv_sec + res.tv_nsec * 1e-9;
1266
0
    }
1267
180k
#endif
1268
180k
    return 0;
1269
180k
}
1270
1271
1272
int
1273
PyTime_Monotonic(PyTime_t *result)
1274
116
{
1275
116
    if (py_get_monotonic_clock(result, NULL, 1) < 0) {
1276
0
        *result = 0;
1277
0
        return -1;
1278
0
    }
1279
116
    return 0;
1280
116
}
1281
1282
1283
int
1284
PyTime_MonotonicRaw(PyTime_t *result)
1285
180k
{
1286
180k
    if (py_get_monotonic_clock(result, NULL, 0) < 0) {
1287
0
        *result = 0;
1288
0
        return -1;
1289
0
    }
1290
180k
    return 0;
1291
180k
}
1292
1293
1294
int
1295
_PyTime_MonotonicWithInfo(PyTime_t *tp, _Py_clock_info_t *info)
1296
0
{
1297
0
    return py_get_monotonic_clock(tp, info, 1);
1298
0
}
1299
1300
1301
int
1302
_PyTime_PerfCounterWithInfo(PyTime_t *t, _Py_clock_info_t *info)
1303
0
{
1304
0
    return _PyTime_MonotonicWithInfo(t, info);
1305
0
}
1306
1307
1308
int
1309
PyTime_PerfCounter(PyTime_t *result)
1310
116
{
1311
116
    return PyTime_Monotonic(result);
1312
116
}
1313
1314
1315
int
1316
PyTime_PerfCounterRaw(PyTime_t *result)
1317
180k
{
1318
180k
    return PyTime_MonotonicRaw(result);
1319
180k
}
1320
1321
1322
int
1323
_PyTime_localtime(time_t t, struct tm *tm)
1324
64
{
1325
#ifdef MS_WINDOWS
1326
    if (t >= 0) {
1327
        /* For non-negative timestamps, use localtime_s() */
1328
        int error = localtime_s(tm, &t);
1329
        if (error != 0) {
1330
            errno = error;
1331
            PyErr_SetFromErrno(PyExc_OSError);
1332
            return -1;
1333
        }
1334
        return 0;
1335
    }
1336
1337
    /* For negative timestamps, use FILETIME-based conversion */
1338
    return _PyTime_windows_filetime(t, tm, 1);
1339
#else /* !MS_WINDOWS */
1340
1341
#if defined(_AIX) && (SIZEOF_TIME_T < 8)
1342
    /* bpo-34373: AIX does not return NULL if t is too small or too large */
1343
    if (t < -2145916800 /* 1902-01-01 */
1344
       || t > 2145916800 /* 2038-01-01 */) {
1345
        errno = EINVAL;
1346
        PyErr_SetString(PyExc_OverflowError,
1347
                        "localtime argument out of range");
1348
        return -1;
1349
    }
1350
#endif
1351
1352
64
    errno = 0;
1353
64
    if (localtime_r(&t, tm) == NULL) {
1354
0
        if (errno == 0) {
1355
0
            errno = EINVAL;
1356
0
        }
1357
0
        PyErr_SetFromErrno(PyExc_OSError);
1358
0
        return -1;
1359
0
    }
1360
64
    return 0;
1361
64
#endif /* MS_WINDOWS */
1362
64
}
1363
1364
1365
int
1366
_PyTime_gmtime(time_t t, struct tm *tm)
1367
0
{
1368
#ifdef MS_WINDOWS
1369
    /* For non-negative timestamps, use gmtime_s() */
1370
    if (t >= 0) {
1371
        int error = gmtime_s(tm, &t);
1372
        if (error != 0) {
1373
            errno = error;
1374
            PyErr_SetFromErrno(PyExc_OSError);
1375
            return -1;
1376
        }
1377
        return 0;
1378
    }
1379
1380
    /* For negative timestamps, use FILETIME-based conversion */
1381
    return _PyTime_windows_filetime(t, tm, 0);
1382
#else /* !MS_WINDOWS */
1383
0
    if (gmtime_r(&t, tm) == NULL) {
1384
0
#ifdef EINVAL
1385
0
        if (errno == 0) {
1386
0
            errno = EINVAL;
1387
0
        }
1388
0
#endif
1389
0
        PyErr_SetFromErrno(PyExc_OSError);
1390
0
        return -1;
1391
0
    }
1392
0
    return 0;
1393
0
#endif /* MS_WINDOWS */
1394
0
}
1395
1396
1397
PyTime_t
1398
_PyDeadline_Init(PyTime_t timeout)
1399
0
{
1400
0
    PyTime_t now;
1401
    // silently ignore error: cannot report error to the caller
1402
0
    (void)PyTime_MonotonicRaw(&now);
1403
0
    return _PyTime_Add(now, timeout);
1404
0
}
1405
1406
1407
PyTime_t
1408
_PyDeadline_Get(PyTime_t deadline)
1409
0
{
1410
0
    PyTime_t now;
1411
    // silently ignore error: cannot report error to the caller
1412
0
    (void)PyTime_MonotonicRaw(&now);
1413
0
    return deadline - now;
1414
0
}