[Python-checkins] bpo-34672: Try to pass the C library's own timezone strings back to it. (GH-9288)

Benjamin Peterson webhook-mailer at python.org
Fri Sep 14 12:09:08 EDT 2018


https://github.com/python/cpython/commit/5633c4f342d957df2ef0d67b9bfb472a0d28a76b
commit: 5633c4f342d957df2ef0d67b9bfb472a0d28a76b
branch: master
author: Benjamin Peterson <benjamin at python.org>
committer: GitHub <noreply at github.com>
date: 2018-09-14T09:09:04-07:00
summary:

bpo-34672: Try to pass the C library's own timezone strings back to it. (GH-9288)

files:
A Misc/NEWS.d/next/Library/2018-09-13-21-04-23.bpo-34672.BYuKKS.rst
M Modules/timemodule.c

diff --git a/Misc/NEWS.d/next/Library/2018-09-13-21-04-23.bpo-34672.BYuKKS.rst b/Misc/NEWS.d/next/Library/2018-09-13-21-04-23.bpo-34672.BYuKKS.rst
new file mode 100644
index 000000000000..59d106b60042
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2018-09-13-21-04-23.bpo-34672.BYuKKS.rst
@@ -0,0 +1,2 @@
+Add a workaround, so the ``'Z'`` :func:`time.strftime` specifier on the musl
+C library can work in some cases.
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index dbe2fbaf0796..8118b31c9173 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -523,6 +523,10 @@ time_localtime(PyObject *self, PyObject *args)
 #endif
 }
 
+#if defined(__linux__) && !defined(__GLIBC__)
+static const char *utc_string = NULL;
+#endif
+
 PyDoc_STRVAR(localtime_doc,
 "localtime([seconds]) -> (tm_year,tm_mon,tm_mday,tm_hour,tm_min,\n\
                           tm_sec,tm_wday,tm_yday,tm_isdst)\n\
@@ -565,11 +569,32 @@ gettmarg(PyObject *args, struct tm *p, const char *format)
     if (Py_TYPE(args) == &StructTimeType) {
         PyObject *item;
         item = PyTuple_GET_ITEM(args, 9);
-        p->tm_zone = item == Py_None ? NULL : (char*)PyUnicode_AsUTF8(item);
+        if (item != Py_None) {
+            p->tm_zone = PyUnicode_AsUTF8(item);
+            if (p->tm_zone == NULL) {
+                return 0;
+            }
+#if defined(__linux__) && !defined(__GLIBC__)
+            // Make an attempt to return the C library's own timezone strings to
+            // it. musl refuses to process a tm_zone field unless it produced
+            // it. See issue #34672.
+            if (utc_string && strcmp(p->tm_zone, utc_string) == 0) {
+                p->tm_zone = utc_string;
+            }
+            else if (tzname[0] && strcmp(p->tm_zone, tzname[0]) == 0) {
+                p->tm_zone = tzname[0];
+            }
+            else if (tzname[1] && strcmp(p->tm_zone, tzname[1]) == 0) {
+                p->tm_zone = tzname[1];
+            }
+#endif
+        }
         item = PyTuple_GET_ITEM(args, 10);
-        p->tm_gmtoff = item == Py_None ? 0 : PyLong_AsLong(item);
-        if (PyErr_Occurred())
-            return 0;
+        if (item != Py_None) {
+            p->tm_gmtoff = PyLong_AsLong(item);
+            if (PyErr_Occurred())
+                return 0;
+        }
     }
 #endif /* HAVE_STRUCT_TM_TM_ZONE */
     return 1;
@@ -1736,6 +1761,13 @@ PyInit_time(void)
     PyModule_AddIntConstant(m, "_STRUCT_TM_ITEMS", 11);
     PyModule_AddObject(m, "struct_time", (PyObject*) &StructTimeType);
     initialized = 1;
+
+#if defined(__linux__) && !defined(__GLIBC__)
+    struct tm tm;
+    if (gmtime_r(0, &tm) != NULL)
+        utc_string = tm.tm_zone;
+#endif
+
     return m;
 }
 



More information about the Python-checkins mailing list