Filter by Date and Time
-
You can filter query results by date and time in one of the following ways:
-
The
now()andtoday()functions are evaluated server-side when the query is executed. -
In this article:
Filter by an explicit date
-
To filter by an explicit date-time value, compare the date field directly with a
DateTimevalue. -
Use UTC values to avoid time-zone-related issues. RavenDB stores and compares date-time values in UTC.
In the C# examples below, DateTimeKind is passed to theDateTimeconstructor to mark the value as UTC. -
Unlike the Restrictions on
now()andtoday(),
explicit date values are deterministic and can be used in Exploration queries and Subscription queries.
Filter by single date
The following query returns all employees hired on or after January 1st, 1995 (UTC):
- Query
- Query_async
- DocumentQuery
- DocumentQuery_async
- RawQuery
- RawQuery_async
- RQL
var cutoff = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = session
.Query<Employee>()
.Where(e => e.HiredAt >= cutoff)
.ToList();
var cutoff = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = await asyncSession
.Query<Employee>()
.Where(e => e.HiredAt >= cutoff)
.ToListAsync();
var cutoff = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = session.Advanced
.DocumentQuery<Employee>()
.WhereGreaterThanOrEqual("HiredAt", cutoff)
.ToList();
var cutoff = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = await asyncSession.Advanced
.AsyncDocumentQuery<Employee>()
.WhereGreaterThanOrEqual("HiredAt", cutoff)
.ToListAsync();
var cutoff = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = session.Advanced
.RawQuery<Employee>("from Employees where HiredAt >= $cutoff")
.AddParameter("cutoff", new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc))
.ToList();
var cutoff = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = await asyncSession.Advanced
.AsyncRawQuery<Employee>("from Employees where HiredAt >= $cutoff")
.AddParameter("cutoff", new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc))
.ToListAsync();
from Employees
where HiredAt >= "1995-01-01T00:00:00.0000000Z"
Filter by date range
You can filter by a date range by combining two predicates.
The following query returns all employees hired between 1995-01-01 (inclusive) and 2010-01-01 (exclusive):
- Query
- Query_async
- DocumentQuery
- DocumentQuery_async
- RawQuery
- RawQuery_async
- RQL
var from = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var to = new DateTime(2010, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = session
.Query<Employee>()
.Where(e => e.HiredAt >= from && e.HiredAt < to)
.ToList();
var from = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var to = new DateTime(2010, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = await asyncSession
.Query<Employee>()
.Where(e => e.HiredAt >= from && e.HiredAt < to)
.ToListAsync();
var from = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var to = new DateTime(2010, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = session.Advanced
.DocumentQuery<Employee>()
.WhereGreaterThanOrEqual("HiredAt", from)
.AndAlso()
.WhereLessThan("HiredAt", to)
.ToList();
var from = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var to = new DateTime(2010, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = await asyncSession.Advanced
.AsyncDocumentQuery<Employee>()
.WhereGreaterThanOrEqual("HiredAt", from)
.AndAlso()
.WhereLessThan("HiredAt", to)
.ToListAsync();
List<Employee> employees = session.Advanced
.RawQuery<Employee>("from Employees where HiredAt >= $from and HiredAt < $to")
.AddParameter("from", new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc))
.AddParameter("to", new DateTime(2010, 1, 1, 0, 0, 0, DateTimeKind.Utc))
.ToList();
List<Employee> employees = await asyncSession.Advanced
.AsyncRawQuery<Employee>("from Employees where HiredAt >= $from and HiredAt < $to")
.AddParameter("from", new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc))
.AddParameter("to", new DateTime(2010, 1, 1, 0, 0, 0, DateTimeKind.Utc))
.ToListAsync();
from Employees
where HiredAt >= "1995-01-01T00:00:00.0000000Z"
and HiredAt < "2010-01-01T00:00:00.0000000Z"
Filter by date range using between
When both bounds are inclusive, RQL offers a dedicated between operator,
equivalent to field >= from AND field <= to.
The following query returns all employees hired between January 1st, 1995 and January 1st, 2010, inclusive:
- Query
- Query_async
- DocumentQuery
- DocumentQuery_async
- RawQuery
- RawQuery_async
- RQL
// LINQ has no dedicated Between method -
// the query translator emits the 'between' operator in the generated RQL
// when both bounds are inclusive.
var from = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var to = new DateTime(2010, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = session
.Query<Employee>()
.Where(e => e.HiredAt >= from && e.HiredAt <= to)
.ToList();
// LINQ has no dedicated Between method — the query translator emits
// RQL 'between' when both bounds are inclusive.
var from = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var to = new DateTime(2010, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = await asyncSession
.Query<Employee>()
.Where(e => e.HiredAt >= from && e.HiredAt <= to)
.ToListAsync();
var from = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var to = new DateTime(2010, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = session.Advanced
.DocumentQuery<Employee>()
.WhereBetween("HiredAt", from, to)
.ToList();
var from = new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc);
var to = new DateTime(2010, 1, 1, 0, 0, 0, DateTimeKind.Utc);
List<Employee> employees = await asyncSession.Advanced
.AsyncDocumentQuery<Employee>()
.WhereBetween("HiredAt", from, to)
.ToListAsync();
List<Employee> employees = session.Advanced
.RawQuery<Employee>("from Employees where HiredAt between $from and $to")
.AddParameter("from", new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc))
.AddParameter("to", new DateTime(2010, 1, 1, 0, 0, 0, DateTimeKind.Utc))
.ToList();
List<Employee> employees = await asyncSession.Advanced
.AsyncRawQuery<Employee>("from Employees where HiredAt between $from and $to")
.AddParameter("from", new DateTime(1995, 1, 1, 0, 0, 0, DateTimeKind.Utc))
.AddParameter("to", new DateTime(2010, 1, 1, 0, 0, 0, DateTimeKind.Utc))
.ToListAsync();
from Employees
where HiredAt between "1995-01-01T00:00:00.0000000Z"
and "2010-01-01T00:00:00.0000000Z"
Filter using now()
-
RQL provides the
now()function for comparing date fields with the current UTC date-time.
In RQL, the function name is case-insensitive. For example,now()andNOW()are equivalent. -
now()is evaluated server-side when the query is executed, so the value reflects the server clock, not the client clock. Usenow()when you need to compare a date field with the current UTC date-time when the query runs. -
For example, the following query returns employees whose HiredAt date is before the current server time:
- Query
- Query_async
- DocumentQuery
- DocumentQuery_async
- RawQuery
- RawQuery_async
- RQL
List<Employee> employees = session
.Query<Employee>()
.Where(e => e.HiredAt < RavenQuery.Now())
.ToList();List<Employee> employees = await asyncSession
.Query<Employee>()
.Where(e => e.HiredAt < RavenQuery.Now())
.ToListAsync();List<Employee> employees = session.Advanced
.DocumentQuery<Employee>()
.WhereLessThan("HiredAt", RavenDocumentQuery.Now())
.ToList();List<Employee> employees = await asyncSession.Advanced
.AsyncDocumentQuery<Employee>()
.WhereLessThan("HiredAt", RavenDocumentQuery.Now())
.ToListAsync();List<Employee> employees = session.Advanced
.RawQuery<Employee>("from Employees where HiredAt <= now()")
.ToList();List<Employee> employees = await asyncSession.Advanced
.AsyncRawQuery<Employee>("from Employees where HiredAt < now()")
.ToListAsync();from Employees
where HiredAt < now() -
All comparison operators are supported (
=,!=,<,<=,>,>=).
For example, the following query returns orders whose RequireAt date is after the current server time:- Query
- Query_async
- DocumentQuery
- DocumentQuery_async
- RawQuery
- RawQuery_async
- RQL
List<Order> orders = session
.Query<Order>()
.Where(o => o.RequireAt > RavenQuery.Now())
.ToList();List<Order> orders = await asyncSession
.Query<Order>()
.Where(o => o.RequireAt > RavenQuery.Now())
.ToListAsync();List<Order> orders = session.Advanced
.DocumentQuery<Order>()
.WhereGreaterThan("RequireAt", RavenDocumentQuery.Now())
.ToList();List<Order> orders = await asyncSession.Advanced
.AsyncDocumentQuery<Order>()
.WhereGreaterThan("RequireAt", RavenDocumentQuery.Now())
.ToListAsync();List<Order> orders = session.Advanced
.RawQuery<Order>("from Orders where RequireAt > now()")
.ToList();List<Order> orders = await asyncSession.Advanced
.AsyncRawQuery<Order>("from Orders where RequireAt > now()")
.ToListAsync();from Orders
where RequireAt > now() -
You can also combine
now()with other predicates.
For example, query for employees named Alice who were hired on or before the current server time:- Query
- Query_async
- DocumentQuery
- DocumentQuery_async
- RawQuery
- RawQuery_async
- RQL
List<Employee> aliceHired = session
.Query<Employee>()
.Where(e => e.HiredAt <= RavenQuery.Now() && e.FirstName == "Alice")
.ToList();List<Employee> aliceHired = await asyncSession
.Query<Employee>()
.Where(e => e.HiredAt <= RavenQuery.Now() && e.FirstName == "Alice")
.ToListAsync();List<Employee> aliceHired = session.Advanced
.DocumentQuery<Employee>()
.WhereLessThanOrEqual("HiredAt", RavenDocumentQuery.Now())
.AndAlso()
.WhereEquals("FirstName", "Alice")
.ToList();List<Employee> aliceHired = await asyncSession.Advanced
.AsyncDocumentQuery<Employee>()
.WhereLessThanOrEqual("HiredAt", RavenDocumentQuery.Now())
.AndAlso()
.WhereEquals("FirstName", "Alice")
.ToListAsync();List<Employee> aliceHired = session.Advanced
.RawQuery<Employee>("from Employees where HiredAt <= now() and FirstName = 'Alice'")
.ToList();List<Employee> aliceHired = await asyncSession.Advanced
.AsyncRawQuery<Employee>("from Employees where HiredAt <= now() and FirstName = 'Alice'")
.ToListAsync();from Employees
where HiredAt <= now() and FirstName = 'Alice'
Filter using now() with offset
-
now()can accept an optional positive or negative offset string, such as+7d,-3d, or+1d5h. -
When an offset is provided, RavenDB first SHIFTS the current time by the specified amount
and then ROUNDS the generated time value down to the start of the smallest unit in the offset. -
This keeps the generated time value stable for the duration of the smallest unit in the offset,
allowing identical queries to benefit from the server query cache and return304 Not Modifiedwhen applicable. Learn more about caching in: Result caching with time functions.
Negative offset (past)
-
Use a negative offset to compare a date field with a time value in the past.
-
For example:
now('-7d')subtracts 7 days from the current server time and then rounds the generated time value down to the start of that UTC day. The generated timestamp is truncated to00:00:00.000UTC, discarding the hour, minute, second, and millisecond components.If the server’s current UTC time is
2026-05-10T14:37:22Z, thennow('-7d')is evaluated as follows:Shift:
2026-05-10T14:37:22Z - 7 days=>2026-05-03T14:37:22Z
Round down to the day:2026-05-03T14:37:22Z=>2026-05-03T00:00:00Z
So this predicate:HiredAt <= now('-7d')
effectively becomes:HiredAt <= 2026-05-03T00:00:00Z -
The following query returns employees whose HiredAt value is earlier than or equal to 7 days ago,
rounded down to the day:- Query
- Query_async
- DocumentQuery
- DocumentQuery_async
- RawQuery
- RawQuery_async
- RQL
List<Employee> employees = session.Query<Employee>()
.Where(e => e.HiredAt <= RavenQuery.Now("-7d"))
.ToList();List<Employee> employees = await asyncSession.Query<Employee>()
.Where(e => e.HiredAt <= RavenQuery.Now("-7d"))
.ToListAsync();List<Employee> employees = session.Advanced
.DocumentQuery<Employee>()
.WhereLessThanOrEqual("HiredAt", RavenDocumentQuery.Now("-7d"))
.ToList();List<Employee> employees = await asyncSession.Advanced
.AsyncDocumentQuery<Employee>()
.WhereLessThanOrEqual("HiredAt", RavenDocumentQuery.Now("-7d"))
.ToListAsync();// Using raw RQL - the offset string is passed directly to now()
List<Employee> employees = session.Advanced
.RawQuery<Employee>("from Employees where HiredAt <= now('-7d')")
.ToList();
// Using parameter - the offset string is supplied via AddParameter().
// Note: with a parameter, repeated calls won't return 304 Not Modified.
List<Employee> employeesParam = session.Advanced
.RawQuery<Employee>("from Employees where HiredAt <= now($offset)")
.AddParameter("offset", "-7d")
.ToList();// Using raw RQL - the offset string is passed directly to now()
List<Employee> employees = await asyncSession.Advanced
.AsyncRawQuery<Employee>("from Employees where HiredAt <= now('-7d')")
.ToListAsync();
// Using parameter - the offset string is supplied via AddParameter().
// Note: with a parameter, repeated calls won't return 304 Not Modified.
List<Employee> employeesParam = await asyncSession.Advanced
.AsyncRawQuery<Employee>("from Employees where HiredAt <= now($offset)")
.AddParameter("offset", "-7d")
.ToListAsync();// Offset string is passed as a literal string:
from Employees
where HiredAt <= now('-7d')
// Offset string is passed as a parameter:
// Note: with a parameter, repeated calls won't return 304 Not Modified.
from Employees
where HiredAt <= now($offset)
{ "offset": "-7d" }
Positive offset (future)
-
Use a positive offset to compare a date field with a time value in the future.
-
For example:
now('+7d')adds 7 days to the current server time and then rounds the generated time value down to the start of that UTC day. The generated timestamp is truncated to00:00:00.000UTC, discarding the hour, minute, second, and millisecond components.If the server's current UTC time is
2026-05-10T14:37:22Z, thennow('+7d')is evaluated as follows:Shift:
2026-05-10T14:37:22Z + 7 days=>2026-05-17T14:37:22Z
Round down to the day:2026-05-17T14:37:22Z=>2026-05-17T00:00:00Z
So this predicate:RequireAt <= now('+7d')
effectively becomes:RequireAt <= 2026-05-17T00:00:00Z -
The following query returns orders whose RequireAt value is earlier than or equal to 7 days from now,
rounded down to the day:
- Query
- Query_async
- DocumentQuery
- DocumentQuery_async
- RawQuery
- RawQuery_async
- RQL
List<Order> orders = session.Query<Order>()
.Where(o => o.RequireAt <= RavenQuery.Now("+7d"))
.ToList();
List<Order> orders = await asyncSession.Query<Order>()
.Where(o => o.RequireAt <= RavenQuery.Now("+7d"))
.ToListAsync();
List<Order> orders = session.Advanced
.DocumentQuery<Order>()
.WhereLessThanOrEqual("RequireAt", RavenDocumentQuery.Now("+7d"))
.ToList();
List<Order> orders = await asyncSession.Advanced
.AsyncDocumentQuery<Order>()
.WhereLessThanOrEqual("RequireAt", RavenDocumentQuery.Now("+7d"))
.ToListAsync();
// Using raw RQL - the offset string is passed directly to now()
List<Order> orders = session.Advanced
.RawQuery<Order>("from Orders where RequireAt <= now('+7d')")
.ToList();
// Using parameter - the offset string is supplied via AddParameter().
// Note: with a parameter, repeated calls won't return 304 Not Modified.
List<Order> ordersParam = session.Advanced
.RawQuery<Order>("from Orders where RequireAt <= now($offset)")
.AddParameter("offset", "+7d")
.ToList();
// Using raw RQL - the offset string is passed directly to now()
List<Order> orders = await asyncSession.Advanced
.AsyncRawQuery<Order>("from Orders where RequireAt <= now('+7d')")
.ToListAsync();
// Using parameter - the offset string is supplied via AddParameter().
// Note: with a parameter, repeated calls won't return 304 Not Modified.
List<Order> ordersParam = await asyncSession.Advanced
.AsyncRawQuery<Order>("from Orders where RequireAt <= now($offset)")
.AddParameter("offset", "+7d")
.ToListAsync();
// Offset string is passed as a literal string:
from Orders
where RequireAt <= now('+7d')
// Offset string is passed as a parameter:
// Note: with a parameter, repeated calls won't return 304 Not Modified.
from Orders
where RequireAt <= now($offset)
{ "offset": "+7d" }
Offset format
-
The offset is a signed sequence of
<number><unit>tokens.
Whitespace is allowed after the sign and between tokens.
Unit names are case-insensitive.Unit Short form Aliases Years yyear,yearsMonths momonth,monthsDays dday,daysHours hhour,hoursMinutes mmin,minute,minutesSeconds ssec,second,seconds -
Rules:
- The sign (
+or-) is optional. When no sign is specified, the offset is treated as positive. - Units must appear in strictly descending order:
years → months → days → hours → minutes → seconds. For example,'+5h1d'is rejected. - A unit may not appear more than once.
- The smallest unit present determines the rounding precision.
- An empty offset string, such as
now(''), is rejected.
- The sign (
-
Examples:
Offset Effect +7dAdd 7 days, then round down to the start of the day. -3dSubtract 3 days, then round down to the start of the day. +1d5hAdd 1 day and 5 hours, then round down to the start of the hour. 7y0sAdd 7 years, then round down to the start of the second. 0hDo not shift the time, but round down to the start of the hour. +1 year 6 monthsAdd 1 year and 6 months, then round down to the start of the month. (whitespace allowed). 1Y2MO3D4H5M6SAdd all specified units; unit names are case-insensitive.
Filter using today()
-
RQL provides the
today()function for comparing date fields with the start of the current UTC day,(00:00:00.000).
In RQL, the function name is case-insensitive. For example,today()andTODAY()are equivalent. -
today()is evaluated server-side when the query is executed, so the value reflects the server clock, not the client clock. Usetoday()when you need to compare a date field with the start of the current UTC day, rather than with the current date and time. -
today()does not accept any arguments. To filter relative to another day, use now() with offset instead.
For example, usenow('+1d')to compare with the start of tomorrow’s UTC day. -
The following query returns employees whose HiredAt value is earlier than the start of the current UTC day:
- Query
- Query_async
- DocumentQuery
- DocumentQuery_async
- RawQuery
- RawQuery_async
- RQL
List<Employee> employees = session
.Query<Employee>()
.Where(e => e.HiredAt < RavenQuery.Today())
.ToList();List<Employee> employees = await asyncSession
.Query<Employee>()
.Where(e => e.HiredAt < RavenQuery.Today())
.ToListAsync();List<Employee> employees = session.Advanced
.DocumentQuery<Employee>()
.WhereLessThan("HiredAt", RavenDocumentQuery.Today())
.ToList();List<Employee> employees = await asyncSession.Advanced
.AsyncDocumentQuery<Employee>()
.WhereLessThan("HiredAt", RavenDocumentQuery.Today())
.ToListAsync();List<Employee> employees = session.Advanced
.RawQuery<Employee>("from Employees where HiredAt < today()")
.ToList();List<Employee> employees = await asyncSession.Advanced
.AsyncRawQuery<Employee>("from Employees where HiredAt < today()")
.ToListAsync();from Employees
where HiredAt < today() -
today()andnow()can be combined in the same query.
For example, to return all employees hired so far today:from Employees
where HiredAt >= today() and HiredAt <= now()
Restrictions
-
Exploration queries
Bothnow()andtoday()are not supported in exploration queryies.
For example, the following query is not allowed:// Not allowed: now() / today() are not supported in exploration query filter clauses
from Employees
filter HiredAt <= now()In exploration queries, these functions are blocked in
filterclauses becausefilterexpressions are evaluated as JavaScript expressions. Sincenow()andtoday()depend on the query execution time, using them in this context produces time-dependent results that conflict with the query result caching mechanism.Filtering by an explicit date is fully supported in exploration queries.
-
Subscription queries
Bothnow()andtoday()are not supported in subscription queries.
For example, the following query is not allowed:// Not allowed: now() / today() are not supported in subscription queries
from Employees
where HiredAt <= now()In subscription queries, these functions are blocked because a subscription is an ongoing task. Using
now()ortoday()would make the matching results depend on when the subscription task evaluates each document,
yielding nondeterministic results: the set of matching documents could change dynamically even when the documents themselves have not changed.Filtering by an explicit date is fully supported in subscription queries.
today()does not accept arguments
To filter relative to another day, usenow()with an offset instead, for examplenow('+1d').
- Invalid
now()offset values
When usingnow()with an offset, the offset must be a non-empty string in a valid offset format.
Result caching with time functions
When query caching is enabled, the server can return 304 Not Modified for time-based queries only while the resolved time value remains unchanged
and no documents in the queried collection have been added, modified, or deleted in the meantime.
-
today()
today()resolves to the start of the current UTC day (00:00:00).
Because this value remains the same throughout the UTC day, repeated queries can receive304 Not Modifiedfrom the server (provided no documents in the queried collection have changed in the meantime).
When the UTC day changes,today()resolves to a new value and the query is re-evaluated. -
now() without an offset
now()without an offset resolves to the current UTC date and time each time the query is executed.
Because the value changes on every call, the server re-evaluates the query and does not return304 Not Modified. -
now() with a literal offset string
now()with a literal offset string is rounded down to the smallest time unit specified in the offset
(e.g.'+7d'rounds to the day,'+1h30m'rounds to the minute).
Repeated queries can receive304 Not Modifiedfrom the server until the rounded value changes
(and as long as the queried collection has not changed).Note:
When the offset is supplied as a query parameter (e.g.now($offset)) instead of a literal string (now('-7d')),
the server can't tell from the query text alone what valuenow()will resolve to - it can't evaluate the parameter at query-planning time, and the value could be different on the next call. It therefore behaves likenow()without an offset: the query is re-run every time, and304 Not Modifiedis never returned.Parameterized offsets are only reachable through raw RQL,
e.g. viasession.Advanced.RawQuery/AsyncRawQuerycombined withAddParameter.
Client-side caching must be enabled
-
The behavior described above relies on the client's HTTP response cache to recognize the server's
304 Not Modifiedreply and serve the previous result from memory. -
If client-side caching is disabled, the client does not store responses and does not send the cache-validation header (
If-None-Match). The server therefore cannot reply with304 Not Modified, and every call returns a full200 OKresponse, even whentoday()ornow('<offset>')resolved to the same value. -
Client-side caching can be disabled at different scopes:
- per-session, by setting
session.Advanced.NoCachingor by using the NoCaching session option, - per-query, by using
IDocumentQuery.NoCaching()/DocumentQueryCustomization.NoCaching(), or - store-level, by setting
DocumentConventions.MaxHttpCacheSize = 0.
- per-session, by setting
Aggressive caching bypasses server re-evaluation
-
When the request runs inside an Aggressive caching scope,
the client can return the previously cached response without contacting the server at all, as long as:- the cached entry is younger than the duration passed to
AggressivelyCacheFor(...), - the query does not use
WaitForNonStaleResultsand was not issued withNoCaching(), and - in
AggressiveCacheMode.TrackChanges(the default), the client's background database-changes notification has not flagged the cached entry as possibly modified.
- the cached entry is younger than the duration passed to
-
As a consequence,
now()andtoday()queries can return stale results inside an aggressive caching block.
The server-side non-determinism fornow()and the daily ETag rollover fortoday()that normally trigger a fresh evaluation are irrelevant once the client decides to skip the round-trip. In particular, atoday()query cached just before midnight UTC can keep returning the previous day's result even after the UTC day has changed.
The cached response is refreshed only when:- the cache entry's age exceeds the duration passed to
AggressivelyCacheFor(...)
or the store-levelAggressiveCache.Durationdefault, - a database change is observed via the Changes API
(only when running inAggressiveCacheMode.TrackChanges, which is the default), or - the aggressive-caching scope is exited.
- the cache entry's age exceeds the duration passed to
-
If you need
now()ortoday()to be re-evaluated on every call,
run the query outside the aggressive caching scope, or wrap the call instore.DisableAggressiveCaching().
Assuming the request reaches the server and client-side HTTP caching is enabled,
the following table summarizes regular query caching behavior:
| Expression | Resolves to | Can the server return 304? | Valid until |
|---|---|---|---|
today() | Start of the current UTC day (00:00:00) | ✅ yes | Until UTC day rolls over or the queried collection changes. |
now() (no offset) | Current UTC date and time | ❌ no | n/a Re-evaluated on every call. |
now('<offset>') (literal string offset) | now + offsetFloored to the smallest unit in the offset. ( '+7d' → day, '+1h30m' → minute, '+15s' → second) | ✅ yes | Floored value changes or the queried collection changes. |
now($param) (parameter offset) | now + offsetTreated as non-deterministic. | ❌ no | n/a Re-evaluated on every call. |
Syntax
- LINQ (Session.Query)
// Inside a System.Linq.Expressions.Expression<Func<T, bool>>:
RavenQuery.Now() // current server UTC time
RavenQuery.Now(string offset) // current server UTC time + offset, rounded
RavenQuery.Today() // start of current UTC day
- DocumentQuery
RavenDocumentQuery.Now()
RavenDocumentQuery.Now(string offset)
RavenDocumentQuery.Today()
- RQL
now()
now('<offset>')
today()
| Parameter | Type | Description |
|---|---|---|
| offset | string | (optional, now() only) Signed time-shift expression (e.g. '+7d', '-1d5h').Sets the rounding unit. |