Search notes:

SQLite: date and time related functions

Although SQLite does not have an explicit date or time data type, it has five functions that are related to date and time:
Function Default format Returned data type
time ( datetimestring, modifiers… ) %H:%M:%S text
date ( datetimestring, modifiers… ) %Y-%m-%d text
datetime ( datetimestring, modifiers… ) %H:%M:%S %Y-%M-%d text
julianday( datetimestring, modifiers… ) %J real
strftime (format, datetimestring, modifiers… ) As per format text
The first four differ from the last one in that they use a default format for the returned value while strftime allows (and requires) to explicitly define the returned format.
Another difference is that julianday returns a value in the datatype real while the others (even strftime('%J', …)) returns a value as text.
Thus, the following to expressions are equivalent:
select date    (            'now');
select strftime('%Y-%m-%d', 'now');
TODO: Version 3.38.0 (2022-02-22) added the sixth function unixepoch().

datetimestring

The datetimestring specifies a point in time on which the function is applied.
The arguably simplest datetimestring is 'now': it specifies the current UTC date and time. The following example shows how the same date-time is formatted differently with the time, date and datetime functions. It also demonstrates how strftime is used to return a user defined format:
.mode   column
.header on

select
   time    (                             'now') "time",
   date    (                             'now') "date",
   datetime(                             'now') "datetime",
   strftime('Minutes past the hour: %M', 'now') "strftime";
--
-- time        date        datetime             strftime                 
-- ----------  ----------  -------------------  -------------------------
-- 15:32:24    2019-09-22  2019-09-22 15:32:24  Minutes past the hour: 32
Github repository about-sqlite, path: /functions/date-time/now.sql
The complete list of datetimestrings is:
datetimestring ISO 8601 compliant comment
YYYY-MM-DD Year, month and day of month.
YYYY-MM-DD HH:MM As above, plus hours and minutes
YYYY-MM-DD HH:MM:SS As above, plus seconds
YYYY-MM-DD HH:MM:SS.SSS As above, plus fractions of seconds
YYYY-MM-DDTHH:MM Note the T between the day (DD) and the hour (HH).
YYYY-MM-DDTHH:MM:SS
YYYY-MM-DDTHH:MM:SS.SSS
HH:MM Hours and minuts only
HH:MM:SS As above, plus seconds
HH:MM:SS.SSS As above, plus fractional seconds
now Current date, time, fractional seconds, in UTC.
DDDDDDDDDD Julian day number
The following example uses strftime to render the same date (which is specified by the datetimestring '2018-03-05') in a British, American and Swiss format
.mode   column
.header on

select
   strftime('%d/%m/%Y', '2018-03-05') british,
   strftime('%m/%d/%Y', '2018-03-05') american,
   strftime('%d.%m.%Y', '2018-03-05') swiss
;
--
-- british     american    swiss     
-- ----------  ----------  ----------
-- 05/03/2018  03/05/2018  05.03.2018
Github repository about-sqlite, path: /functions/date-time/strftime-datetimestring.sql

Modifiers

All functions allow to modify the date time that was specified with the datetimestring.
One modifier is localtime. This modifier interprets a date value as UTC and converts it to local time. Thus, it might be useful to print the current date and time in local time:
The following example prints now in UTC and localtime. Because the computer on which it was run is configured with UTC+2 (see date +%z), there is a (positive) 2 hour difference between the UTC and localtime in the result:
.mode   column
.header on

select
   time('now')                now_utc,
   time('now', 'localtime')   now_localtime;
--
-- now_utc     now_localtime
-- ----------  -------------
-- 16:02:13    18:02:13     
Github repository about-sqlite, path: /functions/date-time/now-localtime.sql
Other modifiers allow to add or subtract units of periods:
.mode   column
.header on

select
   datetime('now'           ) now,
   time    ('now', '5 hours') now_5,
   date    ('now', '-4 days') now_min_4d;
--             
-- now                  now_5       now_min_4d
-- -------------------  ----------  ----------
-- 2019-09-22 16:19:34  21:19:34    2019-09-18
Github repository about-sqlite, path: /functions/date-time/add-subtract-period.sql
A nice features is the combination of modifiers:
.mode   column
.header on

select
    datetime('now',
             'start of day',
             '+3 hours',
             '+12 minutes') "3 hours, 12 minuts past midnight";
--
-- 3 hours, 12 minuts past midnight
-- --------------------------------
-- 2019-09-22 03:12:00             
Github repository about-sqlite, path: /functions/date-time/modifier-combination.sql

Modifier unixepoch

A special modifier is 'unixepoch'. It interprets datetimestring as seconds per 1970-01-01 in UTC. In the following example, the datetime of 0 and a calculated one are shown:
.mode column
.header    on

select
   datetime(0, 'unixepoch') start_of_unix_epoch,
   datetime( (2019 - 1970) * 365 * 24 * 60 * 60 +
                              12 * 24 * 60 * 60 +  -- 12 Leap years
                               7 * 24 * 60 * 60 +  --  8th day of the year (epoch starts with first!)
                                   15 * 60 * 60 +  --  15th hour
                                        32 * 60 +  --  32th minute
                                              7 ,  --  7 second
                             'unixepoch')  calculated;
;
--
-- start_of_unix_epoch  calculated         
-- -------------------  -------------------
-- 1970-01-01 00:00:00  2019-01-08 15:32:07
Github repository about-sqlite, path: /functions/date-time/unixepoch.sql
In order to get a localtime rather than a UTC time, the unixepoch modifier must be combined with localtime modifier:
.header on
.mode   column
.width  10 19 19

with now  as (
   select strftime('%s', 'now') as unix_epoch
)
select
   now.unix_epoch                                     unix_epoch,
   datetime(now.unix_epoch, 'unixepoch'             ) UTC,
   datetime(now.unix_epoch, 'unixepoch', 'localtime') localTime
from
   now;
--
-- unix_epoch  UTC                  localTime
-- ----------  -------------------  -------------------
-- 1586506681  2020-04-10 08:18:01  2020-04-10 10:18:01
Github repository about-sqlite, path: /functions/date-time/unixepoch-localtime.sql

Weekday

Another interesting modifier is 'weekday n' which returns the next date that falls on the given weekday (0 = Sunday):
.mode   column
.header on

select
   date('2019-09-20', 'weekday 0') next_sunday,
   date('2019-09-20', 'weekday 1') next_monday,
   date('2019-09-20', 'weekday 2') next_tuesday,
   date('2019-09-20', 'weekday 3') next_wednesday,
   date('2019-09-20', 'weekday 4') next_thursday,
   date('2019-09-20', 'weekday 5') next_friday,
   date('2019-09-20', 'weekday 6') next_saturday;
--
-- next_sunday  next_monday  next_tuesday  next_wednesday  next_thursday  next_friday  next_saturday
-- -----------  -----------  ------------  --------------  -------------  -----------  -------------
-- 2019-09-22   2019-09-23   2019-09-24    2019-09-25      2019-09-26     2019-09-20   2019-09-21   
Github repository about-sqlite, path: /functions/date-time/weekday.sql

Calculating start of week

2021-11-30 is a Tuesday, the start (Sunday) of the corresponding week is 2021-11-28. The following steps try to explain how this date can be calculated:
select                                  date('2021-11-30', 'weekday 0')      ; -- Next sunday: 2021-12-15
select                        julianday(date('2021-11-30', 'weekday 0'))     ; -- Julian Day is 2459553.5
select                        julianday(date('2021-11-30', 'weekday 0'))-7   ; -- Subtracting 7 days returns Julian Day 2459546.5
select                   date(julianday(date('2021-11-30', 'weekday 0'))-7)  ; -- Convert Julian Day to date: 2021-11-28 (which is 2021-11-28)
select strftime('%Y-%W', date(julianday(date('2021-11-30', 'weekday 0'))-7)) ; -- Select date's year and week (2021-47)
select strftime('%Y-%W', date(julianday(date('2021-12-07', 'weekday 0')) -7));

julianday

julianday(…) returns a number (a real) that specifies the (fractional) days since the start of the proleptic Gregorian calendar (noon of November 24th, 4714 B.C).
.mode   column
.header on

select
    datetime ('0'                  )                           start_of_julian_day,
    julianday('now', 'start of day')                           todays_julian_day,
    julianday('2017-08-28'         ) - julianday('2017-07-28') days_between,
    julianday('2017-08-28 06:00:00') - julianday('2017-07-28') fractional_days_between;
--
-- start_of_julian_day   todays_julian_day  days_between  fractional_days_between
-- --------------------  -----------------  ------------  -----------------------
-- -4713-11-24 12:00:00  2458748.5          31.0          31.25                  
Github repository about-sqlite, path: /functions/date-time/julianday.sql
See also Julianischer Tag

Returning a Julian Day or a Unix Epoch

The two strftime format strings %J and %s a Julian Day or a Unix Epoch, respectively. Note, although the returned values are numerical in nature, their data type is text. However, the data type of julianday() is real:
.mode   column
.header on

select
          strftime ('%J', '1970-01-01 00:00:00')  julDay_J  ,
          julianday(      '1970-01-01 00:00:00')  julDay    ,
          strftime ('%s', '1970-01-01 00:00:00')  unixEpoch ,
   typeof(strftime ('%J', '1970-01-01 00:00:00')) dataType_1,
   typeof(julianday(      '1970-01-01 00:00:00')) dataType_2
--
-- julDay_J    julDay      unixEpoch   dataType_1  dataType_2
-- ----------  ----------  ----------  ----------  ----------
-- 2440587.5   2440587.5   0           text        real      
Github repository about-sqlite, path: /functions/date-time/strftime-julian-day_unix-epoch.sql

datetimestring DDDDD

A datetimestring that consists of numbers is interpreted as Julian Day unless followed by the modifier 'unixepoch:
.mode   column
.header on

select
    datetime('0'                   ) a,
    datetime('0'      , 'unixepoch') b,
    datetime('2440616'             ) c,
    datetime('2440616', 'unixepoch') d;
--
-- a                     b                    c                    d                  
-- --------------------  -------------------  -------------------  -------------------
-- -4713-11-24 12:00:00  1970-01-01 00:00:00  1970-01-29 12:00:00  1970-01-29 05:56:56
Github repository about-sqlite, path: /functions/date-time/formatstring-DDDDD.sql

strftime

select datetime('now');
-- 2017-01-17 11:10:56

select strftime('%H:%M:%S %d.%m.%Y', 'now');
-- 11:10:56 17.01.2017

select strftime('%s', '1970-01-01 00:00:00');
-- 0

select strftime('%s', '1970-01-01 00:00:01');
-- 1

select strftime('%s', '2016-09-17 22:34:18');
-- 1474151658

select datetime(1474151658, 'unixepoch');
-- 2016-09-17 22:34:18
Github repository about-sqlite, path: /functions/date-time/strftime.sql
See also some general notes about strftime.

See also

functions

Index