Filtering content based on year in a front-end yearly archive.
8 replies
Last updated: Nov 24, 2023
I
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
2024but if you're on
2022or
2023it should.
Nov 24, 2023, 5:45 PM
You could use the
Potential downside is that the year param probably needs to be handled as a string.
string::split()function to split on
-and get the first index:
*[_type == 'post' && string::split(date, "-")[0] == $year] // params { 'year': '2023', }
Nov 24, 2023, 5:51 PM
You can also replace the
This would filter the year 2023.
string::split()predicate with:
&& date >= "2023" && date < "2024"
Nov 24, 2023, 6:00 PM
I
thanks for your reply geoff! I'm curious, since it's a duration rather than just a simple date:
isn't it a bit more complicated?
🤔
duration:{…} 3 properties _type:duration start:2022-11-05T12:16:00.000Z end:2023-01-08T12:17:00.000Z
🤔
Nov 24, 2023, 6:04 PM
That may be different from the question I thought I was answering, which was about filtering by year, yearly archives, etc. I may have misunderstood you.
Nov 24, 2023, 6:06 PM
I think you could still use the comparison operators, but the
>=would be against
duration.startand
<would be against
duration.end. Does that accomplish what you’re after?
Nov 24, 2023, 6:07 PM
I
*[ _type == 'exhibition' && ( // Condition 1: Posts that started within the specified year (duration.start >= $startOfYear && duration.start <= $endOfYear) || // Condition 2: Posts that ended within the specified year (duration.end >= $startOfYear && duration.end <= $endOfYear) || // Condition 3: Posts that spanned the entire specified year (duration.start < $startOfYear && duration.end > $endOfYear) )]
Nov 24, 2023, 6:13 PM
I
chat gpt helped me out 🙂
Nov 24, 2023, 6:13 PM
A
GROQ string comparisons are using lexicographic ordering rules, just as in JavaScript.
That means that timestamps in the standard RFC 3339 and ISO 8601 formats, such as:
are lexicographically ordered, if they're in the same time zone.
In other words,
This is because lexicographic ordering ensures
This also means you can omit any trailing part when using
It seems hacky, but it actually isn't when you think about it. And it's fast. The
That means that timestamps in the standard RFC 3339 and ISO 8601 formats, such as:
2022-11-05T12:16:00.000Z
In other words,
laterDateTime > newerDateTimeis always true. The same goes for
>=,
<,
<=.
This is because lexicographic ordering ensures
2>
1and so on. Since such timestamps are written with the most significant part (year) first, and each part is always equally long, they are comparable:
This also means you can omit any trailing part when using
<=and
>=. For example,
"2023-03-02T00:00:00Z" >= "2023"will be true, and also true for any date past the year 2023.
It seems hacky, but it actually isn't when you think about it. And it's fast. The
string::split()trick also works, but is not optimized to an efficient filter operation.
Nov 24, 2023, 8:02 PM
Sanity– build remarkable experiences at scale
Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.