so I have model with a DateTimeField. Now when I store it in the database it gives me the correct time. However, when I print out the time, the time is ahead by 4 hours. This is probably due to some timezone issue. So I did some research and in my settings.py I have set a timezone:
TIME_ZONE = 'Canada/Eastern'
But it still doesn't work. Any ideas on how to solve this issue?
EDIT: How I define the field: Date = models.DateTimeField(auto_now_add=True)
If you're using Mysql/SQLite, as database doesn't store timezone info, so, after you defined timezone in settings.py, Django will convert your local time to UTC time each time before insert into the database. Don't worry, each time before you use this DateTime filed,Django would convert it back to local time automatically.
I don't know if this explanation can solve your problem.Also,remember define USE_TZ =True in settings.py.
Related
I am trying to fetch data based on DateTime Field! I wrote the following script for the same:
import datetime as dt
from dasboard.models import Visionsystem
from django.utils.timezone import make_aware
min_dt = dt.datetime.combine(dt.date.today(), dt.time(7, 15))
max_dt = dt.datetime.combine(dt.date.today(), dt.time(15, 44))
# Changing format for Django
min_dt_aware = make_aware(min_dt)
max_dt_aware = make_aware(max_dt)
# Fetching all the data between 7:15:00 to 15:44:00 for current day
l1 = Visionsystem.objects.filter(start_datetime__range=(min_dt_aware, max_dt_aware))
print(l1) yields empty list and Checking str(l1.query) gives:
'SELECT `visionsystem`.`id`, `visionsystem`.`Start_Datetime` ... FROM `visionsystem` WHERE
`visionsystem`.`Start_Datetime` BETWEEN 2019-10-16 01:45:00 AND 2019-10-16 10:14:00'
Desired query would be:
'SELECT `visionsystem`.`id`, `visionsystem`.`Start_Datetime` ... FROM `visionsystem` WHERE
`visionsystem`.`Start_Datetime` BETWEEN 2019-10-16 07:15:00 AND 2019-10-16 15:44:00'
I don't understand why Django-ORM is querying with a different time then what's specified ?
My timezone settings ( in settings.py ):
TIME_ZONE = 'Asia/Kolkata'
USE_I18N = True
USE_L10N = True
USE_TZ = True
How do I resolve this, to fetch the required data from 7:15:00 to 15:44:00, for current day ? NOTE: I am using MySQL Database!!
models.py file:
from django.db import models
class Visionsystem(models.Model):
start_datetime = models.DateTimeField(db_column='Start_Datetime', blank=True, null=True)
class Meta:
managed = False
db_table = 'visionsystem'
MySql doesn't supports timezones, It stores datetime in UTC, while your django
application timezone is Asia/Kolkata (UTC +5:30).
Here django automatically converts your application timezone to UTC before querying to MySQL database. This makes sense as when you save data using django application, it converts datetime to UTC time, so 07:15:00 Kolkata time would be stored as 01:45:00 in UTC.
Solution:
You can store MySql data in UTC timezone, If existing data is in Kolkata timezone, run update query by subtracting -5:30 and save all new data in UTC timezone.
OR
If your application doesn't need to support multiple timezone, you can change application timezone to UTC. This is quick solution but not a good idea as timezone information is truncated.
In short
Django saves store UTC in database.
If you don't mention a timezone, the timezone you mentioned in settings.py is taken (in your case, Asia/Kolkata is taken, so make_aware function assumes, you are entering a datetime with timezone Asia/Kolkata. But as mentioned in step 1., it is saved as UTC. Both time points to same time - that is, time described by both UTC and Asia/Kolkata is same).
In addition to both 1 and 2, django convert your timezone_aware datetime (ie. min_dt_aware and max_dt_aware) to UTC, to make the correctness of your query during query execution.
Here is the detailed explanation.
Time zones overview
When support for time zones is enabled, Django stores date-time information in UTC in the database, uses time-zone-aware date-time objects internally, and translates them to the end user’s time zone in templates and forms.
Value is shown as UTC, which is printed in SQL query:
import pytz
utc = pytz.UTC
# Print the utc value of min_dt_aware and max_dt_aware
print(min_dt_aware.astimezone(utc), max_dt_aware.astimezone(utc))
# So, as you can see, these utc values are which you see in SQL queries.
You can use timezone.now(), it worked for me. For this first you need to import timezone,from django.utils import timezone https://docs.djangoproject.com/en/3.1/topics/i18n/timezones/
In my models, I have a DateTimeField say
class ReturnEvent(models.Model):
book_title = models.CharField()
return_time = models.DateTimeField()
When I retrieve the return_time to be printed, for example:
return_event = ReturnEvent.objects.get(id=1)
print(return_event.return_time.strftime("%H:%M"))
I am seeing the datetime unaware time like:
2016-06-18 08:18:00+00:00
However, I like to see the local time using strftime.
2016-06-18 10:18:00+02:00
Is there a quick solution for this?
If you have USE_TZ = True in your settings, Django stores all the datetime objects in the database as UTC and convert them to your TIME_ZONE=XYZ from settings.py on the fly when rendering in the templates.
That is why, when retrieved from the database, datetime object is timezone aware but it has UTC as its timezone (hence +00:00 in 2016-06-18 08:18:00+00:00). As, you are converting the time to str yourself (and not rendering in the template) so Django does not convert it to your TIME_ZONE setting. You need to convert it yourself to your desired TimeZone.
If you want to convert it to the TimeZone from your TIME_ZONE setting, you can do
from django.utils import timezone
to_tz = timezone.get_default_timezone()
print return_event.return_time.astimezone(to_tz).strftime("%H:%M")
I have a timezone aware object:
date = timezone.now()
and then I am getting the user's timezone using some middleware, so I have it as a string, like:
tz = "America/New_York"
This is probably a really simple question but I have not been able to find the answer anywhere: How do I change the timezone of the date object to the user's timezone? I tried date.localize(tz) but that gave me an error. What am I doing wrong.
You need to convert the string to a timezone object, then use astimezone()
import pytz
timezone = pytz.timezone(tz)
your_date_with_usertimezone = date.astimezone(timezone)
When I post a time with timezone information eg:2013-02-27T14:00:00-05:00 to a Django datetime field throws a form error "Enter a valid date/time.".
My form field is defined as below
time = forms.DateTimeField()
I also tried passing in date formats to the form filed. eg:
DATE_FORMATS = [
'%Y-%m-%dT%H:%M:%S-%z',
]
time = forms.DateTimeField(input_formats=DATE_FORMATS)
Does Django DateTimeField not support time with timezone information?
Yes! Django DateTimeField supports timezones, but if you take a look at the documentation, you have to specify it separately from the actual DateTime in your form. Specifically, the documentation recommends that you activate a timezone on a per user basis, otherwise you will always end up entering the DateTime in the default timezone.
https://docs.djangoproject.com/en/dev/topics/i18n/timezones/#time-zone-aware-input-in-forms
This is the documentation I used for my project, and it worked out well.
In addition, if you need to specify a specific timezone in a form field, you can always create a drop down field with all of the timezones in it, and then save the DateTime in your view with the correct timezone.
I suppose time zone management was added to Django 1.4, so the problem is quite new.
I used a simple model
class Sample(models.Model):
...
date_generated = models.DateTimeField(auto_now_add = True)
When I try to retrieve a newly created record its fails.
min_datetime = datetime.now() - timedelta(seconds = 300)
sample = Sample.objects.get(date_generated__gte = min_datetime)
and the server issues a warning.
DateTimeField received a naive DateTime (2012-06-29 15:02:15.074000) while time zone support is active.
I figured out two solutions to that problem.
Disable time zone management in settings.py
USE_TZ = False
but this is not always desirable.
2. changing
date_generated = models.DateTimeField(auto_now_add = True)
to
date_generated = models.DateTimeField(default=datetime.now())
is the solution that keeps time zone management working
Use timezone utils of django
from django.utils import timezone
date_generated = models.DateTimeField(default=timezone.now)
The problem is on your end: datetime.now() is not TZ aware, so you're the one feeding in a naive TZ. See the Django docs on this issue. The reason it works when setting default=datetime.now is that you're forcing the value to a naive datetime, so when you later compare it with another naive datetime, there's no problem.
You need to get "now" the following way:
import datetime
from django.utils.timezone import utc
now = datetime.datetime.utcnow().replace(tzinfo=utc)
Be careful setting a DateTimeField default value of datetime.now(), as that will compute a single value when Apache/nginx loads Django (or when you start the development server), and all subsequent records will receive that value.
Always use auto_now_add for that reason.