Django Timezone Configuration - python

My django project is correctly enable the timezone in settings.
However, the datetime field of Django ORM object is a naive datetime object as shown in Block 3.
The expected result should be same as the output of Block 4 without any manually conversion.
In [1]: from django.conf import settings
...: settings.USE_TZ, settings.TIME_ZONE
Out[1]: (True, 'Asia/Hong_Kong')
In [2]: from qms.models import Quota
In [3]: q = Quota.objects.get(pk=1)
...: q.create_date, q.write_date
Out[3]:
(datetime.datetime(2021, 3, 10, 17, 37, 42, 489818),
datetime.datetime(2021, 3, 10, 17, 37, 42, 489818))
In [4]: from django.utils import timezone
...: timezone.make_aware(q.create_date,timezone.utc), \
...: timezone.make_aware(q.write_date, timezone.utc)
Out[4]:
(datetime.datetime(2021, 3, 10, 17, 37, 42, 489818, tzinfo=<UTC>),
datetime.datetime(2021, 3, 10, 17, 37, 42, 489818, tzinfo=<UTC>))
Record in SQL
Column
value
id
1
create_date
2021-03-10 17:37:42.489818+00
write_date
2021-03-10 17:37:42.489818+00
name
email
Django Model Definition
class Quota(models.models):
name = models.CharField(max_length=255)
create_date = models.DateTimeField(auto_now_add=True)
write_date = models.DateTimeField(auto_now=True)
The PostgreSQL database schema and settings, Table "public.qms_quota"
Column
Type
Modifiers
id
integer
not null default nextval('qms_quota_id_seq'::regclass)
create_date
timestamp with time zone
not null
write_date
timestamp with time zone
not null
name
character varying(255)
not null
SHOW TIMEZONE;
TimeZone
----------
UTC
Questions
How can I get the timezone-aware datetime object directly without any conversion?
Or the manual conversion is expected ?

The root-cause is a bug from a connection pool library django_postgrespool2==2.0.1.
When you use the your connection engine with "django_postgrespool2", it will NOT correctly handle the timezone settings. Releated Issue
TLDR: use engine django.db.backends.postgresql

You can use django.utils.timezone.localtime to convert the datetime received from the DB to localtime:
from django.utils.timezone import localtime
q = Quota.objects.get(pk=1)
print(localtime(q.create_date), localtime(q.write_date))

Related

How to check if a Marshmallow schema's Datetime field is less than today's date?

I have an endpoint that accepts POST method. The POST body contains a DateTime field of format - "%Y-%m-%d %H:%MZ". I need to validate if that datetime is less than current Datetime in UTC. I'm using Marshmallow to validate the request body.
run_datetime = fields.DateTime(format="%Y-%m-%d %H:%MZ")
Are there any inbuilt validators for this case to validate DateTime field. Or should I be writing a custom function for this to compare the run_datetime with today's UTC's datetime.
There is no built-in validator that can solve your particular issue at hand, take a look at the available validators here.
Although, defining your own validator is trivially easy, for your particular case: fields.Datetime will accept an argument named validate which can take a function that returns a bool. For example, I quickly defined a lambda here to validate if the datetime is more recent than "now":
from datetime import datetime
from marshmallow import Schema, fields
NOW = datetime(2020, 11, 23, 14, 23, 0, 579974)
class User(Schema):
id = fields.Integer(required=True)
name = fields.String(required=True)
# Define an arbitrary datetime here like NOW or just use datetime.now()
date_created = fields.DateTime(required=True, validate=lambda x: x > NOW)
# This will succeed
User().load(dict(
id=10,
name="Test",
# Note that this date is more recent than previously defined NOW
date_created="2020-11-23T14:24:40.224965",
))
#{'date_created': datetime.datetime(2020, 11, 23, 14, 24, 40, 224965),
# 'id': 10,
# 'name': 'Test'}
# While this will fail
User().load(dict(
id=10,
name="Test",
# Here the date is one month behind than NOW
date_created="2020-10-23T14:24:40.224965",
))
# ValidationError: {'date_created': ['Invalid value.']}

How to use timedelta with timezone.now as default?

In Django models, How to increment the date field using timezone.now?
working:
end_date = models.DateTimeField(default=timezone.now() + timezone.timedelta(days=365))
Not Working
end_date = models.DateTimeField(default=timezone.now + timezone.timedelta(days=365))
I think timezone.now is a function which runs every time when the object is created. so that error occurs.
You could use a function:
def f():
return timezone.now() + timezone.timedelta(days=365)
...
end_date = models.DateTimeField(default=f)
The current time in that timezone is the added with the timedelta anytime a new end_date is created by default:
>>> from django.utils import timezone
>>> from datetime import timedelta
>>> def f():
... return timezone.now() + timezone.timedelta(days=365)
...
>>> f()
datetime.datetime(2018, 6, 25, 19, 42, 49, 761389, tzinfo=<UTC>)
>>> f()
datetime.datetime(2018, 6, 25, 19, 43, 2, 953158, tzinfo=<UTC>)
Sample run with Django:
In [1]: from testapp import models
In [2]: models.Test.objects.create().date_added
Out[2]: datetime.datetime(2018, 6, 25, 20, 5, 28, 316214, tzinfo=<UTC>)
In [3]: models.Test.objects.create().date_added
Out[3]: datetime.datetime(2018, 6, 25, 20, 5, 33, 114624, tzinfo=<UTC>)
A good approach would be to use the post_save signal. Import it with
from django.db.models.signals import post_save and then create a handler function like this:
def handler_function(sender, instance, created, **kwargs):
if sender == YourModel and created:
instance.end_date = timezone.now() + timezone.timedelta(days=365)
instance.save()
post_save.connect(handler_function, sender=YourModel)
This will work for sure, I hope this also applies to your case. Let me know if you need further help!

Storing Time Difference Django

On my Django site, I am saving a user's reactions so when a user clicks a button, I store it as a created time and when the user clicks it second time, I stored the time as a finish time and so forth. Here it is my model;
class UserStatus(models.Model):
STATUS_TYPES = (
('online', 'online'),
('offline', 'offline')
)
user = models.ForeignKey(User)
status_type = models.CharField(max_length=30, choices=STATUS_TYPES, default='online')
created_time = models.DateTimeField(auto_now_add=True)
finish_time = models.DateTimeField(blank=True, null=True)
time_diff = models.DateTimeField(blank=True, null=True)
I added time_diff to show the time difference between created_time and finish time. When I try an example in the shell, I use;
user_status.created_time
datetime.datetime(2016, 3, 31, 12, 50, 21, tzinfo=<UTC>)
user_status.finish_time
datetime.datetime(2016, 3, 31, 12, 51, 37, 998593, tzinfo=<UTC>)
user_status.finish_time - user_status.created_time
datetime.timedelta(0, 76, 998593)
Everything seems to be fine until now, however when I wrote user_status.save() it gave an error;
line 93, in parse_datetime
match = datetime_re.match(value)
TypeError: expected string or buffer
I did not understand why it gave such an error.
Thank you in advance.
Now you try to use DateTimeField, but this field can only be used for storing date and time (but not time difference). You should use DurationField for storing timedelta.

django postgresql - extra datetime

In my project I have object with datetime field
startdate = models.DateTimeField(default="1999-01-01 00:00:00")
I need create new object and send datetime = "2015-12-9"
calen = models.calendar()
calen.startdate = datetime.strptime(request.POST["date"], "%Y-%m-%d")
calen.save()
In this object I see
calen.startdate => datetime.datetime(2015, 12, 9, 0, 0)
all right.
in pqAdmin3, postgres DB this field = "2015-12-09 08:00:00+02"
wrong 8 hours!!!! ->6+2
When I select this object calen.startdate
datetime.datetime(2015, 12, 9, 6, 0, tzinfo=<UTC>)
extra 6:00!!!!
I tried to make a complete date, now(),but all the same is extra 6 hours
Do not use django.utils.datetime for database fields. Use timezone instead.
from django.utils import timezone
now = timezone.now()

how can i get the right datetime info to the user registered date in django?

i create a website using django .and now i want show the number of users registered today,
so i write this code
from django.utils import timezone
from django.contrib.auth import get_user_model
um=get_user_model()
now=timezone.now()
todayusers=um.objects.filter(date_joined__day=now.day,date_joined__month=now.month,date_joined__year=now.year).count()
today it is 4th july 2014 ,and i find today mywebsite get two users registered
but it show todayusers =0
i do not knwo why ?
so i change the code to make it simple
todayusers=um.objects.filter(date_joined__day=4).count()
it show todayusers=0
and i change it to
todayusers=um.objects.filter(date_joined__day=3).count()
ok ,this time ,it show todayusers=2
i find one of the user ,its user id is 13,so i get that user
u13=um.objects.get(ud=13)
now i check its date_joined ,this datetime filed
u13.date_joined.day=4
that means ,it should be 4th july ,why when i query it in django ,it can not find
my django TIME_ZONE = 'Asia/Shanghai'
any one can help me
See if this works
todayusers=um.objects.filter(date__year='2014',
date__month='07', date__day='04').count()
OR
start_date = datetime.date(2014, 7, 4)
end_date = datetime.date(2014, 7, 4)
todayusers = um.objects.filter(date__range=(start_date, end_date)).count()
OR
todayusers = um.objects.filter(date__gte=datetime.datetime.today()).count()
OR
from pytz import timezone
from datetime import datetime
asia_sh = timezone("Asia/Shanghai")
startdate = datetime(2014, 07, 04, 0, 0, 0, tzinfo=asia_sh)
enddate = datetime(2014, 07, 04, 23, 59, 59, tzinfo=aisa_sh)
todayusers = um.objects.filter(date__range=(start_date, end_date)).count()

Categories

Resources