summaryrefslogtreecommitdiffstats
path: root/Modules/_datetimemodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_datetimemodule.c')
-rw-r--r--Modules/_datetimemodule.c80
1 files changed, 16 insertions, 64 deletions
diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c
index 1d583a5..5289222 100644
--- a/Modules/_datetimemodule.c
+++ b/Modules/_datetimemodule.c
@@ -3287,6 +3287,11 @@ timezone_str(PyDateTime_TimeZone *self)
Py_INCREF(self->name);
return self->name;
}
+ if ((PyObject *)self == PyDateTime_TimeZone_UTC ||
+ (GET_TD_DAYS(self->offset) == 0 &&
+ GET_TD_SECONDS(self->offset) == 0 &&
+ GET_TD_MICROSECONDS(self->offset) == 0))
+ return PyUnicode_FromString("UTC");
/* Offset is normalized, so it is negative if days < 0 */
if (GET_TD_DAYS(self->offset) < 0) {
sign = '-';
@@ -4083,44 +4088,6 @@ datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us,
tzinfo);
}
-static 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
- * worm around that.
- */
- diff = x - (double)result;
- if (diff <= -1.0 || diff >= 1.0) {
- PyErr_SetString(PyExc_OverflowError,
- "timestamp out of range for platform time_t");
- result = (time_t)-1;
- }
- return result;
-}
-
-/* Round a double to the nearest long. |x| must be small enough to fit
- * in a C long; this is not checked.
- */
-static double
-_PyTime_RoundHalfEven(double x)
-{
- double rounded = round(x);
- if (fabs(x-rounded) == 0.5)
- /* halfway case: round to even */
- rounded = 2.0*round(x/2.0);
- return rounded;
-}
-
/* Internal helper.
* Build datetime from a Python timestamp. Pass localtime or gmtime for f,
* to control the interpretation of the timestamp. Since a double doesn't
@@ -4129,32 +4096,17 @@ _PyTime_RoundHalfEven(double x)
* to get that much precision (e.g., C time() isn't good enough).
*/
static PyObject *
-datetime_from_timestamp(PyObject *cls, TM_FUNC f, double timestamp,
+datetime_from_timestamp(PyObject *cls, TM_FUNC f, PyObject *timestamp,
PyObject *tzinfo)
{
time_t timet;
- double fraction;
- int us;
+ long us;
- timet = _PyTime_DoubleToTimet(timestamp);
- if (timet == (time_t)-1 && PyErr_Occurred())
+ if (_PyTime_ObjectToTimeval(timestamp,
+ &timet, &us, _PyTime_ROUND_HALF_EVEN) == -1)
return NULL;
- fraction = timestamp - (double)timet;
- us = (int)_PyTime_RoundHalfEven(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, (int)us, tzinfo);
}
/* Internal helper.
@@ -4227,11 +4179,11 @@ static PyObject *
datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
{
PyObject *self;
- double timestamp;
+ PyObject *timestamp;
PyObject *tzinfo = Py_None;
static char *keywords[] = {"timestamp", "tz", NULL};
- if (! PyArg_ParseTupleAndKeywords(args, kw, "d|O:fromtimestamp",
+ if (! PyArg_ParseTupleAndKeywords(args, kw, "O|O:fromtimestamp",
keywords, &timestamp, &tzinfo))
return NULL;
if (check_tzinfo_subclass(tzinfo) < 0)
@@ -4255,10 +4207,10 @@ datetime_fromtimestamp(PyObject *cls, PyObject *args, PyObject *kw)
static PyObject *
datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
{
- double timestamp;
+ PyObject *timestamp;
PyObject *result = NULL;
- if (PyArg_ParseTuple(args, "d:utcfromtimestamp", &timestamp))
+ if (PyArg_ParseTuple(args, "O:utcfromtimestamp", &timestamp))
result = datetime_from_timestamp(cls, gmtime, timestamp,
Py_None);
return result;
@@ -4761,7 +4713,7 @@ local_timezone(PyDateTime_DateTime *utc_time)
if (seconds == NULL)
goto error;
Py_DECREF(delta);
- timestamp = PyLong_AsLong(seconds);
+ timestamp = _PyLong_AsTime_t(seconds);
Py_DECREF(seconds);
if (timestamp == -1 && PyErr_Occurred())
return NULL;