- New function time.tzset() provides access to the C library tzet()

function, if supported.  (SF patch #675422, by Stuart Bishop.)
This commit is contained in:
Guido van Rossum 2003-03-14 21:51:36 +00:00
parent 538f1d842c
commit d11b62edd0
7 changed files with 338 additions and 78 deletions

View File

@ -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)

View File

@ -50,6 +50,7 @@ Eric Beser
Stephen Bevan
Ron Bickers
Dominic Binks
Stuart Bishop
Roy Bixler
Martin Bless
Pablo Bleyer

View File

@ -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.

View File

@ -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);
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");
PyMODINIT_FUNC
inittime(void)
static PyObject *
time_tzset(PyObject *self, PyObject *args)
{
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);
if (!PyArg_ParseTuple(args, ":tzset"))
return NULL;
m = PyImport_ImportModule("time");
if (m == NULL) {
return NULL;
}
tzset();
/* 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;
}

70
configure vendored
View File

@ -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

View File

@ -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,

View File

@ -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