0

Currently, I tried to understand how timezone.localize work.

naive datetime (without timezone information)

Now, I try to create a naive datetime (without timezone information). I assume everything will respect to UTC

>>> d = datetime.datetime.fromtimestamp(1535500800)
>>> d
datetime.datetime(2018, 8, 29, 0, 0)
>>> time.mktime(d.timetuple())
1535500800.0
>>> d.hour
0

(Screenshot from https://www.epochconverter.com/ , by using 1535500800 as timestamp. Red rectangles are for UTC timezone) enter image description here


Everything seems fine. Now, I would like to experiment with timezone.localize


datetime with timezone using timezone.localize

>>> d = datetime.datetime.fromtimestamp(1535500800)
>>> d
datetime.datetime(2018, 8, 29, 0, 0)
>>> kl_timezone = timezone('Asia/Kuala_Lumpur')
>>> d = kl_timezone.localize(d)
>>> d
datetime.datetime(2018, 8, 29, 0, 0, tzinfo=<DstTzInfo 'Asia/Kuala_Lumpur' +08+8:00:00 STD>)
>>> time.mktime(d.timetuple())
1535500800.0
>>> d.hour
0

(Screenshot from https://www.epochconverter.com/ , by using 1535500800 as timestamp. Blue rectangles are for Kuala Lumpur timezone)

enter image description here

The time information highlight in blue rectangle is Kuala Lumpur timezone. Hence, I'm expecting after running d = kl_timezone.localize(d), d.hour will return 8.

This is because

  • Given 1535500800 timestamp, UTC residents treat it as 12:00 am
  • Given 1535500800 timestamp, Kuala Lumpur residents treat it as 8:00 am

But, d.hour is returning 0, even after I use kl_timezone.localize(d).

Isn't d.hour should return 8, because at timestamp 1535500800, Kuala Lumpur is 8:00 am?

Am I having wrong expectation on timezone.localize?

Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875

1 Answers1

3

datetime.fromtimestamp actually converts the to a timestamp in your local timezone. To get the timestamp with respect to UTC, you would use datetime.utcfromtimestamp. From there, you would make it aware, with localize or replace. Then, to determine what the time would be in Kuala Lumpur, you would use astimezone

>>> from datetime import datetime
>>> import pytz
>>> from pytz import timezone
>>> d = datetime.utcfromtimestamp(1535500800)  # naive
>>> d
datetime.datetime(2018, 8, 29, 0, 0)
>>> utc_tz = timezone('UTC')
>>> utc_d = utc_tz.localize(d)  # or utc_d = d.replace(tzinfo=pytz.utc)
>>> utc_d
datetime.datetime(2018, 8, 29, 0, 0, tzinfo=<UTC>)
>>> kl_tz = timezone('Asia/Kuala_Lumpur')
>>> kl_d = utc_d.astimezone(kl_tz)  # convert from UTC to Malaysia
>>> kl_d
datetime.datetime(2018, 8, 29, 8, 0, tzinfo=<DstTzInfo 'Asia/Kuala_Lumpur' +08+8:00:00 STD>)

To get back to POSIX timestamp, you would use timestamp

>>> kl_d.timestamp()
>>> 1535500800.0
Scratch'N'Purr
  • 9,959
  • 2
  • 35
  • 51
  • Ok. I can see using `astimezone` is returning correct hour value. However, I notice the timestamp value changed as well. I do expect timestamp stayed the time - https://gist.github.com/yccheok/673b14af3d8bde75d656a2e2d17dc164 . Isn't the timestamp should stay the same? (Timestamp stays same across different timezone - https://stackoverflow.com/questions/23062515/do-unix-timestamps-change-across-timezones) – Cheok Yan Cheng Aug 29 '18 at 10:33
  • The timestamp value with respect to UTC timezone would not change, but `mktime` that you used in your example converts it with respect to your *local* time. If you want to convert it to seconds w.r.t to UTC, I would suggest using [`timestamp`](https://docs.python.org/3/library/datetime.html#datetime.datetime.timestamp) (e.g. `kl_d.timestamp()`) – Scratch'N'Purr Aug 29 '18 at 11:38
  • Ok. Now I notice that I'm using the wrong way to get timestamp. `kl_d.timestamp()` is the correct way instead of `time.mktime(kl_d.timetuple())` – Cheok Yan Cheng Aug 29 '18 at 14:15