From b3e3d8b23ede2bbf4cfccaa3e91955b20a8d415f Mon Sep 17 00:00:00 2001 From: stumpylog <797416+stumpylog@users.noreply.github.com> Date: Thu, 20 Aug 2026 10:06:12 -0700 Subject: [PATCH] docs(search): correct the RFC3339 timestamp claim, it works when quoted The previous commit's warning said a timestamp carrying a time of day was not understood at all, and told users to fall back to whole-day range bounds. Both halves were wrong. Only the bare unquoted spelling fails: added:2005-01-01T00:00:00Z -> no match added:"2005-01-01T00:00:00Z" -> matches added:[2005-01-01T00:00:00Z to 2006-01-01T00:00:00Z] -> matches That is the ordinary quoting rule the surrounding docs already state, the same one "-1 week" and "next monday" obey, so present the timestamp as a working form rather than as a limitation and drop the false workaround: range bounds carrying a time of day work fine. A bound must be bare inside range brackets, where quoting it is rejected outright, so document both halves of the rule rather than just "quote it". Keep the zero-width warning distinct from the quoting rule now sitting above it, since a reader who just learned quoting rescues "next monday" would otherwise assume it rescues "-3 days". It does not: re-verified against documents added at exactly those instants, the quoted offsets still match only that one instant. Pin the working spellings, which is the assertion that was missing: nothing covered the quoted or range-bound forms, so a regression of a working feature went undetected. Also pin that quoting does not rescue the zero-width group. Co-Authored-By: Claude Opus 5 --- docs/usage.md | 7 +++++-- .../tests/search/test_documented_syntax.py | 14 +++++++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/docs/usage.md b/docs/usage.md index 8bc8f270c..63412bb49 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -981,18 +981,21 @@ created:2005-03-04 added:january modified:"next monday" added:"last monday" +added:"2005-01-01T00:00:00Z" created:[2005-01-01 to 2005-01-31] +added:[2005-06-15T09:00:00Z to 2005-06-15T17:00:00Z] ``` - `tomorrow`, like `today` and `yesterday`, covers that whole day. - An ISO date such as `2005-03-04` covers that whole day, and `2005-01` covers that whole month. - A month name such as `january` covers that whole month in the current year. - `next ` and `last ` each cover that whole day and must be quoted. A bare weekday name such as `monday` is not accepted. -- A range takes two of the above as its bounds, for example `created:[2005 to 2009]` or `added:[2005-01-01 to 2005-01-31]`. +- A full timestamp such as `2005-01-01T00:00:00Z` matches that exact instant. Like the other expressions above, it has to be quoted when it stands on its own: `added:"2005-01-01T00:00:00Z"`. +- A range takes two of the above as its bounds, for example `created:[2005 to 2009]` or `added:[2005-01-01 to 2005-01-31]`. Bounds may carry a time of day, and inside the brackets they are written without quotes. !!! warning - `now`, `noon`, `midnight` and relative offsets such as `"-3 days"` or `"-1 week"` are accepted by the parser but resolve to a single instant rather than to a span of time, so they match only a document whose timestamp is exactly that instant, which in practice means no documents at all. Spellings like `now-3days` and `"3 days ago"` are rejected outright. A timestamp carrying a time of day, such as `2005-01-01T00:00:00Z`, is not understood either: the time portion is split off and searched as ordinary text, which usually leaves the query matching nothing. To bound a search by time, use a range with whole-day bounds instead. + `now`, `noon`, `midnight` and relative offsets such as `"-3 days"` or `"-1 week"` are accepted by the parser but resolve to a single instant rather than to a span of time, so they match only a document whose timestamp is exactly that instant, which in practice means no documents at all. Quoting does not change this. Spellings like `now-3days` and `"3 days ago"` are rejected outright. #### Searching custom fields diff --git a/src/documents/tests/search/test_documented_syntax.py b/src/documents/tests/search/test_documented_syntax.py index 0e5340a8e..d9a4d5530 100644 --- a/src/documents/tests/search/test_documented_syntax.py +++ b/src/documents/tests/search/test_documented_syntax.py @@ -271,6 +271,11 @@ class TestDocumentedDateForms: ("added:2005-03", "old"), ("added:[2005-01-01 to 2005-12-31]", "old"), ("added:[2005 to 2009]", "old"), + # A full timestamp works, but only quoted when it stands alone, + # and only unquoted when it is a range bound. The bare standalone + # spelling is pinned as a non-match below. + ('added:"2005-03-04T15:30:00Z"', "old"), + ("added:[2005-03-04T09:00:00Z to 2005-03-04T17:00:00Z]", "old"), ], ) def test_documented_date_form_matches_its_day_or_month( @@ -291,12 +296,19 @@ class TestDocumentedDateForms: "added:now", "added:noon", "added:midnight", + # Quoting is what rescues the other multi-word date expressions, + # so pin that it does not rescue these: the problem is the width + # of the resulting range, not the way the value is delimited. + 'added:"now"', + 'added:"midnight"', 'added:"-3 days"', 'added:"-1 week"', # The trap: this reports no diagnostics but parses as # And(added:now, "3", "days") - added:now plus stray text. "added:now - 3 days", - # A time-of-day component is split off and searched as text. + # The bare, unquoted spelling of a full timestamp. The quoted and + # range-bound spellings above do work and match this fixture's + # document; only this one silently degrades to a non-match. "added:2005-03-04T15:30:00Z", ], )