summaryrefslogtreecommitdiffstats
path: root/Modules/timemodule.c
diff options
context:
space:
mode:
authorAlexander Belopolsky <alexander.belopolsky@gmail.com>2016-09-12 02:55:16 (GMT)
committerAlexander Belopolsky <alexander.belopolsky@gmail.com>2016-09-12 02:55:16 (GMT)
commit18f3a9b93ccd4caeda3c34d1ce850c2cc33f7722 (patch)
tree1691d0eaaeaa74e1bbb641bada5a6186815349e0 /Modules/timemodule.c
parenta3222b8424e932783e417411e428779d08d2b8a9 (diff)
downloadcpython-18f3a9b93ccd4caeda3c34d1ce850c2cc33f7722.zip
cpython-18f3a9b93ccd4caeda3c34d1ce850c2cc33f7722.tar.gz
cpython-18f3a9b93ccd4caeda3c34d1ce850c2cc33f7722.tar.bz2
Closes #25283: Make tm_gmtoff and tm_zone available on all platforms.
Diffstat (limited to 'Modules/timemodule.c')
-rw-r--r--Modules/timemodule.c114
1 files changed, 81 insertions, 33 deletions
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 9474644..ea7d906 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -250,10 +250,8 @@ static PyStructSequence_Field struct_time_type_fields[] = {
{"tm_wday", "day of week, range [0, 6], Monday is 0"},
{"tm_yday", "day of year, range [1, 366]"},
{"tm_isdst", "1 if summer time is in effect, 0 if not, and -1 if unknown"},
-#ifdef HAVE_STRUCT_TM_TM_ZONE
{"tm_zone", "abbreviation of timezone name"},
{"tm_gmtoff", "offset from UTC in seconds"},
-#endif /* HAVE_STRUCT_TM_TM_ZONE */
{0}
};
@@ -275,7 +273,11 @@ static PyTypeObject StructTimeType;
static PyObject *
-tmtotuple(struct tm *p)
+tmtotuple(struct tm *p
+#ifndef HAVE_STRUCT_TM_TM_ZONE
+ , const char *zone, int gmtoff
+#endif
+)
{
PyObject *v = PyStructSequence_New(&StructTimeType);
if (v == NULL)
@@ -296,6 +298,10 @@ tmtotuple(struct tm *p)
PyStructSequence_SET_ITEM(v, 9,
PyUnicode_DecodeLocale(p->tm_zone, "surrogateescape"));
SET(10, p->tm_gmtoff);
+#else
+ PyStructSequence_SET_ITEM(v, 9,
+ PyUnicode_DecodeLocale(zone, "surrogateescape"));
+ SET(10, gmtoff);
#endif /* HAVE_STRUCT_TM_TM_ZONE */
#undef SET
if (PyErr_Occurred()) {
@@ -348,9 +354,26 @@ time_gmtime(PyObject *self, PyObject *args)
return PyErr_SetFromErrno(PyExc_OSError);
}
buf = *local;
+#ifdef HAVE_STRUCT_TM_TM_ZONE
return tmtotuple(&buf);
+#else
+ return tmtotuple(&buf, "UTC", 0);
+#endif
}
+#ifndef HAVE_TIMEGM
+static time_t
+timegm(struct tm *p)
+{
+ /* XXX: the following implementation will not work for tm_year < 1970.
+ but it is likely that platforms that don't have timegm do not support
+ negative timestamps anyways. */
+ return p->tm_sec + p->tm_min*60 + p->tm_hour*3600 + p->tm_yday*86400 +
+ (p->tm_year-70)*31536000 + ((p->tm_year-69)/4)*86400 -
+ ((p->tm_year-1)/100)*86400 + ((p->tm_year+299)/400)*86400;
+}
+#endif
+
PyDoc_STRVAR(gmtime_doc,
"gmtime([seconds]) -> (tm_year, tm_mon, tm_mday, tm_hour, tm_min,\n\
tm_sec, tm_wday, tm_yday, tm_isdst)\n\
@@ -391,7 +414,18 @@ time_localtime(PyObject *self, PyObject *args)
return NULL;
if (pylocaltime(&when, &buf) == -1)
return NULL;
+#ifdef HAVE_STRUCT_TM_TM_ZONE
return tmtotuple(&buf);
+#else
+ {
+ struct tm local = buf;
+ char zone[100];
+ int gmtoff;
+ strftime(zone, sizeof(buf), "%Z", &buf);
+ gmtoff = timegm(&buf) - when;
+ return tmtotuple(&local, zone, gmtoff);
+ }
+#endif
}
PyDoc_STRVAR(localtime_doc,
@@ -1146,6 +1180,27 @@ PyDoc_STRVAR(get_clock_info_doc,
Get information of the specified clock.");
static void
+get_zone(char *zone, int n, struct tm *p)
+{
+#ifdef HAVE_STRUCT_TM_TM_ZONE
+ strncpy(zone, p->tm_zone ? p->tm_zone : " ", n);
+#else
+ tzset();
+ strftime(zone, n, "%Z", p);
+#endif
+}
+
+static int
+get_gmtoff(time_t t, struct tm *p)
+{
+#ifdef HAVE_STRUCT_TM_TM_ZONE
+ return p->tm_gmtoff;
+#else
+ return timegm(p) - t;
+#endif
+}
+
+static void
PyInit_timezone(PyObject *m) {
/* This code moved from PyInit_time wholesale to allow calling it from
time_tzset. In the future, some parts of it can be moved back
@@ -1177,7 +1232,6 @@ PyInit_timezone(PyObject *m) {
otz1 = PyUnicode_DecodeLocale(tzname[1], "surrogateescape");
PyModule_AddObject(m, "tzname", Py_BuildValue("(NN)", otz0, otz1));
#else /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/
-#ifdef HAVE_STRUCT_TM_TM_ZONE
{
#define YEAR ((time_t)((365 * 24 + 6) * 3600))
time_t t;
@@ -1186,13 +1240,13 @@ PyInit_timezone(PyObject *m) {
char janname[10], julyname[10];
t = (time((time_t *)0) / YEAR) * YEAR;
p = localtime(&t);
- janzone = -p->tm_gmtoff;
- strncpy(janname, p->tm_zone ? p->tm_zone : " ", 9);
+ get_zone(janname, 9, p);
+ janzone = -get_gmtoff(t, p);
janname[9] = '\0';
t += YEAR/2;
p = localtime(&t);
- julyzone = -p->tm_gmtoff;
- strncpy(julyname, p->tm_zone ? p->tm_zone : " ", 9);
+ get_zone(julyname, 9, p);
+ julyzone = -get_gmtoff(t, p);
julyname[9] = '\0';
if( janzone < julyzone ) {
@@ -1214,8 +1268,6 @@ PyInit_timezone(PyObject *m) {
janname, julyname));
}
}
-#else
-#endif /* HAVE_STRUCT_TM_TM_ZONE */
#ifdef __CYGWIN__
tzset();
PyModule_AddIntConstant(m, "timezone", _timezone);
@@ -1225,25 +1277,6 @@ PyInit_timezone(PyObject *m) {
Py_BuildValue("(zz)", _tzname[0], _tzname[1]));
#endif /* __CYGWIN__ */
#endif /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/
-
-#if defined(HAVE_CLOCK_GETTIME)
- PyModule_AddIntMacro(m, CLOCK_REALTIME);
-#ifdef CLOCK_MONOTONIC
- PyModule_AddIntMacro(m, CLOCK_MONOTONIC);
-#endif
-#ifdef CLOCK_MONOTONIC_RAW
- PyModule_AddIntMacro(m, CLOCK_MONOTONIC_RAW);
-#endif
-#ifdef CLOCK_HIGHRES
- PyModule_AddIntMacro(m, CLOCK_HIGHRES);
-#endif
-#ifdef CLOCK_PROCESS_CPUTIME_ID
- PyModule_AddIntMacro(m, CLOCK_PROCESS_CPUTIME_ID);
-#endif
-#ifdef CLOCK_THREAD_CPUTIME_ID
- PyModule_AddIntMacro(m, CLOCK_THREAD_CPUTIME_ID);
-#endif
-#endif /* HAVE_CLOCK_GETTIME */
}
@@ -1350,17 +1383,32 @@ PyInit_time(void)
/* Set, or reset, module variables like time.timezone */
PyInit_timezone(m);
+#if defined(HAVE_CLOCK_GETTIME)
+ PyModule_AddIntMacro(m, CLOCK_REALTIME);
+#ifdef CLOCK_MONOTONIC
+ PyModule_AddIntMacro(m, CLOCK_MONOTONIC);
+#endif
+#ifdef CLOCK_MONOTONIC_RAW
+ PyModule_AddIntMacro(m, CLOCK_MONOTONIC_RAW);
+#endif
+#ifdef CLOCK_HIGHRES
+ PyModule_AddIntMacro(m, CLOCK_HIGHRES);
+#endif
+#ifdef CLOCK_PROCESS_CPUTIME_ID
+ PyModule_AddIntMacro(m, CLOCK_PROCESS_CPUTIME_ID);
+#endif
+#ifdef CLOCK_THREAD_CPUTIME_ID
+ PyModule_AddIntMacro(m, CLOCK_THREAD_CPUTIME_ID);
+#endif
+#endif /* HAVE_CLOCK_GETTIME */
+
if (!initialized) {
if (PyStructSequence_InitType2(&StructTimeType,
&struct_time_type_desc) < 0)
return NULL;
}
Py_INCREF(&StructTimeType);
-#ifdef HAVE_STRUCT_TM_TM_ZONE
PyModule_AddIntConstant(m, "_STRUCT_TM_ITEMS", 11);
-#else
- PyModule_AddIntConstant(m, "_STRUCT_TM_ITEMS", 9);
-#endif
PyModule_AddObject(m, "struct_time", (PyObject*) &StructTimeType);
initialized = 1;
return m;