From 61b3f376d0a0eac8e3b8969a2df05b5691b8f20c Mon Sep 17 00:00:00 2001 From: callumalpass Date: Thu, 6 Aug 2026 16:10:16 +1000 Subject: [PATCH] Add query execution timezone context --- 11-querying.md | 36 +++++++++++++++++++++++++++++++++- schemas/v0.3/query.schema.json | 5 +++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/11-querying.md b/11-querying.md index 6b1e041..092ca78 100644 --- a/11-querying.md +++ b/11-querying.md @@ -7,6 +7,7 @@ A query selects records from a collection. The canonical query-object schema is ```yaml types: [task] +timezone: Australia/Melbourne context: this: path: projects/alpha.md @@ -33,6 +34,33 @@ Schema violations and semantic preflight failures such as cyclic projection dependencies or duplicate result names produce `invalid_query` and abort before candidate evaluation. +## Temporal Execution Context + +A query MAY supply `timezone` as an IANA timezone identifier. It is ephemeral +execution context: it applies only to this invocation and is not collection or +saved-view state. `UTC` is the canonical identifier for Coordinated Universal +Time. Numeric offsets and ambient aliases such as `local` are not valid query +timezone identifiers because they cannot model daylight-saving transitions or +identify a durable calendar authority. + +The effective query timezone is resolved in this order: + +1. the invocation's `timezone` +2. the collection's configured timezone +3. the implementation's documented local-runtime default + +An invalid invocation timezone produces `invalid_timezone` and aborts before +candidate evaluation. An implementation MUST NOT silently substitute another +timezone for a supplied value. + +The execution authority captures the current instant once per query. `now()`, +`today()`, conversion of datetimes to calendar dates, and calendar arithmetic +MUST all use that captured instant and the same effective timezone throughout +the execution. Callers do not supply the current instant through this field. + +Interactive callers SHOULD send their current IANA timezone on every temporal +query. Headless callers MAY omit it to use the durable collection default. + ## Types `types` is an OR filter. A record is included if it matches at least one listed @@ -59,7 +87,7 @@ When no context is supplied, `this` is null. Supplying an unresolved context produces `context_not_found` and aborts the query before candidate evaluation. An invalid context is handled according to the collection validation level. -Query time, timezone, and collection state are fixed for the context and all +Query time, effective timezone, and collection state are fixed for the context and all candidates in one execution. A caller MUST NOT replace or mutate the context between candidate evaluations. @@ -333,6 +361,12 @@ View execution returns the query envelope and adds `meta.view: { path, id }`, using the resolved view-record path and named-view ID. +A saved-view execution invocation MAY supply `timezone` with the same syntax, +precedence, validation, and fixed-clock semantics as a direct query. The +invocation timezone is applied after named-view resolution and is not written +into the saved view. This lets one portable `today()` view follow its caller's +calendar day without local post-filtering or daily view rewrites. + Property-metadata keys MAY name effective fields, `file.*` values, `projection.*` values, or selection outputs. They provide labels, descriptions, format hints, and visibility hints. `select` remains the source of result diff --git a/schemas/v0.3/query.schema.json b/schemas/v0.3/query.schema.json index 2fec377..01273fa 100644 --- a/schemas/v0.3/query.schema.json +++ b/schemas/v0.3/query.schema.json @@ -5,6 +5,11 @@ "type": "object", "properties": { "types": { "$ref": "#/$defs/typeList" }, + "timezone": { + "type": "string", + "minLength": 1, + "description": "IANA timezone used for this query execution" + }, "context": { "$ref": "#/$defs/queryContext" }, "projections": { "$ref": "#/$defs/projectionSet" }, "where": { "$ref": "#/$defs/expression" },