Assuming there's a starting time from 00:00 to 00:00 every day, how best are Django objects filtered by time, based on the current day? I initially came up with this:
from django.utils import timezone
yesterday = timezone.now() - timezone.timedelta(1)
qs = Foo.objects.filter(date__gte=yesterday)
##
yesterday = datetime.date.today() - datetime.timedelta(1)
qs = Foo.objects.filter(date__gte=yesterday)
However, this is not particularly right. I would prefer time starting exactly from 00:00 to timezone.now() -so something like Foo.objects.filter(date__range=[00:00, timezone.now()]) Thank you.
Assuming date field is actually a datetime.
If you need all records with date containing todays date, you can use __date:
qs = Foo.objects.filter(date__date=timezone.now())
If you need, for example, all yesterdays records, but with time not greater than timezone.now(), this way:
qs = Foo.objects.filter(
date__date=timezone.now() - timezone.timedelta(1),
date__lte=timezone.now() - timezone.timedelta(1)
)
Yevgeniy Kosmak's answer is correct, use datetime_field__date= filter.
Here are the Django docs
Also you can use date/datetime - timedelta() pattern with others arguments in timedelta, like
timedelta(
days=50,
seconds=27,
microseconds=10,
milliseconds=29000,
minutes=5,
hours=8,
weeks=2
)
docs are here
I have model with two fields:
class Event(models.Model):
date = models.DateField(_(u'Date'))
time = models.TimeField(_(u'Time'))
I need to find all objects where date&time is in 24 hours from now.
I am able to do this when using DateTime field, but I am not sure how to achieve this when fields are separated. Thanks in advance.
For the simple case (not sure if all are simple cases though...), this should do the trick:
import datetime
today = datetime.datetime.now()
tomorrow = today + datetime.timedelta(days=1)
qs_today = queryset.filter(
date=today.date(),
time__gte=today.time(),
)
qs_tomorrow = queryset.filter(
date=tomorrow.date(),
time__lt=tomorrow.time(),
)
qs = qs_today | qs_tomorrow
As you state you can do what you want with a DateTimeField, but now with the separate fields, I understand your issue is how to combine them.
Looking at the docs for DateField - your date variable is a datetime.date instance and similarly for TimeField time is a datetime.time. You can convert these into a datetime.datetime by using combine()
import datetime as dt
datetime = dt.datetime.combine(date,time)
You now have the datetime object as you would have from DateTimeField. You say in the question you can do the 24 hour from now bit from there, although let me know in comments if you need that made explicit.
Caveat I combine will fail where one of the fields is None - you state this can't happen, so I haven't added any error checking or validation of this.
EDIT
It occurs to me that the problem may not be the combination, but adding the calculated field to the Event object. You could look at this Q&A, or this. In summary you define the calculated value in a function in your class and then make it a property - either with a decorator or a function call. There's an example in the docs, adapting for your case:
def _get_datetime(self):
'''Returns a combination of date and time as a datetime'''
return dt.datetime.combine(self.date,self.time)
datetime = property(_get_datetime)
This should behave in the same way as you would expect a DateTimeField to behave.
You can use Q objects to search for "yesterday after current time or today before current time":
from django.db.models import Q
from .models import Event
from datetime import datetime, timedelta
def get_event_during_last_day():
now = datetime.now()
today = now.date()
yesterday = (now - timedelta(day=1)).date()
time = now.time()
query_yesterday = Q(date=yesterday, time__gt=time)
query_today = Q(date=today, time__lt=time)
return Event.objects.filter(query_yesterday | query_today)
I have a queryste:
winner_check = Winner.objects.filter(win_date=date.today())
where win_date is datetime and date.today() gives only date... Is there anyway that I can convert win_date to only date and filter this queryset.
I want to filter all the winners which have same date.
Thanks in advance.
You can't. But you can create range from 2 datetimes and filter your queryset by it. Also you can separately filter by win_date__year, win_date__month and win_date__day.
You can filter using __year, __month and __day:
today = date.today()
Winner.objects.filter(win_date__year=today.year,
win_date__month=today.month,
win_date__day=today.day)
docs
The most efficient way is to use the __range lookup between two datetimes or the combination of __gte/__lt lookups for today/tomorrow dates:
import datetime
today = datetime.date.today()
tomorrow = today + datetime.timedelta(days=1)
winner_check = Winner.objects.filter(win_date__gte=today,
win_date__lt=tomorrow)
This will lead to filtering the win_date from TODAY 0:00:00 to TODAY 23:59:59
I have a model
class Booked(models.Model):
start_date_time = models.DateTimeField()
end_date_time = models.DateTimeField()
resource = models.ForeignKey(Resouce)
How do I check if a particular datetime range doesn't fall between the start or end datetimes of any of the booked objects?
I want to check if I can book a resource with say book_start_date and book_end_date without it being already booked during that range
Use __lte and __gte with exists() to check if there is something in the date range:
Booked.objects.exists(start_date_time__lte=book_end_date,
end_date_time__gte=book_start_date)
See also: Determine Whether Two Date Ranges Overlap.
I am trying to filter a DateTimeField comparing with a date. I mean:
MyObject.objects.filter(datetime_attr=datetime.date(2009,8,22))
I get an empty queryset list as an answer because (I think) I am not considering time, but I want "any time".
Is there an easy way in Django for doing this?
I have the time in the datetime setted, it is not 00:00.
Such lookups are implemented in django.views.generic.date_based as follows:
{'date_time_field__range': (datetime.datetime.combine(date, datetime.time.min),
datetime.datetime.combine(date, datetime.time.max))}
Because it is quite verbose there are plans to improve the syntax using __date operator. Check "#9596 Comparing a DateTimeField to a date is too hard" for more details.
YourModel.objects.filter(datetime_published__year='2008',
datetime_published__month='03',
datetime_published__day='27')
// edit after comments
YourModel.objects.filter(datetime_published=datetime(2008, 03, 27))
doest not work because it creates a datetime object with time values set to 0, so the time in database doesn't match.
Here are the results I got with ipython's timeit function:
from datetime import date
today = date.today()
timeit[Model.objects.filter(date_created__year=today.year, date_created__month=today.month, date_created__day=today.day)]
1000 loops, best of 3: 652 us per loop
timeit[Model.objects.filter(date_created__gte=today)]
1000 loops, best of 3: 631 us per loop
timeit[Model.objects.filter(date_created__startswith=today)]
1000 loops, best of 3: 541 us per loop
timeit[Model.objects.filter(date_created__contains=today)]
1000 loops, best of 3: 536 us per loop
contains seems to be faster.
Now Django has __date queryset filter to query datetime objects against dates in development version. Thus, it will be available in 1.9 soon.
Mymodel.objects.filter(date_time_field__contains=datetime.date(1986, 7, 28))
the above is what I've used. Not only does it work, it also has some inherent logical backing.
As of Django 1.9, the way to do this is by using __date on a datetime object.
For example:
MyObject.objects.filter(datetime_attr__date=datetime.date(2009,8,22))
This produces the same results as using __year, __month, and __day and seems to work for me:
YourModel.objects.filter(your_datetime_field__startswith=datetime.date(2009,8,22))
assuming active_on is a date object, increment it by 1 day then do range
next_day = active_on + datetime.timedelta(1)
queryset = queryset.filter(date_created__range=(active_on, next_day) )
You can do like this
MyObject.objects.filter(datetime_field__date=datetime.date(2009,8,22))
or if you want to filter between 2 dates
MyObject.objects.filter(
datetime_field__date__range=(datetime.date(2009,8,22), datetime.date(2009,9,22))
)
You can filter by the Date as per as the date format is the same with your django date format. Default format is ISO YYYY-MM-DD
target_date = "2009-08-22"
qs = MyObject.objects.filter(datetime_attr__date=target_date)
There's a fantastic blogpost that covers this here: Comparing Dates and Datetimes in the Django ORM
The best solution posted for Django>1.7,<1.9 is to register a transform:
from django.db import models
class MySQLDatetimeDate(models.Transform):
"""
This implements a custom SQL lookup when using `__date` with datetimes.
To enable filtering on datetimes that fall on a given date, import
this transform and register it with the DateTimeField.
"""
lookup_name = 'date'
def as_sql(self, compiler, connection):
lhs, params = compiler.compile(self.lhs)
return 'DATE({})'.format(lhs), params
#property
def output_field(self):
return models.DateField()
Then you can use it in your filters like this:
Foo.objects.filter(created_on__date=date)
EDIT
This solution is definitely back end dependent. From the article:
Of course, this implementation relies on your particular flavor of SQL having a DATE() function. MySQL does. So does SQLite. On the other hand, I haven’t worked with PostgreSQL personally, but some googling leads me to believe that it does not have a DATE() function. So an implementation this simple seems like it will necessarily be somewhat backend-dependent.
MyObject.objects.filter(datetime_attr__date=datetime.date(2009,8,22))
Here is an interesting technique-- I leveraged the startswith procedure as implemented with Django on MySQL to achieve the result of only looking up a datetime through only the date. Basically, when Django does the lookup in the database it has to do a string conversion for the DATETIME MySQL storage object, so you can filter on that, leaving out the timestamp portion of the date-- that way %LIKE% matches only the date object and you'll get every timestamp for the given date.
datetime_filter = datetime(2009, 8, 22)
MyObject.objects.filter(datetime_attr__startswith=datetime_filter.date())
This will perform the following query:
SELECT (values) FROM myapp_my_object \
WHERE myapp_my_object.datetime_attr LIKE BINARY 2009-08-22%
The LIKE BINARY in this case will match everything for the date, no matter the timestamp. Including values like:
+---------------------+
| datetime_attr |
+---------------------+
| 2009-08-22 11:05:08 |
+---------------------+
Hopefully this helps everyone until Django comes out with a solution!
See the article Django Documentation
ur_data_model.objects.filter(ur_date_field__gte=datetime(2009, 8, 22), ur_date_field__lt=datetime(2009, 8, 23))
Hm.. My solution is working:
Mymodel.objects.filter(date_time_field__startswith=datetime.datetime(1986, 7, 28))
Model.objects.filter(datetime__year=2011, datetime__month=2, datetime__day=30)
In Django 1.7.6 works:
MyObject.objects.filter(datetime_attr__startswith=datetime.date(2009,8,22))
person = Profile.objects.get(id=1)
tasks = Task.objects.filter(assigned_to=person, time_stamp__year=person.time_stamp.utcnow().year)
all my model do have time_stamp so I used the person objects to obtain the current year
You can filter between some day ranges
2016-01-01 00:00:00 <--> 2016-04-01 23:59:59.99999
User.objects.filter(date_joined__gte=datetime.combine(datetime.strptime('2016-
01-01', '%Y-%d-%m'), datetime.min.time()),
date_joined__lte=datetime.combine(datetime.strptime('2016-04-01', '%Y-%d-%m'),
datetime.max.time())).count()
2016-01-01 00:00:00 <--> 2016-01-14 00:00:00
User.objects.filter(date_joined__gte='2016-01-01', date_joined__lte='2016-1-14').count()
Just as simple as that if you have a datetimefield your can use datetime.date.today()
context['now'] = Mymodel.objects.filter(date_time_field=datetime.date.today())