Get tz offset from string - python

I have a date which is in local time:
date: "2013-12-02 22:00:00"
and another value the tz:
timezone_offset: "GMT-0800"
If I : dateutil.parser.parse(date).isoformat() I will get:
"2013-12-02T22:00:00+0000"
I want to implement the date in ISO format with the tz info and get a result of:
"2013-12-02T22:00:00-0800"
Something close to: parse(date,tzinfos=??).isoformat() ? How can I get the tzinfo from the string timezone_offset ?

>>> from dateutil.parser import parse
>>> dt = parse("2013-12-02 22:00:00" + "GMT+0800")
>>> dt.isoformat()
'2013-12-02T22:00:00-08:00'
Note: the sign is reversed.
You could also do it using only stdlib:
>>> from datetime import datetime
>>> dt = datetime.strptime("2013-12-02 22:00:00", "%Y-%m-%d %H:%M:%S")
>>> dt = dt.replace(tzinfo=FixedOffset(-8*60, "GMT+0800"))
>>> dt.isoformat()
'2013-12-02T22:00:00-08:00'
where FixedOffset is taken from datetime docs:
from datetime import tzinfo, timedelta
class FixedOffset(tzinfo):
"""Fixed offset in minutes east from UTC."""
def __init__(self, offset, name):
self.__offset = timedelta(minutes = offset)
self.__name = name
def utcoffset(self, dt):
return self.__offset
def tzname(self, dt):
return self.__name
def dst(self, dt):
return timedelta(0)
Here's the same using pytz module:
>>> from datetime import datetime
>>> import pytz
>>> dt = datetime.strptime("2013-12-02 22:00:00", "%Y-%m-%d %H:%M:%S")
>>> dt = pytz.timezone('Etc/GMT+8').localize(dt)
>>> dt.isoformat()
'2013-12-02T22:00:00-08:00'

Here are two approaches you could use:
>>> import datetime
>>> dtnow = datetime.datetime.now();dtutcnow = datetime.datetime.utcnow()
>>> dtnow
datetime.datetime(2013, 11, 12, 9, 10, 48, 404000)
>>> dtutcnow
datetime.datetime(2013, 11, 12, 15, 10, 48, 404000)
>>> delta = dtnow - dtutcnow
>>> delta
datetime.timedelta(-1, 64800)
>>> hh,mm = divmod((delta.days * 24*60*60 + delta.seconds + 30) // 60, 60)
>>> hh,mm
(-6, 0)
>>> "%s%+02d:%02d" % (dtnow.isoformat(), hh, mm)
'2013-11-12T09:10:48.404000-6:00'
Or this:
>>> import datetime, pytz # 3rd Party
>>> datetime.datetime.now(pytz.timezone('US/Central')).strftime('%Y-%m-%dT%H:%M:%S.%f%z')
'2013-11-12T09:15:20.688000-0600'
>>>
The main advantage of the second method is it makes your time string 'timezone aware'. From the docs:
There are two kinds of date and time objects: “naive” and “aware”.
This distinction refers to whether the object has any notion of time
zone, daylight saving time, or other kind of algorithmic or political
time adjustment. Whether a naive datetime object represents
Coordinated Universal Time (UTC), local time, or time in some other
timezone is purely up to the program, just like it’s up to the program
whether a particular number represents metres, miles, or mass. Naive
datetime objects are easy to understand and to work with, at the cost
of ignoring some aspects of reality.
Hope this helps!

Related

Python - Adding offset to time

I have a time string, say
str = "2018-09-23 14:46:55"
and an offset
offset = "0530"
I want to get str2 with offset added, ie
str2 = "2018-09-23 20:16:55"
Please guide.
You can use the datetime module:
from datetime import datetime, timedelta
x = "2018-09-23 14:46:55"
offset = "0530"
res = datetime.strptime(x, '%Y-%m-%d %H:%M:%S') + \
timedelta(hours=int(offset[:2]), minutes=int(offset[2:]))
print(res)
datetime.datetime(2018, 9, 23, 20, 16, 55)
Use timedelta to add offset to a datetime object.
from datetime import datetime, timedelta
str = "2018-09-23 14:46:55"
str = datetime.strptime(str, "%Y-%m-%d %H:%M:%S")
str2 = str + timedelta(hours=5, minutes=30)
print(str2)

python convert PST time to UTC isoformat

ex:
I have a date string
2018-02-17 16:15:36.519 PST
How do i convert into isoformat in UTC like below
2018-02-18T00:15:36.519Z
I tried this
from dateutil.parser import parse
d1='2018-02-17 16:15:36.519 PST'
print parse(d1)
it prints like this. How do i convert it to UTC with Z at the end.
2018-02-17 16:15:36.519000-08:00
EDIT
using python 2.7.
import dateutil
import pytz
from dateutil.parser import parse
d1='2018-02-17 16:15:36.519 PST'
d2=dateutil.parser.parse(d1)
d2.replace(tzinfo=pytz.utc) - d2.utcoffset()
d3=(d2.replace(tzinfo=pytz.utc) - d2.utcoffset()).isoformat()
print d3
then formatting with Z as suggested
To parse a time string with a timezone abbreviation (PST) into a timezone-aware datetime object:
import dateparser # pip install dateparser
pst_dt = dateparser.parse('2018-02-17 16:15:36.519 PST')
# -> datetime.datetime(2018, 2, 17, 16, 15, 36, 519000, tzinfo=<StaticTzInfo 'PST'>)
To convert the time to UTC timezone:
import datetime as DT
utc_dt = pst_dt.astimezone(DT.timezone.utc)
# -> datetime.datetime(2018, 2, 18, 0, 15, 36, 519000, tzinfo=datetime.timezone.utc)
To print it in the desired format:
print(utc_dt.isoformat()) # -> 2018-02-18T00:15:36.519000+00:00
print(utc_dt.strftime('%Y-%m-%dT%H:%M:%S.%fZ')) # -> 2018-02-18T00:15:36.519000Z
On Python 2.7 there is no DT.timezone.utc:
utc_naive = psd_dt.replace(tzinfo=None) - psd_dt.utcoffset()
print utc_naive.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
# -> 2018-02-18T00:15:36.519000Z
Note: in the general case the timezone abbreviation (such as PST) may be ambiguous. See Parsing date/time string with timezone abbreviated name in Python?
In your specific case, the time string corresponds to unique UTC time:
>>> from collections import defaultdict
>>> import datetime as DT
>>> import pytz
>>> naive_dt, tzabbr = DT.datetime(2018, 2, 17, 16, 15, 36, 519000), 'PST'
>>> utc_times = defaultdict(list)
>>> for zone in pytz.all_timezones:
... dt = pytz.timezone(zone).localize(naive_dt, is_dst=None)
... if dt.tzname() == tzabbr: # same timezone abbreviation
... utc_times[dt.astimezone(pytz.utc)].append(zone)
>>> for utc_dt, timezones in utc_times.items():
... print(f'{utc_dt:%c %Z}', *timezones, sep='\n\t')
Sun Feb 18 00:15:36 2018 UTC
America/Dawson
America/Ensenada
America/Los_Angeles
America/Santa_Isabel
America/Tijuana
America/Vancouver
America/Whitehorse
Canada/Pacific
Canada/Yukon
Mexico/BajaNorte
PST8PDT
US/Pacific
US/Pacific-New
See linux convert time(for different timezones) to UTC
This is a demo code from python2.7, FYI, thanks!
from datetime import datetime
from pytz import utc, timezone
def get_current_pst_time():
print('------------(1) Current time to PST time----------------')
local_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
utc_time = datetime.now(tz=utc).strftime('%Y-%m-%d %H:%M:%S')
pst_time = datetime.now(tz=utc).astimezone(timezone('US/Pacific')).strftime('%Y-%m-%d %H:%M:%S')
is_summary_time = bool(datetime.now(tz=utc).astimezone(timezone('US/Pacific')).dst())
print('is it a summary time? %s.' % is_summary_time)
print('local time is %s.' % local_time)
print('utc time is %s.' % utc_time)
print('pst time is %s.' % pst_time)
def convert_pst_time_to_utc_time(pst_time_str):
print('------------(2) PST time to UTC time----------------')
print('pst time is %s.' % pst_time_str)
temp_time = datetime.strptime(pst_time_str, '%Y-%m-%d %H:%M:%S')
pacific_timezone = timezone('US/Pacific')
pst_time = pacific_timezone.localize(temp_time, is_dst=None)
assert pst_time.tzinfo is not None
assert pst_time.tzinfo.utcoffset(pst_time) is not None
is_summary_time = bool(pst_time.dst())
print('is it a summary time? %s.' % is_summary_time)
utc_time = pst_time.astimezone(timezone('utc'))
print('utc time is %s.' % utc_time.strftime('%Y-%m-%d %H:%M:%S'))
def convert_utc_time_to_pst_time(utc_time_str):
print('------------(3) UTC time to PST time----------------')
print('utc time is %s.' % utc_time_str)
temp_time = datetime.strptime(utc_time_str, '%Y-%m-%d %H:%M:%S')
utc_timezone = timezone('utc')
utc_time = utc_timezone.localize(temp_time, is_dst=None)
assert utc_time.tzinfo is not None
assert utc_time.tzinfo.utcoffset(utc_time) is not None
pst_time = utc_time.astimezone(timezone('US/Pacific'))
is_summary_time = bool(pst_time.dst())
print('is it a summary time? %s.' % is_summary_time)
print('pst time is %s.' % pst_time.strftime('%Y-%m-%d %H:%M:%S'))
if __name__ == '__main__':
get_current_pst_time()
convert_pst_time_to_utc_time('2019-12-03 02:00:00')
convert_pst_time_to_utc_time('2020-07-03 02:00:00')
convert_utc_time_to_pst_time('2019-12-03 10:00:00')
convert_utc_time_to_pst_time('2020-07-03 09:00:00')

getting incorrect utc to local time for timezone given

If I run this url : https://api.sunrise-sunset.org/json?lat=12.98&lng=77.61&date=2017-08-26
I get sunrise time: "12:38:14 AM"
and this is UTC time, if I convert it to given timezone using :
from datetime import datetime
import pytz
from dateutil import tz
def convertUTCtoLocal(date, utcTime, timezone):
""" converts UTC time to given timezone
"""
to_zone = pytz.timezone(timezone)
from_zone = _tz.gettz('UTC')
utc = _datetime.strptime('%s %s' % (date, utcTime), '%Y-%m-%d %H:%M:%S')
utc = utc.replace(tzinfo=from_zone)
local = utc.astimezone(to_zone)
return str(local.time())
but this returns 18:08:16 which is evening time , so what am I doing wrong here.
given timzone is Asia/Kolkata
Example:
>>> from datetime import datetime
>>> from dateutil import tz
>>> from_zone = tz.gettz('UTC')
>>> to_zone = tz.gettz('Asia/Kolkata')
>>> utc = datetime.strptime('2011-01-21 02:37:21', '%Y-%m-%d %H:%M:%S')
>>> utcTime = "12:38:16" ## from json URL we get AM/PM but I remove it.
>>> utc = datetime.strptime('2017-08-26 {}'.format(utcTime), '%Y-%m-%d %H:%M:%S')
>>> utc
datetime.datetime(2017, 8, 26, 12, 38, 16)
>>> utc = utc.replace(tzinfo=from_zone)
>>> central = utc.astimezone(to_zone)
>>> central
datetime.datetime(2017, 8, 26, 18, 8, 16, tzinfo=tzfile('/usr/share/zoneinfo/Asia/Kolkata'))
The problem was that you had "12:38:16 AM" which is actual "00:38:16" so you can't just strip "AM". I changed your function so it will work with "AM" and "PM" hours, just don't strip "AM" and "PM" before using the function:
import pytz
from _datetime import datetime
from dateutil import tz
def convertUTCtoLocal(date, utcTime, timezone):
""" converts UTC time to given timezone
"""
to_zone = pytz.timezone(timezone)
from_zone = tz.gettz('UTC')
## for formating with AM and PM hours in strptime you need to add
## %p at the end, also instead of %H you need to use %I
utc = datetime.strptime('%s %s' % (date, utcTime), '%Y-%m-%d %I:%M:%S %p')
utc = utc.replace(tzinfo=from_zone)
local = utc.astimezone(to_zone)
return str(local.time())
date = '2017-08-26'
utcTime = '12:38:14 AM' ## Don't strip AM or PM
timezone = 'Asia/Kolkata'
x = convertUTCtoLocal(date, utcTime, timezone)
print(x)
Also, you can see working example here.

How to parse Date(928142400000+0200)?

I have JSON response object with string representing date and time:
"event":{
"type":"Type",
"date-time":"\/Date(928142400000+0200)\/",
},
I am not sure:
what format is that
how can I parse it in python app
how can I convert python date into this format
Any suggestions?
928142400000 is the time in milliseconds since the UNIX epoch, +0200 is the timezone.
With the dateutil library or datetime.timezone() objects you can model the timezone offset, the timestamp itself is parsable with datetime.datetime.fromtimestamp(), provided you divide the value by 1000.0:
import datetime
import re
timestamp_parse = re.compile(r'Date\((\d+)([+-]\d{4})\)')
timestamp, offset = timestamp_parse.search(datetime_value).groups()
tzoffset = datetime.timedelta(hours=int(offset[1:3]), minutes=int(offset[3:]))
if offset[0] == '-':
tzoffset *= -1
tzoffset = datetime.timezone(tzoffset)
dt = datetime.datetime.fromtimestamp(int(timestamp) / 1000.0).replace(tzinfo=tzoffset)
The dateutil.tz.tzoffset() object version is similar:
import datetime
import re
import dateutil.tz
timestamp_parse = re.compile(r'Date\((\d+)([+-]\d{4})\)')
timestamp, offset = timestamp_parse.search(datetime_value).groups()
tzoffset = int(offset[1:3]) * 3600 + int(offset[3:]) * 60
if offset[0] == '-':
tzoffset *= -1
tzoffset = dateutil.tz.tzoffset(None, tzoffset)
dt = datetime.datetime.fromtimestamp(int(timestamp) / 1000.0).replace(tzinfo=tzoffset)
Demo:
>>> import datetime
>>> import re
>>> datetime_value = "/Date(928142400000+0200)/"
>>> timestamp_parse = re.compile(r'Date\((\d+)([+-]\d{4})\)')
>>> timestamp, offset = timestamp_parse.search(datetime_value).groups()
>>> tzoffset = datetime.timedelta(hours=int(offset[1:3]), minutes=int(offset[3:]))
>>> if offset[0] == '-':
... tzoffset *= -1
...
>>> tzoffset = datetime.timezone(tzoffset)
>>> datetime.datetime.fromtimestamp(int(timestamp) / 1000.0).replace(tzinfo=tzoffset)
datetime.datetime(1999, 5, 31, 10, 20, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))

Convert GMT based time to UTC python

I get a date like 2014/08/19 03:38:46 GMT-4 from the database.
How do I convert this into UTC formatted date in Python?
PS: I use Python 2.6.6
Having a non-naive datetime object, you only should invoke astimezone method with desired timezone
>>> import pytz
>>> from dateutil import parser
# dateutil.parser get a datetime object from string, we ensure that is a non-naive datetime
>>> parser.parse('2014/08/19 03:38:46 GMT-4')
datetime.datetime(2014, 8, 19, 3, 38, 46, tzinfo=tzoffset(None, 14400))
>>> dt = parser.parse('2014/08/19 03:38:46 GMT-4')
>>> dt.astimezone (pytz.utc)
datetime.datetime(2014, 8, 18, 23, 38, 46, tzinfo=<UTC>)
You are right in your comment, utc time should go behind, so while I think another solution, what about this
>>> dt = parser.parse('2014/08/19 03:38:46 GMT-4')
>>> dt.replace(tzinfo=pytz.utc) + dt.tzinfo._offset
datetime.datetime(2014, 8, 19, 7, 38, 46, tzinfo=<UTC>)
GMT-4 is ambiguous: is it time in America/New_Your (-0400 utc offset) or in Europe/Moscow (+0400)?
$ TZ=GMT-4 date +%Z%z
GMT+0400
$ TZ=UTC-4 date +%Z%z
UTC+0400
$ TZ=America/New_York date +%Z%z
EDT-0400
$ TZ=Europe/Moscow date +%Z%z
MSK+0400
Your comment suggests that you need the sign of the utc offset reversed.
Python 2.6 has no fixed-offset timezones in stdlib. You could use the example implementation from the datetime docs:
from datetime import tzinfo, timedelta, datetime
ZERO = timedelta(0)
class FixedOffset(tzinfo):
"""Fixed UTC offset: `local = utc + offset`."""
def __init__(self, offset, name):
self.__offset = timedelta(hours=offset)
self.__name = name
def utcoffset(self, dt):
return self.__offset
def tzname(self, dt):
return self.__name
def dst(self, dt):
return ZERO
utc = FixedOffset(0, "UTC")
Then to parse the time string, you could use strptime():
dt = datetime.strptime("2014/08/19 03:38:46 GMT-4", "%Y/%m/%d %H:%M:%S GMT-4")
aware = dt.replace(tzinfo=FixedOffset(-4, "GMT-4"))
print(aware) # -> 2014-08-19 03:38:46-04:00
print(aware.astimezone(utc)) # -> 2014-08-19 07:38:46+00:00

Categories