How do I find difference between times in different timezones in Python? - python

I am trying to calculate difference(in seconds) between two date/times formatted as following:
2010-05-11 17:07:33 UTC
2010-05-11 17:07:33 EDT
time1 = '2010-05-11 17:07:33 UTC'
time2 = '2010-05-11 17:07:33 EDT'
delta = time.mktime(time.strptime(time1,"%Y-%m-%d %H:%M:%S %Z"))-\
time.mktime(time.strptime(time2, "%Y-%m-%d %H:%M:%S %Z"))
The problem I got is EDT is not recognized, the specific error is
ValueError: time data '2010-05-11 17:07:33 EDT' does not match format '%Y-%m-%d %H:%M:%S %Z'

Check out the pytz world timezone definitions library.
This library allows accurate and cross platform timezone calculations using Python 2.3 or higher. It also solves the issue of ambiguous times at the end of daylight savings, which you can read more about in the Python Library Reference (datetime.tzinfo).
It takes advantage of the tz database, which should include EDT, and allow you to perform the calculations you need to (and probably more reliably & accurately than your current implementation).

In addition to pytz, check out python-dateutil. The relativedelta functionality is outstanding.
Here's a sample of using them together:
from datetime import datetime
from dateutil.relativedelta import *
import pytz
if __name__ == '__main__':
date_one = datetime.now(pytz.timezone('US/Eastern'))
date_two = datetime.now(pytz.timezone('US/Mountain'))
rdelta = relativedelta(date_one, date_two)
print(rdelta)

From docs for strptime
Support for the %Z directive is based
on the values contained in tzname and
whether daylight is true. Because of
this, it is platform-specific except
for recognizing UTC and GMT which are
always known (and are considered to be
non-daylight savings timezones).

Related

Python what is the correct timefomat for: 2018-11-13T20:20:39+00:00

I need to get a now() timestamp like this following: 2018-11-13T20:20:39+00:00 What is the correct format string for this?
To get an isoformat() string with time zone offset (the +00:00 at the end of the string) you need to supply a tzinfo object when constructing the datetime. the easiest way to do this is with the pytz library - pytz.timezone("UTC") returns the tzinfo for UTC.
There's another issue though, which is that technically that string doesn't quite match default isoformat() output because it has no microseconds. So a full example for the output requested would be:
import datetime
import pytz
datetime.datetime.now(tz=pytz.timezone("UTC")).replace(microsecond=0).isoformat()
This appears to be the isoformat.
You could use
import datetime as dt
# Get current time in utc
# Because the datetime object is timezone aware the +00:00 will be printed
current_time = dt.datetime.now(dt.timezone.utc)
# timespec will round the solution upto seconds
iso_string = current_time.isoformat(timespec="seconds")
print(iso_string)
will print 2019-11-19T19:51:46+00:00.

Timestamp to non UTC Datetime object is substracting hours twice

I have the following timestamp 1550588656 which translates to 2019-02-19 15:04:16+00:00 in UTC time convention.
I want to convert it to my country's time convention (UTC or GMT -3 in this time of the year) so it should translate to 2019-02-19 12:04:16+00:00
I have read on other SO questions that first I have to convert the timestamp to an UTC aware Datetime object and then localize it, I'm doing it like this
# string format time
naive_datetime = datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
# string parse time
naive_datetime = datetime.strptime(naive_datetime, "%Y-%m-%d %H:%M:%S")
# make naive Datetime object UTC aware
utc_datetime = naive_datetime.replace(tzinfo=pytz.UTC)
So now it's not a naive Datetime object, from here I should be able to localize it to my country's timezone. In Python that is pytz.timezone('America/Santiago')
So it should go something like this
cltime = pytz.timezone('America/Santiago')
local_datetime = utc_datetime.astimezone(cltime)
But I'm getting 2019-02-19 09:04:16-03:00 (UTC or GTM -6 ) as a result and I don't know why.
Can someone explain? My intuition tells me it's probably a simple thing I'm not looking at, but I've spent some minutes in it and I haven't been able to tell yet.
If you look at the documentation for fromtimestamp:
Return the local date and time corresponding to the POSIX timestamp
So the problem is that it is already doing a conversion from UTC to the local time, and you're doing it a second time.
First of all you have epoc time (UTC timestamp). You need to convert it into datetime object (native) which is followed by converting native time to aware time and than finally convert it to your local time.
Convert your timestamp to native datetime object
native_datetime = datetime.fromtimestamp(1550588656)
convert native datetime object to aware time (add timezone info, will add timezone info to native timezone UTC for current)
import pytz
utc_time = native_datetime.replace(tzinfo=pytz.timezone("UTC"))
localising aware datetime to your local datetime
local_time = utc_time.astimezone(pytz.timezone("America/Santiago"))
You can replace "America/Santiago" with your local time zone
I think this would help you to solve your problem. Thanks!

UTCNow offsetting in Python

How would I exactly go about offsetting the timestamp returned by datetime.utcnow() by any amount of time such as a day?
For example:
now = datetime.utcnow().isoformat() + 'Z'
I need the above offset by a day. Having a minor issue when my script crosses into the daylight savings time conversion but I dont need to see past it however since it loads today also it dies because the python script errors doing work on the date today now.
To simply add a certain delta time onto UTC add a timedelta:
from datetime import datetime, timedelta
now = (datetime.utcnow() + timedelta(days=3)).isoformat() + 'Z'
print(now)
Output:
2018-11-06T16:55:06.535804Z
More info on python with timezones can be found at Python UTC datetime object's ISO format doesn't include Z (Zulu or Zero offset)
With 3.7 datetime.strptime and datetime.strftime even recognize 01:30 as %z - up to 3.6 the colon would make it crash :)

Python timezone '%z' directive for datetime.strptime() not available

Using '%z' pattern of datetime.strptime()
I have a string text that represent a date and I'm perfectly able to parse it and transform it into a clean datetime object:
date = "[24/Aug/2014:17:57:26"
dt = datetime.strptime(date, "[%d/%b/%Y:%H:%M:%S")
Except that I can't catch the entire date string with the timezone using the %z pattern as specified here
date_tz = 24/Aug/2014:17:57:26 +0200
dt = datetime.strptime(date, "[%d/%b/%Y:%H:%M:%S %z]")
>>> ValueError: 'z' is a bad directive in format '[%d/%b/%Y:%H:%M:%S %z]'
Because as this bug report says
strftime() is implemented per platform
I precise that there is no such a problem with the naive tzinfo directive '%Z'
Workaround : Casting tzinfo string into tzinfo object
I can perfectly make the following workaround by transforming the GST time format string into a tzinfo object [as suggested here][4] using dateutil module
and then insert tzinfo into datetime object
Question: Make %z available for my plateform?
But as I will obviously need %z pattern for further project I would like to find a solution to avoid this workaround and using external module for this simple task.
Can you suggest me some reading on it? I supposed that newer version of python (I'm on 2.7) can handle it but I'd rather not changing my version now for this little but crucial detail.
[EDIT]
Well, seeing comments make me reformulated my question how to parse Email time zone indicator using strptime() without being aware of locale time?
strptime() is implemented in pure Python. Unlike strftime(); it [which directives are supported] doesn't depend on platform. %z is supported since Python 3.2:
>>> from datetime import datetime
>>> datetime.strptime('24/Aug/2014:17:57:26 +0200', '%d/%b/%Y:%H:%M:%S %z')
datetime.datetime(2014, 8, 24, 17, 57, 26, tzinfo=datetime.timezone(datetime.timedelta(0, 7200)))
how to parse Email time zone indicator using strptime() without being aware of locale time?
There is no concrete timezone implementation in Python 2.7. You could easily implement the UTC offset parsing, see How to parse dates with -0400 timezone string in python?
In continue to #j-f-sebastians 's answer, here is a fix for python 2.7
Instead of using:
datetime.strptime(t,'%Y-%m-%dT%H:%M %z')
use the timedelta to account for the timezone, like this:
from datetime import datetime,timedelta
def dt_parse(t):
ret = datetime.strptime(t[0:16],'%Y-%m-%dT%H:%M')
if t[17]=='+':
ret-=timedelta(hours=int(t[18:20]),minutes=int(t[20:]))
elif t[17]=='-':
ret+=timedelta(hours=int(t[18:20]),minutes=int(t[20:]))
return ret
print(dt_parse('2017-01-12T14:12 -0530'))
The Answer of Uri is great, saved my life, but when you have
USE_TZ = True you need to be careful with the time, for avoid the warning "RuntimeWarning: DateTimeField" is better if you add the utc to the return.
import pytz
from datetime import datetime, timedelta
def dt_parse(t):
ret = datetime.strptime(t[0:19],'%Y-%m-%dT%H:%M:%S')
if t[23]=='+':
ret-=timedelta(hours=int(t[24:26]), minutes=int(t[27:]))
elif t[23]=='-':
ret+=timedelta(hours=int(t[24:26]), minutes=int(t[27:]))
return ret.replace(tzinfo=pytz.UTC)

How to convert UTC-4 to US/Eastern in python?

I read time stamps from text file. These time stamps are in UTC-4. I need to convert them to US/Eastern.
import datetime
datetime_utc4 = datetime.datetime.strptime("12/31/2012 16:15", "%m/%d/%Y %H:%M")
How do I convert it to US/Eastern? One-line answer would be best.
Note: my original question stated EST to EDT. But it does not change the essence of the question, which is how to go from one time zone to another. Upon some reading (following comments) I gather that python (pytz in particular) does not treat EST and EDT as separate time zones, rather as two flavors of US/Eastern. But this is an implementation detail. It is common to refer to EST and EDT as two different time zones, see e.g. here.
Based on your update and comments, I now understand that you have data that is fixed at UTC-4 and you want to correct this so that it is valid in US Eastern Time, including both EST/EDT where appropriate. Here is how you do that with pytz.
from datetime import datetime
import pytz
dt = datetime.strptime("12/31/2012 16:15", "%m/%d/%Y %H:%M") \
.replace(tzinfo = pytz.FixedOffset(-240)) \
.astimezone(pytz.timezone('America/New_York'))
Note that I used the America/New_York time zone id. This is the most correct form of identifier. You could instead use US/Eastern and it would work just fine, but be aware that this is an alias, and it is just there for backwards compatibility.

Categories

Resources