summaryrefslogtreecommitdiffstats
path: root/Python/pytime.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@haypocalc.com>2012-02-08 22:03:19 (GMT)
committerVictor Stinner <victor.stinner@haypocalc.com>2012-02-08 22:03:19 (GMT)
commit4195b5caea0fe1446160e78d69420732ead7e78b (patch)
tree5c01264aed26942fcb932f9aab73856dd65af684 /Python/pytime.c
parent72476eae5fe4d7bc4d4c4e30471cd83a501707de (diff)
downloadcpython-4195b5caea0fe1446160e78d69420732ead7e78b.zip
cpython-4195b5caea0fe1446160e78d69420732ead7e78b.tar.gz
cpython-4195b5caea0fe1446160e78d69420732ead7e78b.tar.bz2
Backout f8409b3d6449: the PEP 410 is not accepted yet
Diffstat (limited to 'Python/pytime.c')
-rw-r--r--Python/pytime.c343
1 files changed, 18 insertions, 325 deletions
diff --git a/Python/pytime.c b/Python/pytime.c
index 8679bcc..bec1c71 100644
--- a/Python/pytime.c
+++ b/Python/pytime.c
@@ -18,36 +18,24 @@
extern int ftime(struct timeb *);
#endif
-#define MICROSECONDS 1000000
-
void
-_PyTime_get(_PyTime_t *ts)
+_PyTime_gettimeofday(_PyTime_timeval *tp)
{
#ifdef MS_WINDOWS
FILETIME system_time;
ULARGE_INTEGER large;
- ULONGLONG value;
+ ULONGLONG microseconds;
GetSystemTimeAsFileTime(&system_time);
large.u.LowPart = system_time.dwLowDateTime;
large.u.HighPart = system_time.dwHighDateTime;
- /* 116,444,736,000,000,000: number of 100 ns between
+ /* 11,644,473,600,000,000: number of microseconds between
the 1st january 1601 and the 1st january 1970 (369 years + 89 leap
days). */
- value = large.QuadPart - 116444736000000000;
- ts->seconds = 0;
- ts->numerator = value;
- ts->denominator = (_PyTime_fraction_t)10000000;
+ microseconds = large.QuadPart / 10 - 11644473600000000;
+ tp->tv_sec = microseconds / 1000000;
+ tp->tv_usec = microseconds % 1000000;
#else
-
-#ifdef HAVE_GETTIMEOFDAY
- struct timeval tv;
- int err;
-#endif
-#if defined(HAVE_FTIME)
- struct timeb t;
-#endif
-
/* There are three ways to get the time:
(1) gettimeofday() -- resolution in microseconds
(2) ftime() -- resolution in milliseconds
@@ -59,325 +47,30 @@ _PyTime_get(_PyTime_t *ts)
#ifdef HAVE_GETTIMEOFDAY
#ifdef GETTIMEOFDAY_NO_TZ
- err = gettimeofday(&tv);
+ if (gettimeofday(tp) == 0)
+ return;
#else /* !GETTIMEOFDAY_NO_TZ */
- err = gettimeofday(&tv, (struct timezone *)NULL);
-#endif /* !GETTIMEOFDAY_NO_TZ */
- if (err == 0)
- {
- ts->seconds = tv.tv_sec;
- ts->numerator = tv.tv_usec;
- ts->denominator = MICROSECONDS;
+ if (gettimeofday(tp, (struct timezone *)NULL) == 0)
return;
- }
+#endif /* !GETTIMEOFDAY_NO_TZ */
#endif /* !HAVE_GETTIMEOFDAY */
#if defined(HAVE_FTIME)
- ftime(&t);
- ts->seconds = t.time;
- ts->numerator = t.millitm;
- ts->denominator = 1000;
+ {
+ struct timeb t;
+ ftime(&t);
+ tp->tv_sec = t.time;
+ tp->tv_usec = t.millitm * 1000;
+ }
#else /* !HAVE_FTIME */
- ts->seconds = time(NULL);
- ts->numerator = 0;
- ts->denominator = 1;
+ tp->tv_sec = time(NULL);
+ tp->tv_usec = 0;
#endif /* !HAVE_FTIME */
#endif /* MS_WINDOWS */
}
void
-_PyTime_gettimeofday(_PyTime_timeval *tv)
-{
- _PyTime_t ts;
- _PyTime_fraction_t k;
- time_t sec;
-
- _PyTime_get(&ts);
- tv->tv_sec = ts.seconds;
- if (ts.numerator) {
- if (ts.numerator > ts.denominator) {
- sec = Py_SAFE_DOWNCAST(ts.numerator / ts.denominator,
- _PyTime_fraction_t, time_t);
- /* ignore integer overflow because _PyTime_gettimeofday() has
- no return value */
- tv->tv_sec += sec;
- ts.numerator = ts.numerator % ts.denominator;
- }
- if (MICROSECONDS >= ts.denominator) {
- k = (_PyTime_fraction_t)MICROSECONDS / ts.denominator;
- tv->tv_usec = (long)(ts.numerator * k);
- }
- else {
- k = ts.denominator / (_PyTime_fraction_t)MICROSECONDS;
- tv->tv_usec = (long)(ts.numerator / k);
- }
- }
- else {
- tv->tv_usec = 0;
- }
-}
-
-static PyObject*
-_PyLong_FromTime_t(time_t value)
-{
-#if SIZEOF_TIME_T <= SIZEOF_LONG
- return PyLong_FromLong(value);
-#else
- assert(sizeof(time_t) <= sizeof(PY_LONG_LONG));
- return PyLong_FromLongLong(value);
-#endif
-}
-
-#if defined(HAVE_LONG_LONG)
-# define _PyLong_FromTimeFraction_t PyLong_FromLongLong
-#else
-# define _PyLong_FromTimeFraction_t PyLong_FromSize_t
-#endif
-
-/* Convert a timestamp to a PyFloat object */
-static PyObject*
-_PyTime_AsFloat(_PyTime_t *ts)
-{
- double d;
- d = (double)ts->seconds;
- d += (double)ts->numerator / (double)ts->denominator;
- return PyFloat_FromDouble(d);
-}
-
-/* Convert a timestamp to a PyLong object */
-static PyObject*
-_PyTime_AsLong(_PyTime_t *ts)
-{
- PyObject *a, *b, *c;
-
- a = _PyLong_FromTime_t(ts->seconds);
- if (a == NULL)
- return NULL;
- b = _PyLong_FromTimeFraction_t(ts->numerator / ts->denominator);
- if (b == NULL)
- {
- Py_DECREF(a);
- return NULL;
- }
- c = PyNumber_Add(a, b);
- Py_DECREF(a);
- Py_DECREF(b);
- return c;
-}
-
-/* Convert a timestamp to a decimal.Decimal object */
-static PyObject*
-_PyTime_AsDecimal(_PyTime_t *ts)
-{
- static PyObject* module = NULL;
- static PyObject* decimal = NULL;
- static PyObject* exponent_context = NULL;
- static PyObject* context = NULL;
- /* exponent cache, dictionary of:
- int (denominator) => Decimal (1/denominator) */
- static PyObject* exponent_cache = NULL;
- PyObject *t = NULL;
- PyObject *key, *exponent, *quantized;
- _Py_IDENTIFIER(quantize);
- _Py_IDENTIFIER(__truediv__);
-
- if (!module) {
- module = PyImport_ImportModuleNoBlock("decimal");
- if (module == NULL)
- return NULL;
- }
-
- if (!decimal) {
- decimal = PyObject_GetAttrString(module, "Decimal");
- if (decimal == NULL)
- return NULL;
- }
-
- if (context == NULL)
- {
- /* Use 12 decimal digits to store 10,000 years in seconds + 9
- decimal digits for the floating part in nanoseconds + 1 decimal
- digit to round correctly.
-
- context = decimal.Context(22, rounding=decimal.ROUND_HALF_EVEN)
- exponent_context = decimal.Context(1, rounding=decimal.ROUND_HALF_EVEN)
- */
- PyObject *context_class, *rounding;
- context_class = PyObject_GetAttrString(module, "Context");
- if (context_class == NULL)
- return NULL;
- rounding = PyObject_GetAttrString(module, "ROUND_HALF_EVEN");
- if (rounding == NULL)
- {
- Py_DECREF(context_class);
- return NULL;
- }
- context = PyObject_CallFunction(context_class, "iO", 22, rounding);
- if (context == NULL)
- {
- Py_DECREF(context_class);
- Py_DECREF(rounding);
- return NULL;
- }
-
- exponent_context = PyObject_CallFunction(context_class, "iO", 1, rounding);
- Py_DECREF(context_class);
- Py_DECREF(rounding);
- if (exponent_context == NULL)
- {
- Py_CLEAR(context);
- return NULL;
- }
- }
-
- /* t = decimal.Decimal(value) */
- if (ts->seconds) {
- PyObject *f = _PyLong_FromTime_t(ts->seconds);
- t = PyObject_CallFunction(decimal, "O", f);
- Py_CLEAR(f);
- }
- else {
- t = PyObject_CallFunction(decimal, "iO", 0, context);
- }
- if (t == NULL)
- return NULL;
-
- if (ts->numerator)
- {
- /* t += decimal.Decimal(numerator, ctx) / decimal.Decimal(denominator, ctx) */
- PyObject *a, *b, *c, *d, *x;
-
- x = _PyLong_FromTimeFraction_t(ts->numerator);
- if (x == NULL)
- goto error;
- a = PyObject_CallFunction(decimal, "OO", x, context);
- Py_CLEAR(x);
- if (a == NULL)
- goto error;
-
- x = _PyLong_FromTimeFraction_t(ts->denominator);
- if (x == NULL)
- {
- Py_DECREF(a);
- goto error;
- }
- b = PyObject_CallFunction(decimal, "OO", x, context);
- Py_CLEAR(x);
- if (b == NULL)
- {
- Py_DECREF(a);
- goto error;
- }
-
- c = _PyObject_CallMethodId(a, &PyId___truediv__, "OO",
- b, context);
- Py_DECREF(a);
- Py_DECREF(b);
- if (c == NULL)
- goto error;
-
- d = PyNumber_Add(t, c);
- Py_DECREF(c);
- if (d == NULL)
- goto error;
- Py_DECREF(t);
- t = d;
- }
-
- if (exponent_cache == NULL) {
- exponent_cache = PyDict_New();
- if (exponent_cache == NULL)
- goto error;
- }
-
- key = _PyLong_FromTimeFraction_t(ts->denominator);
- if (key == NULL)
- goto error;
- exponent = PyDict_GetItem(exponent_cache, key);
- if (exponent == NULL) {
- /* exponent = decimal.Decimal(1) / decimal.Decimal(resolution) */
- PyObject *one, *denominator;
-
- one = PyObject_CallFunction(decimal, "i", 1);
- if (one == NULL) {
- Py_DECREF(key);
- goto error;
- }
-
- denominator = PyObject_CallFunction(decimal, "O", key);
- if (denominator == NULL) {
- Py_DECREF(key);
- Py_DECREF(one);
- goto error;
- }
-
- exponent = _PyObject_CallMethodId(one, &PyId___truediv__, "OO",
- denominator, exponent_context);
- Py_DECREF(one);
- Py_DECREF(denominator);
- if (exponent == NULL) {
- Py_DECREF(key);
- goto error;
- }
-
- if (PyDict_SetItem(exponent_cache, key, exponent) < 0) {
- Py_DECREF(key);
- Py_DECREF(exponent);
- goto error;
- }
- Py_DECREF(key);
- }
-
- /* t = t.quantize(exponent, None, context) */
- quantized = _PyObject_CallMethodId(t, &PyId_quantize, "OOO",
- exponent, Py_None, context);
- if (quantized == NULL)
- goto error;
- Py_DECREF(t);
- t = quantized;
-
- return t;
-
-error:
- Py_XDECREF(t);
- return NULL;
-}
-
-PyObject*
-_PyTime_Convert(_PyTime_t *ts, PyObject *format)
-{
- assert(ts->denominator != 0);
-
- if (format == NULL || (PyTypeObject *)format == &PyFloat_Type)
- return _PyTime_AsFloat(ts);
- if ((PyTypeObject *)format == &PyLong_Type)
- return _PyTime_AsLong(ts);
-
- if (PyType_Check(format))
- {
- PyObject *module, *name;
- _Py_IDENTIFIER(__name__);
- _Py_IDENTIFIER(__module__);
-
- module = _PyObject_GetAttrId(format, &PyId___module__);
- name = _PyObject_GetAttrId(format, &PyId___name__);
- if (module != NULL && PyUnicode_Check(module)
- && name != NULL && PyUnicode_Check(name))
- {
- if (PyUnicode_CompareWithASCIIString(module, "decimal") == 0
- && PyUnicode_CompareWithASCIIString(name, "Decimal") == 0)
- return _PyTime_AsDecimal(ts);
- }
- else
- PyErr_Clear();
- }
-
- PyErr_Format(PyExc_ValueError, "Unknown timestamp format: %R", format);
- return NULL;
-}
-
-void
_PyTime_Init()
{
/* Do nothing. Needed to force linking. */