Skip to content

Dates & Times

Flow-Like has one temporal type: Date. A Date value is an instant — a point on the timeline — held in UTC. It is not a calendar day, and it does not carry a timezone. Any offset in the input is folded into UTC when the value is parsed; local time exists only where a value is displayed.

LayerRepresentation
Pin and variable value (JSON on the wire)RFC3339 string with a Z suffix — "2026-08-17T12:00:00Z"
Runtimechrono::DateTime<Utc>
Struct schema / JSON Schema{"type": "string", "format": "date-time"} ("format": "date" is also read as a Date)
Event, REST and MCP payload schema{"type": "string"}
WASM node pinpin type date or datetime
Table columnArrow Timestamp(Millisecond, "UTC")
Legacy shape, still accepted on input{"secs_since_epoch": 1786968000, "nanos_since_epoch": 0}

Fractional seconds appear in the string only when they are non-zero, and then with 3, 6, or 9 digits: "2026-08-17T12:00:00.123456Z".

A new Date variable defaults to the moment it was created, written as an ISO string. See Variables for defaults, exposure, and runtime configuration.

SourceHow
Current timeNow — always UTC
A stringParse DateTime
Any other valueCast it to Date with Try Transform
A struct fieldBreak Struct turns format: date-time fields into Date pins
An event payloadDate pins render as a datetime-local control in the event form
ArithmeticAdd Duration on an existing Date

With the Format pin left empty, Parse DateTime tries these in order and takes the first that succeeds:

  1. RFC33392026-08-17T12:00:00Z, 2026-08-17T12:00:00.123+02:00. An offset is converted to UTC, so 12:00+02:00 becomes 10:00Z.

  2. RFC2822Mon, 17 Aug 2026 12:00:00 +0000.

  3. An all-digit string — read as Unix seconds.

  4. Common layouts, in this order:

    %Y-%m-%d %H:%M:%S %Y-%m-%dT%H:%M:%S
    %Y-%m-%d %H:%M:%S%.f %Y-%m-%dT%H:%M:%S%.f
    %Y-%m-%d
    %d/%m/%Y %m/%d/%Y %d.%m.%Y %Y/%m/%d %d-%m-%Y %m-%d-%Y

Two rules govern everything on that list. A layout with no offset is read as UTC, not as local time — 2026-08-17 12:00:00 is 12:00 UTC. A layout with no time component becomes midnight UTC.

Give Format a chrono format string and the node tries NaiveDateTime first, then NaiveDate (which lands on midnight). Both results are interpreted as UTC.

Casting a value to Date with Try Transform accepts more shapes than the parse node:

InputResult
RFC3339 stringConverted to UTC
%Y-%m-%d, %d/%m/%Y, %m/%d/%Y, %Y-%m-%d %H:%M:%SRead as UTC
Integer greater than 946684800000 (the year 2000 in millis)Unix milliseconds
Any smaller integerUnix seconds
FloatSeconds, fractional part as nanoseconds
{"secs_since_epoch": …, "nanos_since_epoch": …}The legacy shape

Event forms and generated payload schemas use a third, stricter reader: RFC3339, %Y-%m-%d %H:%M:%S%.f %:z, the four %Y-%m-%d[T ]%H:%M:%S[%.f] variants, and plain %Y-%m-%d. Numbers follow the same millis/seconds threshold as casting.

Table and inspector views read dates back out of values the backend has already flattened. A column declared temporal is parsed by magnitude — days, seconds, millis, micros, or nanos. A column that is merely an Int64 is only shown as a date when its name promises an instant (created_at, date_of_birth, expires) and the result lands between 1990 and 2100. That keeps duration, rating, and estimate rendering as the numbers they are.

Format DateTime takes a Date and a format string. Two names are presets (matched case-insensitively); anything else is treated as a chrono pattern.

Format pinOutput for 2026-08-17T12:00:00Z
rfc3339 (default)2026-08-17T12:00:00+00:00
rfc2822Mon, 17 Aug 2026 12:00:00 +0000
%Y-%m-%d %H:%M:%S2026-08-17 12:00:00
%d.%m.%Y %H:%M17.08.2026 12:00
%B %e, %YAugust 17, 2026

All output below is for 2026-08-17T12:00:00Z, a Monday.

Date

PlaceholderMeaningOutput
%YYear, zero-padded2026
%yYear within century26
%CCentury20
%mMonth number08
%bMonth, abbreviatedAug
%BMonth, fullAugust
%dDay of month, zero-padded17
%eDay of month, space-padded17
%aWeekday, abbreviatedMon
%AWeekday, fullMonday
%jDay of year229
%u / %wWeekday number (Mon=1 / Sun=0)1 / 1
%U / %WWeek of year (Sunday- / Monday-based)33 / 33
%G / %VISO week-year and ISO week number2026 / 34

Time

PlaceholderMeaningOutput
%HHour, 24-hour, zero-padded12
%kHour, 24-hour, space-padded12
%IHour, 12-hour, zero-padded12
%lHour, 12-hour, space-padded12
%p / %PAM/PM — upper and lowerPM / pm
%MMinute00
%SSecond00
%.3fFractional seconds, dot included, fixed width.000
%3fFractional seconds, no dot000
%.fFractional seconds, only when non-zero(empty)
%sUnix timestamp in seconds1786968000

Zone and composites

PlaceholderMeaningOutput
%zOffset+0000
%:zOffset with colon+00:00
%ZZone nameUTC
%F%Y-%m-%d2026-08-17
%T%H:%M:%S12:00:00
%R%H:%M12:00
%D / %x%m/%d/%y08/17/26
%XLocale time12:00:00
%cFull timestampMon Aug 17 12:00:00 2026
%+ISO 8601 / RFC33392026-08-17T12:00:00+00:00
%%A literal percent sign%

Formatting always renders UTC. There is no node that converts a Date into another timezone — if a user-facing string must be local, format it in the interface layer, which knows the viewer’s zone.

NodeGives you
To Dateyear, month (1–12), day (1–31), weekday (0 = Monday, 6 = Sunday), day_of_year (1–366)
To Timehour (0–23), minute, second, nanosecond
Add DurationA new Date; days/hours/minutes/seconds are additive and may be negative. Overflow is an error, not a wrap
DateTime Differencetotal_seconds (signed), split days/hours/minutes/seconds, and a human_readable string. Has Error pins because it also accepts the legacy secs_since_epoch shape

App tables are LanceDB tables with an Arrow schema, so a Date has to become a physical column type.

Type in the table designerArrow typeHolds
TimestampTimestamp(Millisecond, "UTC")An instant — the physical form of a Flow-Like Date
DateDate32A calendar day with no time, stored as a day count since 1970-01-01

When you create a table through the API or an agent, the type name is one of timestamp, datetime, timestamp_ms, timestamp:ms:utc (all the same), or date / date32.

The first write to a new table infers the schema. A string column whose non-null values all parse as RFC3339 is promoted to Timestamp(Millisecond, "UTC") — which is exactly what a Date pin produces, so dates land in a real timestamp column without any declaration.

After that, the stored schema is authoritative and every later write is serialized against it:

  • A column that was inferred as text stays text forever, even once every later row is a valid RFC3339 string. One malformed value in the first batch decides the column. Declare the schema up front when the first batch is not trustworthy.
  • Tables written before UTC-aware timestamps keep working. An RFC3339 value written into a timezone-less timestamp column is converted to a naive UTC wall clock, and a naive string written into a UTC column is read as UTC.
  • Storage is millisecond resolution. Microseconds and nanoseconds present in the Date value are truncated on write.

The read path matters, because the same column produces different JSON depending on how you reach it:

Read throughA Timestamp column returnsA Date32 column returns
Table reads — list, filter, vector queryEpoch milliseconds as an integer: 1786881600000A day count as an integer: 20682
A SQL query over the tableRFC3339 string: "2026-08-17T12:00:00.000Z" (timezone-less columns keep the suffix-less form 2026-08-17T12:00:00.000)"2026-08-17"

A raw table read hands you a number, not a date string. Cast it back to a Date before doing date work with it — the millis/seconds threshold described above resolves it correctly. The table viewer does the same thing for you, which is why an integer column named created_at still renders as a date.

Filters are SQL fragments evaluated against the physical column, so a timestamp needs a typed literal. A bare integer does not coerce and the update fails:

-- fails: an integer literal is not a timestamp
created_at = 1786881600000
-- works
created_at = CAST(1786881600000 AS TIMESTAMP(3))
created_at >= TIMESTAMP '2026-08-17 12:00:00'

The rest of the fragment follows ordinary SQL rules: escape a quote in a string literal by doubling it (label = 'it''s a'), and compare against IS NULL rather than = NULL. Adding a timestamp column to an existing table works the same way, through CAST('2026-08-17' AS TIMESTAMP).

NodePurpose
DateTime to SQL TimestampTurns a Date into a TIMESTAMP '2026-08-17 12:00:00.000000' literal, plus the same instant in epoch microseconds
Time Range FilterBuilds a half-open col >= … AND col < … WHERE clause
Time Bin AggregationGroups rows into fixed intervals via date_bin
Date Truncate AggregationTruncates to hour, day, month, and so on, then aggregates

Time Range Filter accepts relative expressions as well as ISO strings, which avoids a Now-plus-arithmetic chain for the common “last day” case:

ExpressionMeaning
nowThe moment the node runs
-24h, -7d, -30m, +1wSigned offset from now; units are s, m, h, d, w
2026-08-17T12:00:00Z, 2026-08-17 12:00:00, 2026-08-17Absolute, read as UTC
SymptomCause
A time is off by exactly the local offsetA string with no offset was parsed — those are UTC, never local
A time is off by the offset it explicitly carriedThe offset was given to the explicit-format path, which discards it. Leave the format empty for RFC3339 input
A day and month are swappedAuto-detection tries %d/%m/%Y before %m/%d/%Y
An epoch value lands in the far futureA millisecond value went through a path that reads seconds, or vice versa
A date column reads as plain text in a tableThe first write to that table contained a value that was not RFC3339
Sub-millisecond precision disappearedTable storage is millisecond resolution
An update touches no rows, or errors on the filterThe timestamp literal was not cast — use CAST(… AS TIMESTAMP(3))
The run aborts inside a format nodeAn unrecognized % placeholder