summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2003-03-14 21:51:36 (GMT)
committerGuido van Rossum <guido@python.org>2003-03-14 21:51:36 (GMT)
commitd11b62edd077428935f93b36ae8d65ebaa684cca (patch)
tree9dc367fe07572083aea392a93c9aab9100ad25e4
parent538f1d842c3dfeff279c084d616c03113ec5dd94 (diff)
downloadcpython-d11b62edd077428935f93b36ae8d65ebaa684cca.zip
cpython-d11b62edd077428935f93b36ae8d65ebaa684cca.tar.gz
cpython-d11b62edd077428935f93b36ae8d65ebaa684cca.tar.bz2
- New function time.tzset() provides access to the C library tzet()
function, if supported. (SF patch #675422, by Stuart Bishop.)
-rw-r--r--Lib/test/test_time.py83
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/timemodule.c218
-rwxr-xr-xconfigure70
-rw-r--r--configure.in33
-rw-r--r--pyconfig.h.in4
7 files changed, 336 insertions, 76 deletions
diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py
index 460c989..4459f3e 100644
--- a/Lib/test/test_time.py
+++ b/Lib/test/test_time.py
@@ -48,11 +48,92 @@ class TimeTestCase(unittest.TestCase):
except ValueError:
self.fail('conversion specifier: %r failed.' % format)
-
def test_asctime(self):
time.asctime(time.gmtime(self.t))
self.assertRaises(TypeError, time.asctime, 0)
+ def test_tzset(self):
+ from os import environ
+
+ # Epoch time of midnight Dec 25th 2002. Never DST in northern
+ # hemisphere.
+ xmas2002 = 1040774400.0
+
+ org_TZ = environ.get('TZ',None)
+ try:
+
+ # Make sure we can switch to UTC time and results are correct
+ # Note that unknown timezones default to UTC.
+ for tz in ('UTC','GMT','Luna/Tycho'):
+ environ['TZ'] = 'US/Eastern'
+ time.tzset()
+ environ['TZ'] = tz
+ time.tzset()
+ self.failUnlessEqual(
+ time.gmtime(xmas2002),time.localtime(xmas2002)
+ )
+ self.failUnlessEqual(time.timezone,time.altzone)
+ self.failUnlessEqual(time.daylight,0)
+ self.failUnlessEqual(time.timezone,0)
+ self.failUnlessEqual(time.altzone,0)
+ self.failUnlessEqual(time.localtime(xmas2002).tm_isdst,0)
+
+ # Make sure we can switch to US/Eastern
+ environ['TZ'] = 'US/Eastern'
+ time.tzset()
+ self.failIfEqual(time.gmtime(xmas2002),time.localtime(xmas2002))
+ self.failUnlessEqual(time.tzname,('EST','EDT'))
+ self.failUnlessEqual(len(time.tzname),2)
+ self.failUnlessEqual(time.daylight,1)
+ self.failUnlessEqual(time.timezone,18000)
+ self.failUnlessEqual(time.altzone,14400)
+ self.failUnlessEqual(time.localtime(xmas2002).tm_isdst,0)
+ self.failUnlessEqual(len(time.tzname),2)
+
+ # Now go to the southern hemisphere. We want somewhere all OS's
+ # know about that has DST.
+ environ['TZ'] = 'Australia/Melbourne'
+ time.tzset()
+ self.failIfEqual(time.gmtime(xmas2002),time.localtime(xmas2002))
+ self.failUnless(time.tzname[0] in ('EST','AEST'))
+ self.failUnless(time.tzname[1] in ('EST','EDT','AEDT'))
+ self.failUnlessEqual(len(time.tzname),2)
+ self.failUnlessEqual(time.daylight,1)
+ self.failUnlessEqual(time.timezone,-36000)
+ self.failUnlessEqual(time.altzone,-39600)
+ self.failUnlessEqual(time.localtime(xmas2002).tm_isdst,1)
+
+ # Get some times from a timezone that isn't wallclock timezone
+ del environ['TZ']
+ time.tzset()
+ if time.timezone == 0:
+ environ['TZ'] = 'US/Eastern'
+ else:
+ environ['TZ'] = 'UTC'
+ time.tzset()
+ nonlocal = time.localtime(xmas2002)
+
+ # Then the same time in wallclock timezone
+ del environ['TZ']
+ time.tzset()
+ local = time.localtime(xmas2002)
+
+ # And make sure they arn't the same
+ self.failIfEqual(local,nonlocal)
+
+ # Do some basic sanity checking after wallclock time set
+ self.failUnlessEqual(len(time.tzname),2)
+ time.daylight
+ time.timezone
+ time.altzone
+ finally:
+ # Repair TZ environment variable in case any other tests
+ # rely on it.
+ if org_TZ is not None:
+ environ['TZ'] = org_TZ
+ elif environ.has_key('TZ'):
+ del environ['TZ']
+
def test_main():
test_support.run_unittest(TimeTestCase)
diff --git a/Misc/ACKS b/Misc/ACKS
index abc1c75..e968bc71 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -50,6 +50,7 @@ Eric Beser
Stephen Bevan
Ron Bickers
Dominic Binks
+Stuart Bishop
Roy Bixler
Martin Bless
Pablo Bleyer
diff --git a/Misc/NEWS b/Misc/NEWS
index 877fb9e..0158c0f 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -32,6 +32,9 @@ Core and builtins
Extension modules
-----------------
+- New function time.tzset() provides access to the C library tzet()
+ function, if supported. (SF patch #675422.)
+
- Using createfilehandler, deletefilehandler, createtimerhandler functions
on Tkinter.tkinter (_tkinter module) no longer crashes the interpreter.
See SF bug #692416.
diff --git a/Modules/timemodule.c b/Modules/timemodule.c
index 745ba8c..fc81ca4 100644
--- a/Modules/timemodule.c
+++ b/Modules/timemodule.c
@@ -554,85 +554,63 @@ PyDoc_STRVAR(mktime_doc,
Convert a time tuple in local time to seconds since the Epoch.");
#endif /* HAVE_MKTIME */
-static PyMethodDef time_methods[] = {
- {"time", time_time, METH_VARARGS, time_doc},
-#ifdef HAVE_CLOCK
- {"clock", time_clock, METH_VARARGS, clock_doc},
-#endif
- {"sleep", time_sleep, METH_VARARGS, sleep_doc},
- {"gmtime", time_gmtime, METH_VARARGS, gmtime_doc},
- {"localtime", time_localtime, METH_VARARGS, localtime_doc},
- {"asctime", time_asctime, METH_VARARGS, asctime_doc},
- {"ctime", time_ctime, METH_VARARGS, ctime_doc},
-#ifdef HAVE_MKTIME
- {"mktime", time_mktime, METH_VARARGS, mktime_doc},
-#endif
-#ifdef HAVE_STRFTIME
- {"strftime", time_strftime, METH_VARARGS, strftime_doc},
-#endif
- {"strptime", time_strptime, METH_VARARGS, strptime_doc},
- {NULL, NULL} /* sentinel */
-};
+#ifdef HAVE_WORKING_TZSET
+void inittimezone(PyObject *module);
+static PyObject *
+time_tzset(PyObject *self, PyObject *args)
+{
+ PyObject* m;
-PyDoc_STRVAR(module_doc,
-"This module provides various functions to manipulate time values.\n\
-\n\
-There are two standard representations of time. One is the number\n\
-of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer\n\
-or a floating point number (to represent fractions of seconds).\n\
-The Epoch is system-defined; on Unix, it is generally January 1st, 1970.\n\
-The actual value can be retrieved by calling gmtime(0).\n\
-\n\
-The other representation is a tuple of 9 integers giving local time.\n\
-The tuple items are:\n\
- year (four digits, e.g. 1998)\n\
- month (1-12)\n\
- day (1-31)\n\
- hours (0-23)\n\
- minutes (0-59)\n\
- seconds (0-59)\n\
- weekday (0-6, Monday is 0)\n\
- Julian day (day in the year, 1-366)\n\
- DST (Daylight Savings Time) flag (-1, 0 or 1)\n\
-If the DST flag is 0, the time is given in the regular time zone;\n\
-if it is 1, the time is given in the DST time zone;\n\
-if it is -1, mktime() should guess based on the date and time.\n\
-\n\
-Variables:\n\
-\n\
-timezone -- difference in seconds between UTC and local standard time\n\
-altzone -- difference in seconds between UTC and local DST time\n\
-daylight -- whether local time should reflect DST\n\
-tzname -- tuple of (standard time zone name, DST time zone name)\n\
-\n\
-Functions:\n\
-\n\
-time() -- return current time in seconds since the Epoch as a float\n\
-clock() -- return CPU time since process start as a float\n\
-sleep() -- delay for a number of seconds given as a float\n\
-gmtime() -- convert seconds since Epoch to UTC tuple\n\
-localtime() -- convert seconds since Epoch to local time tuple\n\
-asctime() -- convert time tuple to string\n\
-ctime() -- convert time in seconds to string\n\
-mktime() -- convert local time tuple to seconds since Epoch\n\
-strftime() -- convert time tuple to string according to format specification\n\
-strptime() -- parse string to time tuple according to format specification");
+ if (!PyArg_ParseTuple(args, ":tzset"))
+ return NULL;
+ m = PyImport_ImportModule("time");
+ if (m == NULL) {
+ return NULL;
+ }
-PyMODINIT_FUNC
-inittime(void)
-{
- PyObject *m;
- char *p;
- m = Py_InitModule3("time", time_methods, module_doc);
+ tzset();
- /* Accept 2-digit dates unless PYTHONY2K is set and non-empty */
- p = Py_GETENV("PYTHONY2K");
- PyModule_AddIntConstant(m, "accept2dyear", (long) (!p || !*p));
- /* Squirrel away the module's dictionary for the y2k check */
- moddict = PyModule_GetDict(m);
- Py_INCREF(moddict);
+ /* Reset timezone, altzone, daylight and tzname */
+ inittimezone(m);
+ Py_DECREF(m);
+
+ Py_INCREF(Py_None);
+ return Py_None;
+}
+
+PyDoc_STRVAR(tzset_doc,
+"tzset(zone)\n\
+\n\
+Initialize, or reinitialize, the local timezone to the value stored in\n\
+os.environ['TZ']. The TZ environment variable should be specified in\n\
+standard Uniz timezone format as documented in the tzset man page\n\
+(eg. 'US/Eastern', 'Europe/Amsterdam'). Unknown timezones will silently\n\
+fall back to UTC. If the TZ environment variable is not set, the local\n\
+timezone is set to the systems best guess of wallclock time.\n\
+Changing the TZ environment variable without calling tzset *may* change\n\
+the local timezone used by methods such as localtime, but this behaviour\n\
+should not be relied on.");
+#endif /* HAVE_WORKING_TZSET */
+
+void inittimezone(PyObject *m) {
+ /* This code moved from inittime wholesale to allow calling it from
+ time_tzset. In the future, some parts of it can be moved back
+ (for platforms that don't HAVE_WORKING_TZSET, when we know what they
+ are), and the extranious calls to tzset(3) should be removed.
+ I havn't done this yet, as I don't want to change this code as
+ little as possible when introducing the time.tzset and time.tzsetwall
+ methods. This should simply be a method of doing the following once,
+ at the top of this function and removing the call to tzset() from
+ time_tzset():
+
+ #ifdef HAVE_TZSET
+ tzset()
+ #endif
+
+ And I'm lazy and hate C so nyer.
+ */
#if defined(HAVE_TZNAME) && !defined(__GLIBC__) && !defined(__CYGWIN__)
tzset();
#ifdef PYOS_OS2
@@ -712,6 +690,96 @@ inittime(void)
Py_BuildValue("(zz)", _tzname[0], _tzname[1]));
#endif /* __CYGWIN__ */
#endif /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/
+}
+
+
+static PyMethodDef time_methods[] = {
+ {"time", time_time, METH_VARARGS, time_doc},
+#ifdef HAVE_CLOCK
+ {"clock", time_clock, METH_VARARGS, clock_doc},
+#endif
+ {"sleep", time_sleep, METH_VARARGS, sleep_doc},
+ {"gmtime", time_gmtime, METH_VARARGS, gmtime_doc},
+ {"localtime", time_localtime, METH_VARARGS, localtime_doc},
+ {"asctime", time_asctime, METH_VARARGS, asctime_doc},
+ {"ctime", time_ctime, METH_VARARGS, ctime_doc},
+#ifdef HAVE_MKTIME
+ {"mktime", time_mktime, METH_VARARGS, mktime_doc},
+#endif
+#ifdef HAVE_STRFTIME
+ {"strftime", time_strftime, METH_VARARGS, strftime_doc},
+#endif
+ {"strptime", time_strptime, METH_VARARGS, strptime_doc},
+#ifdef HAVE_WORKING_TZSET
+ {"tzset", time_tzset, METH_VARARGS, tzset_doc},
+#endif
+ {NULL, NULL} /* sentinel */
+};
+
+
+PyDoc_STRVAR(module_doc,
+"This module provides various functions to manipulate time values.\n\
+\n\
+There are two standard representations of time. One is the number\n\
+of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer\n\
+or a floating point number (to represent fractions of seconds).\n\
+The Epoch is system-defined; on Unix, it is generally January 1st, 1970.\n\
+The actual value can be retrieved by calling gmtime(0).\n\
+\n\
+The other representation is a tuple of 9 integers giving local time.\n\
+The tuple items are:\n\
+ year (four digits, e.g. 1998)\n\
+ month (1-12)\n\
+ day (1-31)\n\
+ hours (0-23)\n\
+ minutes (0-59)\n\
+ seconds (0-59)\n\
+ weekday (0-6, Monday is 0)\n\
+ Julian day (day in the year, 1-366)\n\
+ DST (Daylight Savings Time) flag (-1, 0 or 1)\n\
+If the DST flag is 0, the time is given in the regular time zone;\n\
+if it is 1, the time is given in the DST time zone;\n\
+if it is -1, mktime() should guess based on the date and time.\n\
+\n\
+Variables:\n\
+\n\
+timezone -- difference in seconds between UTC and local standard time\n\
+altzone -- difference in seconds between UTC and local DST time\n\
+daylight -- whether local time should reflect DST\n\
+tzname -- tuple of (standard time zone name, DST time zone name)\n\
+\n\
+Functions:\n\
+\n\
+time() -- return current time in seconds since the Epoch as a float\n\
+clock() -- return CPU time since process start as a float\n\
+sleep() -- delay for a number of seconds given as a float\n\
+gmtime() -- convert seconds since Epoch to UTC tuple\n\
+localtime() -- convert seconds since Epoch to local time tuple\n\
+asctime() -- convert time tuple to string\n\
+ctime() -- convert time in seconds to string\n\
+mktime() -- convert local time tuple to seconds since Epoch\n\
+strftime() -- convert time tuple to string according to format specification\n\
+strptime() -- parse string to time tuple according to format specification\n\
+tzset() -- change the local timezone");
+
+
+PyMODINIT_FUNC
+inittime(void)
+{
+ PyObject *m;
+ char *p;
+ m = Py_InitModule3("time", time_methods, module_doc);
+
+ /* Accept 2-digit dates unless PYTHONY2K is set and non-empty */
+ p = Py_GETENV("PYTHONY2K");
+ PyModule_AddIntConstant(m, "accept2dyear", (long) (!p || !*p));
+ /* Squirrel away the module's dictionary for the y2k check */
+ moddict = PyModule_GetDict(m);
+ Py_INCREF(moddict);
+
+ /* Set, or reset, module variables like time.timezone */
+ inittimezone(m);
+
#ifdef MS_WINDOWS
/* Helper to allow interrupts for Windows.
If Ctrl+C event delivered while not sleeping
@@ -901,3 +969,5 @@ floatsleep(double secs)
return 0;
}
+
+
diff --git a/configure b/configure
index 2e9574b..09337d8 100755
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
#! /bin/sh
-# From configure.in Revision: 1.391 .
+# From configure.in Revision: 1.392 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.53 for python 2.3.
#
@@ -16550,6 +16550,74 @@ _ACEOF
fi
+# tzset(3) exists and works like we expect it to
+echo "$as_me:$LINENO: checking for working tzset()" >&5
+echo $ECHO_N "checking for working tzset()... $ECHO_C" >&6
+if test "${ac_cv_working_tzset+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+
+if test "$cross_compiling" = yes; then
+ ac_cv_working_tzset=no
+else
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+#include "confdefs.h"
+
+#include <stdlib.h>
+#include <time.h>
+int main()
+{
+ int gmt_hour;
+ int eastern_hour;
+ time_t now;
+ now = time((time_t*)NULL);
+ putenv("TZ=GMT");
+ tzset();
+ gmt_hour = localtime(&now)->tm_hour;
+ putenv("TZ=US/Eastern");
+ tzset();
+ eastern_hour = localtime(&now)->tm_hour;
+ if (eastern_hour == gmt_hour)
+ exit(1);
+ exit(0);
+}
+
+_ACEOF
+rm -f conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ ac_cv_working_tzset=yes
+else
+ echo "$as_me: program exited with status $ac_status" >&5
+echo "$as_me: failed program was:" >&5
+cat conftest.$ac_ext >&5
+( exit $ac_status )
+ac_cv_working_tzset=no
+fi
+rm -f core core.* *.core conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
+fi
+fi
+
+echo "$as_me:$LINENO: result: $ac_cv_working_tzset" >&5
+echo "${ECHO_T}$ac_cv_working_tzset" >&6
+if test "$ac_cv_working_tzset" = yes
+then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_WORKING_TZSET 1
+_ACEOF
+
+fi
+
# Look for subsecond timestamps in struct stat
echo "$as_me:$LINENO: checking for tv_nsec in struct stat" >&5
echo $ECHO_N "checking for tv_nsec in struct stat... $ECHO_C" >&6
diff --git a/configure.in b/configure.in
index f73df53..bcde551 100644
--- a/configure.in
+++ b/configure.in
@@ -2500,6 +2500,39 @@ then
[Define if nice() returns success/failure instead of the new priority.])
fi
+# tzset(3) exists and works like we expect it to
+AC_MSG_CHECKING(for working tzset())
+AC_CACHE_VAL(ac_cv_working_tzset, [
+AC_TRY_RUN([
+#include <stdlib.h>
+#include <time.h>
+int main()
+{
+ int gmt_hour;
+ int eastern_hour;
+ time_t now;
+ now = time((time_t*)NULL);
+ putenv("TZ=GMT");
+ tzset();
+ gmt_hour = localtime(&now)->tm_hour;
+ putenv("TZ=US/Eastern");
+ tzset();
+ eastern_hour = localtime(&now)->tm_hour;
+ if (eastern_hour == gmt_hour)
+ exit(1);
+ exit(0);
+}
+],
+ac_cv_working_tzset=yes,
+ac_cv_working_tzset=no,
+ac_cv_working_tzset=no)])
+AC_MSG_RESULT($ac_cv_working_tzset)
+if test "$ac_cv_working_tzset" = yes
+then
+ AC_DEFINE(HAVE_WORKING_TZSET, 1,
+ [Define if tzset() actually switches the local timezone in a meaningful way.])
+fi
+
# Look for subsecond timestamps in struct stat
AC_MSG_CHECKING(for tv_nsec in struct stat)
AC_CACHE_VAL(ac_cv_stat_tv_nsec,
diff --git a/pyconfig.h.in b/pyconfig.h.in
index e2dd4d2..37fd5fc 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -613,6 +613,10 @@
/* Define to 1 if you have the `wcscoll' function. */
#undef HAVE_WCSCOLL
+/* Define if tzset() actually switches the local timezone in a meaningful way.
+ */
+#undef HAVE_WORKING_TZSET
+
/* Define to 1 if you have the `_getpty' function. */
#undef HAVE__GETPTY