Why is PST (America/Los_Angeles) time conversion to UTC, 1 hour behind?

Viewed 1492

I have sensor data with a timestamp known to be in PST (Pacific Standard Time). Let's say that the timestamp is: 2020-10-21 10:00:00. I want to convert that timestamp to UTC. UTC-to-PST conversion is UTC-8. So the expected timestamp in UTC is 8 hours forward: 2020-10-21 18:00:00.

I tried to do the conversion:

>>> import pytz
>>> from datetime import datetime
>>> ts = datetime(2020,10,21,10,0,0)
>>> ts_local = pytz.timezone('America/Los_Angeles').localize(ts, is_dst=False)
>>> ts_local.strftime('%Y-%m-%d %H:%M:%S %Z%z')
'2020-10-21 10:00:00 PDT-0700'
>>> ts_local.astimezone(pytz.utc).strftime('%Y-%m-%d %H:%M:%S %Z%z')
'2020-10-21 17:00:00 UTC+0000'

But you can see that the conversion is 1 hour behind what is expected. This seems to make sense since ts_local appears to be in PDT. However, because I'd set is_dst=False, I expected ts_local to be in PST.

  • I've tried is_dst=True and is_dst=None (even though those flag values don't make sense since the timestamp is in Standard Time) but the resulting ts_local remains in PDT.
  • I've tried this conversion in Python 3.7.4 and Python 2.7.17 and gotten the same result.
  • I've also tried this conversion using the 'US/Pacific' pytz timezone but same issue.

I've read some other SO answers for how to do the conversion and what I've done is what has been suggested.

2 Answers

Based on the information given in the question, to me, setting a time zone (that has DST changes!) is the wrong approach if you simply have a fixed offset from UTC by x hours in your data. This assumes that your sensor's clock doesn't have DST changes coded into its memory.

My suggestion would therefore be to use a fixed offset tzinfo:

from datetime import datetime, timedelta, timezone

dt = datetime.fromisoformat("2020-10-21 10:00:00")

# we know dt is UTC-8, so you can set the fixed offset:
dt_tzset = dt.replace(tzinfo=timezone(timedelta(hours=-8)))

# now you can convert to UTC easily:
dt_utc = dt_tzset.astimezone(timezone.utc)
print(dt_utc)
# 2020-10-21 18:00:00+00:00

From the pytz docs:

The is_dst parameter is ignored for most timestamps. It is only used during DST transition ambiguous periods to resolve that ambiguity.

There is no ambiguity about 2020-10-21 18:00:00 in America/Los_Angeles. It is unambiguously UTC-7 (PDT).

An example of an ambiguous timestamp in America/Los_Angeles is 2020-11-01 01:00:00 because there are two of them due to the DST fall-back transition. The first is 01:00 PDT, the second is 01:00 PST.

Related