now() and today()
now() is the current time as a datetime in UTC; today() is its date, and today(zone) the
date in a zone (an IANA name or an offset).
type_of(now()) // "datetime"
now() == now() // true
type_of(today("Europe/Berlin")) // "date"
g.add_v("event").property("at", now()).values("at").count().next() // 1
The start of the evaluation
Like PostgreSQL's now() (CURRENT_TIMESTAMP), now() is the time the script evaluation
started, the same value for every call in it: a script that stamps a thousand elements stamps
them all with one instant, and now() == now() holds. In the playground a whole script is one
unit, so now() is the start of that unit. A saved query called
from a script sees its caller's now().
now() and today() are script functions, evaluated before the traversal runs: the traversal
gets the resulting value as a constant (inject(now()), property("at", now()),
has("at", P.lt(now()))). The journal of a Store and a change set
record that value, never the call, so a replay or a recovery writes the same instant, not the time
of the replay.
today() is the date of now() in UTC, PostgreSQL's current_date in a UTC session. For the
date in another zone pass the zone, or convert the instant yourself:
today("UTC") == today() // true
g.inject(now()).as_local("America/Los_Angeles").as_date(GType.DATE).next() == today("America/Los_Angeles") // true
Pinning the clock (hosts)
A host that needs a deterministic clock (tests, a replay of a recorded session) pins it on its
engine with graphersal::script::pin_now; every evaluation on that engine then returns the
pinned instant, until it is unpinned with None:
use graphersal::script::{engine_with_options, pin_now};
use graphersal::temporal::DateTime;
let mut engine = engine_with_options(&limits, authorizer, &presets);
pin_now(&mut engine, Some("2023-08-02T23:30:00-07:00".parse::<DateTime>()?));
// now() is 2023-08-02T23:30:00-07:00, today() is 2023-08-03 (the UTC date)
pin_now(&mut engine, None); // the system clock again
The system clock is read through web_time, so now() works the same in the WebAssembly
playground.