SQLiteには本物の日付型は存在しない
PostgreSQLやMySQLから来た人がほぼ確実につまずくポイントです。SQLiteのストレージクラスは NULL、INTEGER、REAL、TEXT、BLOB の5つだけ。DATE も DATETIME も TIMESTAMP もありません。CREATE TABLE で created_at DATETIME と書けば SQLite は受け付けてくれますが、実際にはテキストか数値として保存されているだけです。
その代わりに、SQLite には次の3つの形式を理解する日付関数群が用意されています。
- ISO 8601 形式のテキスト —
'2026-04-23'、'2026-04-23 10:15:00'、'2026-04-23T10:15:00.123Z'など。 - Unix タイムスタンプ — 1970-01-01 UTC からの経過秒数を整数で保持。
- ユリウス通日(Julian day) — 紀元前4714年からの経過日数(小数あり)を実数で保持。
どれか一つに決めて、最後まで統一してください。一番読みやすく、文字列のままでも正しくソートできるのが ISO 8601 のテキスト形式で、これがデファクトの選択肢になっています。
「今すぐ」を表す方法は4通り — テキスト形式の日付、テキスト形式の日時、Unix秒、ユリウス日。どれも同じ瞬間を別の形で表現しているだけです。
SQLite の日付関数 5 つ
SQLite には日付・時刻まわりの組み込み関数が 5 つ用意されていて、これだけ押さえておけばだいたい事足ります。
date(time, ...)—YYYY-MM-DD形式を返すtime(time, ...)—HH:MM:SS形式を返すdatetime(time, ...)—YYYY-MM-DD HH:MM:SS形式を返すjulianday(time, ...)— 実数を返す(日数の差分計算に便利)strftime(format, time, ...)— 任意のフォーマットの文字列を返す
どの関数も、第1引数に時刻の値を渡し、そのあとに修飾子(modifier)を好きなだけ並べて指定する形になっています。
'unixepoch' を忘れずに付けてください。これは「渡している整数は Unix タイムスタンプですよ」と日付関数に伝えるための指定子です。これを書かないと、SQLite はその数値をユリウス日として扱ってしまいます。
strftime でカスタム日付フォーマット
日付フォーマットを自在に組み立てたいときの主役が strftime です。書式指定子は C や Python でおなじみの % 形式そのままなので、すんなり馴染めるはずです。
よく使うフォーマット指定子はこのあたりです:
%Y— 4桁の年。%m— 月(01〜12)。%d— 日(01〜31)。%H、%M、%S— 時、分、秒。%w— 曜日(0=日曜)。%j— 年内の通算日(001〜366)。%s— Unixタイムスタンプ。%f— 小数点付きの秒(SS.SSS)。
SQLiteにはEXTRACTやYEAR()のような専用関数がないので、日付の一部を取り出したいときも strftime を使います。欲しい部分だけをフォーマットして、必要なら数値にキャストするだけです:
strftime は常に文字列を返すので、数値として計算したり比較したい場合は CAST(... AS INTEGER) で囲んでください。
モディファイア:演算子いらずの日付計算
SQLite の日付処理が気持ちよく書けるのは、この機能のおかげです。時刻引数の後ろに モディファイア 文字列をいくつでも並べられて、書いた順に適用されていきます。
よく使う修飾子(modifier)
実務でほぼ毎日使うのはこのあたりです。
'+N days'や'-N days'、同じ要領でhours、minutes、seconds、months、yearsも指定できます。'start of day'、'start of month'、'start of year'— その境界に切り捨て。'weekday N'— 次の指定曜日へ進める(0=日曜)。'localtime'と'utc'— タイムゾーンの変換。
「月末日を取得する」テクニックは覚えておく価値ありです。月初に移動 → 1ヶ月足す → 1日引く の順に修飾子をつなげるだけ。SQLite には LAST_DAY 関数がありませんが、修飾子のチェーンで同じ結果が得られます。
UTC とローカル時刻の使い分け
'now' が返すのは常に UTC です。ローカル時刻が欲しい場合は、明示的に指定する必要があります。
'localtime' 修飾子は UTC 値をシステムのローカルタイムゾーンに変換します。逆方向が 'utc' 修飾子で、入力をローカル時刻として扱い UTC に変換します。
安全な運用のコツは、保存はすべて UTC で行い、表示するときだけローカルに変換することです。保存時にタイムゾーンを混在させると、サマータイムの切り替わるタイミング、つまり年に2回だけ顔を出す厄介なバグの温床になります。
sqlite で日付を比較・範囲で絞り込む
日付を ISO 8601 形式のテキストで保存しておけば、比較や BETWEEN がそのまま使えます。ISO 8601 は辞書順でソートしても時系列順と一致するからです。これがデフォルト形式に採用されている最大の理由です。
半開区間(>= start、< end)を使うのは身につけておきたい習慣です。「30日の0時は含まれるの?含まれないの?」という悩みを根本から解消できます。
「直近7日間」を取得したいときは、境界の計算をSQLite側に任せましょう。
日付の差分を計算する
SQLite には DATEDIFF 関数がありません。とはいえ、次の 2 つのパターンを押さえておけば、日付の差分はだいたい何でも計算できます。
julianday() の差分は日単位(小数まで含む精度)で返ってくるので、24 をかければ時間、1440 をかければ分になります。一方 strftime('%s', ...) の差分は秒単位なので、整数で扱いたいときに便利です。
日数を丸めて整数で取りたい場合は、CAST(... AS INTEGER) で小数部を切り捨てます:
日付の保存形式は1つに統一する
現実的な選択肢は3つあります。普段使いでおすすめな順に並べると、こんな感じです。
- ISO 8601形式のテキスト(
TEXT)。ダンプしても読みやすく、ソートも正しく効き、SQLiteの日付関数とも相性抜群。基本はこれを選んでおけば間違いありません。 - Unix秒(
INTEGER)。サイズが小さくて比較も速く、タイムゾーンの曖昧さもありません。数百万行を扱うようなテーブルではこちらが有利。読み出すときはdatetime(col, 'unixepoch')が必要です。 - ユリウス日(
REAL)。日付計算をゴリゴリやる場合や、1カラムでサブ秒精度を保ちたい場合以外、わざわざ選ぶ価値はあまりありません。
逆に絶対にやってはいけないのが、同じカラム内で複数のフォーマットを混在させることです。日付関数はどちらの形式でも文句を言わずに受け取ってくれますが、インデックス・ソート・比較の結果はめちゃくちゃになります。
DEFAULT (datetime('now')) は SQLite における DEFAULT CURRENT_TIMESTAMP の書き方で、アプリ側で何もしなくても、新しい行が追加されるたびに現在の UTC 時刻が自動的に入ります。
期間ごとに集計する
月単位・週単位・時間単位で行をまとめたいときは、strftime の出番です。
「時間帯ごとの注文数」「曜日ごとの登録数」「分単位のイベント数」など、考え方はどれも同じです。欲しい粒度だけを切り出すフォーマット文字列を選び、それで GROUP BY して集計するだけです。
次回:集約関数について
グループ化の話が出たついでに触れておくと、ここで使った COUNT(*) はSQLiteの集約関数の中でも一番シンプルなものです。次回は SUM、AVG、MIN、MAX といった集約関数を一通り取り上げて、複数行を1つのサマリ値にまとめる方法を見ていきます。
よくある質問
SQLite に DATE 型や DATETIME 型はありますか?
ありません。SQLite には専用の日付型が存在しないので、ISO 8601 形式の TEXT(例: '2026-04-23 10:15:00')、Unix タイムスタンプの INTEGER、ユリウス日の REAL のいずれかで保存します。組み込みの日付関数はこの 3 形式すべてを受け付け、デフォルトでは ISO 8601 形式の文字列を返します。
現在の日付・時刻を取得するには?
用途に応じて使い分けます。日付だけなら date('now')、時刻だけなら time('now')、両方なら datetime('now')、Unix タイムスタンプが欲しい場合は strftime('%s', 'now') です。デフォルトは UTC で返ってくるので、ローカルタイムが必要なときは modifier に 'localtime' を渡します(例: datetime('now', 'localtime'))。
日付に日数や月数を足し引きするには?
日付関数の引数に modifier 文字列を渡すだけです。例えば date('2026-04-23', '+7 days')、date('now', '-1 month')、datetime('now', '+2 hours', '+30 minutes') のように書けます。modifier は左から順に適用され、days、hours、minutes、seconds、months、years などの単位が使えます。
2 つの日付の差分を計算するには?
日数で出すなら julianday(end) - julianday(start)。ユリウス日は浮動小数点なので、結果には端数(時間以下)まで含まれます。秒単位なら Unix タイムスタンプを引き算する strftime('%s', end) - strftime('%s', start) が定番です。SQLite には DATEDIFF のような関数はありませんが、この 2 つでほぼすべてのケースをカバーできます。