Date/Time Functions
The largest category, and the one where the databases agree least. KQL works with four temporal
kinds — DATE, TIME, TIMESTAMP and INSTANT — described in docs/TEMPORAL.md; this page is
about the functions over them.
Where the engines disagreed, the answer is pinned
Most functions here render straight through. Two do not, and they are worth knowing about:
dayofweek counts Monday as 1 and Sunday as 7, the ISO way. Left alone, the engines gave three
different numbers for the same Sunday — 0, 1 and 7 — and several took the answer from a session
setting (NLS_TERRITORY, DATEFIRST, WEEK_START), so the same query could differ between two
connections to the same database. week is ISO-8601 for the same reason: week 1 is the one
containing the first Thursday, which is why early January sometimes falls in week 52 or 53 of the
previous year.
Where an engine's own answer depends on a session setting, the dialect computes it from a fixed anchor instead of asking the session.
Prefer the named boundaries to date_trunc
day_begin, week_begin, month_begin, quarter_begin, year_begin and their _end partners
are the portable way to snap a value to a period. date_trunc(part, value) does the same for
'day', 'month', 'quarter' and 'year' — and only those four, because that is the set every
dialect can express. Ask for 'hour' and SQLite used to answer with a blank column rather than an
error; it now fails by name.
The _end functions return the last day of the period, always a date. That is deliberate:
"the last instant" has no value independent of precision. For a timestamp range, filter half-open
with begin and the next begin.
Distances count whole units, toward zero
days_between, months_between and years_between follow java.time's ChronoUnit: complete
units only, and the remainder is dropped in the direction of the sign.
months_between('2023-01-31', '2023-03-30') → 1 -- the second month is not complete
Durations are literals, not function calls
2d4h two days and four hours
1y2mo one year and two months
-2d4h *both* components negated — 52 hours back, not 2 days back and 4 hours forward
Units are ms s min h d w mo q y, and they must be written largest-first (1y2mo15d, not
15d2mo1y); the other order is a positioned error rather than a silent reordering. A leading minus
applies to the whole literal, so mixed signs cannot be written — that is the one shape the notation
does not have.
Oracle is the exception worth naming: it keeps YEAR TO MONTH and DAY TO SECOND in separate
types, so a duration mixing the two (1y2mo3d) has no value there. Adding it to a date works —
that expands into steps — but using it as a value does not.
now, clock_now and today
now is the statement's timestamp and does not move within it. clock_now reads the wall clock at
the moment of the call, so it may advance mid-statement on the engines that distinguish the two
(PostgreSQL clock_timestamp(), MariaDB SYSDATE()); elsewhere the two are equal. today is the
current date.
Parsing, formatting and zones
parse_date, parse_time and parse_timestamp read text with a format mask, to_char writes it.
The mask is written once in KQL's vocabulary and translated per dialect — the tokens are on the
Data Type Formatting Functions page. SQLite has no mask-based parsing at all and SQL Server takes
culture or style codes rather than masks, so both declare the three unsupported.
at_zone and to_utc cross named time zones. SQLite has no time-zone database and declares both
unsupported; the other seven support them.
now
now() → TIMESTAMP
Statement timestamp — fixed for the whole statement (PostgreSQL statement_timestamp(), otherwise CURRENT_TIMESTAMP).
Sample query:
// now: the current timestamp.
FIND orders o
FETCH now() current_ts
Generated SQL
duckdb · oracle · snowflake · mssql · mariadb · sqlite · trino
-- now: the current timestamp.
SELECT
CURRENT_TIMESTAMP AS current_ts
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| postgresql | statement_timestamp() AS current_ts |
clock_now
clock_now() → TIMESTAMP
Wall-clock timestamp read at the moment of the call. Unlike now, it may advance within a single statement on dialects that distinguish the two (PostgreSQL clock_timestamp(), MySQL/MariaDB SYSDATE()); elsewhere it equals now.
Sample query:
// clock_now: the current wall-clock timestamp.
FIND orders o
FETCH clock_now() wall_clock_ts
Generated SQL
duckdb · oracle · snowflake · mssql · sqlite · trino
-- clock_now: the current wall-clock timestamp.
SELECT
CURRENT_TIMESTAMP AS wall_clock_ts
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | SYSDATE() AS wall_clock_ts |
| postgresql | clock_timestamp() AS wall_clock_ts |
today
today() → DATE
Current date.
Sample query:
// today: the current date.
FIND orders o
FETCH today() todays_date
Generated SQL
oracle · snowflake · postgresql · mariadb · sqlite · trino
-- today: the current date.
SELECT
CURRENT_DATE AS todays_date
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| duckdb | today() AS todays_date |
| mssql | CAST(GETDATE() AS DATE) AS todays_date |
year
year(value: date/time) → INTEGER
Extracts the year part of a date or timestamp.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to extract from |
Sample query:
// year: the year component of the order date.
FIND orders o
FETCH year(o.order_date) order_year
Generated SQL
duckdb · snowflake · mssql · mariadb · trino
-- year: the year component of the order date.
SELECT
year(o.order_date) AS order_year
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| oracle · postgresql | EXTRACT(YEAR FROM o.order_date) AS order_year |
| sqlite | CAST(strftime('%Y', o.order_date) AS INTEGER) AS order_year |
month
month(value: date/time) → INTEGER
Extracts the month part of a date or timestamp.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to extract from |
Sample query:
// month: the month component of the order date.
FIND orders o
FETCH month(o.order_date) order_month
Generated SQL
duckdb · snowflake · mssql · mariadb · trino
-- month: the month component of the order date.
SELECT
month(o.order_date) AS order_month
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| oracle · postgresql | EXTRACT(MONTH FROM o.order_date) AS order_month |
| sqlite | CAST(strftime('%m', o.order_date) AS INTEGER) AS order_month |
day
day(value: date/time) → INTEGER
Extracts the day part of a date or timestamp.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to extract from |
Sample query:
// day: the day-of-month of the order date.
FIND orders o
FETCH day(o.order_date) order_day
Generated SQL
duckdb · snowflake · mssql · mariadb · trino
-- day: the day-of-month of the order date.
SELECT
day(o.order_date) AS order_day
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| oracle · postgresql | EXTRACT(DAY FROM o.order_date) AS order_day |
| sqlite | CAST(strftime('%d', o.order_date) AS INTEGER) AS order_day |
hour
hour(value: date/time) → INTEGER
Extracts the hour part of a date or timestamp.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to extract from |
Sample query:
// hour: the hour component of a TIMESTAMP.
FIND check_temporal c
FETCH hour(c.timestamp_timestamp) hour_of_day
Generated SQL
duckdb · snowflake · mariadb · trino
-- hour: the hour component of a TIMESTAMP.
SELECT
hour(c.timestamp_timestamp) AS hour_of_day
FROM
check_temporal c
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| oracle · postgresql | EXTRACT(HOUR FROM c.timestamp_timestamp) AS hour_of_day |
| mssql | DATEPART(HOUR, c.timestamp_timestamp) AS hour_of_day |
| sqlite | CAST(strftime('%H', c.timestamp_timestamp) AS INTEGER) AS hour_of_day |
minute
minute(value: date/time) → INTEGER
Extracts the minute part of a date or timestamp.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to extract from |
Sample query:
// minute: the minute component of a TIMESTAMP.
FIND check_temporal c
FETCH minute(c.timestamp_timestamp) minute_of_hour
Generated SQL
duckdb · snowflake · mariadb · trino
-- minute: the minute component of a TIMESTAMP.
SELECT
minute(c.timestamp_timestamp) AS minute_of_hour
FROM
check_temporal c
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| oracle · postgresql | EXTRACT(MINUTE FROM c.timestamp_timestamp) AS minute_of_hour |
| mssql | DATEPART(MINUTE, c.timestamp_timestamp) AS minute_of_hour |
| sqlite | CAST(strftime('%M', c.timestamp_timestamp) AS INTEGER) AS minute_of_hour |
second
second(value: date/time) → INTEGER
Extracts the second part of a date or timestamp.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to extract from |
Sample query:
// second: the second component of a TIMESTAMP.
FIND check_temporal c
FETCH second(c.timestamp_timestamp) second_of_minute
Generated SQL
duckdb · snowflake · mariadb · trino
-- second: the second component of a TIMESTAMP.
SELECT
second(c.timestamp_timestamp) AS second_of_minute
FROM
check_temporal c
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| oracle · postgresql | EXTRACT(SECOND FROM c.timestamp_timestamp) AS second_of_minute |
| mssql | DATEPART(SECOND, c.timestamp_timestamp) AS second_of_minute |
| sqlite | CAST(strftime('%S', c.timestamp_timestamp) AS INTEGER) AS second_of_minute |
quarter
quarter(value: date/time) → INTEGER
Quarter of the year, 1-4.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to extract from |
Sample query:
// quarter: which quarter of the year the order falls in.
FIND orders o
FETCH quarter(o.order_date) order_quarter
Generated SQL
duckdb · snowflake · mariadb · trino
-- quarter: which quarter of the year the order falls in.
SELECT
quarter(o.order_date) AS order_quarter
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mssql | DATEPART(quarter, o.order_date) AS order_quarter |
| oracle | TO_NUMBER(TO_CHAR(o.order_date, 'Q')) AS order_quarter |
| postgresql | EXTRACT(QUARTER FROM o.order_date) AS order_quarter |
| sqlite | ((CAST(strftime('%m', o.order_date) AS INTEGER) + 2) / 3) AS order_quarter |
week
week(value: date/time) → INTEGER
ISO-8601 week of the year, 1-53. Week 1 is the one containing the first Thursday, so early January can fall in week 52 or 53 of the previous year.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to extract from |
Sample query:
// week: the ISO-8601 week number of the order date.
FIND orders o
FETCH week(o.order_date) order_week
Generated SQL
duckdb · trino
-- week: the ISO-8601 week number of the order date.
SELECT
week(o.order_date) AS order_week
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | WEEKOFYEAR(o.order_date) AS order_week |
| mssql | DATEPART(iso_week, o.order_date) AS order_week |
| oracle | TO_NUMBER(TO_CHAR(o.order_date, 'IW')) AS order_week |
| postgresql | EXTRACT(WEEK FROM o.order_date) AS order_week |
| snowflake | WEEKISO(o.order_date) AS order_week |
| sqlite | ((CAST(strftime('%j', date(o.order_date, '-3 days', 'weekday 4')) AS INTEGER) - 1) / 7 + 1) AS order_week |
dayofweek
dayofweek(value: date/time) → INTEGER
Day of the week the ISO way: Monday is 1 and Sunday is 7. Engines disagree wildly here — some count Sunday as 0, some as 1 — so this is normalised, and the same query gives the same number on every database.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to extract from |
Sample query:
// dayofweek: which weekday the order was placed on, Monday = 1.
FIND orders o
FETCH dayofweek(o.order_date) order_weekday
Generated SQL
duckdb
-- dayofweek: which weekday the order was placed on, Monday = 1.
SELECT
isodow(o.order_date) AS order_weekday
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | (WEEKDAY(o.order_date) + 1) AS order_weekday |
| mssql | ((DATEDIFF(day, '19000101', o.order_date) % 7) + 1) AS order_weekday |
| oracle | (TRUNC(o.order_date) - TRUNC(o.order_date, 'IW') + 1) AS order_weekday |
| postgresql | EXTRACT(ISODOW FROM o.order_date) AS order_weekday |
| snowflake | DAYOFWEEKISO(o.order_date) AS order_weekday |
| sqlite | (((CAST(strftime('%w', o.order_date) AS INTEGER) + 6) % 7) + 1) AS order_weekday |
| trino | day_of_week(o.order_date) AS order_weekday |
dayofyear
dayofyear(value: date/time) → INTEGER
Day of the year, 1-366.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to extract from |
Sample query:
// dayofyear: how far into the year the order date is.
FIND orders o
FETCH dayofyear(o.order_date) order_dayofyear
Generated SQL
duckdb · snowflake · mariadb
-- dayofyear: how far into the year the order date is.
SELECT
dayofyear(o.order_date) AS order_dayofyear
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mssql | DATEPART(dayofyear, o.order_date) AS order_dayofyear |
| oracle | TO_NUMBER(TO_CHAR(o.order_date, 'DDD')) AS order_dayofyear |
| postgresql | EXTRACT(DOY FROM o.order_date) AS order_dayofyear |
| sqlite | CAST(strftime('%j', o.order_date) AS INTEGER) AS order_dayofyear |
| trino | day_of_year(o.order_date) AS order_dayofyear |
parse_date
parse_date(value: TEXT, format: TEXT) → DATE
Parses value into a date using the format mask.
The format mask is written in KQL's own vocabulary and translated per dialect, like to_char's — see the Formatting Functions page for the tokens.
| Argument | Type | Description |
|---|---|---|
| value | TEXT | the text to parse |
| format | TEXT | the format mask |
Generated SQL
Unsupported: mssql, sqlite
parse_time
parse_time(value: TEXT, format: TEXT) → TIME
Parses value into a time using the format mask.
The format mask is written in KQL's own vocabulary and translated per dialect, like to_char's — see the Formatting Functions page for the tokens.
| Argument | Type | Description |
|---|---|---|
| value | TEXT | the text to parse |
| format | TEXT | the format mask |
Generated SQL
Unsupported: mssql, sqlite
parse_timestamp
parse_timestamp(value: TEXT, format: TEXT) → TIMESTAMP
Parses value into a timestamp using the format mask.
The format mask is written in KQL's own vocabulary and translated per dialect, like to_char's — see the Formatting Functions page for the tokens.
| Argument | Type | Description |
|---|---|---|
| value | TEXT | the text to parse |
| format | TEXT | the format mask |
Generated SQL
Unsupported: mssql, sqlite
date_trunc
date_trunc(part: TEXT, value: date/time) → argument-dependent
Truncates value to the given precision, e.g. date_trunc('month', o.order_date).
| Argument | Type | Description |
|---|---|---|
| part | TEXT | the precision to truncate to, e.g. 'month' |
| value | date/time | the date or timestamp to truncate |
Sample query:
// date_trunc: truncate the order date to the month.
FIND orders o
FETCH date_trunc('month', o.order_date) month_start
Generated SQL
duckdb · snowflake · postgresql · trino
-- date_trunc: truncate the order date to the month.
SELECT
date_trunc('month', o.order_date) AS month_start
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | (MAKEDATE(YEAR(o.order_date), 1) + INTERVAL (MONTH(o.order_date) - 1) MONTH) AS month_start |
| mssql | DATEADD(MONTH, DATEDIFF(MONTH, 0, o.order_date), 0) AS month_start |
| oracle | TRUNC(o.order_date, 'MM') AS month_start |
| sqlite | date(o.order_date, 'start of month') AS month_start |
make_date
make_date(year: INTEGER, month: INTEGER, day: INTEGER) → DATE
Builds a date from year, month and day.
| Argument | Type | Description |
|---|---|---|
| year | INTEGER | the calendar year |
| month | INTEGER | the month of year, 1-12 |
| day | INTEGER | the day of month, 1-31 |
Sample query:
// make_date: build a DATE from year, month and day.
FIND orders o
FETCH make_date(2024, 1, 31) built
Generated SQL
duckdb · postgresql
-- make_date: build a DATE from year, month and day.
SELECT
make_date(2024, 1, 31) AS built
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | STR_TO_DATE(CONCAT(2024, '-', 1, '-', 31), '%Y-%m-%d') AS built |
| mssql | DATEFROMPARTS(2024, 1, 31) AS built |
| oracle | TO_DATE(2024 || '-' || 1 || '-' || 31, 'YYYY-MM-DD') AS built |
| snowflake | DATE_FROM_PARTS(2024, 1, 31) AS built |
| sqlite | date(printf('%04d-%02d-%02d', 2024, 1, 31)) AS built |
| trino | date(format('%04d-%02d-%02d', 2024, 1, 31)) AS built |
make_time
make_time(hour: INTEGER, minute: INTEGER, second: INTEGER) → TIME
Builds a time from hour, minute and second.
| Argument | Type | Description |
|---|---|---|
| hour | INTEGER | the hour of day, 0-23 |
| minute | INTEGER | the minute of hour, 0-59 |
| second | INTEGER | the second of minute, 0-59 |
Sample query:
// make_time: build a TIME from hour, minute and second.
FIND orders o
FETCH make_time(14, 30, 0) built
Generated SQL
duckdb · postgresql
-- make_time: build a TIME from hour, minute and second.
SELECT
make_time(14, 30, 0) AS built
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | MAKETIME(14, 30, 0) AS built |
| mssql | TIMEFROMPARTS(14, 30, 0, 0, 0) AS built |
| oracle | LPAD(14, 2, '0') || ':' || LPAD(30, 2, '0') || ':' || LPAD(0, 2, '0') AS built |
| snowflake | TIME_FROM_PARTS(14, 30, 0) AS built |
Unsupported: sqlite, trino
make_timestamp
make_timestamp(year: INTEGER, month: INTEGER, day: INTEGER, hour: INTEGER, minute: INTEGER, second: INTEGER) → TIMESTAMP
Builds a timestamp from its six components.
| Argument | Type | Description |
|---|---|---|
| year | INTEGER | the calendar year |
| month | INTEGER | the month of year, 1-12 |
| day | INTEGER | the day of month, 1-31 |
| hour | INTEGER | the hour of day, 0-23 |
| minute | INTEGER | the minute of hour, 0-59 |
| second | INTEGER | the second of minute, 0-59 |
Sample query:
// make_timestamp: build a TIMESTAMP from its parts.
FIND orders o
FETCH make_timestamp(2024, 1, 31, 14, 30, 0) built
Generated SQL
duckdb · postgresql
-- make_timestamp: build a TIMESTAMP from its parts.
SELECT
make_timestamp(2024, 1, 31, 14, 30, 0) AS built
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | STR_TO_DATE(CONCAT(2024, '-', 1, '-', 31, ' ', 14, ':', 30, ':', 0), '%Y-%m-%d %H:%i:%s') AS built |
| mssql | DATETIME2FROMPARTS(2024, 1, 31, 14, 30, 0, 0, 0) AS built |
| oracle | TO_TIMESTAMP(2024 || '-' || 1 || '-' || 31 || ' ' || 14 || ':' || 30 || ':' || 0, 'YYYY-MM-DD HH24:MI:SS') AS built |
| snowflake | TIMESTAMP_NTZ_FROM_PARTS(2024, 1, 31, 14, 30, 0) AS built |
Unsupported: sqlite, trino
days_between
days_between(start: date/time, end: date/time) → INTEGER
Signed number of complete days from start to end — whole 24-hour periods that fit inside the interval, not midnights crossed.
For two dates the two readings coincide, which is why the difference only shows with a time of day: days_between('2023-01-01 23:00', '2023-01-02 01:00') is 0, because two hours is not a day, even though a midnight lies between them.
Measured before this was settled, the engines split five to three: DuckDB, PostgreSQL, SQL Server, Snowflake and SQLite counted the boundary, MariaDB, Oracle and Trino the elapsed day. All eight now count the elapsed day, matching ChronoUnit.DAYS.
| Argument | Type | Description |
|---|---|---|
| start | date/time | the start of the span |
| end | date/time | the end of the span |
Sample query:
// days_between: signed day distance between two dates.
FIND check_temporal c
FETCH days_between("2023-03-01", "2023-02-01") signed_minus28
Generated SQL
duckdb
-- days_between: signed day distance between two dates.
SELECT
CAST(trunc(date_diff('second', DATE '2023-03-01', DATE '2023-02-01') / 86400.0) AS INTEGER) AS signed_minus28
FROM
check_temporal c
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | TIMESTAMPDIFF(DAY, DATE '2023-03-01', DATE '2023-02-01') AS signed_minus28 |
| mssql | (DATEDIFF_BIG(second, CAST('2023-03-01' AS DATE), CAST('2023-02-01' AS DATE)) / 86400) AS signed_minus28 |
| oracle | TRUNC(CAST(DATE '2023-02-01' AS DATE) - CAST(DATE '2023-03-01' AS DATE)) AS signed_minus28 |
| postgresql | CAST(trunc(EXTRACT(EPOCH FROM (CAST(DATE '2023-02-01' AS timestamp) - CAST(DATE '2023-03-01' AS timestamp))) / 86400.0) AS INTEGER) AS signed_minus28 |
| snowflake | TRUNC(DATEDIFF(second, DATE '2023-03-01', DATE '2023-02-01') / 86400) AS signed_minus28 |
| sqlite | CAST(julianday('2023-02-01') - julianday('2023-03-01') AS INTEGER) AS signed_minus28 |
| trino | (date_diff('second', CAST(DATE '2023-03-01' AS TIMESTAMP), CAST(DATE '2023-02-01' AS TIMESTAMP)) / 86400) AS signed_minus28 |
months_between
months_between(start: date/time, end: date/time) → INTEGER
Signed number of whole months completed from start to end; months_between('2023-01-31', '2023-03-30') = 1 — the second month is not complete.
| Argument | Type | Description |
|---|---|---|
| start | date/time | the start of the span |
| end | date/time | the end of the span |
Sample query:
// months_between: whole completed months between two dates.
FIND check_temporal c
FETCH months_between("2023-01-31", "2023-03-31") whole_two
Generated SQL
duckdb · postgresql
-- months_between: whole completed months between two dates.
SELECT
(CAST(EXTRACT(YEAR FROM age(DATE '2023-03-31', DATE '2023-01-31')) * 12 + EXTRACT(MONTH FROM age(DATE '2023-03-31', DATE '2023-01-31')) AS INTEGER)) AS whole_two
FROM
check_temporal c
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | TIMESTAMPDIFF(MONTH, DATE '2023-01-31', DATE '2023-03-31') AS whole_two |
| mssql | (DATEDIFF(month, CAST('2023-01-31' AS DATE), CAST('2023-03-31' AS DATE)) - CASE WHEN DAY(CAST('2023-03-31' AS DATE)) < DAY(CAST('2023-01-31' AS DATE)) THEN 1 ELSE 0 END) AS whole_two |
| oracle | TRUNC(MONTHS_BETWEEN(DATE '2023-03-31', DATE '2023-01-31')) AS whole_two |
| snowflake | (DATEDIFF(month, DATE '2023-01-31', DATE '2023-03-31') - CASE WHEN DAY(DATE '2023-03-31') < DAY(DATE '2023-01-31') THEN 1 ELSE 0 END) AS whole_two |
| sqlite | (CASE WHEN ((CAST(strftime('%Y', '2023-03-31') AS INTEGER) * 12 + CAST(strftime('%m', '2023-03-31') AS INTEGER)) - (CAST(strftime('%Y', '2023-01-31') AS INTEGER) * 12 + CAST(strftime('%m', '2023-01-31') AS INTEGER))) > 0 AND CAST(strftime('%d', '2023-03-31') AS INTEGER) < CAST(strftime('%d', '2023-01-31') AS INTEGER) THEN ((CAST(strftime('%Y', '2023-03-31') AS INTEGER) * 12 + CAST(strftime('%m', '2023-03-31') AS INTEGER)) - (CAST(strftime('%Y', '2023-01-31') AS INTEGER) * 12 + CAST(strftime('%m', '2023-01-31') AS INTEGER))) - 1 WHEN ((CAST(strftime('%Y', '2023-03-31') AS INTEGER) * 12 + CAST(strftime('%m', '2023-03-31') AS INTEGER)) - (CAST(strftime('%Y', '2023-01-31') AS INTEGER) * 12 + CAST(strftime('%m', '2023-01-31') AS INTEGER))) < 0 AND CAST(strftime('%d', '2023-03-31') AS INTEGER) > CAST(strftime('%d', '2023-01-31') AS INTEGER) THEN ((CAST(strftime('%Y', '2023-03-31') AS INTEGER) * 12 + CAST(strftime('%m', '2023-03-31') AS INTEGER)) - (CAST(strftime('%Y', '2023-01-31') AS INTEGER) * 12 + CAST(strftime('%m', '2023-01-31') AS INTEGER))) + 1 ELSE ((CAST(strftime('%Y', '2023-03-31') AS INTEGER) * 12 + CAST(strftime('%m', '2023-03-31') AS INTEGER)) - (CAST(strftime('%Y', '2023-01-31') AS INTEGER) * 12 + CAST(strftime('%m', '2023-01-31') AS INTEGER))) END) AS whole_two |
| trino | date_diff('month', DATE '2023-01-31', DATE '2023-03-31') AS whole_two |
years_between
years_between(start: date/time, end: date/time) → INTEGER
Signed number of whole years completed from start to end.
| Argument | Type | Description |
|---|---|---|
| start | date/time | the start of the span |
| end | date/time | the end of the span |
Sample query:
// years_between: whole years from order to shipment.
FIND orders o
FETCH years_between(o.order_date, o.shipped_date) years
Generated SQL
duckdb · postgresql
-- years_between: whole years from order to shipment.
SELECT
CAST(EXTRACT(YEAR FROM age(o.shipped_date, o.order_date)) AS INTEGER) AS years
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | TIMESTAMPDIFF(YEAR, o.order_date, o.shipped_date) AS years |
| mssql | (DATEDIFF(YEAR, o.order_date, o.shipped_date) - CASE WHEN DATEADD(YEAR, DATEDIFF(YEAR, o.order_date, o.shipped_date), o.order_date) > o.shipped_date THEN 1 ELSE 0 END) AS years |
| oracle | TRUNC(MONTHS_BETWEEN(o.shipped_date, o.order_date) / 12) AS years |
| snowflake | FLOOR(MONTHS_BETWEEN(o.shipped_date, o.order_date) / 12) AS years |
| sqlite | (CASE WHEN (CAST(strftime('%Y', o.shipped_date) AS INTEGER) - CAST(strftime('%Y', o.order_date) AS INTEGER)) > 0 AND strftime('%m-%d', o.shipped_date) < strftime('%m-%d', o.order_date) THEN (CAST(strftime('%Y', o.shipped_date) AS INTEGER) - CAST(strftime('%Y', o.order_date) AS INTEGER)) - 1 WHEN (CAST(strftime('%Y', o.shipped_date) AS INTEGER) - CAST(strftime('%Y', o.order_date) AS INTEGER)) < 0 AND strftime('%m-%d', o.shipped_date) > strftime('%m-%d', o.order_date) THEN (CAST(strftime('%Y', o.shipped_date) AS INTEGER) - CAST(strftime('%Y', o.order_date) AS INTEGER)) + 1 ELSE (CAST(strftime('%Y', o.shipped_date) AS INTEGER) - CAST(strftime('%Y', o.order_date) AS INTEGER)) END) AS years |
| trino | date_diff('year', o.order_date, o.shipped_date) AS years |
calendar_distance
calendar_distance(start: date/time, end: date/time) → DURATION
Calendar (civil) distance from start to end as a mixed interval (years/months/days + clock): calendar_distance('2025-01-01', '2026-05-15 12:00') = 1y4mo14d12h. Use ts − ts for a fixed elapsed span.
| Argument | Type | Description |
|---|---|---|
| start | date/time | the start of the span |
| end | date/time | the end of the span |
Sample query:
// calendar_distance: calendar span from order to shipment (NULL when not yet shipped).
FIND orders o
FETCH calendar_distance(o.order_date, o.shipped_date) span
Generated SQL
duckdb · postgresql
-- calendar_distance: calendar span from order to shipment (NULL when not yet shipped).
SELECT
(CAST(CAST(EXTRACT(EPOCH FROM (o.order_date)) AS BIGINT) AS VARCHAR) || ';' || CAST(CAST(EXTRACT(EPOCH FROM (o.shipped_date)) AS BIGINT) AS VARCHAR)) AS span
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | CONCAT(UNIX_TIMESTAMP(o.order_date), ';', UNIX_TIMESTAMP(o.shipped_date)) AS span |
| mssql | CONCAT(DATEDIFF_BIG(SECOND, '1970-01-01', o.order_date), ';', DATEDIFF_BIG(SECOND, '1970-01-01', o.shipped_date)) AS span |
| oracle | (TO_CHAR(ROUND((CAST(o.order_date AS DATE) - DATE '1970-01-01') * 86400)) || ';' || TO_CHAR(ROUND((CAST(o.shipped_date AS DATE) - DATE '1970-01-01') * 86400))) AS span |
| snowflake | (CAST(DATE_PART(EPOCH_SECOND, o.order_date) AS VARCHAR) || ';' || CAST(DATE_PART(EPOCH_SECOND, o.shipped_date) AS VARCHAR)) AS span |
| sqlite | (CAST(CAST(strftime('%s', o.order_date) AS INTEGER) AS VARCHAR) || ';' || CAST(CAST(strftime('%s', o.shipped_date) AS INTEGER) AS VARCHAR)) AS span |
| trino | (CAST(CAST(to_unixtime(o.order_date) AS BIGINT) AS VARCHAR) || ';' || CAST(CAST(to_unixtime(o.shipped_date) AS BIGINT) AS VARCHAR)) AS span |
day_add
day_add(value: date/time, n: INTEGER) → argument-dependent
value shifted by n days; n may be any expression.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to shift |
| n | INTEGER | the number of days to add |
Sample query:
// day_add: seven days after the order date.
FIND orders o
FETCH day_add(o.order_date, 7) plus_week
Generated SQL
duckdb · mariadb
-- day_add: seven days after the order date.
SELECT
(o.order_date + INTERVAL (7) DAY) AS plus_week
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mssql | DATEADD(DAY, 7, o.order_date) AS plus_week |
| oracle | (o.order_date + NUMTODSINTERVAL(7, 'DAY')) AS plus_week |
| postgresql | (o.order_date + 7 * INTERVAL '1 day') AS plus_week |
| snowflake | DATEADD('day', 7, o.order_date) AS plus_week |
| sqlite | date(o.order_date, printf('%+d days', 7)) AS plus_week |
| trino | date_add('day', 7, o.order_date) AS plus_week |
month_add
month_add(value: date/time, n: INTEGER) → argument-dependent
value shifted by n months, clamped to the end of the month: month_add('2023-01-31', 1) = 2023-02-28.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to shift |
| n | INTEGER | the number of months to add |
Sample query:
// month_add: one month after the order date.
FIND orders o
FETCH month_add(o.order_date, 1) next_month
Generated SQL
duckdb · mariadb
-- month_add: one month after the order date.
SELECT
(o.order_date + INTERVAL (1) MONTH) AS next_month
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mssql | DATEADD(MONTH, 1, o.order_date) AS next_month |
| oracle | (ADD_MONTHS(o.order_date, 1) - GREATEST(EXTRACT(DAY FROM ADD_MONTHS(o.order_date, 1)) - EXTRACT(DAY FROM o.order_date), 0)) AS next_month |
| postgresql | (o.order_date + 1 * INTERVAL '1 month') AS next_month |
| snowflake | DATEADD('month', 1, o.order_date) AS next_month |
| sqlite | min(date(o.order_date, printf('%+d months', 1)), date(o.order_date, 'start of month', printf('%+d months', 1 + 1), '-1 day')) AS next_month |
| trino | date_add('month', 1, o.order_date) AS next_month |
year_add
year_add(value: date/time, n: INTEGER) → argument-dependent
value shifted by n years, clamped (Feb 29 + 1 year = Feb 28).
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to shift |
| n | INTEGER | the number of years to add |
Sample query:
// year_add: one year after the order date.
FIND orders o
FETCH year_add(o.order_date, 1) next_year
Generated SQL
duckdb · mariadb
-- year_add: one year after the order date.
SELECT
(o.order_date + INTERVAL (1) YEAR) AS next_year
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mssql | DATEADD(YEAR, 1, o.order_date) AS next_year |
| oracle | (ADD_MONTHS(o.order_date, 1 * 12) - GREATEST(EXTRACT(DAY FROM ADD_MONTHS(o.order_date, 1 * 12)) - EXTRACT(DAY FROM o.order_date), 0)) AS next_year |
| postgresql | (o.order_date + 1 * INTERVAL '1 year') AS next_year |
| snowflake | DATEADD('year', 1, o.order_date) AS next_year |
| sqlite | min(date(o.order_date, printf('%+d years', 1)), date(o.order_date, 'start of month', printf('%+d months', 1 * 12 + 1), '-1 day')) AS next_year |
| trino | date_add('year', 1, o.order_date) AS next_year |
day_begin
day_begin(value: date/time) → argument-dependent
Start of the day (time becomes 00:00:00).
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to floor to the day |
Sample query:
// day_begin: midnight at the start of a TIMESTAMP's day.
FIND check_temporal c
FETCH day_begin(c.timestamp_timestamp) start_of_day
Generated SQL
duckdb · snowflake · postgresql · trino
-- day_begin: midnight at the start of a TIMESTAMP's day.
SELECT
date_trunc('day', c.timestamp_timestamp) AS start_of_day
FROM
check_temporal c
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | CAST(DATE(c.timestamp_timestamp) AS DATETIME) AS start_of_day |
| mssql | CAST(CAST(c.timestamp_timestamp AS DATE) AS DATETIME2) AS start_of_day |
| oracle | TRUNC(CAST(c.timestamp_timestamp AS DATE)) AS start_of_day |
| sqlite | datetime(c.timestamp_timestamp, 'start of day') AS start_of_day |
week_begin
week_begin(value: date/time) → argument-dependent
Monday of the week (pairs with week_end). Grouping by this is the reliable way to bucket by week: it is a real date, so it sorts, and it has none of the year-boundary trouble of grouping by year and week together — 2026-12-28 is in week 1, but of 2027.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to floor to the week |
Sample query:
// week_begin: Monday of the order's week — the sortable weekly grouping key.
FIND orders o
FETCH week_begin(o.order_date) week_start
Generated SQL
duckdb · postgresql · trino
-- week_begin: Monday of the order's week — the sortable weekly grouping key.
SELECT
date_trunc('week', o.order_date) AS week_start
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | (DATE(o.order_date) - INTERVAL WEEKDAY(o.order_date) DAY) AS week_start |
| mssql | DATEADD(day, -(DATEDIFF(day, 0, o.order_date) % 7), CAST(o.order_date AS DATE)) AS week_start |
| oracle | TRUNC(o.order_date, 'IW') AS week_start |
| snowflake | DATEADD(day, -(DAYOFWEEKISO(o.order_date) - 1), o.order_date) AS week_start |
| sqlite | date(o.order_date, '-6 days', 'weekday 1') AS week_start |
month_begin
month_begin(value: date/time) → argument-dependent
First day of the month (pairs with month_end).
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to floor to the month |
Sample query:
// month_begin: first day of the order's month.
FIND orders o
FETCH month_begin(o.order_date) m_begin
Generated SQL
duckdb · snowflake · postgresql · trino
-- month_begin: first day of the order's month.
SELECT
date_trunc('month', o.order_date) AS m_begin
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | (MAKEDATE(YEAR(o.order_date), 1) + INTERVAL (MONTH(o.order_date) - 1) MONTH) AS m_begin |
| mssql | DATEADD(MONTH, DATEDIFF(MONTH, 0, o.order_date), 0) AS m_begin |
| oracle | TRUNC(o.order_date, 'MM') AS m_begin |
| sqlite | date(o.order_date, 'start of month') AS m_begin |
quarter_begin
quarter_begin(value: date/time) → argument-dependent
First day of the quarter.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to floor to the quarter |
Sample query:
// quarter_begin: first day of the order's quarter.
FIND orders o
FETCH quarter_begin(o.order_date) q_begin
Generated SQL
duckdb · snowflake · postgresql · trino
-- quarter_begin: first day of the order's quarter.
SELECT
date_trunc('quarter', o.order_date) AS q_begin
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | (MAKEDATE(YEAR(o.order_date), 1) + INTERVAL (QUARTER(o.order_date) - 1) * 3 MONTH) AS q_begin |
| mssql | DATEADD(QUARTER, DATEDIFF(QUARTER, 0, o.order_date), 0) AS q_begin |
| oracle | TRUNC(o.order_date, 'Q') AS q_begin |
| sqlite | date(o.order_date, 'start of month', printf('%+d months', -((CAST(strftime('%m', o.order_date) AS INTEGER) - 1) % 3))) AS q_begin |
year_begin
year_begin(value: date/time) → argument-dependent
First day of the year.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to floor to the year |
Sample query:
// year_begin: first day of the order's year.
FIND orders o
FETCH year_begin(o.order_date) y_begin
Generated SQL
duckdb · snowflake · postgresql · trino
-- year_begin: first day of the order's year.
SELECT
date_trunc('year', o.order_date) AS y_begin
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | MAKEDATE(YEAR(o.order_date), 1) AS y_begin |
| mssql | DATEADD(YEAR, DATEDIFF(YEAR, 0, o.order_date), 0) AS y_begin |
| oracle | TRUNC(o.order_date, 'YYYY') AS y_begin |
| sqlite | date(o.order_date, 'start of year') AS y_begin |
week_end
week_end(value: date/time) → DATE
Sunday of the week.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to take the week end of |
Sample query:
// week_end: Sunday of the order's week.
FIND orders o
FETCH week_end(o.order_date) week_close
Generated SQL
duckdb
-- week_end: Sunday of the order's week.
SELECT
CAST(date_trunc('week', o.order_date) + INTERVAL 6 DAY AS DATE) AS week_close
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | (DATE(o.order_date) - INTERVAL WEEKDAY(o.order_date) DAY + INTERVAL 6 DAY) AS week_close |
| mssql | DATEADD(day, 6 - (DATEDIFF(day, 0, o.order_date) % 7), CAST(o.order_date AS DATE)) AS week_close |
| oracle | (TRUNC(o.order_date, 'IW') + 6) AS week_close |
| postgresql | CAST(date_trunc('week', o.order_date) + INTERVAL '6 days' AS DATE) AS week_close |
| snowflake | DATEADD(day, 7 - DAYOFWEEKISO(o.order_date), o.order_date) AS week_close |
| sqlite | date(o.order_date, 'weekday 0') AS week_close |
| trino | CAST(date_trunc('week', o.order_date) + INTERVAL '6' DAY AS DATE) AS week_close |
month_end
month_end(value: date/time) → DATE
Last day of the month (Excel EOMONTH): month_end('2024-02-10') = 2024-02-29.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to take the month end of |
Sample query:
// month_end: last day of the order's month.
FIND orders o
FETCH month_end(o.order_date) m_end
Generated SQL
duckdb · snowflake
-- month_end: last day of the order's month.
SELECT
last_day(o.order_date) AS m_end
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | LAST_DAY(o.order_date) AS m_end |
| mssql | EOMONTH(o.order_date) AS m_end |
| oracle | TRUNC(LAST_DAY(o.order_date)) AS m_end |
| postgresql | CAST(date_trunc('month', o.order_date) + INTERVAL '1 month - 1 day' AS DATE) AS m_end |
| sqlite | date(o.order_date, 'start of month', '+1 month', '-1 day') AS m_end |
| trino | last_day_of_month(o.order_date) AS m_end |
quarter_end
quarter_end(value: date/time) → DATE
Last day of the quarter.
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to take the quarter end of |
Sample query:
// quarter_end: last day of the order's quarter.
FIND orders o
FETCH quarter_end(o.order_date) q_end
Generated SQL
duckdb
-- quarter_end: last day of the order's quarter.
SELECT
last_day(date_trunc('quarter', o.order_date) + INTERVAL 2 MONTH) AS q_end
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | LAST_DAY(MAKEDATE(YEAR(o.order_date), 1) + INTERVAL (QUARTER(o.order_date) * 3 - 1) MONTH) AS q_end |
| mssql | EOMONTH(DATEADD(QUARTER, DATEDIFF(QUARTER, 0, o.order_date), 0), 2) AS q_end |
| oracle | LAST_DAY(ADD_MONTHS(TRUNC(o.order_date, 'Q'), 2)) AS q_end |
| postgresql | CAST(date_trunc('quarter', o.order_date) + INTERVAL '3 months - 1 day' AS DATE) AS q_end |
| snowflake | LAST_DAY(o.order_date, 'quarter') AS q_end |
| sqlite | date(o.order_date, 'start of month', printf('%+d months', 3 - ((CAST(strftime('%m', o.order_date) AS INTEGER) - 1) % 3)), '-1 day') AS q_end |
| trino | last_day_of_month(date_trunc('quarter', o.order_date) + INTERVAL '2' MONTH) AS q_end |
year_end
year_end(value: date/time) → DATE
Last day of the year (December 31).
| Argument | Type | Description |
|---|---|---|
| value | date/time | the date or timestamp to take the year end of |
Sample query:
// year_end: last day of the order's year.
FIND orders o
FETCH year_end(o.order_date) y_end
Generated SQL
duckdb
-- year_end: last day of the order's year.
SELECT
last_day(date_trunc('year', o.order_date) + INTERVAL 11 MONTH) AS y_end
FROM
orders o
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | LAST_DAY(MAKEDATE(YEAR(o.order_date), 1) + INTERVAL 11 MONTH) AS y_end |
| mssql | DATEFROMPARTS(YEAR(o.order_date), 12, 31) AS y_end |
| oracle | LAST_DAY(ADD_MONTHS(TRUNC(o.order_date, 'YYYY'), 11)) AS y_end |
| postgresql | CAST(date_trunc('year', o.order_date) + INTERVAL '1 year - 1 day' AS DATE) AS y_end |
| snowflake | LAST_DAY(o.order_date, 'year') AS y_end |
| sqlite | date(o.order_date, 'start of year', '+1 year', '-1 day') AS y_end |
| trino | last_day_of_month(date_trunc('year', o.order_date) + INTERVAL '11' MONTH) AS y_end |
at_zone
at_zone(value: date/time, zone: TEXT) → TIMESTAMP
Reads value as a model-zone wall-clock value and returns its wall-clock in the named zone (e.g. for day-bucketing: date(at_zone(o.ts, 'Europe/Berlin'))).
| Argument | Type |
|---|---|
| value | date/time |
| zone | TEXT |
Sample query:
// at_zone: read a model-zone wall-clock value in another zone.
FIND check_temporal c
FETCH at_zone(c.ts_diff_base, 'America/New_York') in_new_york
Generated SQL
duckdb · postgresql
-- at_zone: read a model-zone wall-clock value in another zone.
SELECT
((c.ts_diff_base AT TIME ZONE 'UTC') AT TIME ZONE 'America/New_York') AS in_new_york
FROM
check_temporal c
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | CONVERT_TZ(c.ts_diff_base, 'UTC', 'America/New_York') AS in_new_york |
| mssql | CAST(((CAST(c.ts_diff_base AS datetime2) AT TIME ZONE 'UTC') AT TIME ZONE 'Eastern Standard Time') AS datetime2) AS in_new_york |
| oracle | CAST(FROM_TZ(CAST(c.ts_diff_base AS TIMESTAMP), 'UTC') AT TIME ZONE 'America/New_York' AS TIMESTAMP) AS in_new_york |
| snowflake | CONVERT_TIMEZONE('UTC', 'America/New_York', c.ts_diff_base) AS in_new_york |
| trino | CAST(with_timezone(c.ts_diff_base, 'UTC') AT TIME ZONE 'America/New_York' AS TIMESTAMP) AS in_new_york |
Unsupported: sqlite
to_utc
to_utc(value: date/time, zone: TEXT) → TIMESTAMP
Inverse of at_zone: reads value as a wall-clock in the named zone and returns the model-zone wall-clock value.
| Argument | Type |
|---|---|
| value | date/time |
| zone | TEXT |
Sample query:
// to_utc: read a zoned wall-clock value and return it in UTC.
FIND check_temporal c
FETCH to_utc(c.ts_diff_base, 'America/New_York') as_utc
Generated SQL
duckdb · postgresql
-- to_utc: read a zoned wall-clock value and return it in UTC.
SELECT
((c.ts_diff_base AT TIME ZONE 'America/New_York') AT TIME ZONE 'UTC') AS as_utc
FROM
check_temporal c
The remaining dialects differ only in this expression:
| Dialect | Expression |
|---|---|
| mariadb | CONVERT_TZ(c.ts_diff_base, 'America/New_York', 'UTC') AS as_utc |
| mssql | CAST(((CAST(c.ts_diff_base AS datetime2) AT TIME ZONE 'Eastern Standard Time') AT TIME ZONE 'UTC') AS datetime2) AS as_utc |
| oracle | CAST(FROM_TZ(CAST(c.ts_diff_base AS TIMESTAMP), 'America/New_York') AT TIME ZONE 'UTC' AS TIMESTAMP) AS as_utc |
| snowflake | CONVERT_TIMEZONE('America/New_York', 'UTC', c.ts_diff_base) AS as_utc |
| trino | CAST(with_timezone(c.ts_diff_base, 'America/New_York') AT TIME ZONE 'UTC' AS TIMESTAMP) AS as_utc |
Unsupported: sqlite