使用尼泊尔日期时Django查询报错,如何实现合法日期范围查询?
Hey there! The issue you're facing makes total sense—Django's default DateField strictly validates dates against the Gregorian calendar, which doesn't recognize April 32nd (since the Nepali Bikram Sambat calendar has different month lengths). Let's break down the best ways to fix this:
Option 1: Convert Nepali (BS) Dates to Gregorian (AD) for Queries
The most straightforward fix is to translate your BS date range into valid Gregorian dates before querying. Use a reliable Python library like nepalicalendar to handle the conversion seamlessly:
First, install the library:
pip install nepalicalendar
Then modify your query code to convert the BS dates to AD:
from nepalicalendar import BSDate # Convert your BS start/end dates to valid Gregorian dates bs_start = BSDate(2077, 4, 1) ad_start_date = bs_start.to_ad() bs_end = BSDate(2077, 4, 32) ad_end_date = bs_end.to_ad() # Now query using the valid Gregorian dates Django expects search_range = Trans.objects.filter( tr_date__gte=ad_start_date, tr_date__lte=ad_end_date )
This works because ad_start_date and ad_end_date will be valid Gregorian dates that Django's DateField accepts, while still targeting the exact range of Nepali dates you need.
Option 2: Custom Form Field for BS Date Input
If you're accepting user input of BS dates (e.g., via a form), create a custom form field that automatically converts BS dates to Gregorian before validation. This prevents the ValidationError at the input stage:
from django import forms from nepalicalendar import BSDate class BSDateInputField(forms.DateField): def to_python(self, value): if not value: return None try: # Split the BS date string into year, month, day components bs_year, bs_month, bs_day = map(int, value.split('-')) # Convert to Gregorian date return BSDate(bs_year, bs_month, bs_day).to_ad() except (ValueError, TypeError): raise forms.ValidationError("Please enter a valid Nepali date in YYYY-MM-DD format")
Use this field in your form, and when users submit 2077-04-32, it'll get converted to the correct Gregorian date without triggering Django's validation error.
Option 3: Store BS Dates Separately (If Required)
If you absolutely need to store BS dates directly in the database (instead of Gregorian), avoid using DateField since it won't recognize non-Gregorian valid dates. Instead:
- Store the BS year, month, and day as separate
IntegerFields in your model. - Query using these integer fields to target the desired range:
search_range = Trans.objects.filter( bs_year=2077, bs_month=4, bs_day__gte=1, bs_day__lte=32 )
This bypasses Django's date validation entirely, but note that you'll lose built-in date-related features (like easy date sorting), so use this only if the first two options don't fit your use case.
内容的提问来源于stack exchange,提问作者Rishi

