Not naive timezone when querying django - django

I have deleted all timezone-naive entries out of my Sqlite-DB. So now they remaining entries have a datefield like this:
2016-09-04 13:28:16+00
When I now run my query like this:
result = Feedentry.objects.filter(date_published__gt=timezone('Europe/Berlin').localize(datetime(2016, 8, 31, 17)))
First I receive no error, but as soon as I want to access the result (or len(result)) I receive the following error:
raise ValueError('Not naive datetime (tzinfo is already set)')
Any ideas how to solve it or what I did wrong?

Django always stores datetimes in UTC. And in SQLite it doesn't store any timezone information at all:
[Databases other than PostgreSQL] store datetimes without time zone information. If you switch from USE_TZ = False to USE_TZ = True, you must convert your data from local time to UTC – which isn’t deterministic if your local time has DST.
So first you need to go through your database and convert all the values to UTC; otherwise, Django will not interpret the values correctly.
As for your comparison, it is correct if you're using pytz.timezone and a naive datetime. But the error message implies that whatever datetime you're passing to localize() is already timezone-aware. To convert a timezone-aware datetime you need to use datetime.astimezone(), as noted in the pytz documentation.

Related

Date exported is displayed as UTC

I'm trying to export some data from Django to Excel using openpyxl.
The exported datetimes are correctly interpreted as such in Excel, but their printout is in UTC, not in local timezone (CET in this case) as I'd expect.
I tried to use to_excel, but that only outputs datetimes converted to excel's internal float format. Which is in addition also interpreted as float, not datetime. When formatted as datetime, it's still in UTC
I also tried to use Django's django.utils.timezone.localtime, but again the dates are rendered in UTC.
I could just subtract the timezone offset from my dates, but I feel it's more likely I'm missing something here.
How can I export datetime data such that Excel would display it in my local timezone?
I had the similar problem and solved it in the following way.
May be it helps.
from dateutil.tz import tzutc, tzlocal
TZ_UTC = tzutc() # UTC timezone
TZ_LOCAL = tzlocal() # Local timezone
datevalue = value #value I get from API I am using, which is datetime object.
# For some reason I don't get tzinfo filled).
datevalue = datevalue.replace(tzinfo=TZ_UTC) # Adding time zone info for UTC
datevalue = datevalue.astimezone(TZ_LOCAL) # Converting to local timezone
datevalue = datevalue.replace(tzinfo=None) # Removing tzinfo to correctly record local time to Excel
cell.value = datevalue
Excel itself has no concept of timezones and will always dates and times naively. In this context the only sane thing to do is to convert to UTC which is what openpyxl does. openpyxl.utils.datetime is the module to look at if you want to change this
I ended up using a combination of javascript & server-side processing:
At the client HTML I create an input for user's local timezone:
<input type="hidden" value="" name="tz" id="xls-tz"/>
and populate its value (using jQuery):
$("#xls-tz").val(new Date().getTimezoneOffset());
At the server, I parse the timezone offset & write to openpyxl accordingly:
tz_offs = int(request.GET.get("tz", "0"))
ws.cell(row=row, column=2, value=item.time - timedelta(minutes=tz_offs))
That comes IMO pretty close to what I needed.
Thanks Charlie for the hint about Excel not being TZ aware.

Django template tag, python timezone aware dates different results

I have :
TIME_ZONE = 'Europe/Paris'
USE_L10N = True
USE_TZ = True
in my settings.py file. I am living in Istanbul/Turkey and there is one hour difference between Paris and Istanbul.
In the admin side when selecting a date, django correctly shows 1 hour difference. And using template tag i am getting the datetime i have set in the admin.
But when i pass the datetime via python using beginning_date.strftime("%H:%M") python substracts 1 hour from the value that was set via admin which is not true.
How can i solve this?
Use the Django template defaultfilters to format your dates in Python code.
from django.template.defaultfilters import date as _date
_date(datetime_object, "%H:%M")
And, maybe related: Django cannot reliably use alternate time zones in a Windows. See documentation.
I don't think Turkey has anything to do with it.
My guess is that the one-hour difference you're seeing is between the Paris timezone—which is being used, by default, to interpret and display dates—and UTC—which is being used to store the datetime, and which is the timezone of the datetime returned from the database.
If that's correct, then you can just use django.utils.timezone.localtime to convert the datetime to the current time zone (which by default will be TIME_ZONE):
localtime(beginning_date).strftime("%H:%M")

Django, Python datetime.now() and storing the timezones

How does Django internally store a datetime field? Does it translate local time to UTC before storing? I am giving it a naive datetime generated from stdlib.
a = Message( fromm = fromm, to = to,
sent_time = datetime.datetime.now(), content = content)
Django ORM stores date time in your SQL database's corresponding field. The underlying SQL column is determined by the used database. E.g. for MySQL, the mappings are defined here:
https://github.com/django/django/blob/master/django/db/backends/mysql/creation.py#L16
Conversion from Django to SQL:
https://github.com/django/django/blob/master/django/db/backends/mysql/base.py#L272
Conversion from SQL to Django:
https://github.com/django/django/blob/master/django/db/models/fields/init.py#L1186
Python datetime.datetime.now() is so-called timezone-naive datetime and doesn't have any timezone information. Thus, you may lose information when storing times with it and it's usage is discouraged. It returns the local time. It seems that that if timezone information is omitted, the Django USE_TZ setting determines if the default timezone information is retrofitted internally.
Instead, you should use django.utils.timezone.now() (local time with timezone) or django.utils.timezone.utcnow() (time with UTC timezone).
More info
https://docs.djangoproject.com/en/dev/topics/i18n/timezones/#naive-and-aware-datetime-objects

Django timezone confusion

The timezone for my users is fixed to PST.
I can't make timezone.now() output the correct time. In settings.py I have the timezone set to US/Pacific and USE_TZ=False. Am I doing something wrong? The timezone.now() is 9 hours ahead.
Also, if I want to adjust the timezones some time later, is there a nice way to do it? Django's documentation seems kinda messy in this regard.
USE_TZ = False tells django to ignore timezone information. Switch it to USE_TZ = True and you should be fine.
With this in place, changing timezones in future should be as simple as updating the timezone setting as the timezone is saved with the date when USE_TZ = True
You should really have USE_TZ=True and the timezone set to US/Pacific. Then all the dates will be stored as UTC and converted to PDT on the front-end. This makes it easier if/when you have to change timezones later since all of the datetimes are stored as UTC rather than a naive PDT.

django.utils.timezone returning naive date?

using django 1.4 I have a model with a datetimefield. I imported django.utils.timezone to use as the default value.
from django.utils import timezone
date = models.DateTimeField(default=timezone.now)
however I still receive the warning about DateTimeField received naive date.
i have set USE_TZ to true so it should be returning aware datetimes
djangos putting in a default date value that isn't tz aware because the field isnt nullable by default. setting null to true means it will just set the date to to NULL instead so the warning isnt raised:
date = models.DateTimeField(default=timezone.now, null=True)
In my case, I kept receiving the issue when I ran tests. This is because of a past migration that incorrectly used datetime instead of timezone. I reverted back to the migration before the one causing the warning, deleted it, ran makemigrations again. This solved the issue for me.
now()
Returns an aware or naive datetime that represents the current
point in time when USE_TZ is True or False respectively.
https://docs.djangoproject.com/en/dev/ref/utils/#django.utils.timezone.now
I know this is side-stepping the issue but have you tried auto_now_add=True on your field instead? No need to use default for what you want.
On the other hand your version should work as well if you have indeed USE_TZ=True.
I'd say it does work, and you get the RunTimeWarning from somewhere where you set the date field directly instead and not from the default. Try to narrow down when is the warning triggered more exactly.