Dates and Times in SQLite
Parse and format ISO-8601 date text, where dialects diverge most.
Dates and Times in SQLite
In the warehouse this differs. SQLite has no dedicated DATE or TIMESTAMP type. Dates live as TEXT in ISO-8601 (
'2026-03-01'or'2026-03-01T09:14:00Z'), and you manipulate them with thedate(),datetime(), andstrftime()functions. Real warehouses have nativeDATE/TIMESTAMPtypes and different function names: Postgres usesdate_trunc('month', ts)andEXTRACT(YEAR FROM ts); BigQuery usesDATE_TRUNC/FORMAT_DATE; Snowflake usesDATE_TRUNC/TO_CHAR. The concepts below (truncate, extract a part, filter a window) transfer everywhere; the exact syntax does not. Because ISO-8601 text also sorts and compares chronologically as plain strings, a lot of date filtering needs no functions at all.
The core functions (SQLite)
date(ts)truncates a timestamp to the day:date('2026-03-01T09:14:00Z')→'2026-03-01'.strftime(fmt, ts)formats or extracts.strftime('%Y-%m', ts)→'2026-03'(year-month);%Yyear,%mmonth,%dday,%wday-of-week (0=Sunday).
Worked example (extract year-month):
SELECT
order_id,
strftime('%Y-%m', order_ts) AS order_year_month
FROM orders;
Anatomy.
strftime( '%Y-%m' , order_ts )
└ format ┘ └ ISO text timestamp ┘
date( order_ts ) -> 'YYYY-MM-DD' (day truncation)
order_ts >= '2026-01-01' -> string compare = chronological filter
Filtering a window. Because ISO text sorts correctly, a rolling window is just a string range: WHERE order_ts >= '2026-01-01' AND order_ts < '2026-04-01'. Prefer half-open ranges (>= start AND < next_start) over BETWEEN for timestamps, so you don't accidentally include or exclude the boundary instant.
Pitfall. strftime returns text, so strftime('%m', ts) is '03' (string), not the number 3. Cast if you need arithmetic. And strftime/date only work on valid ISO-8601 strings; a malformed date like '03/01/2026' returns NULL silently. Validate/standardize date text before relying on these functions.
Recap. In SQLite dates are ISO text: date() truncates to day, strftime() extracts/formats, and plain string comparison filters windows, but the function names change in every real warehouse, so lean on the portable concepts.
CREATE TABLE orders (
order_id INTEGER,
order_ts TEXT -- ISO-8601
);
INSERT INTO orders VALUES
(1, '2026-01-15T10:00:00Z'),
(2, '2026-02-03T14:30:00Z'),
(3, '2026-02-28T23:59:00Z');SELECT
order_id,
strftime('%Y-%m', order_ts) AS order_year_month
FROM orders;Apply
Your turn
The task this lesson builds to.
Extract the year-month (YYYY-MM) from each order's timestamp. Return order_id and order_year_month.
3 hints and 1 automated check are waiting in the workspace.
Practice
Make it stick
A second problem on the same idea, so it survives past today.
Build a date-spine preview for a daily mart, filtered to a rolling window of 2026-01-01 (inclusive) up to 2026-04-01 (exclusive). For each in-window order return:
order_idorder_date: the timestamp truncated to the day (YYYY-MM-DD)order_year_month:YYYY-MMday_of_week: the numeric day-of-week as text viastrftime('%w', ...)(0=Sunday …6=Saturday)
Sort the output by order_date ascending.
3 hints and 1 automated check are waiting in the workspace.