12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 |
- import re
- from datetime import timedelta
- from django.utils import timezone
- from django_filters import rest_framework as filters
- from django_filters.fields import IsoDateTimeField, RangeField
- from django_filters.widgets import DateRangeWidget
- # Workaround https://github.com/carltongibson/django-filter/issues/1403
- class StartEndDateRangeWidget(DateRangeWidget):
- """
- A range widget that uses 'start' and 'end' query params
- """
- suffixes = ["start", "end"]
- def suffixed(self, name, suffix):
- return suffix
- RELATIVE_TIME_REGEX = re.compile(r"now\s*\-\s*\d+\s*(m|h|d)\s*$")
- class RelativeIsoDateTimeField(IsoDateTimeField):
- """
- Allow relative terms like now or now-1h. Only 0 or 1 subtraction operation is permitted.
- Accepts
- - now
- - - (subtraction)
- - m (minutes)
- - h (hours)
- - d (days)
- """
- def strptime(self, value, format):
- # Check for relative time, if panic just assume it's a datetime
- result = timezone.now()
- if value == "now":
- return result
- if RELATIVE_TIME_REGEX.match(value):
- spaces_stripped = value.replace(" ", "")
- numbers = int(re.findall(r"\d+", spaces_stripped)[0])
- if spaces_stripped[-1] == "m":
- result -= timedelta(minutes=numbers)
- if spaces_stripped[-1] == "h":
- result -= timedelta(hours=numbers)
- if spaces_stripped[-1] == "d":
- result -= timedelta(days=numbers)
- return result
- return super().strptime(value, format)
- class StartEndRelativeIsoDateTimeRangeField(RangeField):
- widget = StartEndDateRangeWidget
- def __init__(self, *args, **kwargs):
- fields = (RelativeIsoDateTimeField(), RelativeIsoDateTimeField())
- super().__init__(fields, *args, **kwargs)
- class StartEndRelativeIsoDateTimeRangeFilter(filters.IsoDateTimeFromToRangeFilter):
- field_class = StartEndRelativeIsoDateTimeRangeField
|