SQL Where Clause and Django Timezone - python

I have noticed that when I return records from my SQL database using the following: the_records = records.objects.filter(datetime__contains="2015-01-15"), I get back the wrong records because the timezone is affecting the function call somehow - I know this because if I temporarily disable the timezone, the right records are returned. Can anyone offer assistance on what I should do to fix this problem (I still need to use the timezone).
Regards, Mark

I'm assuming that datetime is a Django DateTime field, and you're trying to get the results that have a value that matches the date '2015-01-15', ignoring the actual time.
In that case, you probably want to do a date query, like: Records.objects.filter(datetime__date=datetime.date(2015, 1, 15))

If you need to query your db with a timezone specific date, you can just create a datetime object that is aware of it's timezone.
Example:
# Get your timezone
from django.utils import timezone
my_timezone = timezone.get_current_timezone()
# Get create your timezone aware datetime object
from datetime import datetime
query_date = datetime(2015,01,15).replace(tzinfo=my_timezone)
# now you can run your query with a timezone specific datetime object
the_records = records.objects.filter(datetime=query_date)
This should solve your issue and get you the accurate results you need.
Please let me know if you still have any questions.
This link has more info related to django timezones if you are interested in learning more.

Related

How to get the value of a DateTimeField in peewee

class Test(Model):
time = DateTimeField()
# ...
row = Test.select()[0]
test.time
This returns a string that looks like this: 2017-01-23 01:01:39+01:00. How can I get it as a datetime object instead? Do I have to parse it manually?
Also I would be interested if there is any documentation on how to use the DateTimeField. The official documentation doesn't have anything on it.
Are you using SQLite? If so, SQLite doesn't have a dedicated datetime type, so datetimes are stored as strings in the DB. What peewee will do is recognize certain datetime formats coming out of the DB and convert them to datetime objects. What you need to do is ensure that either:
When you create/save your object, that you assign a datetime object to the field.
When reading back pre-existing data, that the data is in a recognized format.
The formats peewee supports out-of-the-box for datetime field are:
YYYY-mm-dd HH:MM:SS.ffffff
YYYY-mm-dd HH:MM:SS
YYYY-mm-dd
It looks like your has zone info. I'd suggest converting to UTC and dropping the zone info. That should fix it.
Have you tried adding a default like this?
time = DateTimeField(default=datetime.datetime.now())
Or when adding an entry add it as a datetime.datetime object directly:
test = Test(....., time=datetime.datetime.strptime("2018-3-15", '%Y-%m-%d'))
In the second case you don't need to specify anything in the class definition...

How to set Postgres Datetime field into Odoo Datetime field

I am trying to display set time of Postgres database time to datetime field into Odoo.
I am creating field is that to set the time.
last_modify_article = fields.Datetime("Last Modify Date")
But my DateTime :~ 2017-08-28T08:43:56+0200 is perfectly stored in Postgres database but in Odoo saw in different.
So, my question is that how can I manage the database date-time in the field.
Here is the Postgres Time
And
Here is Odoo field to set datetime in UTC
Actually the database stores the Datetime field according to the system timezone. In Odoo, views which will be automatically converted according to the user's timezone if it is set.
On your images, I can see the time difference id +5:30 ie, Asia/Kolakata timezone. So your custom operations on Datetime field need the proper conversion of Timezone according to the user.
Odoo views and ORM methods are treated the tz with moment.js and the pytz conversions. This is actually a good feature to manage different timezones in Odoo.
You can use astimezone on Datetime objects:
def astimezone(self, tz): # known case of datetime.datetime.astimezone
""" tz -> convert to local time in new timezone tz """
return datetime(1, 1, 1)
or
fields.Datetime.context_timestamp(self, datetime.strptime(value, DEFAULT_SERVER_DATETIME_FORMAT))
Odoo is designed to have the date and time stored as UTC in the database and convert it to the user's timezone on the front-end.
What time zone is set for your user? You can click your name in the top right, then Preferences. Time zone should be shown on the popup form.
You can use pytz library to convert datetime based on user's timezone. See the code sample.
import pytz
import datetime
def current_user_datetime(self):
currenttimezone = pytz.timezone(self.env.context.get('tz'))
user_datetime = datetime.datetime.now(currenttimezone)
self.timefield = user_datetime

Create timezone-aware ISODate with pymongo

I'm looking for a way to store a timezone-aware datetime object in mongoDB.
I read here: Create an ISODate with pyMongo that storing a datetime object in MongoDB with pymongo will result in a ISODate object being stored (or an object that looks like this when querying from the shell)
Using the datetime.replace(tzinfo=[...]) method, there is a way to make the datetime object aware of its timezone. Unfortunately, when storing such object in mongoDB, the timezone information seems to be lost.
My question is: is there a way to store the timezone in the ISODate object itself, so that it looks like something like this: ISODate("2012-07-14T01:00:00+01:00") when querying the shell and so that the datetime object is still timezone aware when reloaded with pymongo later on?
Thanks a lot for your help!
No, there's not a way to do that. MongoDB's ISODate is just a wrapper around a Date object, which is just a moment in time represented by an integer corresponding to the number of milliseconds elapsed since Jan 1, 1970 UTC. There is no way for it to retain an offset.
You might consider storing it just as a string, perhaps in a secondary field so you can still query for that moment in time while still knowing the local time and offset.
Also, assuming you're using tzdb time zones from either pytz or dateutil, such as "Europe/London", you should recognize that there's no way to determine a time zone from just an offset. So if you really need to reconstruct a full tz aware datetime, then you'll also have to store the time zone identifier in a separate field.
from datetime import datetime
from dateutil.tz import *
def to_utc(date_time):
return date_time.replace(tzinfo=tzlocal()).astimezone(tzoffset(None, 0))

Django + Postgres Timezones

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.

How to get user's local timezone other than server timezone(UTC) in python?

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)

Categories