Commit 5d7d0db4 authored by jbrockmendel's avatar jbrockmendel Committed by GitHub

ENH: implement cpython/time.pxd time, localtime (#3767)

* ENH: implement cpython/time.pxd
Co-authored-by: default avatarscoder <stefan_ml@behnel.de>
parent 320fa6d7
"""
Cython implementation of (parts of) the standard library time module.
"""
from libc.stdint cimport int64_t
from cpython.exc cimport PyErr_SetFromErrno
cdef extern from "pytime.h":
ctypedef int64_t _PyTime_t
_PyTime_t _PyTime_GetSystemClock() nogil
double _PyTime_AsSecondsDouble(_PyTime_t t) nogil
from libc.time cimport (
tm,
time_t,
localtime as libc_localtime,
)
cdef inline double time() nogil:
cdef:
_PyTime_t tic
tic = _PyTime_GetSystemClock()
return _PyTime_AsSecondsDouble(tic)
cdef inline int _raise_from_errno() except -1 with gil:
PyErr_SetFromErrno(RuntimeError)
return <int> -1 # Let the C compiler know that this function always raises.
cdef inline tm localtime() nogil except *:
"""
Analogue to the stdlib time.localtime. The returned struct
has some entries that the stdlib version does not: tm_gmtoff, tm_zone
"""
cdef:
time_t tic = <time_t>time()
tm* result
result = libc_localtime(&tic)
if result is NULL:
_raise_from_errno()
# Fix 0-based date values (and the 1900-based year).
# See tmtotuple() in https://github.com/python/cpython/blob/master/Modules/timemodule.c
result.tm_year += 1900
result.tm_mon += 1
result.tm_wday = (result.tm_wday + 6) % 7
result.tm_yday += 1
return result[0]
# mode: run
# tag: py3only,pytime
import time
from cpython cimport time as ctime
def test_time():
"""
>>> tic1, tic2, tic3 = test_time()
>>> tic1 <= tic3 # sanity check
True
>>> tic1 <= tic2
True
>>> tic2 <= tic3
True
"""
# check that ctime.time() matches time.time() to within call-time tolerance
tic1 = time.time()
tic2 = ctime.time()
tic3 = time.time()
return tic1, tic2, tic3
def test_localtime():
"""
>>> ltp, ltc = test_localtime()
>>> ltp.tm_year == ltc['tm_year'] or (ltp.tm_year, ltc['tm_year'])
True
>>> ltp.tm_mon == ltc['tm_mon'] or (ltp.tm_mon, ltc['tm_mon'])
True
>>> ltp.tm_mday == ltc['tm_mday'] or (ltp.tm_mday, ltc['tm_mday'])
True
>>> ltp.tm_hour == ltc['tm_hour'] or (ltp.tm_hour, ltc['tm_hour'])
True
>>> ltp.tm_min == ltc['tm_min'] or (ltp.tm_min, ltc['tm_min'])
True
>>> ltp.tm_sec == ltc['tm_sec'] or (ltp.tm_sec, ltc['tm_sec'])
True
>>> ltp.tm_wday == ltc['tm_wday'] or (ltp.tm_wday, ltc['tm_wday'])
True
>>> ltp.tm_yday == ltc['tm_yday'] or (ltp.tm_yday, ltc['tm_yday'])
True
>>> ltp.tm_isdst == ltc['tm_isdst'] or (ltp.tm_isdst, ltc['tm_isdst'])
True
"""
ltp = time.localtime()
ltc = ctime.localtime()
if ltp.tm_sec != ltc.tm_sec:
# If the time.localtime call is just before the end of a second and the
# ctime.localtime call is just after the beginning of the next second,
# re-call. This should not occur twice in a row.
ltp = time.localtime()
ltc = ctime.localtime()
return ltp, ltc
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment