
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeGreat 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.
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:
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.
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().
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.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store