Commits

Luke Plant committed 32462fb

Fixed end range of DateTimeFilter so that it respects the number of days in the month and doesn't wrap to the next month

Fixes issue #3

  • Participants
  • Parent commits 0bffeed

Comments (0)

Files changed (3)

 * Added and documented ``Filter.render_choice_object`` which can
   be overridden for easy customization of filters.
 
+* Fixed various bugs with DateTimeFilter
+
 Version 0.3.2
 -------------
 

File django_easyfilters/filters.py

             if range_type is MONTH:
                 first, last = 1, 12
             elif range_type is DAY:
-                first, last = 1, 31
+                first, last = 1, (results[0][0] + relativedelta(months=1, days=-1)).day
             else:
                 first = results[0][0].year
                 last = results[-1][0].year
             for i, bucket in enumerate(buckets):
                 count = sum(row[1] for row in bucket)
                 start_val = first + bucketsize * i
+                end_val = min(start_val + bucketsize, last)
                 start_date = dt_template.replace(**dict({range_type.dateattr: start_val}))
-                end_date = start_date + relativedelta(**dict({range_type.relativedeltaattr: bucketsize - 1}))
+                end_date = dt_template.replace(**dict({range_type.dateattr: end_val}))
 
                 choice = DateChoice.from_datetime_range(range_type, start_date, end_date)
                 date_choice_counts.append((choice, count))
         # (which might be nothing) to what can be chosen, to give context to the
         # link.
 
-        # Note this is used is bridging to the 'add' choices, and in bridging
+        # Note this is used in bridging to the 'add' choices, and in bridging
         # between 'remove' choices
 
         if len(choices) == 0:

File django_easyfilters/tests/filterset.py

         # Expect '10' and '20' as choices
         self.assertEqual(['10', '20'], [c.label for c in choices if c.link_type == FILTER_ADD])
 
+    def test_datetime_filter_day_ranges_end(self):
+        """
+        Test that the ranges for day selection end at the right point (e.g. 31)
+        """
+        # September
+        for i in range(1, 30):
+            Person.objects.create(name="Joe", date_of_birth=date(2011, 9, i))
+
+        params = MultiValueDict({'date_of_birth':['2011-09']})
+
+        f = DateTimeFilter('date_of_birth', Person, params)
+        qs = Person.objects.all()
+        qs_filtered = f.apply_filter(qs)
+        choices = f.get_choices(qs_filtered)
+        self.assertEqual(choices[-1].label[-3:], "-30")
+
+        # October
+        for i in range(1, 31):
+            Person.objects.create(name="Joe", date_of_birth=date(2011, 10, i))
+
+        params = MultiValueDict({'date_of_birth':['2011-10']})
+
+        f = DateTimeFilter('date_of_birth', Person, params)
+        qs = Person.objects.all()
+        qs_filtered = f.apply_filter(qs)
+        choices = f.get_choices(qs_filtered)
+        self.assertEqual(choices[-1].label[-3:], "-31")
+
     def test_numericrange_filter_simple_vals(self):
         # If data is less than max_links, we should get a simple list of values.
         filter1 = NumericRangeFilter('price', Book, MultiValueDict(), max_links=20)