I need to parse a date/time string from user input, and convert to UTC based on timzeone info not available in the string for datetime.strptime() (any suggestions?). Is there a straightforward way of doing this?
Ideally, on google app engine i'd like to grab local time with tzinfo from the browser if possible also.
timezone_string = "GMT-0800"
fields = ("eventstartmonth","eventstartday", "eventstartyear", "eventstarttimehour", "eventstarttimeampm")
date_string = '_'.join(map(lambda x: self.request.get(x), fields))
# date_string = "01_11_2000_1:35_PM"
dt = datetime.datetime.strptime(date_string, "%m_%d_%Y_%I:%M_%p")
# how to convert dt into a tz-aware datetime, and then to UTC
While searching for similar information I came across a demo app engine app (with source included) that demonstrates how to convert timezones in a way that's similar to what you've requested. Unfortunately, though, you'll need to create custom tzinfo classes (explanation/code in the demo app linked above) for each timezone you'll be converting.
If you need to be able to handle any timezone and/or want to take the easy route, I'd recommend using the pytz module. However, keep in mind, pytz is a rather bulky module that you'd have to upload to your GAE instance.
Related
I am currently working with a given time in the following format
"2022-03-21T12:14:28.725Z"
I want to compare this time I get from the internet to the local datetime.datetime.utcnow().timestamp() but I can't seem to get the conversion from string to unix timestamp right. Especially with the milliseconds.
I have already tried to use datetime.fromisoformat('2022-03-21T12:14:28.725Z') but no luck there.
To better understand my situation I am doing this to check the time off-set between a Server and my local machine.
Solution:
How do I translate an ISO 8601 datetime string into a Python datetime object?
from dateutil import parser
parser.parse('2022-03-21T12:14:28.725Z')
I've retrieved a datetime from a bigquery record (using the google.cloud.bigquery library) and need to send it to the google admin sdk reports API in rfc 3339 format according to the 'startTime' parameter of this api method. The API is expecting the datetime to look like this:
2010-10-28T10:26:35.000Z
Which is normally possible by creating a python datetime without tzinfo and calling isoformat like this:
>>> now = datetime.utcnow()
>>> now = now.isoformat("T") + "Z"
>>> now
'2017-06-01T13:05:32.586760Z'
The problem I'm having is that the timestamp coming from BigQuery includes a tzinfo object, and that's causing isoformat to return text that the Google API can't process.
>>> timestamp_from_bigquery
'datetime.datetime(2017, 5, 31, 16, 13, 26, 252000, tzinfo=<UTC>)'
>>> timestamp_from_bigquery.isoformat("T") + "Z"
'2017-05-31T16:13:26.252000+00:00Z'
Specifically, the +00:00 is not accepted by Google's API as startTime. If I manually remove +00:00 from the string the API call works, but I'm not sure how to do this in python without an ugly string hack. Is there some clean way to remove this from the datetime object?
I've also tried this, but results in the same:
>>> timestamp_from_bigquery.replace(tzinfo=None)
'2017-05-31T16:13:26.252000+00:00Z'
Use datetime.datetime.strftime():
datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S.%fZ')
timestamp_from_bigquery.strftime('%Y-%m-%dT%H:%M:%S.%fZ')
Of course make sure the datetimes are in the correct timezone.
I'm trying to figure out what's going on with a timezone conversion that's happening in Django.
My view code is as below, it filters on a date range and groups on the day of creation:
def stats_ad(request):
start_date = datetime.datetime.strptime(request.GET.get('start'), '%d/%m/%Y %H:%M:%S')
end_date = datetime.datetime.strptime(request.GET.get('end'), '%d/%m/%Y %H:%M:%S')
fads = Ad.objects.filter(created__range=[start_date, end_date]).extra(select={'created_date': 'created::date'}).values('created_date').annotate(total=Count('id')).order_by("created_date")
The SQL query that is produced by django when I set the get variable of start to "01/05/2013 00:00:00" and the request end variable to "11/05/2013 23:59:00":
SELECT (created::date) AS "created_date", COUNT("ads_ad"."id") AS "total" FROM "ads_ad" WHERE "ads_ad"."created" BETWEEN E'2013-05-01 00:00:00+10:00' and E'2013-05-11 23:59:59+10:00' GROUP BY created::date, (created::date) ORDER BY "created_date" ASC
If I manually run that on my Postgresql database, it's all good, finds the following:
created_date total
2013-05-10 22
2013-05-11 1
However If I do the following:
for a in fads:
recent_ads.append({"dates": a['created_date'].strftime('%d/%m/%Y'), 'ads': a['total']})
It gives me the following output:
[{"dates": "09/05/2013", "ads": 1}, {"dates": "10/05/2013", "ads": 22}]
I'm at a loss at why it's changed the dates?
Anyone got any ideas?
Cheers,
Ben
Just a through on this. As of Django 1.4, Django now supports timezone aware dates and times. Perhaps it's possible that a conversion between your local timezone and the timezone that the data is stored in (possibly GMT) is taking place at some point. Perhaps that difference crosses the international date line, in which case the dates may show up differently.
Django has an interesting section describing the new timezone support feature.
https://docs.djangoproject.com/en/1.4/topics/i18n/timezones/
That's what came to mind, anyway, when you described your problem. Hope this helps.
Python datetime from the standard python library is a mess.
Probably you are creating naive datetime instances (instances that lack timezone information).
# naive
now = datetime.datetime.now()
# TZ aware
from django.utils.timezone import utc
now = datetime.datetime.utcnow().replace(tzinfo=utc)
In recent Django, datetime storage is always offset-aware, so you better convert naive datetimes - otherwise an automatic (and sometimes wrong) conversion will take place.
Take a look at the docs about Django Time Zones.
In OpenERP, when I try to print the current date and time, it always print the 'UTC' time. But I want to get time in the user timezone . Each user have different timezone.For example 'CST6CDT', 'US/Pacific' or 'Asia/Calcutta'. So I need to get time in user timezone so that I can show the correct datetime in the report. I have tried to change the timezone using localize() and replace() function in datatime module. But I didn't get the correct output.
Got it.
from datetime import datetime
from pytz import timezone
fmt = "%Y-%m-%d %H:%M:%S"
# Current time in UTC
now_utc = datetime.now(timezone('UTC'))
print now_utc.strftime(fmt)
# Convert to US/Pacific time zone
now_pacific = now_utc.astimezone(timezone('US/Pacific'))
print now_pacific.strftime(fmt)
# Convert to Europe/Berlin time zone
now_berlin = now_pacific.astimezone(timezone('Europe/Berlin'))
print now_berlin.strftime(fmt)
Courtesy: http://www.saltycrane.com/blog/2009/05/converting-time-zones-datetime-objects-python/
As of OpenERP 6.1 the timezone of all Python operations happening on the server-side (and in modules) is forced to be UTC. This was a design decision explained in various places [1]. The rendering of datetime values in the user's timezone is meant to be done on the client-side exclusively.
There are very few cases where it makes sense to use the user's timezone instead of UTC on the server-side, but indeed printing datetime values inside reports is one of them, because the client-side will have no chance to convert the contents of the resulting report.
That's why the report engine provides a utility method for doing so: the formatLang() method that is provided in the context of reports (RML-based ones at least) will format the date according to the timezone of the user if you call it with a datetime value and with date_time=True (it uses the tz context variable passed in RPC calls and based on the user's timezone preferences)
You can find example of how this is used in the official addons, for example in the delivery module (l.171).
Have a look at the implementation of formatLang() if you want to know how it actually does the conversion.
[1]: See the OpenERP 6.1 release notes, this other question, as well as comment #4 on bug 918257 or bug 925361.
from: http://help.openerp.com/question/30906/how-to-get-users-timezone-for-python/
DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
import pytz
from openerp import SUPERUSER_ID
# get user's timezone
user_pool = self.pool.get('res.users')
user = user_pool.browse(cr, SUPERUSER_ID, uid)
tz = pytz.timezone(user.context_tz) or pytz.utc
# get localized dates
localized_datetime = pytz.utc.localize(datetime.datetime.strptime(utc_datetime,DATETIME_FORMAT)).astimezone(tz)
DateInUTC = <~ Time variable to convert
To convert to user's timezone:
LocalizedDate = fields.datetime.context_timestamp(cr, uid, DateInUTC, context=context)
To remove the offset:
LocalizedDate = LocalizedDate.replace(tzinfo=None)
So, we have 'Europe/Moscow' TZ in our settings.
Currently this means daylight saving (this is going to change in the future, but at the moment it's UTC+03/04).
I understand that this TZ is used when saving dates to the DB, and when extracting them.
Now, I have to serialize the datetime object to ISO string, including the UTC offset. What is the correct way of doing this?
The dates don't contain the TZ info (i.e. d.strftime('%z') is empty)
I think I could convert them to UTC and serialize with +00:00, but how do I convert them to UTC if I don't know if the specific date is +03 (Moscow winter) or +04 (Moscow summer)
how do I convert them to UTC if I don't know if the specific date is +03 (Moscow winter) or +04 (Moscow summer)
There is no need for UTC conversion, pytz handles such thing for you.
Here's the code to convert from timezone-naive datetime to ISO with timezone offset:
from datetime import datetime
from pytz import timezone
server_timezone = timezone('Europe/Moscow')
server_timezone.localize(datetime(2011, 1, 1)).isoformat()
>>> '2011-01-01T00:00:00+03:00'
server_timezone.localize(datetime(2011, 7, 1)).isoformat()
>>> '2011-07-01T00:00:00+04:00'
First run new_dt = datetime.replace(tzinfo=tz) to create a new timezone-aware datetime. Then run your datetime.strftime() with %z.
Note that you can't then convert the date string back to a timezone-aware datetime directly -- datetime.strptime() doesn't support %z. So you need to instead create a naive datetime and a tzinfo then do datetime.replace(tzinfo=tz) as before.
Some useful external libraries:
http://pytz.sourceforge.net/
http://code.google.com/p/parsedatetime/
http://labix.org/python-dateutil
Also try searching right here on Stack Overflow for more questions on (Python OR django OR appengine) AND (datetime OR timezone OR date OR time OR tzinfo).
ISO-8601 has no notion of "Timezones", only dates and times, and as a convenience, times may be presented with an "offset".
To make matters even more annoying, datetime has only a half-hearted nod in acknowledgement of timezones; the tzinfo attribute on datetime objects is optional, and no implementation of that interface is provided by the main-line python.
The standard answer to this is to just always do everything in UTC; including having the server in UTC, not in local time. This is actually a pretty good idea; it's not the times that are different, only the way individual users prefer to read those times (which is similar to preferring '42' over '0b101010').
You can satisfy your users' (reasonable!) desire to view times in their local timezone by storing the preferred timezone (perhaps just a sitewide preference if everyone is in Moscow) separately from the actual times, and then you can use a robust timezone library (like pytz) to do the formatting to and from local time.