i created a todo model in django with a method of clear old todo that is supposed to delete todos that were published more than 24 hours ago, i can't seem to be able to compare datetime and timezone instances in my if condition
class Todo(models.Model):
description = models.CharField(max_length=200)
Todo_date = models.DateTimeField('Todo Date')
pub_date = models.DateTimeField('Date Published')
def __str__(self):
return self.description
def create_todo(self, description, Todo_date, pub_date):
todo = Todo(description=description,
Todo_date=Todo_date, pub_date=pub_date)
todo.save()
return todo
def delete_todo(self, description):
todo = Todo.objects.get(description=description)
todo.delete()
return "Todo removed"
def clear_old_todo(self):
todos = Todo.objects.all()
time_limit = datetime.timedelta(hours=24)
for todo in todos:
if (timezone.now()-todo.pub_date) > (timezone.now()-time_limit):
todo.delete()
return "old todo cleared"
>>> Todo.clear_old_todo("self")
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "E:\projects\1stDjangoApp\ToDoList\ToDo\models.py", line 36, in clear_old_todo
if (timezone.now()-todo.pub_date) > (timezone.now()-time_limit):
TypeError: '>' not supported between instances of 'datetime.timedelta' and 'datetime.datetime'
Subtracting a datetime from a datetime gives you a timedelta, the difference between the two times. Subtracting a timedelta from a datetime gives you a datetime, a new timestamp different from the first by the amount of the timedelta.
In timezone.now()-todo.pub_date, you're subtracting two datetime.
In timezone.now()-time_limit, you're subtract a timedelta from a datetime.
You either want to do timezone.now() - todo.pub_date to produce a timedelta and check if that timedelta is >/< some specific value (i.e. compare two timedeltas), or you want to do timezone.now() - time_limit to produce a datetime in the past and check whether that is >/< your todo.pub_date datetime.
Related
I am sending some dates from the front made in vue. I am receiving these dates in my viewSet in django, I want to filter data from these received dates.
I have two questions:
How do I convert dates into Python Datetime?
How do I filter the dates equal or greater or equal or less. => <=
In other words: bring records whose date is equal to or greater than another date.
date format in the front: 2021-08-03 10:12:14
date format in the back:
# print(type(fechas['desde']))
fecha <class 'str'>
# print(fechas['desde'])
fecha 2021-08-03 10:12:14
VIEWSET:
class TecnicosViewSet(
mixins.CreateModelMixin,
mixins.UpdateModelMixin,
mixins.RetrieveModelMixin,
mixins.ListModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
queryset = Tecnico.objects.all()
serializer_class = Tecnicoserializer
def list(self, request):
dataQ = request.GET
newQ = json.dumps(dict(dataQ))
newQ1= json.loads(newQ)
tecnicos = ''
fechas= json.loads(newQ1['fechas'][0])
for item in newQ1['tecnicos']:
itemN = json.loads(item)
tecnicos = itemN['tecnicos']
print('fechas', fechas['desde'], fechas['hasta'])
# fecha = datetime.strptime(fechas['desde'], '%Y-%m-%d %H:%M')
print('fecha', type(fechas['desde']))
print('fecha', fechas['desde'])
for id in tecnicos:
ordenes = Servicio_realizados_orden_trabajo.objects.filter(date_range = [fechas['desde'], fechas['hasta']]).filter(state = 1).filter(tecnico = id)
ordenS = ServicioRealizadosserializer(ordenes, many=True)
return Response({'OK'})
As I fixed before: I want to convert that date into understandable python format and then use that transformed date to filter data by that date.
The for loop seen in the viewsewt is where I am trying to do the query.
I think you are pretty close based off your code...
You basically use strptime to convert a string to date in a desired format and then once you have created python datetime objects you can compare them.
Here's an example:
from datetime import datetime
date = datetime.strptime("2021-08-03 10:12:14", "%Y-%m-%d %H:%M:%S")
if date >= datetime.strptime("2021", "%Y"):
print('After or in 2021')
if date >= datetime.strptime("2021-09", "%Y-%m"):
print('After or in September 2021')
I created a form with a DateField and a TimeField. When printing these from the routes.py I get these example values:
TimeField: 17:30:00
DateField: 2021-07-12
How can I turn those values into a datetime object, which I can submit to my Postgres Database? The required object format is DateTime. The Postgres Table is set up as TIMESTAMPTZ. I tried replace() to add the time to the DateField Data. But that does not work. I am new to datetimes and such, so please excuse my ignorance. How do the Timezones work? because I probably need to add the timezone somehow for the TIMESTAMPTZ, right?
Below is the minimal code for the functioning
forms.py
class CreateEvent(Form):
dt = DateField('DateTimePicker')
start_time = TimeField('Start')
submit = SubmitField("Submit")
models.py
class Events(db.Model):
__tablename__='events'
eid = db.Column(db.Integer, primary_key = True)
event_day = db.Column(db.DateTime, nullable=False)
start_time = db.Column(db.DateTime, nullable=False)
def __init__(self, event_day, start_time):
self.event_day = event_day
self.start_time = start_time
routes.py
if request.method == 'POST':
if form.validate() == False:
return render_template('create.html', form=form)
else:
event_day = form.dt.data
start_time = form.start_time.data
print(start_time)
print(event_day)
start_time = event_day.replace(time=start_time)
newevent = Events(event_day, start_time)
db.session.add(newevent)
db.session.commit()
return "Success"
Just in case, here is the Postgres Create Statement for the table:
CREATE TABLE events (
eid serial PRIMARY KEY NOT NULL,
event_day TIMESTAMPTZ NOT NULL,
start_time TIMESTAMPTZ NOT NULL,
);
pip install dateutil:
https://dateutil.readthedocs.io/en/stable/
then:
from dateutil.parser import parse
TimeField = "17:30:00"
DateField = "2021-07-12"
parse(DateField + ' ' + TimeField)
datetime.datetime(2021, 7, 12, 17, 30)
You probably don't need to add a timezone, Postgres will use the timezone setting for the server. Postgres does not actually store the timezone in a timestamptz field. It just uses the timezone setting to rotate the value to a UTC time for storage.
Not tested but as an example, and you may have to install pytz from PIP (if not already present on your system). Python knows so-called naive datetime objects (that have no timezone context), and time zone-aware datetime objects.
So the goal is to build a string with the date and the time, then parse it into a datetime object. Next, we add the desired time zone (in this example it is assumed US/Pacific so change as appropriate).
import datetime
import pytz
TimeField = "17:30:00"
DateField = "2021-07-12"
current_tz = pytz.timezone('US/Pacific')
# parse string into naive datetime object
dt_naive = datetime.datetime.strptime(f"{DateField} {TimeField}", "%Y-%m-%d %H:%M:%S")
# convert to time zone-aware datetime
dt_aware = current_tz.localize(dt_naive)
Say I have a model:
Mymodel(models.Model):
endtimestamp = models.DateTimeField(null=True)
I need a query to get all Mymodel objects with endstimestamp between today's midnight and yesterday midnight.
what have I tried:
today = datetime.datetime.today()
todays_midnigh = datetime.datetime.fromtimestamp(
today.strftime('%Y-%m-%d 00:00:00.0')
)
yesterday_midnight = todays_midnight - datetime.timedelta(days=1)
objs = Mymodel.objects.filter(endtimestamp__range(
yesterday_midnight, todays_midnight)
)
But this line todays_midnigh = datetime.datetime.fromtimestamp(today.strftime('%Y-%m-%d 00:00:00.0')) does not work, and I know there must be a much pythonic and clear way of achieving this.
assumming this from datetime import datetime as dt, do that:
today = dt.today()
todays_midnigh = dt.combine(today,dt.max.time())
or
todays_midnigh = dt.combine(today,dt.min.time())
as appropriate
I am in the process of migrating an application from django 1.2 To 1.4.
I have a daily task object which contains a time of day that task should be completed:
class DailyTask(models.Model):
time = models.TimeField()
last_completed = models.DateTimeField()
name = models.CharField(max_length=100)
description = models.CharField(max_length=1000)
weekends = models.BooleanField()
def __unicode__(self):
return '%s' % (self.name)
class Meta:
db_table = u'dailytask'
ordering = ['name']
In order to check if a task is still required to be completed today, I have the following code:
def getDueDailyTasks():
dueDailyTasks=[]
now = datetime.datetime.now()
try:
dailyTasks = DailyTask.objects.all()
except dailyTask.DoesNotExist:
return None
for dailyTask in dailyTasks:
timeDue = datetime.datetime(now.year,now.month,now.day,dailyTask.time.hour,dailyTask.time.minute,dailyTask.time.second)
if timeDue<now and timeDue>dailyTask.last_completed:
if dailyTask.weekends==False and now.weekday()>4:
pass
else:
dueDailyTasks.append({'id':dailyTask.id,
'due':timeDue,
'name': dailyTask.name,
'description':dailyTask.description})
return dueDailyTasks
This worked fine under 1.2, But under 1.4 I get the error:
can't compare offset-naive and offset-aware datetimes
due to the line
if timeDue<now and timeDue>dailyTask.last_completed
and both comparison clauses throw this error.
I have tried making timeDue timezone aware by adding pytz.UTC as an argument, but this still raises the same error.
I've read some of the docs on timezones but am confused as to whether I just need to make timeDue timezone aware, or whether I need to make a fundamental change to my db and existing data.
Check the thorough document for detail info.
Normally, use django.utils.timezone.now to make an offset-aware current datetime
>>> from django.utils import timezone
>>> timezone.now()
datetime.datetime(2012, 5, 18, 13, 0, 49, 803031, tzinfo=<UTC>)
And django.utils.timezone.make_aware to make an offset-aware datetime
>>> timezone.make_aware(datetime.datetime.now(), timezone.get_default_timezone())
datetime.datetime(2012, 5, 18, 21, 5, 53, 266396, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>)
You could then compare both offset-aware datetimes w/o trouble.
Furthermore, you could convert offset-awared datetime to offset-naive datetime by stripping off timezone info, then it could be compared w/ normal datetime.datetime.now(), under utc.
>>> t = timezone.now() # offset-awared datetime
>>> t.astimezone(timezone.utc).replace(tzinfo=None)
datetime.datetime(2012, 5, 18, 13, 11, 30, 705324)
USE_TZ is True 'by default' (actually it's False by default, but the settings.py file generated by django-admin.py startproject set it to True), then if your DB supports timezone-aware times, values of time-related model fields would be timezone-aware. you could disable it by setting USE_TZ=False(or simply remove USE_TZ=True) in settings.
I am new with python and I am making a system that deals with request.GET method...
when i pass a date to the system, if it is exist then it will look for the database and show data according to that date and other dates, else it will display a date with other date...
here is my code :
from django.utils.xmlutils import SimplerXMLGenerator
from piston.handler import BaseHandler
from booking.models import *
from django.db.models import *
from piston.utils import rc, require_mime, require_extended, validate
import datetime
class BookingHandler(BaseHandler):
allowed_method = ('GET', 'POST', 'PUT', 'DELETE')
fields = ('id', 'date_select', 'product_name', 'quantity', 'price','totalcost', 'first_name', 'last_name', 'contact', 'product')
model = Booking
#for product availability
def read(self, request, id, date_select):
if not self.has_model():
return rc.NOT_IMPLEMENTED
try:
prod = Product.objects.get(id=id)
merge = []
checkDateExist = Booking.objects.filter(date_select=date_select)
if checkDateExist.exists():
entered_date = Booking.objects.values('date_select').distinct('date_select').filter(date_select=date_select)[0]['date_select']
else:
enteredTemp_date = datetime.datetime.strptime(date_select, '%Y-%m-%d')
entered_date = datetime.datetime.strftime(enteredTemp_date,'%Y-%m-%d')
delta = datetime.timedelta(days=3)
target_date = entered_date - delta
day = 1
for x in range(0,5):
delta = datetime.timedelta(days=x+day)
new_date = target_date + delta
maximumProdQuantity = prod.quantity
quantityReserve = Booking.objects.filter(date_select=new_date, product=prod).aggregate(Sum('quantity'))['quantity__sum']
if quantityReserve == None:
quantityReserve = 0
data1 = {'maximum_guest': maximumProdQuantity, 'avialable': quantityReserve, 'date': new_date}
merge.append(data1)
return merge
except self.model.DoesNotExist:
return rc.NOT_HERE
and i got this error :
Piston/0.3dev (Django 1.3.1) crash report:
Method signature does not match.
Signature should be: id, date_select
Exception was: unsupported operand type(s) for -: 'str' and 'datetime.timedelta'
i think in my else statement the entered_date become a string, i do this line entered_date = datetime.datetime.strftime(enteredTemp_date,'%Y-%m-%d') so that the date format will be not 2011-12-01 00:00:00 i just only need 2011-12-01. my question is how can i get 2011-12-01 that is datetime format not a string?
can anyone can give a hint or an idea about my case?
thanks
strftime returns a formatted string. If you want to discard time portion of datetime object, use datetime.date:
entered_date = datetime.datetime.strptime(date_select, '%Y-%m-%d')
entered_date = entered_date.date()
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
'''hi, your need to transfor the stirng to the date formation.
use this :
'''
import datetime
import time
from datetime import timedelta
today = datetime.date.today()
print(today)
# 0r
from datetime import date
today1 = date.today()
print(today1)
tomorrow = today - datetime.timedelta(days=7)
print(str(tomorrow))
# it is ok, because the today is date formation
#but the following it is not ok
event_day= "2021-05-18"
tomorrow = event_day - datetime.timedelta(days=7)
# you should do this:
text='2021-5-10'
x=datetime.datetime.strptime(text, '%Y-%m-%d').date()
print(x) # it's ok
# hope this help you!