Filter content by year range when start and end dates span multiple years
Great question! When you have content with date ranges (like 2022-02-03 to 2023-01-05) and want to filter them by year for a yearly archive, you need to check if the date range overlaps with the selected year.
Here's the approach: a content item should appear in a year's archive if either its start date OR end date falls within that year, or if the range spans across that entire year.
Solution
Assuming you have startDate and endDate fields in your documents:
// Filter for year 2022
*[_type == "yourType" && (
dateTime(startDate) >= dateTime("2022-01-01T00:00:00Z") &&
dateTime(startDate) < dateTime("2023-01-01T00:00:00Z")
) || (
dateTime(endDate) >= dateTime("2022-01-01T00:00:00Z") &&
dateTime(endDate) < dateTime("2023-01-01T00:00:00Z")
) || (
dateTime(startDate) < dateTime("2022-01-01T00:00:00Z") &&
dateTime(endDate) >= dateTime("2023-01-01T00:00:00Z")
)]This checks three conditions:
- Start date is in 2022
- End date is in 2022
- The range spans the entire year (starts before 2022 and ends after 2022)
With a parameter
For a reusable query with a year parameter:
*[_type == "yourType" && (
dateTime(startDate) >= dateTime($year + "-01-01T00:00:00Z") &&
dateTime(startDate) < dateTime(string(count([$year]) + $year) + "-01-01T00:00:00Z")
) || (
dateTime(endDate) >= dateTime($year + "-01-01T00:00:00Z") &&
dateTime(endDate) < dateTime(string(count([$year]) + $year) + "-01-01T00:00:00Z")
) || (
dateTime(startDate) < dateTime($year + "-01-01T00:00:00Z") &&
dateTime(endDate) >= dateTime(string(count([$year]) + $year) + "-01-01T00:00:00Z")
)]Then pass { year: 2022 } as your parameter.
Simpler approach with string comparison
If your dates are stored in ISO 8601 format (YYYY-MM-DD), you can actually use string comparison which is simpler:
*[_type == "yourType" && (
(startDate >= "2022-01-01" && startDate < "2023-01-01") ||
(endDate >= "2022-01-01" && endDate < "2023-01-01") ||
(startDate < "2022-01-01" && endDate >= "2023-01-01")
)]Your example (2022-02-03 to 2023-01-05) would correctly appear in both 2022 and 2023 archives, but not in 2024.
The key insight is checking for range overlap rather than trying to extract the year from each date. This is more reliable and works well with GROQ's capabilities, as GROQ doesn't have built-in functions for extracting year components like JavaScript's getFullYear().
Show original thread8 replies
Sanity – Build the way you think, not the way your CMS thinks
Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.