Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d11b62e

Browse files
committed
- New function time.tzset() provides access to the C library tzet()
function, if supported. (SF patch #675422, by Stuart Bishop.)
1 parent 538f1d8 commit d11b62e

7 files changed

Lines changed: 336 additions & 76 deletions

File tree

Lib/test/test_time.py

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,92 @@ def test_strptime(self):
4848
except ValueError:
4949
self.fail('conversion specifier: %r failed.' % format)
5050

51-
5251
def test_asctime(self):
5352
time.asctime(time.gmtime(self.t))
5453
self.assertRaises(TypeError, time.asctime, 0)
5554

55+
def test_tzset(self):
56+
from os import environ
57+
58+
# Epoch time of midnight Dec 25th 2002. Never DST in northern
59+
# hemisphere.
60+
xmas2002 = 1040774400.0
61+
62+
org_TZ = environ.get('TZ',None)
63+
try:
64+
65+
# Make sure we can switch to UTC time and results are correct
66+
# Note that unknown timezones default to UTC.
67+
for tz in ('UTC','GMT','Luna/Tycho'):
68+
environ['TZ'] = 'US/Eastern'
69+
time.tzset()
70+
environ['TZ'] = tz
71+
time.tzset()
72+
self.failUnlessEqual(
73+
time.gmtime(xmas2002),time.localtime(xmas2002)
74+
)
75+
self.failUnlessEqual(time.timezone,time.altzone)
76+
self.failUnlessEqual(time.daylight,0)
77+
self.failUnlessEqual(time.timezone,0)
78+
self.failUnlessEqual(time.altzone,0)
79+
self.failUnlessEqual(time.localtime(xmas2002).tm_isdst,0)
80+
81+
# Make sure we can switch to US/Eastern
82+
environ['TZ'] = 'US/Eastern'
83+
time.tzset()
84+
self.failIfEqual(time.gmtime(xmas2002),time.localtime(xmas2002))
85+
self.failUnlessEqual(time.tzname,('EST','EDT'))
86+
self.failUnlessEqual(len(time.tzname),2)
87+
self.failUnlessEqual(time.daylight,1)
88+
self.failUnlessEqual(time.timezone,18000)
89+
self.failUnlessEqual(time.altzone,14400)
90+
self.failUnlessEqual(time.localtime(xmas2002).tm_isdst,0)
91+
self.failUnlessEqual(len(time.tzname),2)
92+
93+
# Now go to the southern hemisphere. We want somewhere all OS's
94+
# know about that has DST.
95+
environ['TZ'] = 'Australia/Melbourne'
96+
time.tzset()
97+
self.failIfEqual(time.gmtime(xmas2002),time.localtime(xmas2002))
98+
self.failUnless(time.tzname[0] in ('EST','AEST'))
99+
self.failUnless(time.tzname[1] in ('EST','EDT','AEDT'))
100+
self.failUnlessEqual(len(time.tzname),2)
101+
self.failUnlessEqual(time.daylight,1)
102+
self.failUnlessEqual(time.timezone,-36000)
103+
self.failUnlessEqual(time.altzone,-39600)
104+
self.failUnlessEqual(time.localtime(xmas2002).tm_isdst,1)
105+
106+
# Get some times from a timezone that isn't wallclock timezone
107+
del environ['TZ']
108+
time.tzset()
109+
if time.timezone == 0:
110+
environ['TZ'] = 'US/Eastern'
111+
else:
112+
environ['TZ'] = 'UTC'
113+
time.tzset()
114+
nonlocal = time.localtime(xmas2002)
115+
116+
# Then the same time in wallclock timezone
117+
del environ['TZ']
118+
time.tzset()
119+
local = time.localtime(xmas2002)
120+
121+
# And make sure they arn't the same
122+
self.failIfEqual(local,nonlocal)
123+
124+
# Do some basic sanity checking after wallclock time set
125+
self.failUnlessEqual(len(time.tzname),2)
126+
time.daylight
127+
time.timezone
128+
time.altzone
129+
finally:
130+
# Repair TZ environment variable in case any other tests
131+
# rely on it.
132+
if org_TZ is not None:
133+
environ['TZ'] = org_TZ
134+
elif environ.has_key('TZ'):
135+
del environ['TZ']
136+
56137

57138
def test_main():
58139
test_support.run_unittest(TimeTestCase)

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Eric Beser
5050
Stephen Bevan
5151
Ron Bickers
5252
Dominic Binks
53+
Stuart Bishop
5354
Roy Bixler
5455
Martin Bless
5556
Pablo Bleyer

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ Core and builtins
3232
Extension modules
3333
-----------------
3434

35+
- New function time.tzset() provides access to the C library tzet()
36+
function, if supported. (SF patch #675422.)
37+
3538
- Using createfilehandler, deletefilehandler, createtimerhandler functions
3639
on Tkinter.tkinter (_tkinter module) no longer crashes the interpreter.
3740
See SF bug #692416.

Modules/timemodule.c

Lines changed: 144 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -554,85 +554,63 @@ PyDoc_STRVAR(mktime_doc,
554554
Convert a time tuple in local time to seconds since the Epoch.");
555555
#endif /* HAVE_MKTIME */
556556

557-
static PyMethodDef time_methods[] = {
558-
{"time", time_time, METH_VARARGS, time_doc},
559-
#ifdef HAVE_CLOCK
560-
{"clock", time_clock, METH_VARARGS, clock_doc},
561-
#endif
562-
{"sleep", time_sleep, METH_VARARGS, sleep_doc},
563-
{"gmtime", time_gmtime, METH_VARARGS, gmtime_doc},
564-
{"localtime", time_localtime, METH_VARARGS, localtime_doc},
565-
{"asctime", time_asctime, METH_VARARGS, asctime_doc},
566-
{"ctime", time_ctime, METH_VARARGS, ctime_doc},
567-
#ifdef HAVE_MKTIME
568-
{"mktime", time_mktime, METH_VARARGS, mktime_doc},
569-
#endif
570-
#ifdef HAVE_STRFTIME
571-
{"strftime", time_strftime, METH_VARARGS, strftime_doc},
572-
#endif
573-
{"strptime", time_strptime, METH_VARARGS, strptime_doc},
574-
{NULL, NULL} /* sentinel */
575-
};
557+
#ifdef HAVE_WORKING_TZSET
558+
void inittimezone(PyObject *module);
576559

560+
static PyObject *
561+
time_tzset(PyObject *self, PyObject *args)
562+
{
563+
PyObject* m;
577564

578-
PyDoc_STRVAR(module_doc,
579-
"This module provides various functions to manipulate time values.\n\
580-
\n\
581-
There are two standard representations of time. One is the number\n\
582-
of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer\n\
583-
or a floating point number (to represent fractions of seconds).\n\
584-
The Epoch is system-defined; on Unix, it is generally January 1st, 1970.\n\
585-
The actual value can be retrieved by calling gmtime(0).\n\
586-
\n\
587-
The other representation is a tuple of 9 integers giving local time.\n\
588-
The tuple items are:\n\
589-
year (four digits, e.g. 1998)\n\
590-
month (1-12)\n\
591-
day (1-31)\n\
592-
hours (0-23)\n\
593-
minutes (0-59)\n\
594-
seconds (0-59)\n\
595-
weekday (0-6, Monday is 0)\n\
596-
Julian day (day in the year, 1-366)\n\
597-
DST (Daylight Savings Time) flag (-1, 0 or 1)\n\
598-
If the DST flag is 0, the time is given in the regular time zone;\n\
599-
if it is 1, the time is given in the DST time zone;\n\
600-
if it is -1, mktime() should guess based on the date and time.\n\
601-
\n\
602-
Variables:\n\
603-
\n\
604-
timezone -- difference in seconds between UTC and local standard time\n\
605-
altzone -- difference in seconds between UTC and local DST time\n\
606-
daylight -- whether local time should reflect DST\n\
607-
tzname -- tuple of (standard time zone name, DST time zone name)\n\
608-
\n\
609-
Functions:\n\
610-
\n\
611-
time() -- return current time in seconds since the Epoch as a float\n\
612-
clock() -- return CPU time since process start as a float\n\
613-
sleep() -- delay for a number of seconds given as a float\n\
614-
gmtime() -- convert seconds since Epoch to UTC tuple\n\
615-
localtime() -- convert seconds since Epoch to local time tuple\n\
616-
asctime() -- convert time tuple to string\n\
617-
ctime() -- convert time in seconds to string\n\
618-
mktime() -- convert local time tuple to seconds since Epoch\n\
619-
strftime() -- convert time tuple to string according to format specification\n\
620-
strptime() -- parse string to time tuple according to format specification");
565+
if (!PyArg_ParseTuple(args, ":tzset"))
566+
return NULL;
621567

568+
m = PyImport_ImportModule("time");
569+
if (m == NULL) {
570+
return NULL;
571+
}
622572

623-
PyMODINIT_FUNC
624-
inittime(void)
625-
{
626-
PyObject *m;
627-
char *p;
628-
m = Py_InitModule3("time", time_methods, module_doc);
573+
tzset();
629574

630-
/* Accept 2-digit dates unless PYTHONY2K is set and non-empty */
631-
p = Py_GETENV("PYTHONY2K");
632-
PyModule_AddIntConstant(m, "accept2dyear", (long) (!p || !*p));
633-
/* Squirrel away the module's dictionary for the y2k check */
634-
moddict = PyModule_GetDict(m);
635-
Py_INCREF(moddict);
575+
/* Reset timezone, altzone, daylight and tzname */
576+
inittimezone(m);
577+
Py_DECREF(m);
578+
579+
Py_INCREF(Py_None);
580+
return Py_None;
581+
}
582+
583+
PyDoc_STRVAR(tzset_doc,
584+
"tzset(zone)\n\
585+
\n\
586+
Initialize, or reinitialize, the local timezone to the value stored in\n\
587+
os.environ['TZ']. The TZ environment variable should be specified in\n\
588+
standard Uniz timezone format as documented in the tzset man page\n\
589+
(eg. 'US/Eastern', 'Europe/Amsterdam'). Unknown timezones will silently\n\
590+
fall back to UTC. If the TZ environment variable is not set, the local\n\
591+
timezone is set to the systems best guess of wallclock time.\n\
592+
Changing the TZ environment variable without calling tzset *may* change\n\
593+
the local timezone used by methods such as localtime, but this behaviour\n\
594+
should not be relied on.");
595+
#endif /* HAVE_WORKING_TZSET */
596+
597+
void inittimezone(PyObject *m) {
598+
/* This code moved from inittime wholesale to allow calling it from
599+
time_tzset. In the future, some parts of it can be moved back
600+
(for platforms that don't HAVE_WORKING_TZSET, when we know what they
601+
are), and the extranious calls to tzset(3) should be removed.
602+
I havn't done this yet, as I don't want to change this code as
603+
little as possible when introducing the time.tzset and time.tzsetwall
604+
methods. This should simply be a method of doing the following once,
605+
at the top of this function and removing the call to tzset() from
606+
time_tzset():
607+
608+
#ifdef HAVE_TZSET
609+
tzset()
610+
#endif
611+
612+
And I'm lazy and hate C so nyer.
613+
*/
636614
#if defined(HAVE_TZNAME) && !defined(__GLIBC__) && !defined(__CYGWIN__)
637615
tzset();
638616
#ifdef PYOS_OS2
@@ -712,6 +690,96 @@ inittime(void)
712690
Py_BuildValue("(zz)", _tzname[0], _tzname[1]));
713691
#endif /* __CYGWIN__ */
714692
#endif /* !HAVE_TZNAME || __GLIBC__ || __CYGWIN__*/
693+
}
694+
695+
696+
static PyMethodDef time_methods[] = {
697+
{"time", time_time, METH_VARARGS, time_doc},
698+
#ifdef HAVE_CLOCK
699+
{"clock", time_clock, METH_VARARGS, clock_doc},
700+
#endif
701+
{"sleep", time_sleep, METH_VARARGS, sleep_doc},
702+
{"gmtime", time_gmtime, METH_VARARGS, gmtime_doc},
703+
{"localtime", time_localtime, METH_VARARGS, localtime_doc},
704+
{"asctime", time_asctime, METH_VARARGS, asctime_doc},
705+
{"ctime", time_ctime, METH_VARARGS, ctime_doc},
706+
#ifdef HAVE_MKTIME
707+
{"mktime", time_mktime, METH_VARARGS, mktime_doc},
708+
#endif
709+
#ifdef HAVE_STRFTIME
710+
{"strftime", time_strftime, METH_VARARGS, strftime_doc},
711+
#endif
712+
{"strptime", time_strptime, METH_VARARGS, strptime_doc},
713+
#ifdef HAVE_WORKING_TZSET
714+
{"tzset", time_tzset, METH_VARARGS, tzset_doc},
715+
#endif
716+
{NULL, NULL} /* sentinel */
717+
};
718+
719+
720+
PyDoc_STRVAR(module_doc,
721+
"This module provides various functions to manipulate time values.\n\
722+
\n\
723+
There are two standard representations of time. One is the number\n\
724+
of seconds since the Epoch, in UTC (a.k.a. GMT). It may be an integer\n\
725+
or a floating point number (to represent fractions of seconds).\n\
726+
The Epoch is system-defined; on Unix, it is generally January 1st, 1970.\n\
727+
The actual value can be retrieved by calling gmtime(0).\n\
728+
\n\
729+
The other representation is a tuple of 9 integers giving local time.\n\
730+
The tuple items are:\n\
731+
year (four digits, e.g. 1998)\n\
732+
month (1-12)\n\
733+
day (1-31)\n\
734+
hours (0-23)\n\
735+
minutes (0-59)\n\
736+
seconds (0-59)\n\
737+
weekday (0-6, Monday is 0)\n\
738+
Julian day (day in the year, 1-366)\n\
739+
DST (Daylight Savings Time) flag (-1, 0 or 1)\n\
740+
If the DST flag is 0, the time is given in the regular time zone;\n\
741+
if it is 1, the time is given in the DST time zone;\n\
742+
if it is -1, mktime() should guess based on the date and time.\n\
743+
\n\
744+
Variables:\n\
745+
\n\
746+
timezone -- difference in seconds between UTC and local standard time\n\
747+
altzone -- difference in seconds between UTC and local DST time\n\
748+
daylight -- whether local time should reflect DST\n\
749+
tzname -- tuple of (standard time zone name, DST time zone name)\n\
750+
\n\
751+
Functions:\n\
752+
\n\
753+
time() -- return current time in seconds since the Epoch as a float\n\
754+
clock() -- return CPU time since process start as a float\n\
755+
sleep() -- delay for a number of seconds given as a float\n\
756+
gmtime() -- convert seconds since Epoch to UTC tuple\n\
757+
localtime() -- convert seconds since Epoch to local time tuple\n\
758+
asctime() -- convert time tuple to string\n\
759+
ctime() -- convert time in seconds to string\n\
760+
mktime() -- convert local time tuple to seconds since Epoch\n\
761+
strftime() -- convert time tuple to string according to format specification\n\
762+
strptime() -- parse string to time tuple according to format specification\n\
763+
tzset() -- change the local timezone");
764+
765+
766+
PyMODINIT_FUNC
767+
inittime(void)
768+
{
769+
PyObject *m;
770+
char *p;
771+
m = Py_InitModule3("time", time_methods, module_doc);
772+
773+
/* Accept 2-digit dates unless PYTHONY2K is set and non-empty */
774+
p = Py_GETENV("PYTHONY2K");
775+
PyModule_AddIntConstant(m, "accept2dyear", (long) (!p || !*p));
776+
/* Squirrel away the module's dictionary for the y2k check */
777+
moddict = PyModule_GetDict(m);
778+
Py_INCREF(moddict);
779+
780+
/* Set, or reset, module variables like time.timezone */
781+
inittimezone(m);
782+
715783
#ifdef MS_WINDOWS
716784
/* Helper to allow interrupts for Windows.
717785
If Ctrl+C event delivered while not sleeping
@@ -901,3 +969,5 @@ floatsleep(double secs)
901969

902970
return 0;
903971
}
972+
973+

0 commit comments

Comments
 (0)