ninesalt
ninesalt

Reputation: 4354

fromtimestamp returns different results

I have the following code:

import datetime

dt = 1546955400
print(datetime.datetime.fromtimestamp(dt))

When I run this code on my local machine, I get the correct (expected) time which is

2019-01-08 15:50:00.

However I tried running this exact same code on a VM and the result was 2019-01-08 13:50:00 (two hours earlier). Why is this is happening and how can I fix it so that I always get the first one regardless of where the code is running?

Upvotes: 1

Views: 1537

Answers (2)

ykoavlil
ykoavlil

Reputation: 186

You can use ZoneInfo, for example:

import re
from zoneinfo import ZoneInfo
from datetime import datetime

utc = datetime.now(ZoneInfo('UTC'))
print('Current time according to UTC:', utc)

time_stamp = utc.timestamp()
print('Current timestamp on UTC:', time_stamp)

milliseconds = re.sub(pattern=r'\.\d+', repl='000', string=str(time_stamp))
print('Current timestamp on UTC (milliseconds):', milliseconds)

from_timestamp = datetime.fromtimestamp(time_stamp, ZoneInfo('UTC'))
print('Reverse conversion timestamp to UTC time:', from_timestamp)

Result:

Current time according to UTC: 2024-09-22 16:54:40.678242+00:00

Current timestamp on UTC: 1727024080.678242

Current timestamp on UTC (milliseconds): 1727024080000

Reverse conversion timestamp to UTC time: 2024-09-22 16:54:40.678242+00:00

Upvotes: 0

Martijn Pieters
Martijn Pieters

Reputation: 1121864

datetime.datetime.fromtimestamp() returns local time. From the documentation:

Return the local date and time corresponding to the POSIX timestamp, such as is returned by time.time(). If optional argument tz is None or not specified, the timestamp is converted to the platform’s local date and time, and the returned datetime object is naive.

The timestamp value is an offset in seconds from the UNIX epoch value, midnight 1 January 1970, in the UTC timezone. The local time is a system-wide configured offset from UTC, the local timezone.

If your VM is producing unexpected results, you need to configure the timezone of the OS.

Alternatively, ignore timezones and only deal with time in the UTC timezone. For timestamps, that means using the datetime.datetime.utcfromtimestamp() function.

Your specific timestamp is 13:50 UTC:

>>> dt = 1546955400
>>> from datetime import datetime
>>> datetime.utcfromtimestamp(dt)
datetime.datetime(2019, 1, 8, 13, 50)
>>> print(_)
2019-01-08 13:50:00

so your VM is either set to the UTC or the GMT timezone (the latter is currently at UTC+0, until the switch to the UK daylight saving timezone BST). Your local system is in a UTC+2 timezone, given your stated location from your profile that'd be EEE, Easter European Time.

Another option is to create a timezone-aware timestamp by passing in a tz argument. If you have a specific UTC offset, just create a datetime.timezone() instance for that offset:

utcplus2 = datetime.timezone(datetime.timedelta(hours=2))
datetime.datetime.fromtimestamp(dt, utcplus2)

However, it is usually better to store and operate on UTC datetime instances everywhere, and only convert to specific timezones when displaying information to users. This simplifies datetime handling as it lets you avoid a number of timezone corner cases and problems, such as mixing datetime information from different timezones and timezones with a summer and winter time distinction.

Upvotes: 3

Related Questions