2

I am writing a program that should log the offset of the machine's local time from UTC at regular intervals, if it has changed.

I am aware that it is possible to find the offset at the time the program was started. This can be done by

str(datetime.datetime.now()-datetime.datetime.utcnow())

or

str(datetime.datetime.now().replace(tzinfo=timezone.utc).astimezone())

or other methods.

The problem is that the time returned by datetime.datetime.now() seems to always be in the timezone at which datetime was first imported, rather than the current timezone. That is, changing the local time on my machine is not reflected by the same change in the time given by datetime.datetime.now() .

As an example,

import datetime
datetime.datetime.now() 

reports '2014-09-11 12:35:45.415104'.

I now change my timezone to UTC+4 on the machine.

datetime.datetime.now() 

still reports '2014-09-11 12:35:50.407779'.

How can I obtain the current time on my machine using python (preferably without external libraries and in a platform-agnostic manner)?

I am using Python 3.4.1 on Windows 8.

Sepia
  • 447
  • 6
  • 21
  • Always work with UTC, and only convert to a local timezone for display purposes. – chepner Sep 11 '14 at 11:54
  • I am working in UTC as far as possible. The interest I have in local time is to ensure that changes to local timezone are noted down in the log file. Logging this is a necessary feature for the program. – Sepia Sep 11 '14 at 12:02
  • After consideration, I have flagged this question as a duplicate of the question linked by nmclean ([Make Python respond to Windows timezone changes](http://stackoverflow.com/questions/4360981/make-python-respond-to-windows-timezone-changes)). – Sepia Sep 15 '14 at 16:24
  • I hit this on linux with python 3.10, so not only windows-related – Osman-pasha Jun 22 '22 at 10:03

2 Answers2

0

Try using time.tzname (import time first of course).

If that doesn't work, you will need to call this Windows API function: GetTimeZoneInformation(). It's exposed by Python for Windows Extensions, or perhaps you can invoke it via ctypes.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • Thanks for the suggestions. Unfortunately, time.tztime returns the timezone when time was imported. Changing the timezone on the machine causes no change in the value reported by time.tztime. I forgot to mention that the program should be platform-agnostic. I have edited this into the question. As a last resort, I could look into finding an API call for each major operating system that does what I'm looking for, but this would be a complicated solution. – Sepia Sep 11 '14 at 12:19
  • There is no cross-platform solution unless you want to try spawning a new process each time to check it. Time to get with the per-platform stuff! Should be just one way for all Windows versions, one for Macs, and not sure about *nix...maybe the process-spawning method would be a reasonable fallback for platforms where no better method is implemented. – John Zwinck Sep 11 '14 at 12:24
0

The problem is that the time returned by datetime.datetime.now() seems to always be in the timezone at which datetime was first imported, rather than the current timezone.

Technically, the time is undefined since tzinfo is None. Or as the python documentation calls it, "naive":

An object of type time or datetime may be naive or aware. A datetime object d is aware if d.tzinfo is not None and d.tzinfo.utcoffset(d) does not return None. If d.tzinfo is None, or if d.tzinfo is not None but d.tzinfo.utcoffset(d) returns None, d is naive.

Naturally, if you want now to reflect a timezone, you need to pass a timezone to it.

The local timezone information can be retrieved from time.localtime, time.timezone, and time.altzone. altzone is the Daylight Saving version of the local time zone, and you can determine whether this is currently being used when the tm_isdst attribute of the local time is 1:

import time
local_timezone = time.altzone if time.localtime().tm_isdst == 1 else time.timezone

The value returned is the UTC offset in seconds. So, to get a current datetime, you can build a timedelta from this and subtract it from utcnow:

import datetime
utc_offset = datetime.timedelta(seconds=local_timezone)
now = datetime.utcnow() - utc_offset

However, for your purposes, it seems all you need to do is monitor the result of local_timezone above.

update: Apparently, on Windows, python still does not reflect timezone changes during execution, even with localtime(). On Unix you can call tzset to ensure it is up to date (although it usually happens automatically), but this function isn't available on Windows. See this question for more.

Community
  • 1
  • 1
nmclean
  • 7,564
  • 2
  • 28
  • 37
  • Thanks for your suggestion. As per your update, local_timezone doesn't change when the time zone is changed. The linked question, however, was very helpful. – Sepia Sep 11 '14 at 14:41