Filter content by year range when start and end dates span multiple years

8 replies
Last updated: Jan 18, 2026
I have content that have a duration (example: 2022–02–03 to 2023–01–05), how can I filter these on year? Imagine a front-end having a yearly archive, so the example should not show up if you're on
2024
but if you're on
2022
or
2023
it should.
AI Update

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:

  1. Start date is in 2022
  2. End date is in 2022
  3. 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 thread
8 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.

Was this answer helpful?