Getting Localtime using timezone.now() - django

I'm performing a query where I want to get a list of items added today.
listOfMatches = Matches.objects.filter(
match_starting_time__date=timezone.localdate(timezone.now())
)
Also tried this
listOfMatches=Matches.objects.filter(match_starting_time__date=timezone.now())
All I'm getting is Utc time
print(timezone.now())
I need Local time. I have set Time_zone to
TIME_ZONE = 'Pacific/Fiji'
Can anyone please help?

Related

Saving objects to postgresql with DJango in UTC instead of local timezone?

I have a column in my table called "signed_up_date", which I am using the auto_now_add=True parameter with the DateTimeField() function.
I want this function to save timestamps to the PostgreSQL DB in UTC instead of my local time (EST) which it is currently doing.
Barebones version of the model for quick ref below:
class TutorTest(models.Model):
signed_up_on = models.DateTimeField(auto_now_add=True)
Settings.py
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
I thought based on the docs, if I have Time_Zone set to UTC and UTC_TZ set to True, then the default behavior of Django would be to save as UTC.
I know when I check postgresql timezone I get:
SHOW TIMEZONE;
TimeZone
------------
US/Eastern
(1 row)
I just tried a new model with timezone.now() and it looks like in the db shell I get:
datetime.datetime(2022, 9, 21, 14, 36, 16, 670726, tzinfo=datetime.timezone.utc)
But the db saved it as:
2022-09-21 10:35:26.633116-04
I guess it's the DB in this situation? Confused lol
*** EDIT ***
I think I figured it out. The database takes a UTC time and converts to EST, but when I pull the time out django reads it as UTC. Which works for me lol.
The timestamp which is actually saved in the database would be in UTC, but if you are using some sort of tool such as DBeaver (for example) to look into and query the datbase, then that tool would convert the timestamps as per what is put in its configuration and show those converted timestamps to you. But the underlying data in the database is still in UTC.
Hope this helps.

Can't find objects in my database within month filter

I'm trying to display a count of the mentioned objects using this piece of code:
day = datetime.date.today()
MyModel.objects.filter(submit_date__month=day.month).count()
This returns 0. Trying from a different approach:
MyModel.objects.filter(submit_date__month=day.month).all()
Still, it returns a empty queryset.
Below, a picture with the dates of the entries in the database, which are stored in a DateTimeField with default=timezone.now.
P.S.: USE_TZ = True, TIME_ZONE = 'America/Bahia'
UPDATE: Figured out a workaround
queryset_count = 0
for a in MyModel.objects.filter(submit_date__year=day.year):
if a.submit_date.month == day.month:
queryset_count += 1
I still don't know why the queryset behaved like this, but as time was catching me up, this solved the issue in its own way.

Compare date of datetime object in filter django

I use django 3.1.0
I have a release_time field(a DateTimeFeild) in my model, and i want to retrieve those records that have been released in current date.
here is my model:
class Test(models.Model):
title = models.CharField(max_length=100)
release_time = models.DateTimeField()
end_time = models.DateTimeField()
this is my time settings:
TIME_ZONE = 'Asia/Tehran'
USE_I18N = True
USE_L10N = True
USE_TZ = True
I use the following line to get my data:
cur_time = localtime() // django.utils.timezone.localtime
Test.objects.filter(release_time__date=cur_time.date())
This always returns an empty query set. I am sure that there are records that have this condition.
PLease tell me am I doing this wrong??
UPDATE
This is the WHERE statement in sql query.(the date is right and there is a record in the database with this date.
WHERE DATE(CONVERT_TZ(`contests_test`.`release_time`, 'Asia/Tehran', 'Asia/Tehran')) = 2020-11-23
If i use this query:
Test.objects.filter(release_time__date=TruncDate(Now()))
I get this sql:
WHERE DATE(CONVERT_TZ(`contests_test`.`release_time`, 'UTC', 'Asia/Tehran')) = DATE(CONVERT_TZ(CURRENT_TIMESTAMP, 'UTC', 'Asia/Tehran'))
None of the above doesn't work.
I found a logical work around and I don't depend on this query anymore but this really keeps me awake at nights!!
For getting current date for ORM usage purposes, you may use Django's database functions Now() and truncate it to date using DateTrunc(). This forces usage of database time in the query and also avoids mess with timezones in database and python sides. For example if USE_TZ setting is set to False, .localtime() will fail with error ValueError: localtime() cannot be applied to a naive datetime.
So you may try:
Test.objects.filter(release_time__date = TruncDate(Now()))
As for your query, I can't guess why it does not return data, it is well formed and should be fetching the result. So, it is always a good practice to see what actual sql is executed by Django, by using .query.
Please, execute the following and look at where clause part of the sql statement, it may contain additional hints, like different timezones or whatsoever.
q = Test.objects.filter(
release_time__date=TruncDate( #django.db.models.functions.datetime.TruncDate
Now() # django.db.models.functions.datetime.Now
)
)
print(q.query)

Django. How to correctly save time & timezones

I have this code that behaves in a rather strange way and opens the question, how should I deal with timezones? So, first I have a datetime object I build from the info a user posts:
time_zone = request.POST.get("time_zone")
date_start = request.POST.get("date_start")
time_day = request.POST.get("time_day")
time_zone_obj = pytz.timezone("Etc/" + time_zone) # GMT + 2 in this example
date_start = datetime.strptime(date_start, "%d/%m/%Y")
date_start = date_start.replace(tzinfo=time_zone_obj)
time_day = datetime.strptime(time_day, "%I:%M %p")
date_start = date_start.replace(hour=time_day.hour, minute=time_day.minute)
...
event.date_start = date_start
event.save()
print("event.date_start.hour:%s" % event.date_start.hour)
print("event.date_start.tzinfo:%s" % event.date_start.tzinfo)
print("is_aware(event.date_start:%s)" % is_aware(event.date_start))
return redirect("event_detail", event_id=event.id)
This prints event.date_start.hour:6, event.date_start.tzinfo:Etc/GMT+2 and is_aware:True. Then, inmediatlty after saving the object and printing the hour, it redirects to the event_detail view, very simple:
def event_detail(request, event_id):
event = get_object_or_404(Event, id=event_id)
print("event.date_start.hour:%s" % event.date_start.hour)
print("event.date_start.tzinfo:%s" % event.date_start.tzinfo)
...
And it prints event.date_start.hour:8 and event.date_start.tzinfo:UTC. (it has replaced the tz info with UTC) I don't understand why. I am saving the object with a clear tz_info. Plz note that I printed the hour after I saved the object and then after I retrieved it in the other view. It has a difference of two hours that must have something to do with the timezone the user selected (GMT + 2). Why is this? Which is the best way to save this data?
The user submits "6:00 AM" + "GMT+2" in the form and then later when I want to show the time in the event detail html ({{ event.date_start|date:"h:i A" }}) it displays "8:00 AM".
I assume you're using PostgreSQL to save the timezone aware timestamp.
It's important to understand that (contrary to the name and popular belief) PostgreSQL doesn't save the timezone of the timezone aware timestamp. It's just a way to tell PostgreSQL that the value is not in some local time, but is timezone aware.
PostgreSQL then converts it to UTC and stores as such. If the original timezone is important, you need to store it separately.
More info on the topic: https://www.postgresqltutorial.com/postgresql-timestamp/
The best way to store this data is a separate column (usually called timezone). I use https://pypi.org/project/django-timezone-field/
Then either activate timezone (https://docs.djangoproject.com/en/3.1/ref/utils/#django.utils.timezone.activate) or use localtime (https://docs.djangoproject.com/en/3.1/ref/utils/#django.utils.timezone.localtime) util function.
As per the Django docs,
"When support for time zones is enabled, Django stores DateTime information in UTC in the database. It’s still good practice to store data in UTC in your database. The main reason is the Daylight Saving Time (DST). "
So saving DateTime in UTC format in the database as expected.
Now, going ahead with your requirement. In order to display the time back in the timezone which was used for saving you need to add a column in the DB to store the timezone info.
While retrieving the DateTime, convert it into the required timezone back using the tzinfo stored in DB.
This is the correct way of doing. Hope this helps you understand better.

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.