Close #14180: Factorize code to convert a number of seconds to time_t, timeval or timespec
time.ctime(), gmtime(), time.localtime(), datetime.date.fromtimestamp(), datetime.datetime.fromtimestamp() and datetime.datetime.utcfromtimestamp() now raises an OverflowError, instead of a ValueError, if the timestamp does not fit in time_t. datetime.datetime.fromtimestamp() and datetime.datetime.utcfromtimestamp() now round microseconds towards zero instead of rounding to nearest with ties going away from zero.
This commit is contained in:
parent
3cac309939
commit
5d272cc6a2
@ -395,12 +395,17 @@ Other constructors, all class methods:
|
|||||||
.. classmethod:: date.fromtimestamp(timestamp)
|
.. classmethod:: date.fromtimestamp(timestamp)
|
||||||
|
|
||||||
Return the local date corresponding to the POSIX timestamp, such as is returned
|
Return the local date corresponding to the POSIX timestamp, such as is returned
|
||||||
by :func:`time.time`. This may raise :exc:`ValueError`, if the timestamp is out
|
by :func:`time.time`. This may raise :exc:`OverflowError`, if the timestamp is out
|
||||||
of the range of values supported by the platform C :c:func:`localtime` function.
|
of the range of values supported by the platform C :c:func:`localtime` function.
|
||||||
It's common for this to be restricted to years from 1970 through 2038. Note
|
It's common for this to be restricted to years from 1970 through 2038. Note
|
||||||
that on non-POSIX systems that include leap seconds in their notion of a
|
that on non-POSIX systems that include leap seconds in their notion of a
|
||||||
timestamp, leap seconds are ignored by :meth:`fromtimestamp`.
|
timestamp, leap seconds are ignored by :meth:`fromtimestamp`.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.3
|
||||||
|
Raise :exc:`OverflowError` instead of :exc:`ValueError` if the timestamp
|
||||||
|
is out of the range of values supported by the platform C
|
||||||
|
:c:func:`localtime` function.
|
||||||
|
|
||||||
|
|
||||||
.. classmethod:: date.fromordinal(ordinal)
|
.. classmethod:: date.fromordinal(ordinal)
|
||||||
|
|
||||||
@ -712,6 +717,11 @@ Other constructors, all class methods:
|
|||||||
and then it's possible to have two timestamps differing by a second that yield
|
and then it's possible to have two timestamps differing by a second that yield
|
||||||
identical :class:`.datetime` objects. See also :meth:`utcfromtimestamp`.
|
identical :class:`.datetime` objects. See also :meth:`utcfromtimestamp`.
|
||||||
|
|
||||||
|
.. versionchanged:: 3.3
|
||||||
|
Raise :exc:`OverflowError` instead of :exc:`ValueError` if the timestamp
|
||||||
|
is out of the range of values supported by the platform C
|
||||||
|
:c:func:`localtime` or :c:func:`gmtime` functions
|
||||||
|
|
||||||
|
|
||||||
.. classmethod:: datetime.utcfromtimestamp(timestamp)
|
.. classmethod:: datetime.utcfromtimestamp(timestamp)
|
||||||
|
|
||||||
@ -737,6 +747,11 @@ Other constructors, all class methods:
|
|||||||
|
|
||||||
timestamp = (dt - datetime(1970, 1, 1, tzinfo=timezone.utc)) / timedelta(seconds=1)
|
timestamp = (dt - datetime(1970, 1, 1, tzinfo=timezone.utc)) / timedelta(seconds=1)
|
||||||
|
|
||||||
|
.. versionchanged:: 3.3
|
||||||
|
Raise :exc:`OverflowError` instead of :exc:`ValueError` if the timestamp
|
||||||
|
is out of the range of values supported by the platform C
|
||||||
|
:c:func:`gmtime` function.
|
||||||
|
|
||||||
|
|
||||||
.. classmethod:: datetime.fromordinal(ordinal)
|
.. classmethod:: datetime.fromordinal(ordinal)
|
||||||
|
|
||||||
|
@ -39,9 +39,22 @@ do { \
|
|||||||
(tv_end.tv_usec - tv_start.tv_usec) * 0.000001)
|
(tv_end.tv_usec - tv_start.tv_usec) * 0.000001)
|
||||||
|
|
||||||
#ifndef Py_LIMITED_API
|
#ifndef Py_LIMITED_API
|
||||||
|
/* Convert a number of seconds, int or float, to time_t. */
|
||||||
|
PyAPI_FUNC(int) _PyTime_ObjectToTime_t(
|
||||||
|
PyObject *obj,
|
||||||
|
time_t *sec);
|
||||||
|
|
||||||
|
/* Convert a number of seconds, int or float, to a timeval structure.
|
||||||
|
usec is in the range [0; 999999] and rounded towards zero.
|
||||||
|
For example, -1.2 is converted to (-2, 800000). */
|
||||||
|
PyAPI_FUNC(int) _PyTime_ObjectToTimeval(
|
||||||
|
PyObject *obj,
|
||||||
|
time_t *sec,
|
||||||
|
long *usec);
|
||||||
|
|
||||||
/* Convert a number of seconds, int or float, to a timespec structure.
|
/* Convert a number of seconds, int or float, to a timespec structure.
|
||||||
nsec is always in the range [0; 999999999]. For example, -1.2 is converted
|
nsec is in the range [0; 999999999] and rounded towards zero.
|
||||||
to (-2, 800000000). */
|
For example, -1.2 is converted to (-2, 800000000). */
|
||||||
PyAPI_FUNC(int) _PyTime_ObjectToTimespec(
|
PyAPI_FUNC(int) _PyTime_ObjectToTimespec(
|
||||||
PyObject *obj,
|
PyObject *obj,
|
||||||
time_t *sec,
|
time_t *sec,
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
/* timefuncs.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Utility function related to timemodule.c. */
|
|
||||||
|
|
||||||
#ifndef TIMEFUNCS_H
|
|
||||||
#define TIMEFUNCS_H
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* Cast double x to time_t, but raise ValueError if x is too large
|
|
||||||
* to fit in a time_t. ValueError is set on return iff the return
|
|
||||||
* value is (time_t)-1 and PyErr_Occurred().
|
|
||||||
*/
|
|
||||||
#ifndef Py_LIMITED_API
|
|
||||||
PyAPI_FUNC(time_t) _PyTime_DoubleToTimet(double x);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif /* TIMEFUNCS_H */
|
|
@ -1360,7 +1360,7 @@ class datetime(date):
|
|||||||
converter = _time.localtime if tz is None else _time.gmtime
|
converter = _time.localtime if tz is None else _time.gmtime
|
||||||
|
|
||||||
t, frac = divmod(t, 1.0)
|
t, frac = divmod(t, 1.0)
|
||||||
us = round(frac * 1e6)
|
us = int(frac * 1e6)
|
||||||
|
|
||||||
# If timestamp is less than one microsecond smaller than a
|
# If timestamp is less than one microsecond smaller than a
|
||||||
# full second, us can be rounded up to 1000000. In this case,
|
# full second, us can be rounded up to 1000000. In this case,
|
||||||
@ -1380,7 +1380,7 @@ class datetime(date):
|
|||||||
def utcfromtimestamp(cls, t):
|
def utcfromtimestamp(cls, t):
|
||||||
"Construct a UTC datetime from a POSIX timestamp (like time.time())."
|
"Construct a UTC datetime from a POSIX timestamp (like time.time())."
|
||||||
t, frac = divmod(t, 1.0)
|
t, frac = divmod(t, 1.0)
|
||||||
us = round(frac * 1e6)
|
us = int(frac * 1e6)
|
||||||
|
|
||||||
# If timestamp is less than one microsecond smaller than a
|
# If timestamp is less than one microsecond smaller than a
|
||||||
# full second, us can be rounded up to 1000000. In this case,
|
# full second, us can be rounded up to 1000000. In this case,
|
||||||
|
@ -977,7 +977,7 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase):
|
|||||||
# exempt such platforms (provided they return reasonable
|
# exempt such platforms (provided they return reasonable
|
||||||
# results!).
|
# results!).
|
||||||
for insane in -1e200, 1e200:
|
for insane in -1e200, 1e200:
|
||||||
self.assertRaises(ValueError, self.theclass.fromtimestamp,
|
self.assertRaises(OverflowError, self.theclass.fromtimestamp,
|
||||||
insane)
|
insane)
|
||||||
|
|
||||||
def test_today(self):
|
def test_today(self):
|
||||||
@ -1736,12 +1736,32 @@ class TestDateTime(TestDate):
|
|||||||
self.verify_field_equality(expected, got)
|
self.verify_field_equality(expected, got)
|
||||||
|
|
||||||
def test_microsecond_rounding(self):
|
def test_microsecond_rounding(self):
|
||||||
# Test whether fromtimestamp "rounds up" floats that are less
|
|
||||||
# than 1/2 microsecond smaller than an integer.
|
|
||||||
for fts in [self.theclass.fromtimestamp,
|
for fts in [self.theclass.fromtimestamp,
|
||||||
self.theclass.utcfromtimestamp]:
|
self.theclass.utcfromtimestamp]:
|
||||||
self.assertEqual(fts(0.9999999), fts(1))
|
zero = fts(0)
|
||||||
self.assertEqual(fts(0.99999949).microsecond, 999999)
|
self.assertEqual(zero.second, 0)
|
||||||
|
self.assertEqual(zero.microsecond, 0)
|
||||||
|
minus_one = fts(-1e-6)
|
||||||
|
self.assertEqual(minus_one.second, 59)
|
||||||
|
self.assertEqual(minus_one.microsecond, 999999)
|
||||||
|
|
||||||
|
t = fts(-1e-8)
|
||||||
|
self.assertEqual(t, minus_one)
|
||||||
|
t = fts(-9e-7)
|
||||||
|
self.assertEqual(t, minus_one)
|
||||||
|
t = fts(-1e-7)
|
||||||
|
self.assertEqual(t, minus_one)
|
||||||
|
|
||||||
|
t = fts(1e-7)
|
||||||
|
self.assertEqual(t, zero)
|
||||||
|
t = fts(9e-7)
|
||||||
|
self.assertEqual(t, zero)
|
||||||
|
t = fts(0.99999949)
|
||||||
|
self.assertEqual(t.second, 0)
|
||||||
|
self.assertEqual(t.microsecond, 999999)
|
||||||
|
t = fts(0.9999999)
|
||||||
|
self.assertEqual(t.second, 0)
|
||||||
|
self.assertEqual(t.microsecond, 999999)
|
||||||
|
|
||||||
def test_insane_fromtimestamp(self):
|
def test_insane_fromtimestamp(self):
|
||||||
# It's possible that some platform maps time_t to double,
|
# It's possible that some platform maps time_t to double,
|
||||||
@ -1749,7 +1769,7 @@ class TestDateTime(TestDate):
|
|||||||
# exempt such platforms (provided they return reasonable
|
# exempt such platforms (provided they return reasonable
|
||||||
# results!).
|
# results!).
|
||||||
for insane in -1e200, 1e200:
|
for insane in -1e200, 1e200:
|
||||||
self.assertRaises(ValueError, self.theclass.fromtimestamp,
|
self.assertRaises(OverflowError, self.theclass.fromtimestamp,
|
||||||
insane)
|
insane)
|
||||||
|
|
||||||
def test_insane_utcfromtimestamp(self):
|
def test_insane_utcfromtimestamp(self):
|
||||||
@ -1758,7 +1778,7 @@ class TestDateTime(TestDate):
|
|||||||
# exempt such platforms (provided they return reasonable
|
# exempt such platforms (provided they return reasonable
|
||||||
# results!).
|
# results!).
|
||||||
for insane in -1e200, 1e200:
|
for insane in -1e200, 1e200:
|
||||||
self.assertRaises(ValueError, self.theclass.utcfromtimestamp,
|
self.assertRaises(OverflowError, self.theclass.utcfromtimestamp,
|
||||||
insane)
|
insane)
|
||||||
@unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps")
|
@unittest.skipIf(sys.platform == "win32", "Windows doesn't accept negative timestamps")
|
||||||
def test_negative_float_fromtimestamp(self):
|
def test_negative_float_fromtimestamp(self):
|
||||||
|
@ -281,7 +281,7 @@ class TimeTestCase(unittest.TestCase):
|
|||||||
# results!).
|
# results!).
|
||||||
for func in time.ctime, time.gmtime, time.localtime:
|
for func in time.ctime, time.gmtime, time.localtime:
|
||||||
for unreasonable in -1e200, 1e200:
|
for unreasonable in -1e200, 1e200:
|
||||||
self.assertRaises(ValueError, func, unreasonable)
|
self.assertRaises(OverflowError, func, unreasonable)
|
||||||
|
|
||||||
def test_ctime_without_arg(self):
|
def test_ctime_without_arg(self):
|
||||||
# Not sure how to check the values, since the clock could tick
|
# Not sure how to check the values, since the clock could tick
|
||||||
@ -365,11 +365,8 @@ class TimeTestCase(unittest.TestCase):
|
|||||||
for time_t in (-1, 2**30, 2**33, 2**60):
|
for time_t in (-1, 2**30, 2**33, 2**60):
|
||||||
try:
|
try:
|
||||||
time.localtime(time_t)
|
time.localtime(time_t)
|
||||||
except ValueError as err:
|
except OverflowError:
|
||||||
if str(err) == "timestamp out of range for platform time_t":
|
|
||||||
self.skipTest("need 64-bit time_t")
|
self.skipTest("need 64-bit time_t")
|
||||||
else:
|
|
||||||
raise
|
|
||||||
except OSError:
|
except OSError:
|
||||||
invalid_time_t = time_t
|
invalid_time_t = time_t
|
||||||
break
|
break
|
||||||
@ -498,19 +495,63 @@ class TestStrftime4dyear(_TestStrftimeYear, _Test4dYear):
|
|||||||
|
|
||||||
|
|
||||||
class TestPytime(unittest.TestCase):
|
class TestPytime(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.invalid_values = (
|
||||||
|
-(2 ** 100), 2 ** 100,
|
||||||
|
-(2.0 ** 100.0), 2.0 ** 100.0,
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_time_t(self):
|
||||||
|
from _testcapi import pytime_object_to_time_t
|
||||||
|
for obj, time_t in (
|
||||||
|
(0, 0),
|
||||||
|
(-1, -1),
|
||||||
|
(-1.0, -1),
|
||||||
|
(-1.9, -1),
|
||||||
|
(1.0, 1),
|
||||||
|
(1.9, 1),
|
||||||
|
):
|
||||||
|
self.assertEqual(pytime_object_to_time_t(obj), time_t)
|
||||||
|
|
||||||
|
for invalid in self.invalid_values:
|
||||||
|
self.assertRaises(OverflowError, pytime_object_to_time_t, invalid)
|
||||||
|
|
||||||
|
def test_timeval(self):
|
||||||
|
from _testcapi import pytime_object_to_timeval
|
||||||
|
for obj, timeval in (
|
||||||
|
(0, (0, 0)),
|
||||||
|
(-1, (-1, 0)),
|
||||||
|
(-1.0, (-1, 0)),
|
||||||
|
(1e-6, (0, 1)),
|
||||||
|
(-1e-6, (-1, 999999)),
|
||||||
|
(-1.2, (-2, 800000)),
|
||||||
|
(1.1234560, (1, 123456)),
|
||||||
|
(1.1234569, (1, 123456)),
|
||||||
|
(-1.1234560, (-2, 876544)),
|
||||||
|
(-1.1234561, (-2, 876543)),
|
||||||
|
):
|
||||||
|
self.assertEqual(pytime_object_to_timeval(obj), timeval)
|
||||||
|
|
||||||
|
for invalid in self.invalid_values:
|
||||||
|
self.assertRaises(OverflowError, pytime_object_to_timeval, invalid)
|
||||||
|
|
||||||
def test_timespec(self):
|
def test_timespec(self):
|
||||||
from _testcapi import pytime_object_to_timespec
|
from _testcapi import pytime_object_to_timespec
|
||||||
for obj, timespec in (
|
for obj, timespec in (
|
||||||
(0, (0, 0)),
|
(0, (0, 0)),
|
||||||
(-1, (-1, 0)),
|
(-1, (-1, 0)),
|
||||||
(-1.0, (-1, 0)),
|
(-1.0, (-1, 0)),
|
||||||
|
(1e-9, (0, 1)),
|
||||||
(-1e-9, (-1, 999999999)),
|
(-1e-9, (-1, 999999999)),
|
||||||
(-1.2, (-2, 800000000)),
|
(-1.2, (-2, 800000000)),
|
||||||
(1.123456789, (1, 123456789)),
|
(1.1234567890, (1, 123456789)),
|
||||||
|
(1.1234567899, (1, 123456789)),
|
||||||
|
(-1.1234567890, (-2, 876543211)),
|
||||||
|
(-1.1234567891, (-2, 876543210)),
|
||||||
):
|
):
|
||||||
self.assertEqual(pytime_object_to_timespec(obj), timespec)
|
self.assertEqual(pytime_object_to_timespec(obj), timespec)
|
||||||
|
|
||||||
for invalid in (-(2 ** 100), -(2.0 ** 100.0), 2 ** 100, 2.0 ** 100.0):
|
for invalid in self.invalid_values:
|
||||||
self.assertRaises(OverflowError, pytime_object_to_timespec, invalid)
|
self.assertRaises(OverflowError, pytime_object_to_timespec, invalid)
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,6 +24,15 @@ Core and Builtins
|
|||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #14180: time.ctime(), gmtime(), time.localtime(),
|
||||||
|
datetime.date.fromtimestamp(), datetime.datetime.fromtimestamp() and
|
||||||
|
datetime.datetime.utcfromtimestamp() now raises an OverflowError, instead of
|
||||||
|
a ValueError, if the timestamp does not fit in time_t.
|
||||||
|
|
||||||
|
- Issue #14180: datetime.datetime.fromtimestamp() and
|
||||||
|
datetime.datetime.utcfromtimestamp() now round microseconds towards zero
|
||||||
|
instead of rounding to nearest with ties going away from zero.
|
||||||
|
|
||||||
- Issue #10543: Fix unittest test discovery with Jython bytecode files.
|
- Issue #10543: Fix unittest test discovery with Jython bytecode files.
|
||||||
|
|
||||||
- Issue #1178863: Separate initialisation from setting when initializing
|
- Issue #1178863: Separate initialisation from setting when initializing
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "_time.h"
|
|
||||||
|
|
||||||
/* Differentiate between building the core module and building extension
|
/* Differentiate between building the core module and building extension
|
||||||
* modules.
|
* modules.
|
||||||
*/
|
*/
|
||||||
@ -2441,15 +2439,15 @@ date_new(PyTypeObject *type, PyObject *args, PyObject *kw)
|
|||||||
|
|
||||||
/* Return new date from localtime(t). */
|
/* Return new date from localtime(t). */
|
||||||
static PyObject *
|
static PyObject *
|
||||||
date_local_from_time_t(PyObject *cls, double ts)
|
date_local_from_object(PyObject *cls, PyObject *obj)
|
||||||
{
|
{
|
||||||
struct tm *tm;
|
struct tm *tm;
|
||||||
time_t t;
|
time_t t;
|
||||||
PyObject *result = NULL;
|
PyObject *result = NULL;
|
||||||
|
|
||||||
t = _PyTime_DoubleToTimet(ts);
|
if (_PyTime_ObjectToTime_t(obj, &t) == -1)
|
||||||
if (t == (time_t)-1 && PyErr_Occurred())
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
tm = localtime(&t);
|
tm = localtime(&t);
|
||||||
if (tm)
|
if (tm)
|
||||||
result = PyObject_CallFunction(cls, "iii",
|
result = PyObject_CallFunction(cls, "iii",
|
||||||
@ -2494,11 +2492,11 @@ date_today(PyObject *cls, PyObject *dummy)
|
|||||||
static PyObject *
|
static PyObject *
|
||||||
date_fromtimestamp(PyObject *cls, PyObject *args)
|
date_fromtimestamp(PyObject *cls, PyObject *args)
|
||||||
{
|
{
|
||||||
double timestamp;
|
PyObject *timestamp;
|
||||||
PyObject *result = NULL;
|
PyObject *result = NULL;
|
||||||
|
|
||||||
if (PyArg_ParseTuple(args, "d:fromtimestamp", ×tamp))
|
if (PyArg_ParseTuple(args, "O:fromtimestamp", ×tamp))
|
||||||
result = date_local_from_time_t(cls, timestamp);
|
result = date_local_from_object(cls, timestamp);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4096,31 +4094,14 @@ datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us,
|
|||||||
* to get that much precision (e.g., C time() isn't good enough).
|
* to get that much precision (e.g., C time() isn't good enough).
|
||||||
*/
|
*/
|
||||||
static PyObject *
|
static PyObject *
|
||||||
datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp,
|
datetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp,
|
||||||
PyObject *tzinfo)
|
PyObject *tzinfo)
|
||||||
{
|
{
|
||||||
time_t timet;
|
time_t timet;
|
||||||
double fraction;
|
long us;
|
||||||
int us;
|
|
||||||
|
|
||||||
timet = _PyTime_DoubleToTimet(timestamp);
|
if (_PyTime_ObjectToTimeval(timestamp, &timet, &us) == -1)
|
||||||
if (timet == (time_t)-1 && PyErr_Occurred())
|
|
||||||
return NULL;
|
return NULL;
|
||||||
fraction = timestamp - (double)timet;
|
|
||||||
us = (int)round_to_long(fraction * 1e6);
|
|
||||||
if (us < 0) {
|
|
||||||
/* Truncation towards zero is not what we wanted
|
|
||||||
for negative numbers (Python's mod semantics) */
|
|
||||||
timet -= 1;
|
|
||||||
us += 1000000;
|
|
||||||
}
|
|
||||||
/* If timestamp is less than one microsecond smaller than a
|
|
||||||
* full second, round up. Otherwise, ValueErrors are raised
|
|
||||||
* for some floats. */
|
|
||||||
if (us == 1000000) {
|
|
||||||
timet += 1;
|
|
||||||
us = 0;
|
|
||||||
}
|
|
||||||
return datetime_from_timet_and_us(cls, f, timet, us, tzinfo);
|
return datetime_from_timet_and_us(cls, f, timet, us, tzinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4181,11 +4162,11 @@ static PyObject *
|
|||||||
datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
|
datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
|
||||||
{
|
{
|
||||||
PyObject *self;
|
PyObject *self;
|
||||||
double timestamp;
|
PyObject *timestamp;
|
||||||
PyObject *tzinfo = Py_None;
|
PyObject *tzinfo = Py_None;
|
||||||
static char *keywords[] = {"timestamp", "tz", NULL};
|
static char *keywords[] = {"timestamp", "tz", NULL};
|
||||||
|
|
||||||
if (! PyArg_ParseTupleAndKeywords(args, kw, "d|O:fromtimestamp",
|
if (! PyArg_ParseTupleAndKeywords(args, kw, "O|O:fromtimestamp",
|
||||||
keywords, ×tamp, &tzinfo))
|
keywords, ×tamp, &tzinfo))
|
||||||
return NULL;
|
return NULL;
|
||||||
if (check_tzinfo_subclass(tzinfo) < 0)
|
if (check_tzinfo_subclass(tzinfo) < 0)
|
||||||
@ -4210,10 +4191,10 @@ datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
|
|||||||
static PyObject *
|
static PyObject *
|
||||||
datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
|
datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
|
||||||
{
|
{
|
||||||
double timestamp;
|
PyObject *timestamp;
|
||||||
PyObject *result = NULL;
|
PyObject *result = NULL;
|
||||||
|
|
||||||
if (PyArg_ParseTuple(args, "d:utcfromtimestamp", ×tamp))
|
if (PyArg_ParseTuple(args, "O:utcfromtimestamp", ×tamp))
|
||||||
result = datetime_from_timestamp(cls, gmtime, timestamp,
|
result = datetime_from_timestamp(cls, gmtime, timestamp,
|
||||||
Py_None);
|
Py_None);
|
||||||
return result;
|
return result;
|
||||||
|
@ -2323,6 +2323,42 @@ run_in_subinterp(PyObject *self, PyObject *args)
|
|||||||
return PyLong_FromLong(r);
|
return PyLong_FromLong(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
_PyLong_FromTime_t(time_t value)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
|
||||||
|
return PyLong_FromLongLong(value);
|
||||||
|
#else
|
||||||
|
assert(sizeof(time_t) <= sizeof(long));
|
||||||
|
return PyLong_FromLong(value);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
test_pytime_object_to_time_t(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *obj;
|
||||||
|
time_t sec;
|
||||||
|
if (!PyArg_ParseTuple(args, "O:pytime_object_to_time_t", &obj))
|
||||||
|
return NULL;
|
||||||
|
if (_PyTime_ObjectToTime_t(obj, &sec) == -1)
|
||||||
|
return NULL;
|
||||||
|
return _PyLong_FromTime_t(sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
test_pytime_object_to_timeval(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *obj;
|
||||||
|
time_t sec;
|
||||||
|
long usec;
|
||||||
|
if (!PyArg_ParseTuple(args, "O:pytime_object_to_timeval", &obj))
|
||||||
|
return NULL;
|
||||||
|
if (_PyTime_ObjectToTimeval(obj, &sec, &usec) == -1)
|
||||||
|
return NULL;
|
||||||
|
return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), usec);
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
test_pytime_object_to_timespec(PyObject *self, PyObject *args)
|
test_pytime_object_to_timespec(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
@ -2333,12 +2369,7 @@ test_pytime_object_to_timespec(PyObject *self, PyObject *args)
|
|||||||
return NULL;
|
return NULL;
|
||||||
if (_PyTime_ObjectToTimespec(obj, &sec, &nsec) == -1)
|
if (_PyTime_ObjectToTimespec(obj, &sec, &nsec) == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
|
return Py_BuildValue("Nl", _PyLong_FromTime_t(sec), nsec);
|
||||||
return Py_BuildValue("Ll", (PY_LONG_LONG)sec, nsec);
|
|
||||||
#else
|
|
||||||
assert(sizeof(time_t) <= sizeof(long));
|
|
||||||
return Py_BuildValue("ll", (long)sec, nsec);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2430,6 +2461,8 @@ static PyMethodDef TestMethods[] = {
|
|||||||
METH_NOARGS},
|
METH_NOARGS},
|
||||||
{"crash_no_current_thread", (PyCFunction)crash_no_current_thread, METH_NOARGS},
|
{"crash_no_current_thread", (PyCFunction)crash_no_current_thread, METH_NOARGS},
|
||||||
{"run_in_subinterp", run_in_subinterp, METH_VARARGS},
|
{"run_in_subinterp", run_in_subinterp, METH_VARARGS},
|
||||||
|
{"pytime_object_to_time_t", test_pytime_object_to_time_t, METH_VARARGS},
|
||||||
|
{"pytime_object_to_timeval", test_pytime_object_to_timeval, METH_VARARGS},
|
||||||
{"pytime_object_to_timespec", test_pytime_object_to_timespec, METH_VARARGS},
|
{"pytime_object_to_timespec", test_pytime_object_to_timespec, METH_VARARGS},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
#include "Python.h"
|
|
||||||
#include "_time.h"
|
|
||||||
|
|
||||||
/* Exposed in timefuncs.h. */
|
|
||||||
time_t
|
|
||||||
_PyTime_DoubleToTimet(double x)
|
|
||||||
{
|
|
||||||
time_t result;
|
|
||||||
double diff;
|
|
||||||
|
|
||||||
result = (time_t)x;
|
|
||||||
/* How much info did we lose? time_t may be an integral or
|
|
||||||
* floating type, and we don't know which. If it's integral,
|
|
||||||
* we don't know whether C truncates, rounds, returns the floor,
|
|
||||||
* etc. If we lost a second or more, the C rounding is
|
|
||||||
* unreasonable, or the input just doesn't fit in a time_t;
|
|
||||||
* call it an error regardless. Note that the original cast to
|
|
||||||
* time_t can cause a C error too, but nothing we can do to
|
|
||||||
* work around that.
|
|
||||||
*/
|
|
||||||
diff = x - (double)result;
|
|
||||||
if (diff <= -1.0 || diff >= 1.0) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"timestamp out of range for platform time_t");
|
|
||||||
result = (time_t)-1;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
/* XXX: It is probably best to move timefuncs.h content in here, and
|
|
||||||
remove it but user code may rely on it. */
|
|
||||||
#include "timefuncs.h"
|
|
@ -3540,31 +3540,6 @@ posix_uname(PyObject *self, PyObject *noargs)
|
|||||||
#endif /* HAVE_UNAME */
|
#endif /* HAVE_UNAME */
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
extract_time(PyObject *t, time_t* sec, long* nsec)
|
|
||||||
{
|
|
||||||
time_t intval;
|
|
||||||
if (PyFloat_Check(t)) {
|
|
||||||
double d = PyFloat_AsDouble(t);
|
|
||||||
double mod;
|
|
||||||
*sec = (time_t)d;
|
|
||||||
mod = fmod(d, 1.0);
|
|
||||||
mod *= 1e9;
|
|
||||||
*nsec = (long)mod;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#if SIZEOF_TIME_T > SIZEOF_LONG
|
|
||||||
intval = PyLong_AsUnsignedLongLongMask(t);
|
|
||||||
#else
|
|
||||||
intval = PyLong_AsLong(t);
|
|
||||||
#endif
|
|
||||||
if (intval == -1 && PyErr_Occurred())
|
|
||||||
return -1;
|
|
||||||
*sec = intval;
|
|
||||||
*nsec = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyDoc_STRVAR(posix_utime__doc__,
|
PyDoc_STRVAR(posix_utime__doc__,
|
||||||
"utime(path[, (atime, mtime)])\n\
|
"utime(path[, (atime, mtime)])\n\
|
||||||
Set the access and modified time of the file to the given values.\n\
|
Set the access and modified time of the file to the given values.\n\
|
||||||
@ -3633,11 +3608,11 @@ posix_utime(PyObject *self, PyObject *args)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 0),
|
||||||
&atimesec, &ansec) == -1)
|
&atimesec, &ansec) == -1)
|
||||||
goto done;
|
goto done;
|
||||||
time_t_to_FILE_TIME(atimesec, ansec, &atime);
|
time_t_to_FILE_TIME(atimesec, ansec, &atime);
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 1),
|
||||||
&mtimesec, &mnsec) == -1)
|
&mtimesec, &mnsec) == -1)
|
||||||
goto done;
|
goto done;
|
||||||
time_t_to_FILE_TIME(mtimesec, mnsec, &mtime);
|
time_t_to_FILE_TIME(mtimesec, mnsec, &mtime);
|
||||||
@ -3681,12 +3656,12 @@ done:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 0),
|
||||||
&atime, &ansec) == -1) {
|
&atime, &ansec) == -1) {
|
||||||
Py_DECREF(opath);
|
Py_DECREF(opath);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 1),
|
||||||
&mtime, &mnsec) == -1) {
|
&mtime, &mnsec) == -1) {
|
||||||
Py_DECREF(opath);
|
Py_DECREF(opath);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -3763,11 +3738,11 @@ posix_futimes(PyObject *self, PyObject *args)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 0),
|
||||||
&atime, &ansec) == -1) {
|
&atime, &ansec) == -1) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 1),
|
||||||
&mtime, &mnsec) == -1) {
|
&mtime, &mnsec) == -1) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -3829,12 +3804,12 @@ posix_lutimes(PyObject *self, PyObject *args)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 0),
|
||||||
&atime, &ansec) == -1) {
|
&atime, &ansec) == -1) {
|
||||||
Py_DECREF(opath);
|
Py_DECREF(opath);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 1),
|
||||||
&mtime, &mnsec) == -1) {
|
&mtime, &mnsec) == -1) {
|
||||||
Py_DECREF(opath);
|
Py_DECREF(opath);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -9610,12 +9585,12 @@ posix_futimesat(PyObject *self, PyObject *args)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 0),
|
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 0),
|
||||||
&atime, &ansec) == -1) {
|
&atime, &ansec) == -1) {
|
||||||
Py_DECREF(opath);
|
Py_DECREF(opath);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (extract_time(PyTuple_GET_ITEM(arg, 1),
|
if (_PyTime_ObjectToTimespec(PyTuple_GET_ITEM(arg, 1),
|
||||||
&mtime, &mnsec) == -1) {
|
&mtime, &mnsec) == -1) {
|
||||||
Py_DECREF(opath);
|
Py_DECREF(opath);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -206,9 +206,7 @@ select_select(PyObject *self, PyObject *args)
|
|||||||
PyObject *ret = NULL;
|
PyObject *ret = NULL;
|
||||||
PyObject *tout = Py_None;
|
PyObject *tout = Py_None;
|
||||||
fd_set ifdset, ofdset, efdset;
|
fd_set ifdset, ofdset, efdset;
|
||||||
double timeout;
|
|
||||||
struct timeval tv, *tvp;
|
struct timeval tv, *tvp;
|
||||||
long seconds;
|
|
||||||
int imax, omax, emax, max;
|
int imax, omax, emax, max;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
@ -225,23 +223,12 @@ select_select(PyObject *self, PyObject *args)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
timeout = PyFloat_AsDouble(tout);
|
if (_PyTime_ObjectToTimeval(tout, &tv.tv_sec, &tv.tv_usec) == -1)
|
||||||
if (timeout == -1 && PyErr_Occurred())
|
|
||||||
return NULL;
|
return NULL;
|
||||||
if (timeout > (double)LONG_MAX) {
|
if (tv.tv_sec < 0) {
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_ValueError, "timeout must be non-negative");
|
||||||
"timeout period too long");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (timeout < 0) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"timeout must be non-negative");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
seconds = (long)timeout;
|
|
||||||
timeout = timeout - (double)seconds;
|
|
||||||
tv.tv_sec = seconds;
|
|
||||||
tv.tv_usec = (long)(timeout * 1E6);
|
|
||||||
tvp = &tv;
|
tvp = &tv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1870,27 +1857,15 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args)
|
|||||||
ptimeoutspec = NULL;
|
ptimeoutspec = NULL;
|
||||||
}
|
}
|
||||||
else if (PyNumber_Check(otimeout)) {
|
else if (PyNumber_Check(otimeout)) {
|
||||||
double timeout;
|
if (_PyTime_ObjectToTimespec(otimeout,
|
||||||
long seconds;
|
&timeout.tv_sec, &timeout.tv_nsec) == -1)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
timeout = PyFloat_AsDouble(otimeout);
|
if (timeout.tv_sec < 0) {
|
||||||
if (timeout == -1 && PyErr_Occurred())
|
|
||||||
return NULL;
|
|
||||||
if (timeout > (double)LONG_MAX) {
|
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
|
||||||
"timeout period too long");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (timeout < 0) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"timeout must be positive or None");
|
"timeout must be positive or None");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
seconds = (long)timeout;
|
|
||||||
timeout = timeout - (double)seconds;
|
|
||||||
timeoutspec.tv_sec = seconds;
|
|
||||||
timeoutspec.tv_nsec = (long)(timeout * 1E9);
|
|
||||||
ptimeoutspec = &timeoutspec;
|
ptimeoutspec = &timeoutspec;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
/* Time module */
|
/* Time module */
|
||||||
|
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "_time.h"
|
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
@ -288,11 +287,7 @@ parse_time_t_args(PyObject *args, char *format, time_t *pwhen)
|
|||||||
whent = time(NULL);
|
whent = time(NULL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
double d = PyFloat_AsDouble(ot);
|
if (_PyTime_ObjectToTime_t(ot, &whent) == -1)
|
||||||
if (PyErr_Occurred())
|
|
||||||
return 0;
|
|
||||||
whent = _PyTime_DoubleToTimet(d);
|
|
||||||
if (whent == (time_t)-1 && PyErr_Occurred())
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*pwhen = whent;
|
*pwhen = whent;
|
||||||
|
@ -70,9 +70,37 @@ _PyTime_gettimeofday(_PyTime_timeval *tp)
|
|||||||
#endif /* MS_WINDOWS */
|
#endif /* MS_WINDOWS */
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static void
|
||||||
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec)
|
error_time_t_overflow(void)
|
||||||
{
|
{
|
||||||
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
|
"timestamp out of range for platform time_t");
|
||||||
|
}
|
||||||
|
|
||||||
|
static time_t
|
||||||
|
_PyLong_AsTime_t(PyObject *obj)
|
||||||
|
{
|
||||||
|
#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
|
||||||
|
PY_LONG_LONG val;
|
||||||
|
val = PyLong_AsLongLong(obj);
|
||||||
|
#else
|
||||||
|
long val;
|
||||||
|
assert(sizeof(time_t) <= sizeof(long));
|
||||||
|
val = PyLong_AsLong(obj);
|
||||||
|
#endif
|
||||||
|
if (val == -1 && PyErr_Occurred()) {
|
||||||
|
if (PyErr_ExceptionMatches(PyExc_OverflowError))
|
||||||
|
error_time_t_overflow();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return (time_t)val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_PyTime_ObjectToDenominator(PyObject *obj, time_t *sec, long *numerator,
|
||||||
|
double denominator)
|
||||||
|
{
|
||||||
|
assert(denominator <= LONG_MAX);
|
||||||
if (PyFloat_Check(obj)) {
|
if (PyFloat_Check(obj)) {
|
||||||
double d, intpart, floatpart, err;
|
double d, intpart, floatpart, err;
|
||||||
|
|
||||||
@ -85,34 +113,61 @@ _PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec)
|
|||||||
|
|
||||||
*sec = (time_t)intpart;
|
*sec = (time_t)intpart;
|
||||||
err = intpart - (double)*sec;
|
err = intpart - (double)*sec;
|
||||||
if (err <= -1.0 || err >= 1.0)
|
if (err <= -1.0 || err >= 1.0) {
|
||||||
goto overflow;
|
error_time_t_overflow();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
floatpart *= 1e9;
|
floatpart *= denominator;
|
||||||
*nsec = (long)floatpart;
|
*numerator = (long)floatpart;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#if defined(HAVE_LONG_LONG) && SIZEOF_TIME_T == SIZEOF_LONG_LONG
|
*sec = _PyLong_AsTime_t(obj);
|
||||||
*sec = PyLong_AsLongLong(obj);
|
if (*sec == (time_t)-1 && PyErr_Occurred())
|
||||||
#else
|
|
||||||
assert(sizeof(time_t) <= sizeof(long));
|
|
||||||
*sec = PyLong_AsLong(obj);
|
|
||||||
#endif
|
|
||||||
if (*sec == -1 && PyErr_Occurred()) {
|
|
||||||
if (PyErr_ExceptionMatches(PyExc_OverflowError))
|
|
||||||
goto overflow;
|
|
||||||
else
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
*numerator = 0;
|
||||||
*nsec = 0;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
overflow:
|
int
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
_PyTime_ObjectToTime_t(PyObject *obj, time_t *sec)
|
||||||
"timestamp out of range for platform time_t");
|
{
|
||||||
|
if (PyFloat_Check(obj)) {
|
||||||
|
double d, intpart, err;
|
||||||
|
|
||||||
|
/*whent = _PyTime_DoubleToTimet(d);*/
|
||||||
|
|
||||||
|
d = PyFloat_AsDouble(obj);
|
||||||
|
(void)modf(d, &intpart);
|
||||||
|
|
||||||
|
*sec = (time_t)intpart;
|
||||||
|
err = intpart - (double)*sec;
|
||||||
|
if (err <= -1.0 || err >= 1.0) {
|
||||||
|
error_time_t_overflow();
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*sec = _PyLong_AsTime_t(obj);
|
||||||
|
if (*sec == (time_t)-1 && PyErr_Occurred())
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyTime_ObjectToTimespec(PyObject *obj, time_t *sec, long *nsec)
|
||||||
|
{
|
||||||
|
return _PyTime_ObjectToDenominator(obj, sec, nsec, 1e9);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyTime_ObjectToTimeval(PyObject *obj, time_t *sec, long *usec)
|
||||||
|
{
|
||||||
|
return _PyTime_ObjectToDenominator(obj, sec, usec, 1e6);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
4
setup.py
4
setup.py
@ -512,9 +512,9 @@ class PyBuildExt(build_ext):
|
|||||||
time_libs.append(lib)
|
time_libs.append(lib)
|
||||||
|
|
||||||
# time operations and variables
|
# time operations and variables
|
||||||
exts.append( Extension('time', ['timemodule.c', '_time.c'],
|
exts.append( Extension('time', ['timemodule.c'],
|
||||||
libraries=time_libs) )
|
libraries=time_libs) )
|
||||||
exts.append( Extension('_datetime', ['_datetimemodule.c', '_time.c']) )
|
exts.append( Extension('_datetime', ['_datetimemodule.c']) )
|
||||||
# random number generator implemented in C
|
# random number generator implemented in C
|
||||||
exts.append( Extension("_random", ["_randommodule.c"]) )
|
exts.append( Extension("_random", ["_randommodule.c"]) )
|
||||||
# bisect
|
# bisect
|
||||||
|
Loading…
x
Reference in New Issue
Block a user