How to use timedelta with timezone.now as default? - python

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!

Related

Django Timezone Configuration

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))

how can i compare timezone.now and item.deadline

Hi I want service old book sale service for university student
I create ItemPost model and when user post their books, ItemPost's deadline saved in deadline
from django.db import models
from django.conf import settings
from django.utils import timezone
def localtime():
return timezone.localtime(timezone.now())
class ItemPost(models.Model):
title = models.TextField(
)
created_at = models.DateTimeField(
default=localtime
)
is_deleted = models.BooleanField(
default=False,
verbose_name="삭제된 포스트",
)
# 마감날짜를 구하는 함수
def deadline_def(self):
year_of_item_created = self.created_at.year
if self.created_at.month <= 6:
return timezone.datetime(year_of_item_created, 6, 30)
else:
return timezone.datetime(year_of_item_created, 12, 31)
deadline = property(deadline_def)
# 등록된 학기가 끝난 포스트인지 확인
def is_ended_semester_def(self):
now = timezone.now()
if now > self.deadline:
return True
return False
is_ended_semester = property(is_ended_semester_def)
def __str__(self):
return self.title
I want compare item's deadline, timezone.now()
and return True or False
but I can't if I command item.is_ended_semester
TypeError: can't compare offset-naive and offset-aware datetimes
how can i solved this problem?
item.deadline
> datetime.datetime(2017, 6, 30, 0, 0)
timezone.now()
> datetime.datetime(2017, 7, 14, 8, 50, 57, 91304, tzinfo=<UTC>)
I solved my problem, using timezone.utc
# 마감날짜를 구하는 함수
def deadline_def(self):
year_of_item_created = self.created_at.year
if self.created_at.month <= 6:
return timezone.datetime(year_of_item_created, 6, 30, tzinfo=timezone.utc)
else:
return timezone.datetime(year_of_item_created, 12, 31, tzinfo=timezone.utc)

Django get months from models.DateTimeField

Is it possible to filter a models.DateTimeField but only get the month in the filter object?
The field is:
time_stamp = models.DateTimeField(
default=timezone.now)
When I filter it, this is what I get:
[datetime.datetime(2016, 9, 22, 15, 2, 48, 867473, tzinfo=),
datetime.datetime(2016, 9, 22, 15, 4, 22, 618675, tzinfo=),
datetime.datetime(2016, 9, 22, 15, 5, 20, 939593, tzinfo=)]
The filter returns 3 rows, but clearly there is too much information. I only require the months, and maybe the year.
How can I achieve this?
Any help or direction would be appreciated,
Thanks
If you are using django 1.10.x there is Extract db function
from django.db.models.functions import Extract
months = MyModel.objects.annotate(month_stamp=Extract('time_stamp', 'month')).values_list('month_stamp', flat=True)
For django 1.9.x
from django.db.models import Func
def Extract(field, date_field='DOW'):
template = "EXTRACT({} FROM %(expressions)s::timestamp)".format(date_field)
return Func(field, template=template)
months = MyModel.objects.annotate(month_stamp=Extract('time_stamp', 'month')).values_list('month_stamp', flat=True)
You can use propety:
Class your_model(models.Model):
time_stamp = models.DateTimeField(
default=timezone.now)
#property
def _get_year(self):
return self.time_stamp.strftime("%Y-%m")
year = property(_get_year) #EDIT

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()

django error validation datetime.datetime, tz format

I'm trying to filter publications by date, with this code but try it, I get this error
from datetime import datetime, timedelta
from_date = datetime.now() - timedelta(days=7)
data = Entry.objects.filter(date_publication=[from_date, datetime.now()])
[u"'[datetime.datetime(2014, 2, 24, 18, 27, 9, 451000), datetime.datetime(2014, 2, 17, 18, 27, 9, 451000)]' tiene un formato incorrecto. Debe ser del tipo YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]."]
class Productos(models.Model):
...
date_publication = models.DateTimeField(auto_now=True)
...
help me! :)
You can try with:
data = Entry.objects.filter(date_publication__gte=from_date, date_publication__lte=datetime.now())

Categories

Resources