表 9.32は、日付/時刻型の値の処理で使用可能な関数を示しています。詳細は、以下の副節で説明します。
表 9.31は、(+
、*
等の)基本的な算術演算子の振舞いを説明しています。
書式設定関数については9.8を参照してください。
8.5を参照して、日付/時刻データ型についての背景となっている情報に精通していなければなりません。
以下のtime
もしくはtimestamp
型の入力を受け取る関数および演算子は全て、実際には2つの種類があります。1つはtime with time zone
型またはtimestamp with time zone
型を取るもので、もう1つはtime without time zone
型もしくはtimestamp without time zone
型を取るものです。
簡略化のため、これらの種類の違いは個別に示していません。
また、+
と*
演算子は可換な2項をとります(例えばdate + integerとinteger + date)。こうした組み合わせは片方のみ示します。
表9.31 日付/時刻演算子
演算子 説明 例 |
---|
日付に日数を加算
|
時刻間隔を日付に加算
|
日付に時刻を加算
|
時間間隔を加算
|
時間間隔をタイムスタンプに加算
|
時間間隔を時分に加算
|
時間間隔の符号を反転
|
日付を減算し、経過日数を返す
|
日付から日数を減算
|
日付から時間間隔を減算
|
時分を減算
|
時分から時刻間隔を減算
|
タイムスタンプから時刻間隔を減算
|
時間間隔を減算
|
タイムスタンプを減算(
|
時間間隔にスカラーを乗算
|
時間間隔をスカラーで除算
|
表9.32 日付/時刻関数演算子
関数 説明 例 |
---|
引数間の減算。日数だけでなく年と月を使用した「言葉による」結果を生成
|
|
現在の日付と時刻(文実行中に変化する)。9.9.4を参照。
|
現在の日付。9.9.4を参照
|
現在の時刻。9.9.4を参照。
|
精度を限定した現在の時刻。9.9.4を参照。
|
現在の日付と時刻(現在のトランザクションの開始時)。9.9.4を参照。
|
精度を限定した現在の日付と時刻(現在のトランザクションの開始時)。9.9.4を参照。
|
タイムスタンプの部分フィールドの取得(
|
時間間隔の部分フィールドの取得(
|
指定された精度で切り捨て。9.9.2参照。
|
指定された時間帯において指定された精度で切り捨て。9.9.2参照
|
指定された精度で切り捨て。9.9.2参照。
|
タイムスタンプの部分フィールドの取得。9.9.1を参照。
|
時間間隔の部分フィールドの取得。9.9.1を参照。
|
日付が有限(+/-無限でない)かどうかの検査
|
タイムスタンプが有限(+/-無限でない)かどうかの検査
|
時間間隔が有限かどうかの検査(今の所常に真)
|
30日周期が1月を表すように時間間隔を調整
|
24時間を1日とする時間間隔の調整
|
|
現在の時刻。9.9.4を参照。
|
精度を限定した現在の時刻。9.9.4を参照。
|
現在の日付と時刻(現在のトランザクションの開始時)。9.9.4を参照。
|
精度を限定した現在の日付と時刻(現在のトランザクションの開始時)。9.9.4を参照。
|
年、月、日フィールドから日付を作成
|
年、月、週、日、時間、分、秒フィールドから時間間隔を作成
|
時、分、秒フィールドから時刻を作成
|
年、月、日、時、分、秒フィールドから時刻を作成
|
年、月、日、時、分、秒フィールドから時間帯付きの時刻を作成。
|
現在の日付と時刻(現在のトランザクションの開始時)。9.9.4を参照。
|
現在の日付と時刻(現在の文の開始時)。9.9.4を参照。
|
現在の日付と時刻(
|
現在の日付と時刻(現在のトランザクションの開始時)。9.9.4を参照。
|
Unixエポック時間(1970-01-01 00:00:00+00からの経過秒数)をtimestamp with time zoneに変換
|
これらの関数に加え、OVERLAPS
SQL演算子がサポートされています。
(start1
,end1
) OVERLAPS (start2
,end2
) (start1
,length1
) OVERLAPS (start2
,length2
)
この式は、2つの時間間隔(その両端で定義されます)が重なる時に真を返します。重ならない場合は偽を返します。
両端は2つの日付、時刻、タイムスタンプとして、もしくは、日付/時刻/タイムスタンプとそれに続く時間間隔として指定できます。
値の組み合わせで指定する場合、開始と終了のいずれを先に記述しても構いません。OVERLAPS
は与えられた値のうち、早い方を開始として扱います。
各時間間隔は、start
<=
time
<
end
という半開区間として見なされます。ただし、start
とend
が同じ値の場合には単一の時間点となります。
これは、例えば端点のみが共通である2つの時間間隔は、重ならないということを意味します。
SELECT (DATE '2001-02-16', DATE '2001-12-21') OVERLAPS (DATE '2001-10-30', DATE '2002-10-30'); Result:true
SELECT (DATE '2001-02-16', INTERVAL '100 days') OVERLAPS (DATE '2001-10-30', DATE '2002-10-30'); Result:false
SELECT (DATE '2001-10-29', DATE '2001-10-30') OVERLAPS (DATE '2001-10-30', DATE '2001-10-31'); Result:false
SELECT (DATE '2001-10-30', DATE '2001-10-30') OVERLAPS (DATE '2001-10-30', DATE '2001-10-31'); Result:true
timestamp with time zone
の値にinterval
の値を加える時(またはinterval
の値を引く時)、日にちの部分は、timestamp with time zone
の日付を指定された日数だけ先に進める、もしくは後に戻し、時刻は同じに保ちます。
(セッションの時間帯がDSTを認識する設定の場合)夏時間の移行に跨っての変化に関しては、interval '1 day'
がinterval '24 hours'
に等しいとは限りません。
例えば、セッションの時間帯が America/Denver
に設定されている時には以下のようになります。
SELECT timestamp with time zone '2005-04-02 12:00:00-07' + interval '1 day'; 結果:2005-04-03 12:00:00-06
SELECT timestamp with time zone '2005-04-02 12:00:00-07' + interval '24 hours'; 結果:2005-04-03 13:00:00-06
その理由はAmerica/Denver
時間帯で2005-04-03 02:00
に夏時間への変更があるからです。
異なる月では日数が異なりますのでage
で返されるmonths
フィールドにはあいまいさがあります。
PostgreSQLのやり方は月をまたがる2つの日付の計算において、日付の早いほうの月を使用します。
例えば、age('2004-06-01', '2004-04-30')
は4月を使用して1 mon 1 day
を得ます。5月は31日あり、4月は30日のため、もし5月を使用するなら結果は1 mon 2 days
となるでしょう。
日付とタイムスタンプの引き算は複雑になることがあります。
引き算をする概念的に単純な方法は、それぞれの値を秒数にEXTRACT(EPOCH FROM ...)
で変換してから、結果を引き算する方法です。この結果は2つの値の間の秒数になります。
これは各月の日数、時間帯の変更、夏時間の調整に対して調整されるでしょう。
「-
」演算子での日付やタイムスタンプの引き算は値の間の(24時間の)日数と時間/分/秒を、同様に調整して返します。
age
関数は年、月、日、時間/分/秒をフィールド毎に引き算し、負のフィールドの値を調整します。
以下の問い合わせは上の各方法の違いを説明する例です。
例の結果はtimezone = 'US/Eastern'
で生成されました。2つの日付の間には夏時間の変更があります。
SELECT EXTRACT(EPOCH FROM timestamptz '2013-07-01 12:00:00') - EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00'); 結果:10537200
SELECT (EXTRACT(EPOCH FROM timestamptz '2013-07-01 12:00:00') - EXTRACT(EPOCH FROM timestamptz '2013-03-01 12:00:00')) / 60 / 60 / 24; 結果:121.958333333333
SELECT timestamptz '2013-07-01 12:00:00' - timestamptz '2013-03-01 12:00:00'; 結果:121 days 23:00:00
SELECT age(timestamptz '2013-07-01 12:00:00', timestamptz '2013-03-01 12:00:00'); 結果:4 mons
EXTRACT
, date_part
EXTRACT(field
FROMsource
)
extract
関数は、日付/時刻の値から年や時などの部分フィールドを抽出します。
source
はtimestamp
型、time
型、またはinterval
型の評価式でなければなりません(date
型の式はtimestamp
型にキャストされますので、同様に使用可能です)。
field
はsourceの値からどのフィールドを抽出するかを選択する識別子もしくは文字列です。
extract
関数はdouble precision
型の値を返します。以下に有効なフィールド名を示します。
century
世紀
SELECT EXTRACT(CENTURY FROM TIMESTAMP '2000-12-16 12:21:13'); Result:20
SELECT EXTRACT(CENTURY FROM TIMESTAMP '2001-02-16 20:38:40'); Result:21
当時の人々にはそのような意識はありませんでしたが、最初の世紀は0001-01-01 00:00:00 ADから始まります。 この定義は全てのグレゴリオ暦を使用する国で適用されています。 0という値の世紀はありません。-1世紀の次は1世紀です。 この定義に納得できなければ、苦情をバチカンローマ聖ペテロ大聖堂のローマ法王に伝えてください。
day
timestamp
値については、(月内の)日付フィールド(1–31)。interval
値については日数。
SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40'); Result:16
SELECT EXTRACT(DAY FROM INTERVAL '40 days 1 minute'); Result:40
decade
年フィールドを10で割ったもの
SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 200
dow
日曜日(0
)から土曜日(6
)までの曜日
SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 5
extract
関数の曜日番号はto_char(...,'D')
関数のそれとは異なる点に注意してください。
doy
年内での通算日数(1–365/366)
SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 47
epoch
timestamp with time zone
型の値において、1970-01-01 00:00:00 UTCからの秒数(負の数の場合もあり)。date
とtimestamp
型の値において、ローカルタイムの1970-01-01 00:00:00からの秒数。interval
型の値ではその時間間隔における全体の秒数。
SELECT EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40.12-08'); Result:982384720.12
SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours'); Result:442800
to_timestamp
で経過秒数をタイムスタンプ値に変換することができます。
SELECT to_timestamp(982384720.12);
Result: 2001-02-17 04:38:40.12+00
hour
時フィールド(0–23)
SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 20
isodow
月曜日(1
)から日曜日(7
)までの曜日
SELECT EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40');
Result: 7
日曜日を除きdow
と同一です。
これはISO 8601曜日番号付けに一致します。
isoyear
日付に当てはまるISO 8601週番号年(intervalには適用できない)。
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01'); Result:2005
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02'); Result:2006
すべてのISO 8601週番号年は1月4日を含む週の月曜日から開始されます。従って、1月上旬、または12月下旬でISO年がグレゴリオ年と異なる可能性があります。
より詳細はweek
フィールドを参照してください。
このフィールドは8.3より前のPostgreSQLリリースでは有効でありません。
microseconds
端数部分も含む秒フィールドに、1,000,000を乗じた値。秒の整数部を含むことに注意。
SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5');
Result: 28500000
millennium
ミレニアム(千年期)
SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 3
1900年代の年は第2ミレニアムです。第3ミレニアムは2001年1月1日から始まりました。
milliseconds
端数部分も含む秒フィールドに、1000を乗た値。秒の整数部を含むことに注意してください。
SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28.5');
Result: 28500
minute
分フィールド (0–59)
SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 38
month
timestamp
型の値に対しては年内の月番号(1–12)。interval
型の値に対しては月数を12で割った余り(0–11)。
SELECT EXTRACT(MONTH FROM TIMESTAMP '2001-02-16 20:38:40'); Result:2
SELECT EXTRACT(MONTH FROM INTERVAL '2 years 3 months'); Result:3
SELECT EXTRACT(MONTH FROM INTERVAL '2 years 13 months'); Result:1
quarter
その日付が含まれる年の四半期(1–4)
SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 1
second
端数を含んだ秒フィールド
SELECT EXTRACT(SECOND FROM TIMESTAMP '2001-02-16 20:38:40'); Result:40
SELECT EXTRACT(SECOND FROM TIME '17:12:28.5'); Result:28.5
timezone
秒単位のUTCからの時間帯オフセット。正の値はUTCより東の時間帯に対応し、負の値はUTCより西の時間帯に対応。 (技術的に言えば、PostgreSQLはうるう秒を制御しないためUTCを使用していない。)
timezone_hour
時間帯オフセットの時の成分。
timezone_minute
時間帯オフセットの分の成分。
week
ISO 8601週番号。 定義ではISO週は月曜日から始まり、その年の1月4日を含む週をその年の第1週としています。 つまり、年の最初の木曜日がある週がその年の第1週となります。
ISO週番号システムでは、1月の早い日にちは前年の第52週もしくは第53週となることがあり、12月の遅い日にちには次年の最初の週の一部となることがあります。
例えば、2005-01-01
は2004年の第53週であり、2006-01-01
は2005年の第52週の一部です、一方2012-12-31
は2013年の第1週の一部となります。
整合性のある結果を得るため、isoyear
フィールドとweek
を併用することを推奨します。
SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 7
year
年フィールド。AD零年
が存在しないことは忘れないでください。このためAD
の年からBC
の年を減ずる時には注意が必要です。
SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40');
Result: 2001
入力値が+/-無限大の場合、extract
は単調増加するフィールド(epoch
、julian
、year
、isoyear
、decade
、century
、millennium
)に対し、+/-無限大を返します。
その他のフィールドに対してはNULLが返されます。
PostgreSQLの9.6より前のバージョンでは、入力が無限大のすべての場合に対してゼロを返していました。
extract
関数は主に演算処理を意図しています。
日付/時刻の値を表示する目的での書式については9.8を参照してください。
date_part
関数は伝統的なIngres上で設計されたもので、標準SQLのextract
関数と等価です。
date_part('field
',source
)
ここでfield
パラメータが名前ではなく文字列値である必要があることに注意してください。
date_part
で有効なフィールド名はextract
と同じです。
SELECT date_part('day', TIMESTAMP '2001-02-16 20:38:40'); Result:16
SELECT date_part('hour', INTERVAL '4 hours 3 minutes'); Result:4
date_trunc
date_trunc
関数は概念的に数値に対するtrunc
関数と類似しています。
date_trunc(field
,source
[,time_zone
])
source
は、データ型timestamp
、timestamp with time zone
もしくはinterval
の評価式です。
(date
型とtime
型の値はそれぞれ自動的にtimestamp
もしくはinterval
にキャストされます。)
field
は、入力値の値をどの精度で切り捨てるかを選択します。
同様に戻り値はtimestamp
、timestamp with time zone
もしくはinterval
型で、指定した精度より下のすべてのフィールドがゼロに設定(日と月については1に設定)されます。
field
の有効値には次のものがあります。
microseconds |
milliseconds |
second |
minute |
hour |
day |
week |
month |
quarter |
year |
decade |
century |
millennium |
入力値がtimestamp with time zone
型の値なら、特定の時間帯を考慮して切り捨てが行われます。たとえば、日
を切り捨てると値はその時間帯での真夜中になります。
デフォルトでは切り捨ては現在のTimeZoneの設定に従いますが、別の時間帯を指定することができるようにオプションのtime_zone
引数が提供されています。
時間帯名は8.5.3に記述されている方法で指定できます。
timestamp without time zone
あるいはinterval
の入力を処理している間は時間帯は指定できません。
これらは額面通りの値で扱われます。
例(現地タイムゾーンはAmerica/New_York
と仮定します):
SELECT date_trunc('hour', TIMESTAMP '2001-02-16 20:38:40'); Result:2001-02-16 20:00:00
SELECT date_trunc('year', TIMESTAMP '2001-02-16 20:38:40'); Result:2001-01-01 00:00:00
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00'); Result:2001-02-16 00:00:00-05
SELECT date_trunc('day', TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40+00', 'Australia/Sydney'); Result:2001-02-16 08:00:00-05
SELECT date_trunc('hour', INTERVAL '3 days 02:47:33'); Result:3 days 02:00:00
AT TIME ZONE
AT TIME ZONE
構文を使用することにより、time stamp without time zoneからtime stamp with time zoneへ、あるいはtime with time zone
の値を異なる時間帯に変換することができます。
表 9.33にその種類を示します。
表9.33 AT TIME ZONE
の種類
演算子 説明 例 |
---|
与えられた時間帯なしタイムスタンプを指定された時間帯にあるとして時間帯ありタイムスタンプに変換します。
|
与えられた時間帯付き時刻を、時刻がその時間帯にあるものとして時間帯なしタイムスタンプに変換します。
|
与えられた時刻with time zoneを新しい時間帯に変換します。 判断するためのデータがないので、現在の有効なUTCオフセットを目的の時間帯のために使用します。
|
これらの式では、設定する時間帯zone
は、('America/Los_Angeles'
のような)テキスト値、または(INTERVAL '-08:00'
のような)時間間隔で指定することができます。
テキストの場合、8.5.3に示した方法で時間帯名称を指定することができます。
時間間隔を使うのはUTCからの固定のオフセットを持つ時間帯でのみ有用なので、一般的に非常に有用であるとは言えません。
以下に例を示します(現在の時間帯(TimeZone)をAmerica/Los_Angeles
と想定しています)。
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'America/Denver'; Result:2001-02-16 19:38:40-08
SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'America/Denver'; Result:2001-02-16 18:38:40
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'Asia/Tokyo' AT TIME ZONE 'America/Chicago'; Result:2001-02-16 05:38:40
最初の例は、時間帯のない値に時間帯を追加し、現在のTimeZone
設定を使ってその値を表示します。
2番目の例は、time stamp with time zone値を指定した時間帯に変換し、その値をwithout a time zoneで返しています。
これは、TimeZone
設定とは異なる値の格納と表示を可能にします。
3番目の例は、東京時間をシカゴ時間に変換します。
関数timezone
(zone
, timestamp
)は、SQL準拠の構文
と等価です。
timestamp
AT TIME ZONE zone
PostgreSQLは、現在の日付時刻に関した値を返す多くの関数を提供します。 これらの標準SQL関数はすべて、現在のトランザクションの開始時刻に基づいた値を返します。
CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP CURRENT_TIME(precision
) CURRENT_TIMESTAMP(precision
) LOCALTIME LOCALTIMESTAMP LOCALTIME(precision
) LOCALTIMESTAMP(precision
)
CURRENT_TIME
およびCURRENT_TIMESTAMP
関数では、時間帯を伴う値を扱います。一方、LOCALTIME
およびLOCALTIMESTAMP
関数では、時間帯を伴わない値を扱います。
CURRENT_TIME
、CURRENT_TIMESTAMP
、LOCALTIME
、およびLOCALTIMESTAMP
関数では、精度のパラメータをオプションで取ることができ、それに合わせて秒フィールドの端数桁を丸める結果をもたらします。
精度のパラメータがない場合、結果は使用可能な最大精度で出力されます。
例:
SELECT CURRENT_TIME; Result:14:39:53.662522-05
SELECT CURRENT_DATE; Result:2019-12-23
SELECT CURRENT_TIMESTAMP; Result:2019-12-23 14:39:53.662522-05
SELECT CURRENT_TIMESTAMP(2); Result:2019-12-23 14:39:53.66-05
SELECT LOCALTIMESTAMP; Result:2019-12-23 14:39:53.662522
これらの関数は現在のトランザクションの開始時刻を返すため、その値はトランザクションが実行されている間は変化しません。 これは仕様であると考えられており、その意図は、単一のトランザクションが一貫性のある「現在」時刻の概念を持ち、同一トランザクション内の複数の変更が同一のタイムスタンプを持つようにすることにあります。
他のデータベースシステムでは、これらの値をより頻繁に増加させることがあります。
PostgreSQLはまた、関数を呼び出した時の実際の現在時刻や現在の文の開始時刻を返す関数も提供します。 非標準SQLの時間関数の全一覧を以下に示します。
transaction_timestamp() statement_timestamp() clock_timestamp() timeofday() now()
transaction_timestamp()
はCURRENT_TIMESTAMP
と等価ですが、明確に何を返すかを反映する名前になっています。
statement_timestamp()
は現在の文の実行開始時刻を返すものです(より具体的にいうと、直前のコマンドメッセージをクライアントから受け取った時刻です)。
statement_timestamp()
およびtransaction_timestamp()
はトランザクションの最初のコマンドでは同じ値を返しますが、その後に引き続くコマンドでは異なる可能性があります。
clock_timestamp()
は実際の現在時刻を返しますので、その値は単一のSQLコマンドであっても異なります。
timeofday()
はPostgreSQLの歴史的な関数です。
clock_timestamp()
同様、実際の現在時刻を返しますが、timestamp with time zone
型の値ではなく、整形されたtext
文字列を返します。now()
はtransaction_timestamp()
と同じもので、伝統的なPostgreSQL関数です。
すべての日付/時刻型はまた、特殊なリテラル値 now
を受け付け、これは現在の日付と時刻(ここでも、トランザクションの開始時刻として解釈されます)を表します。
したがって、下記の3つの実行結果は全て同じものとなります。
SELECT CURRENT_TIMESTAMP; SELECT now(); SELECT TIMESTAMP 'now'; -- but see tip below
たとえばテーブルの列にDEFAULT
句を指定するのに、後から評価される値を指定する際に3番目の形式は使わないでください。
システムはnow
という定数を解析すると、すぐにそれをtimestamp
に変換するので、デフォルト値が必要が時には、テーブルが作成された時刻が使われます。
最初の2つの形式は関数呼び出しなので、デフォルト値が使用されるまで評価されません。
ですから、これらの関数は列の挿入時間をデフォルトとする、望ましい振舞いをします。
(8.5.1.4も見てください。)
以下の関数は、サーバプロセスの実行を遅延させるために使用可能です。
pg_sleep (double precision
) pg_sleep_for (interval
) pg_sleep_until (timestamp with time zone
)
pg_sleep
は、seconds
秒経過するまで、現在のセッションのプロセスを休止させます。
seconds
はdouble precision
型の値です。そのため、小数単位で休止秒数を指定することができます。
pg_sleep_for
はinterval
でより長い休止時間を指定する便利な関数です。
pg_sleep_until
は特定の起床時刻が望まれる場合に便利な関数です。
以下に例を示します。
SELECT pg_sleep(1.5); SELECT pg_sleep_for('5 minutes'); SELECT pg_sleep_until('tomorrow 03:00');
休止時間の有効な分解能はプラットフォームに依存します。0.01秒が一般的な値です。
休止による遅延は最短で指定した時間と同じになります。
サーバの負荷などが要因となり、より長くなる可能性があります。
特に、pg_sleep_until
は指定した時刻ちょうどに起床する保証はありませんが、それより早く起床することはありません。
pg_sleep
またはその亜種を呼び出す時、セッションが必要以上のロックを保持していないことを確実にしてください。
さもないと、他のセッションが休止中のプロセスを待機しなければならないかもしれません。そのためシステム全体の速度が低下することになるかもしれません。