Reputation: 206607
datetime.now()
and datetime.today()
return time in UTC on my computer even though the documentation says they should return local time.
Here's the script I ran:
#!/usr/bin/python
import time
import datetime
if __name__ == "__main__":
print(datetime.datetime.now())
print(datetime.datetime.today())
print(datetime.datetime.fromtimestamp(time.time()))
and here's the output:
2017-11-29 22:47:35.339914
2017-11-29 22:47:35.340399
2017-11-29 22:47:35.340399
The output of running date
right after it is:
Wed, Nov 29, 2017 3:47:43 PM
Why is my installation returning time in UTC?
What can I do get those functions to return local time?
PS We are in MST, which is UTC-7.
PS 2 I realize there are methods to convert a UTC time to local time, such as those explained in Convert a python UTC datetime to a local datetime using only python standard library?. However, I am trying to understand the cause of the fundamental problem and not looking for a method to patch the problem in my own code.
In response to comment by @jwodder:
The output of executing
print(time.altzone)
print(time.timezone)
print(time.tzname)
is:
-3600
0
('Ame', 'ric')
Upvotes: 13
Views: 3478
Reputation: 1145
I think there is some odd behavior going on with things using the glibc time and timezone libraries on Windows. I started noticing this behavior in both python and emacs recently.
The best thing to do is probably to set TZ to the "ugly" version described in the best answer as that seems to fix issues in python and emacs and works correctly in cygwin as well.
Another workaround I tried is to make sure the TZ environment variable is NOT set. The following illustrates the problem around 10:18 New York time in python. I get similar results using either cygwin or CMD on Windows. Emacs illustrates the same problem using the current-time-string
function suggesting it is a glibc issue or at least some library which both python and emacs are using. Interestingly the date
command in cygwin gives the correct result with TZ set to "America/New York" but incorrect if TZ is unset.
Summary: some things (e.g., python, emacs) on Windows seem to not accept "America/New_York" for TZ while some things (e.g., cygwin) do accept it. Using something like EST+05EDT,M4.1.0,M10.5.0
for eastern time (or appropriate ugly equivalent) works.
$ echo $TZ
America/New_York
$ python -i
Python 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2018, 5, 14, 15, 38, 6, 174073)
>>> datetime.datetime.now()
datetime.datetime(2018, 5, 14, 15, 38, 57, 141708)
>>> quit()
$ export TZ=
$ python -i
Python 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2018, 5, 14, 10, 38, 41, 102117)
Upvotes: 1
Reputation: 5603
As you note in your answer, the TZ
environment variable is the key here. On unix-type systems, this supports more "friendly" values like "US/Pacific" or, indeed, "America/Denver", but on Windows, it doesn't. Although it's not available on Windows, the documentation for the time.tzset
function describes the format you'll need to set TZ in to get what you want. It's... not pretty. But it works:
C:\Users\zorb>set TZ=MST+07MDT,M3.2.0,M11.1.0
C:\Users\zorb>python.exe
>>> import time
>>> time.tzname
('MST', 'MDT')
>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2018, 2, 9, 16, 27, 7, 164062)
(This was at 15:27 in Pacific time.) The structure of this format is:
The format for the start and end of daylight time is:
M
(for "month-based")There are also options to specify the time at which daylight time starts and ends (but it defaults to 02:00:00, so unnecessary in this case) and the offset for daylight time (but it defaults to 1 hour, so also not necessary).
(edit) Turns out this is actually a glibc feature, not directly a python one. More detailed info in the glibc docs.
Upvotes: 6
Reputation: 206607
Initially, it appeared to be a problem caused by the use of cygwin.
The question at Cygwin shows UTC time instead of local time helped further isolate the problem to the value of the environment variable TZ
in cygwin.
The updated script:
import time
import datetime
if __name__ == "__main__":
print(datetime.datetime.now())
print(datetime.datetime.today())
print(datetime.datetime.fromtimestamp(time.time()))
print(time.altzone)
print(time.timezone)
print(time.tzname)
Output when run under a Windows CMD shell with, where TZ
is not set:
"D:\Program Files\Python35\python.exe" test.py
2017-11-30 09:39:47.236798
2017-11-30 09:39:47.236799
2017-11-30 09:39:47.236799
21600
25200
('Mountain Standard Time', 'Mountain Daylight Time')
Output when run under a cygwin bash shell with, where TZ
is set to "America/Denver"
:
/cygdrive/D/Program\ Files/Python35/python.exe test.py
2017-11-30 16:39:45.419884
2017-11-30 16:39:45.419884
2017-11-30 16:39:45.419884
-3600
0
('Ame', 'ric')
It's set to "America/Denver"
. When I executed
env TZ="" /cygdrive/D/Program\ Files/Python35/python.exe test.py
I got a more sensible output:
2017-11-30 09:56:08.643368
2017-11-30 09:56:08.643368
2017-11-30 09:56:08.643368
21600
25200
('Mountain Standard Time', 'Mountain Daylight Time')
When I set the environment variable TZ
to "America/Denver"
in the windows CMD shell, I get the same output as when run in the cygwin shell.
It's not clear to me how Python uses the environment variable TZ
and what the correct values are for it.
Upvotes: 2