PostgreSQL 9.3.2文書 | ||||
---|---|---|---|---|
前のページ | 上に戻る | 第 9章関数と演算子 | 次のページ |
表9-27は、日付/時刻型の値の処理で使用可能な関数を示しています。詳細は、以下の副節で説明します。表9-26は、(+、*等の)基本的な算術演算子の振舞いを説明しています。書式設定関数については項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型を取るものです。省略のため、これらの種類の違いは個別に示していません。また、+と*演算子は交代演算子を持ちます(例えばdate + integerとinteger + date)。こうした組み合わせは片方のみ示します。
表 9-26. 日付/時刻演算子
演算子名 | 例 | 結果 |
---|---|---|
+ | date '2001-09-28' + integer '7' | date '2001-10-05' |
+ | date '2001-09-28' + interval '1 hour' | timestamp '2001-09-28 01:00:00' |
+ | date '2001-09-28' + time '03:00' | timestamp '2001-09-28 03:00:00' |
+ | interval '1 day' + interval '1 hour' | interval '1 day 01:00:00' |
+ | timestamp '2001-09-28 01:00' + interval '23 hours' | timestamp '2001-09-29 00:00:00' |
+ | time '01:00' + interval '3 hours' | time '04:00:00' |
- | - interval '23 hours' | interval '-23:00:00' |
- | date '2001-10-01' - date '2001-09-28' | integer '3'(日付) |
- | date '2001-10-01' - integer '7' | date '2001-09-24' |
- | date '2001-09-28' - interval '1 hour' | timestamp '2001-09-27 23:00:00' |
- | time '05:00' - time '03:00' | interval '02:00:00' |
- | time '05:00' - interval '2 hours' | time '03:00:00' |
- | timestamp '2001-09-28 23:00' - interval '23 hours' | timestamp '2001-09-28 00:00:00' |
- | interval '1 day' - interval '1 hour' | interval '1 day -01:00:00' |
- | timestamp '2001-09-29 03:00' - timestamp '2001-09-27 12:00' | interval '1 day 15:00:00' |
* | 900 * interval '1 second' | interval '00:15:00' |
* | 21 * interval '1 day' | interval '21 days' |
* | double precision '3.5' * interval '1 hour' | interval '03:30:00' |
/ | interval '1 hour' / double precision '1.5' | interval '00:40:00' |
表 9-27. 日付/時刻関数
関数名 | 戻り値型 | 説明 | 例 | 結果 |
---|---|---|---|---|
age(timestamp, timestamp)
| interval | 引数間の減算。年と月を使用した"シンボルによる"結果を生成 | age(timestamp '2001-04-10', timestamp '1957-06-13') | 43 years 9 mons 27 days |
age(timestamp) | interval | current_date (午前零時)から減算 | age(timestamp '1957-06-13') | 43 years 8 mons 3 days |
clock_timestamp()
| timestamp with time zone | 現在の日付と時刻です。(文実行時に変わります。)項9.9.4を参照。 | ||
current_date
| date | 現在の日付。項9.9.4を参照 | ||
current_time
| time with time zone | 現在の時刻。項9.9.4を参照。 | ||
current_timestamp
| timestamp with time zone | 現在の日付と時刻(現在のトランザクションの開始日付時刻)。項9.9.4を参照。 | ||
date_part(text, timestamp)
| double precision | 部分フィールドの取得(extract と同じ)。項9.9.1を参照。
| date_part('hour', timestamp '2001-02-16 20:38:40') | 20 |
date_part(text, interval) | double precision | 部分フィールドの取得(extract と同じ)。項9.9.1を参照。
| date_part('month', interval '2 years 3 months') | 3 |
date_trunc(text, timestamp)
| timestamp | 指定された精度で切り捨て。項9.9.2も参照。 | date_trunc('hour', timestamp '2001-02-16 20:38:40') | 2001-02-16 20:00:00 |
extract (field from
timestamp)
| double precision | 部分フィールドの取得。項9.9.1を参照。 | extract(hour from timestamp '2001-02-16 20:38:40') | 20 |
extract (field from
interval) | double precision | 部分フィールドの取得。項9.9.1を参照。 | extract(month from interval '2 years 3 months') | 3 |
isfinite(date)
| boolean | 日付が有限(+/-無限と等しくない)かどうかの検査 | isfinite(date '2001-02-16') | true |
isfinite(timestamp) | boolean | タイムスタンプが有限(+/-無限でない)かどうかの検査 | isfinite(timestamp '2001-02-16 21:28:30') | true |
isfinite(interval) | boolean | 時間間隔が有限かどうかの検査 | isfinite(interval '4 hours') | true |
justify_days(interval)
| interval | 30日周期が1月を表すように時間間隔を調整 | justify_days(interval '35 days') | 1 mon 5 days |
justify_hours(interval)
| interval | 24時間を1日とする時間間隔の調整 | justify_hours(interval '27 hours') | 1 day 03:00:00 |
justify_interval(interval)
| interval | justify_days およびjustify_hours を使用し、さらに符号による調整を行っての時間間隔の調整 | justify_interval(interval '1 mon -1 hour') | 29 days 23:00:00 |
localtime
| time | 現在の時刻。項9.9.4を参照。 | ||
localtimestamp
| timestamp | 現在の日付と時刻(現在のトランザクションの開始)。 項9.9.4を参照。 | ||
now()
| timestamp with time zone | 現在の日付と時刻(現在のトランザクションの開始)。 項9.9.4を参照。 | ||
statement_timestamp()
| timestamp with time zone | 現在の日付と時刻(現在の文の開始)。 項9.9.4を参照。 | ||
timeofday()
| text | 現在の日付と時刻。(clock_timestamp と似ていますが、text型文字列として返す。)項9.9.4を参照。
| ||
transaction_timestamp()
| timestamp with time zone | 現在の日付と時刻(現在のトランザクションの開始)。 項9.9.4を参照。 |
これらの関数に加え、OVERLAPS SQL演算子がサポートされています。
(start1, end1) OVERLAPS (start2, end2) (start1, length1) OVERLAPS (start2, length2)
この式は、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の値を加える時(またはtimestamp with time zoneの値からintervalの値を差し引く時)日にちの部分は、日にちの数で示された timestamp with time zoneの日付を先に進めます(もしくは後に戻します)。夏時間への移行に跨っての変更に関しては(セッションの時間帯がDSTを認識するようになっていれば)、interval '1 day'がinterval '24 hours'に等しい必要はありません。例えば、セッションの時間帯が CST7CDTに設定されている時に、 timestamp with time zone '2005-04-02 12:00-07' + interval '1 day' は、timestamp with time zone '2005-04-03 12:00-06'をもたらします。一方同じ初期timestamp with time zoneにinterval '24 hours'を加えると、timestamp with time zone '2005-04-03 13:00-06'という結果になります。その理由はCST7CDT時間帯で2005-04-03 02:00に夏時間への変更があるからです。
異なる月では日数が異なりますのでage
で返されるmonthsにはあいまいさがあります。PostgreSQLのやり方は月にまたがる2つの日付の計算において、日付の早いほうの月を使用します。例えば、age('2004-06-01', '2004-04-30')は4月を使用して1 mon 1 dayを得ます。一方5月を使用すると、5月は31日あり、4月は30日のため、結果は1 mon 2 daysです。
EXTRACT
, date_part
EXTRACT(field FROM source)
extract
関数は、日付/時刻の値から年や時などの部分フィールドを抽出します。sourceはtimestamp型、time型、またはinterval型の評価式でなければなりません(date型の式はtimestamp型にキャストされますので、同様に使用可能です)。fieldはsourceの値からどのフィールドを抽出するかを選択する識別子もしくは文字列です。extract
関数はdouble precision型の値を返します。以下に有効なフィールド名を示します。
世紀
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世紀です。 この定義に納得できなければ、苦情をバチカンローマ聖パウロ大聖堂のローマ法王に伝えてください。
PostgreSQLリリース8.0以前では、世紀の番号付けの慣習に従っていませんでした。単に年を100で除算したものを返していました。
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
年フィールドを10で割ったもの
SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 200
日曜日(0)から土曜日(6)までの曜日
SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 5
extract
関数の曜日指定番号はto_char(...,'D')
関数のそれとは異なる点に注意してください。
年内での通算日数(1〜365/366)
SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 47
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
以下に、この経過秒数をタイムスタンプ値に変換する方法を示します。
SELECT TIMESTAMP WITH TIME ZONE 'epoch' + 982384720.12 * INTERVAL '1 second';
(to_timestamp
関数は上記の変換をカプセル化します。)
時のフィールド(0〜23)
SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 20
月曜日(1)から日曜日(7)までの曜日
SELECT EXTRACT(ISODOW FROM TIMESTAMP '2001-02-18 20:38:40'); Result: 7
日曜日を除きdowと同一。ISO 8601曜日番号付けに一致。
日付が同期するISO 8601年(intervalには対応しない)。
SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-01'); Result: 2005 SELECT EXTRACT(ISOYEAR FROM DATE '2006-01-02'); Result: 2006
全てのISO年は1月4日を含む週の月曜日から開始されます。従って、1月上旬、または12月下旬でISO年がグレゴリオ年と異なる可能性があります。より詳細はweekフィールドを参照してください。
このフィールドは8.3以前のPostgreSQLリリースでは有効でありません。
端数部分も含み、1,000,000を乗じられた秒フィールド。全ての秒を含むことに注意。
SELECT EXTRACT(MICROSECONDS FROM TIME '17:12:28.5'); Result: 28500000
ミレニアム(1千年期間)
SELECT EXTRACT(MILLENNIUM FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 3
1900年代の年は第2ミレニアムです。第3ミレニアムは2001年1月1日から始まりました。
PostgreSQLリリース8.0以前では、ミレニアムの番号付けの慣習に従っていませんでした。単に年フィールドを1000で割った値を返していました。
端数部分も含み、1000を乗じられた秒フィールド。全ての秒を含むことに注意してください。
SELECT EXTRACT(MILLISECONDS FROM TIME '17:12:28.5'); Result: 28500
分フィールド(0〜59)
SELECT EXTRACT(MINUTE FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 38
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
その日付が含まれる年の四半期(1〜4)。
SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 1
端数を含んだ秒フィールド(0〜59、[1])。
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
秒単位のUTCからの時間帯オフセット。正の値はUTCより東の時間帯に対応し、負の値はUTCより西の時間帯に対応。 (技術的には、PostgreSQLはうるう秒を制御しないためUT1を使用。)
時間帯オフセットの時の成分。
時間帯オフセットの分の成分。
その日の年間通算での週を計算します。(ISO 8601の)定義では週は月曜日から始まり、その年の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
年フィールド。AD零年が存在しないことは忘れないでください。このためADの年からBCの年を減する時には注意が必要です。
SELECT EXTRACT(YEAR FROM TIMESTAMP '2001-02-16 20:38:40'); Result: 2001
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)
sourceは、データ型timestampもしくはintervalの評価式です(データ型dateとtimeはそれぞれ自動的にtimestampもしくはintervalにキャストされます)。fieldは、入力値の値をどの精度で切り捨てるかを選択します。戻り値の値は、選択されたもの以下をゼロに設定(日と月の場合は1に設定)した、全てのフィールドを持つtimestampもしくはinterval型です。
fieldの有効値には次のものがあります。
microseconds |
milliseconds |
second |
minute |
hour |
day |
week |
month |
quarter |
year |
decade |
century |
millennium |
例:
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
AT TIME ZONE
構文を使用することにより、タイムスタンプを異なる時間帯に変換することができます。表9-28にその種類を示します。
表 9-28. AT TIME ZONE Variants
式 | 戻り値 | 説明 |
---|---|---|
timestamp without time zone AT TIME ZONE zone | timestamp with time zone | 与えられた時間帯なしタイムスタンプを指定された時間帯にあるとして取り扱います。 |
timestamp with time zone AT TIME ZONE zone | timestamp without time zone | 与えられた時間帯付きタイムスタンプを新規の時間帯に、時間帯の指定なく変換します。 |
time with time zone AT TIME ZONE zone | time with time zone | 与えられた時刻with time zoneを新しい時間帯に変換します。 |
これらの式では、設定する時間帯zoneは、('PST'のような)テキスト文字列、または(INTERVAL '-08:00'のような)時間間隔で指定することができます。 テキストの場合、項8.5.3に示した方法で時間帯名称を指定することができます。
以下に例を示します(ローカル時間帯をPST8PDTと想定しています)。
SELECT TIMESTAMP '2001-02-16 20:38:40' AT TIME ZONE 'MST'; Result: 2001-02-16 19:38:40-08 SELECT TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-05' AT TIME ZONE 'MST'; Result: 2001-02-16 18:38:40
最初の例は、時間帯のないタイプスタンプを使用し、それをMST時間(UTC-7)として解釈し、UTCタイムスタンプを生成します。それから、UTCタイムスタンプが、表示用にPST(UTC-7)に置き換えられます。2番目の例は、EST(UTC-5)で指定されたタイムスタンプを使用し、MST(UTC-7)でのローカル時間に変換しています。
関数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: 2001-12-23 SELECT CURRENT_TIMESTAMP; Result: 2001-12-23 14:39:53.662522-05 SELECT CURRENT_TIMESTAMP(2); Result: 2001-12-23 14:39:53.66-05 SELECT LOCALTIMESTAMP; Result: 2001-12-23 14:39:53.662522
これらの関数は、現在のトランザクションの開始時刻を返します。 この値は、トランザクションが実行されている間は変化しません。 これは、次の機能を検討した結果です。 単一トランザクションで、"current"時間を一貫性を持った表現を行うことができるようにすることを目的とし、このため、同一トランザクションで何回変更を行っても同一のタイムスタンプを生成します。
注意: 他のデータベースシステムでは、これらの値をより頻繁に増加させることがあります。
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'; -- incorrect for use with DEFAULT
ティップ: テーブルを作成する時、DEFAULT句を指定するのに3番目の形式を使おうとは思わないでしょう。定数が解析された時、システムがnowをtimestampに変換するので、デフォルト値としてテーブルが作成された時刻が使われます。最初の2つの形式は関数呼び出しのためデフォルト値が使用されるまで評価されません。ですから、これらの関数は列の挿入時間をデフォルトとする、望ましい振舞いをします。
以下の関数は、サーバプロセスの実行を遅延させるために使用可能です。
pg_sleep(seconds)
pg_sleep
は、seconds秒経過するまで、現在のセッションのプロセスを休止させます。secondsはdouble precision型の値です。
そのため、小数単位で休止秒数を指定することができます。以下に例を示します。
SELECT pg_sleep(1.5);
注意: 休止時間の有効な分解能はプラットフォームに依存します。0.01秒が一般的な値です。遅延は少なくとも指定した通り行われます。サーバの負荷が要因となり、より長くなる可能性があります。
警告 |
|
[1] | オペレーティングシステムでうるう秒が実装されている場合は60まで。 |