Why datetime.now() and datetime.today() show time in UTC and not local time on my PC? Why datetime.now() and datetime.today() show time in UTC and not local time on my PC? python-3.x python-3.x

Why datetime.now() and datetime.today() show time in UTC and not local time on my PC?


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.0C:\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:

  • Standard time abbrevation (MST)
  • UTC offset of standard time, in hours (+07)
  • Daylight time abbreviation
  • When daylight time starts (see below)
  • When daylight time ends (see below)

The format for the start and end of daylight time is:

  • M (for "month-based")
  • Month number - 3/March or 11/November, in this case.
  • Week of the month - 1 through 5, meaning the 1st through 5th occurrence of the day named below.
  • Day of the week - 0 for Sunday through 6 for Saturday

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.


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 timeimport datetimeif __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.2367982017-11-30 09:39:47.2367992017-11-30 09:39:47.2367992160025200('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.4198842017-11-30 16:39:45.4198842017-11-30 16:39:45.419884-36000('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.6433682017-11-30 09:56:08.6433682017-11-30 09:56:08.6433682160025200('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.


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 $TZAmerica/New_York$ python -iPython 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit (AMD64)] on win32Type "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 -iPython 3.6.4 |Anaconda, Inc.| (default, Jan 16 2018, 10:22:32) [MSC v.1900 64 bit (AMD64)] on win32Type "help", "copyright", "credits" or "license" for more information.>>> import datetime>>> datetime.datetime.now()datetime.datetime(2018, 5, 14, 10, 38, 41, 102117)