To get the LMT info and all the abbrevations tz in pytz - python

import pytz,datetime
tz1 = pytz.timezone('Asia/Shanghai')
tz1
<DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>
>>> str(tz1)
'Asia/Shanghai'
1.how can i get the string of LMT+8:06:00 from the output of tz1?
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
dt1 = tz1.localize(datetime.datetime(2002, 10, 27, 6, 0, 0))
print(dt1.strftime(fmt))
2002-10-27 06:00:00 CST+0800
2.how can i get all the abbrevations of timezone which is composed of 3 upper character such as CST in 2002-10-27 06:00:00 CST+0800?
list(pytz.country_names) get all the abbrevations of country,list(pytz.all_timezones) get all the timezones.
list(pytz.all_timezones)
list(pytz.country_names)

1.how can i get the string of LMT+8:06:00 from the output of tz1?
A single pytz.timezone('Asia/Shanghai') object may correspond to several different tzinfo objects (different tzname(), dst(), and/or utcoffset()). The default representation of tz1 shows one of such objects. You need a concrete date to get the correct tzinfo:
>>> from datetime import datetime
>>> import pytz
>>> tz = pytz.timezone('Asia/Shanghai')
>>> tz
<DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>
>>> fmt = '%Y-%m-%d %H:%M:%S %Z%z'
>>> tz.localize(datetime(2002, 10, 27, 6, 0, 0), is_dst=None).strftime(fmt)
'2002-10-27 06:00:00 CST+0800'
>>> tz.localize(datetime(1902, 10, 27, 6, 0, 0), is_dst=None).strftime(fmt)
'1902-10-27 06:00:00 LMT+0806'
i.e., Asia/Shanghai had +0806 utc offset in 1902.
2.how can i get all the abbrevations of timezone which is composed of 3 upper character such as CST in 2002-10-27 06:00:00 CST+0800?
If you have an aware datetime object then just call its .tzname() method or pass the date to the timezone explicitly:
>>> tz.tzname(datetime(2002, 10, 27, 6, 0, 0), is_dst=None)
'CST'
There is no public API to enumerate all possible tzname() values for a given zoneinfo timezone. You could use DstTzInfo._transition_info attribute, to get the value (without values from a far future (for obvious reasons)):
>>> datetime.now(tz).tzname()
'CST'
>>> {tzname for _, _, tzname in getattr(tz, '_transition_info', [])}
set(['CDT', 'CST', 'LMT'])

Related

Inconsistent datetime parse timezone in Python

When I run the following in Python 3.X
import datetime
DATE_TS_FORMAT = '%Y-%m-%d %H:%M:%S.%f %Z'
date_ts = datetime.datetime(2019, 1, 2, 3, 4, 5, tzinfo=datetime.timezone.utc)
date_ts = date_ts.strftime(DATE_TS_FORMAT)
print(date_ts)
date_ts = datetime.datetime.strptime(date_ts, DATE_TS_FORMAT)
date_ts = date_ts.strftime(DATE_TS_FORMAT)
print(date_ts)
I get
2019-01-02 03:04:05.000000 UTC
2019-01-02 03:04:05.000000
Why did the timezone information disappear and how can I fix this issue?
Inconsistent indeed... The point is that %Z makes strptime accept certain strings (GMT, UTC and any value in time.tzname - docs), but doesn't actually make anything out of it. Ex:
from datetime import datetime
s = "2019-01-02 03:04:05.000000 UTC"
dt = datetime.strptime(s, '%Y-%m-%d %H:%M:%S.%f %Z')
print(repr(dt))
# datetime.datetime(2019, 1, 2, 3, 4, 5)
The resulting datetime object is naive; no sign of UTC anymore.
To account for this behavior, you could post-process the datetime object, something like
if "UTC" in s:
dt = dt.replace(tzinfo=timezone.utc)
(which I think is a bit painful...) or replace "UTC" with something that %z parses to UTC1,
dt = datetime.strptime(s.replace("UTC", "+00:00"), '%Y-%m-%d %H:%M:%S.%f %z')
print(repr(dt))
# datetime.datetime(2019, 1, 2, 3, 4, 5, tzinfo=datetime.timezone.utc)
(which I think is a bit ugly...) or use a suitable parser, e.g.
from dateutil.parser import parse
dt = parse(s)
print(repr(dt))
# datetime.datetime(2019, 1, 2, 3, 4, 5, tzinfo=tzutc())
print(dt.strftime('%Y-%m-%d %H:%M:%S.%f %Z'))
# 2019-01-02 03:04:05.000000 UTC
(which will be a bit slower if performance is an issue...).
1 IMO, this is inconsistent as well; "+00:00" could also be the UTC offset of some time zone that happens to have a UTC offset of 0 hours at that time...

How to render timestamp according to the timezone in Python

I have two datetime objects, they represent the same datetime value in different timezones. I would like to convert them to POSIX timestamp. However appearently calling datetime.timestamp() returns a value regardless of the timezone.
from datetime import datetime
import pytz
dt = datetime(2020, 7, 26, 6, 0)
utc_dt = pytz.utc.localize(dt) # datetime.datetime(2020, 7, 26, 6, 0, tzinfo=<UTC>)
bp = pytz.timezone("Europe/Budapest")
bp_dt = utc_dt.astimezone(bp) # datetime.datetime(2020, 7, 26, 8, 0, tzinfo=<DstTzInfo 'Europe/Budapest' CEST+2:00:00 DST>)
utc_dt.timestamp() # 1595743200.0
bp_dt.timestamp() # 1595743200.0
The documentation of datetime.timestamp() says the following:
For aware datetime instances, the return value is computed as:
(dt - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds()
Running utc_dt - bp_dt returns datetime.timedelta(0). So it seems it calculates with the UTC value of the datetime objects.
I use Python in a web stack. I want the backend to deal with the timezone handling and the client to recieve the precalculated datetime values in the user's timezone in the API responses.
What is the Pythonic way to get timezone aware timestamps?
In short, I would not recommend doing this because you can create a total mess, see my comment.
Technically, you could do it by simply replacing the tzinfo property of the datetime object with UTC. Note that I'm using dateutil.tz here so I can set the initial timezone directly (no localize()).
from datetime import datetime, timezone
from dateutil import tz
dt = datetime(2020, 7, 26, 6, 0, tzinfo=tz.gettz("Europe/Budapest"))
# dt.utcoffset()
# >>> datetime.timedelta(seconds=7200)
# POSIX timestamp that references to 1970-01-01 UTC:
ts_posix = dt.timestamp()
# timestamp that includes the UTC offset:
ts = dt.replace(tzinfo=timezone.utc).timestamp()
# ts-ts_posix
# >>> 7200.0

convert python datetime with timezone to string

I have date time tuples in the format of datetime.datetime(2010, 7, 1, 0, 0, tzinfo=<UTC>)
How can I convert that into a date time string such as 2008-11-10 17:53:59
I am really just getting held up on the tzinfo part.
strftime("%Y-%m-%d %H:%M:%S") works fine without the tzinfo part
The way you seem to be doing it, would work fine for both timezone aware and naive datetime objects. If you want to also add the timezone to your string, you can simply add add it with %z or %Z, or using the isoformat method:
>>> from datetime import timedelta, datetime, tzinfo
>>> class UTC(tzinfo):
... def utcoffset(self, dt):
... return timedelta(0)
...
... def dst(self, dt):
... return timedelta(0)
...
... def tzname(self,dt):
... return "UTC"
>>> source = datetime(2010, 7, 1, 0, 0, tzinfo=UTC())
>>> repr(source)
datetime.datetime(2010, 7, 1, 0, 0, tzinfo=<__main__.UTC object at 0x1054107d0>)
# %Z outputs the tzname
>>> source.strftime("%Y-%m-%d %H:%M:%S %Z")
'2010-07-01 00:00:00 UTC'
# %z outputs the UTC offset in the form +HHMM or -HHMM
>>> source.strftime("%Y-%m-%d %H:%M:%S %z")
'2010-07-01 00:00:00 +0000'
# isoformat outputs the offset as +HH:MM or -HH:MM
>>> source.isoformat()
'2010-07-01T00:00:00+00:00'

What is wrong with my conversion from local time to UTC

According to timeanddate.com, currently Chicago is 5 hours behind UTC. However, my Python app thinks differently:
import datetime
import pytz
local_tz = pytz.timezone('America/Chicago')
local_time = datetime.datetime(2015, 8, 6, 0, 0, tzinfo=local_tz)
utc_time = local_time.astimezone(pytz.utc)
print(local_time)
print(utc_time)
2015-08-06 00:00:00-05:51
2015-08-06 05:51:00+00:00
I am getting the same results with both 'America/Chicago' and 'US/Central'. Why is the offset -05:51 instead of -05:00?
pytz timezone objects need to be initialized with a specific time before they're used, and creating a datetime with a tzinfo= parameter does not allow for that. You have to use the localize method of the pytz object to add the timezone to the datetime.
>>> local_tz = pytz.timezone('America/Chicago')
>>> local_time = local_tz.localize(datetime.datetime(2015, 8, 6, 0, 0))
>>> print local_time
2015-08-06 00:00:00-05:00
>>> utc_time = local_time.astimezone(pytz.utc)
>>> print utc_time
2015-08-06 05:00:00+00:00

convert date time from EU time zone to PST

i have a list of datetimes in EU time zone:
[u'2014-11-01T09:00:00+01:00', u'2014-11-02T00:00:00+01:00', u'2014-11-03T00:00:00+01:00', u'2014-11-04T00:00:00+01:00', u'2014-11-05T00:00:00+01:00', u'2014-11-06T00:00:00+01:00', u'2014-11-07T00:00:00+01:00', u'2014-11-08T00:00:00+01:00', u'2014-11-09T00:00:00+01:00', u'2014-11-10T00:00:00+01:00', u'2014-11-11T00:00:00+01:00', u'2014-11-12T00:00:00+01:00', u'2014-11-13T00:00:00+01:00', u'2014-11-14T00:00:00+01:00', u'2014-11-15T00:00:00+01:00', u'2014-11-16T00:00:00+01:00', u'2014-11-17T00:00:00+01:00', u'2014-11-18T00:00:00+01:00', u'2014-11-19T00:00:00+01:00', u'2014-11-20T00:00:00+01:00', u'2014-11-21T00:00:00+01:00', u'2014-11-22T00:00:00+01:00', u'2014-11-23T00:00:00+01:00', u'2014-11-24T00:00:00+01:00', u'2014-11-25T00:00:00+01:00', u'2014-11-26T00:00:00+01:00', u'2014-11-27T00:00:00+01:00', u'2014-11-28T00:00:00+01:00', u'2014-11-29T00:00:00+01:00', u'2014-11-30T00:00:00+01:00', u'2014-12-01T00:00:00+01:00']
How do i convert each of them to PST time zone?
This should do it:
from pytz import timezone
import pytz
from dateutil.parser import parse
l = [u'2014-11-01T09:00:00+01:00', u'2014-11-02T00:00:00+01:00', u'2014-11-03T00:00:00+01:00', u'2014-11-04T00:00:00+01:00', u'2014-11-05T00:00:00+01:00', u'2014-11-06T00:00:00+01:00', u'2014-11-07T00:00:00+01:00', u'2014-11-08T00:00:00+01:00', u'2014-11-09T00:00:00+01:00', u'2014-11-10T00:00:00+01:00', u'2014-11-11T00:00:00+01:00', u'2014-11-12T00:00:00+01:00', u'2014-11-13T00:00:00+01:00', u'2014-11-14T00:00:00+01:00', u'2014-11-15T00:00:00+01:00', u'2014-11-16T00:00:00+01:00', u'2014-11-17T00:00:00+01:00', u'2014-11-18T00:00:00+01:00', u'2014-11-19T00:00:00+01:00', u'2014-11-20T00:00:00+01:00', u'2014-11-21T00:00:00+01:00', u'2014-11-22T00:00:00+01:00', u'2014-11-23T00:00:00+01:00', u'2014-11-24T00:00:00+01:00', u'2014-11-25T00:00:00+01:00', u'2014-11-26T00:00:00+01:00', u'2014-11-27T00:00:00+01:00', u'2014-11-28T00:00:00+01:00', u'2014-11-29T00:00:00+01:00', u'2014-11-30T00:00:00+01:00', u'2014-12-01T00:00:00+01:00']
amsterdam = timezone('Europe/Amsterdam')
pst = timezone('US/Pacific')
[parse(d).replace(tzinfo=amsterdam).astimezone(pst) for d in l]
There are two independent tasks:
parse rfc 3339 date/time format into an aware datetime object
>>> from dateutil.parser import parse
>>> aware_dt = parse('2014-11-01T09:00:00+01:00')
>>> aware_dt
datetime.datetime(2014, 11, 1, 9, 0, tzinfo=tzoffset(None, 3600))
convert it to America/Los_Angeles timezone
>>> import pytz
>>> tz = pytz.timezone('America/Los_Angeles')
>>> tz.normalize(aware_dt.astimezone(tz))
datetime.datetime(2014, 11, 1, 1, 0, tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>)

Categories

Resources