converting from local to utc timezone - python

I'm attempting to craft a function that takes a time object and converts it to UTC time. The code below appears to be off by one hour. When i run noon through the converter, i get back 18:00:00. But when i run the same data through online converters, i get 17:00:00.
What am i doing wrong here? Any help would be greatly appreciated.
import pytz, datetime
def convert_to_utc(time, tz):
now_dt = datetime.datetime.utcnow()
#get a date object
date_dt = now_dt.date()
#combine the current date object with our given time object
dt = datetime.datetime.combine(date_dt, time)
#get an timezone object for the source timezone
src_tz = pytz.timezone(str(tz))
#stamp the source datetime object with the src timezone
src_dt = dt.replace(tzinfo=src_tz)
#get the offset from utc to given timezone
offset = str(int(src_dt.strftime("%z"))).rstrip('0')
#convert the source datetime object to
utc_dt = src_dt.astimezone(pytz.utc)
#return the converted time and the offset in integer format
return (utc_dt.time(), int(offset))
time = datetime.datetime.strptime('12:00:00', "%H:%M:%S").time()
(TIME, offset) = convert_to_utc(time, 'America/Chicago')
print TIME.strftime("%H:%M:%S")
**EDIT**
Here's the updated(and functional) code in case anyone else needs help converting to/from UTC.
Thanks everyone for your help!
import pytz, datetime
def convert_to_utc(time, tz): #this returns the offset in int form as well
now_dt = datetime.datetime.utcnow()
#get a date object
date_dt = now_dt.date()
#combine the current date object with our given time object
dt = datetime.datetime.combine(date_dt, time)
#get an timezone object for the source timezone
src_tz = pytz.timezone(str(tz))
#stamp the source datetime object with the src timezone
src_dt = src_tz.localize(dt)
#get the offset from utc to given timezone
offset = str(int(src_dt.strftime("%z"))).rstrip('0')
#convert the source datetime object to
utc_dt = src_dt.astimezone(pytz.utc)
#return the converted time and the offset in integer format
return (utc_dt.time(), int(offset))
def convert_from_utc(time, tz):
now_dt = datetime.datetime.now()
date = now_dt.date()
dt = datetime.datetime.combine(date, time)
dest = pytz.timezone(str(tz))
dt = dt.replace(tzinfo=pytz.utc)
dest_dt = dt.astimezone(dest)
return dest_dt.time()
time = datetime.datetime.strptime('12:00:00', "%H:%M:%S").time()
(TIME, offset) = convert_to_utc(time, 'America/Chicago')
print TIME.strftime("%H:%M:%S")
utc_time = datetime.datetime.strptime('17:00:00', "%H:%M:%S").time()
TIME = convert_from_utc(utc_time, 'America/Chicago')
print TIME.strftime("%H:%M:%S")

Change
src_dt = dt.replace(tzinfo=src_tz)
to
src_dt = src_tz.localize(dt)
Using localize adjusts for Daylight Savings Time, while replace does not.
See the section entitled "Localized times and date arithmetic" in the docs.

To convert time in given timezone to UTC time:
from datetime import datetime
import pytz
def convert_to_utc(time, tzname, date=None, is_dst=None):
tz = pytz.timezone(tzname)
if date is None: # use date from current local time in tz
date = datetime.now(tz).date()
dt = tz.localize(datetime.combine(date, time), is_dst=is_dst)
return dt.astimezone(pytz.utc).time(), dt.utcoffset().total_seconds()
if is_dst is None it raises an exception for ambiguous local times.
To convert UTC time to local time in given timezone:
def convert_from_utc(time, tzname, date=None):
tz = pytz.timezone(tzname)
if date is None: # use date from current time in utc
date = datetime.utcnow().date()
dt = datetime.combine(date, time).replace(tzinfo=pytz.utc)
return tz.normalize(dt.astimezone(tz)).time()
Example:
time = datetime.strptime('12:00:00', "%H:%M:%S").time()
utc_time, offset = convert_to_utc(time, 'America/Chicago')
print utc_time.strftime("%H:%M:%S"), offset # -> 17:00:00 -18000.0
utc_time = datetime.strptime('17:00:00', "%H:%M:%S").time()
time = convert_from_utc(utc_time, 'America/Chicago')
print time.strftime("%H:%M:%S") # -> 12:00:00
In general it is preferable to work with full datetime objects to avoid ambiguity with what is the correct date i.e., pass and return datetime objects.

By using the replace method on the datetime, you're not allowing the time zone to be adjusted for daylight savings time. Try using one of the documented methods from the pytz documentation:
src_dt = src_tz.localize(dt)

Related

Get local date time and time in Django

How can I get the local date and time in Django?
I tried this solution. But it works only for the date now.
from django.utils import timezone
now = timezone.localtime(timezone.now()) #OK
date = timezone.localtime(timezone.date()) #Error
time = timezone.localtime(timezone.time()) #Error
Preferably in the same format as for datetime
now = datetime.datetime.now() #'2020-04-28 17:57:34.120383'
date = datetime.datetime.now().date() #'2020-04-28
time = datetime.datetime.now().time() #18:12:08.987472
Extract the date and time from the local instant object.
from django.utils import timezone
now = timezone.localtime(timezone.now())
date = now.date()
time = now.time()

Setting datetime inside QDateTimeEdit widget

I have to set the date and time available as a string in the following format.
"%Y/%m/%d %H:%M:%S"
cur_time = strftime("%H:%M:%S", gmtime())
cur_date = DATA[1]
date_time = cur_date+" "+cur_time
now = QtCore.QDate.fromString(date_time, '%Y/%m/%d %H:%M:%S')
self.dateTimeEdit.setDate(now)
But this is not working.
The format of date and datetime is different from the format of QDate and QDateTime, you should not use% in the Qt format, check the docs for more detail:
Assuming DATA[1] has a format %Y/%m/%d as you try to use, you can use the following code:
cur_time = strftime("%H:%M:%S", gmtime())
cur_date = "2018/11/10"
date_time = cur_date+" "+cur_time
now = QtCore.QDateTime.fromString(date_time, 'yyyy/M/d hh:mm:ss')
self.dateTimeEdit.setDateTime(now)

how to get records for a day relative to timezone in django

I am trying to all the record for a certain day with the following:
entered_at = request.session['entered_at']
entered_at = datetime.strptime(entered_at, "%m-%d-%Y")
day_start = entered_at.replace(hour=00, minute=00)
day_end = entered_at.replace(hour=23, minute=59)
entries = Entry.objects.filter(
customer=customer,
entered_at__lt=day_end,
entered_at__gte=day_start
)
When I do this I get the following warning in my console:
DateTimeField received a naive datetime while time zone support is
active.
I know I can add something like: , day_start = entered_at.replace(hour=00, minute=00, tzinfo=<UTC>)
however, this will not make the range from midnight to 11:59pm relative to the users timezone if I use UTC.
How can I express a full day relative to the users timezone?
I believe you want something like this, using the pytz library. See How to make an unaware datetime timezone aware in python:
import pytz
entered_at = request.session['entered_at']
entered_at = datetime.strptime(entered_at, "%m-%d-%Y")
day_start = entered_at.replace(hour=00, minute=00)
day_end = entered_at.replace(hour=23, minute=59)
timezone = pytz.timezone("America/Los_Angeles")
day_start = timezone.localize(day_start)
day_end = timezone.localize(day_end)
entries = Entry.objects.filter(customer=customer,
entered_at__lt=day_end,
entered_at__gte=day_start)

Guessing the date format python

I am writing a method in a Python module which tries to make live easier to the users. This method implements the creation of events in that calendar.
def update_event(start_datetime=None, end_datetime=None, description=None):
'''
Args:
start_date: string datetime in the format YYYY-MM-DD or in RFC 3339
end_date: string datetime in the format YYYY-MM-DD or in RFC 3339
description: string with description (\n are transforrmed into new lines)
'''
If the user specifies the start_date or the end_date a check up should be made in order to determine if the date is in YYYY-MM-DD format or in the datetime RFC 3339 format.
if (start_date is not None):
# Check whether we have an date or datetime value
# Whole day events are represented as YYYY-MM-DD
# Other events are represented as 2014-04-25T10:47:00.000-07:00
whole_day_event = False
try:
new_start_time = datetime.datetime.strptime(start_date,'YYYY-MM-DD')
# Here the event date is updated
try:
new_start_time = datetime.datetime.strptime(start_date,'%Y-%m-%dT%H:%M:%S%z')
#Here the event date is updated
except ValueError:
return (ErrorCodeWhatever)
except ValueError:
return (ErrorCodeWhatever)
Is this a good way of doing this? Can I check what kind of date I am receiving in a nicer way?
Thanks!
dateutil.parser.parse can be used to attempt to parse strings into datetime objects for you.
from dateutil.parser import parse
def update_event(start_datetime=None, end_datetime=None, description=None):
if start_datetime is not None:
new_start_time = parse(start_datetime)
return new_start_time
d = ['23/04/2014', '24-04-2013', '25th April 2014']
new = [update_event(i) for i in d]
for date in new:
print(date)
# 2014-04-23 00:00:00
# 2013-04-24 00:00:00
# 2014-04-25 00:00:00
Extending #Ffisegydd answer you can also specify your target datetime format that you want like this :-
from dateutil.parser import parse
def update_event(start_datetime=None, end_datetime=None, description=None):
if start_datetime is not None:
new_start_time = parse(start_datetime)
return new_start_time
d = ['06/07/2021 06:40:23.277000','06/07/2021 06:40','06/07/2021']
new = [update_event(i) for i in d]
for date in new:
print(date.strftime('%Y/%m/%d %H:%M:%S.%f'))

Timezone conversion shows an offset of an hour more in OpenShift

I've implemented a REST webservice using flask. It stores and provides events information.
While storing information, I do the following steps:
Take the date, time and timezone.
Localize into the provided timezone
Then convert it into utc timezone
Finally get the utc timestamp and store it in the db.
def __get_timestamp(_datetime):
"""Returns the timestamp from datetime
"""
return time.mktime(_datetime.timetuple())
def __strptime(formatted_dt, tzinfo):
"""Returns the utc timestamp after conversion from entered timezone to utc
"""
tzinfo_dt = tzinfo.localize(datetime.datetime(formatted_dt['year'], formatted_dt['month'], formatted_dt['day'], formatted_dt['hour'], formatted_dt['minute']), is_dst=True)
utc = get_tzinfo()
utc_tz = utc.normalize(tzinfo_dt.astimezone(utc))
return __get_timestamp(utc_tz)
def get_tzinfo(user_timezone="UTC"):
"""Return pytz timezone
"""
return pytz.timezone(user_timezone)
While retrieving information
Retrieve the utc timestamp
Localize it into the utc
Convert it into the required timezone
Return with the required format
def get_tzinfo(user_timezone="UTC"):
"""Return pytz timezone
"""
return pytz.timezone(user_timezone)
def __strftime(ts, tzinfo, format='%Y-%m-%d %I:%M %p'):
"""Return the formatted datetime after converting utc timestamp to required timezone
"""
utc = get_tzinfo()
utc_dt = utc.localize(datetime.datetime.fromtimestamp(ts), is_dst=True)
tzinfo_dt = tzinfo.normalize(utc_dt.astimezone(tzinfo))
formatted_dt = tzinfo_dt.strftime(format)
return formatted_dt
The sequence goes like this
Entered datetime = 2014-03-21 14:00
TimeZone = "Asia/Kathmandu" --> (GMT+05:45) Kathmandu
Resulting timestamp = 1395407700
Final Formatted Output = "2014-03-21 03:00 PM"
The problem seems to be with daylight saving because the same code gives the correct result when tested locally.
Currently the webservice is being run on Openshift
whose server has "EDT" timezone,
while my local settings has "NPT".
How can this be resolved?

Categories