日付/時刻関数と演算子

PostgreSQL 8.0.0 文書
前のページ | 巻戻し | 第 9章関数と演算子 | 早送り | 次のページ

# 9.9. 日付/時刻関数と演算子

表9-26は、日付/時刻型の値の処理で使用可能な関数を示しています。 詳細は、以下の副節で説明します。 表9-25は、(`+`、`*`等の)基本的な算術演算子の振舞いを説明しています。 書式設定関数については項9.8を参照してください。 項8.5を参照して、日付/時刻データ型についての背景となっている情報に精通していなければなりません。

後述の`time`もしくは`timestamp`型の入力を受け取る関数および演算子は全て、実際には2つの種類があります。 ひとつは`time with time zone`型または`timestamp with time zone`型を取るもので、もう1つは`time without time zone`型もしくは`timestamp without time zone`型を取るものです。 省略のため、これらの種類の違いは個別に示していません。 また、`+`と`*`演算子は交代演算子を持ちます。 (例えば、date + integerとinteger + dateです。) こうした組み合わせは片方のみ示します。

表 9-25. 日付/時刻演算子

演算子名 | 例 | 結果
--- | --- | ---
`+` | `date '2001-09-28' + integer '7'` | `date '2001-10-05'`
`+` | `date '2001-09-28' + interval '1 hour'` | `timestamp '2001-09-28 01:00'`
`+` | `date '2001-09-28' + time '03:00'` | `timestamp '2001-09-28 03:00'`
`+` | `interval '1 day' + interval '1 hour'` | `interval '1 day 01:00'`
`+` | `timestamp '2001-09-28 01:00' + interval '23 hours'` | `timestamp '2001-09-29 00:00'`
`+` | `time '01:00' + interval '3 hours'` | `time '04:00'`
`-` | `- interval '23 hours'` | `interval '-23: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'`
`-` | `time '05:00' - time '03:00'` | `interval '02:00'`
`-` | `time '05:00' - interval '2 hours'` | `time '03:00'`
`-` | `timestamp '2001-09-28 23:00' - interval '23 hours'` | `timestamp '2001-09-28 00:00'`
`-` | `interval '1 day' - interval '1 hour'` | `interval '23:00'`
`-` | `timestamp '2001-09-29 03:00' - timestamp '2001-09-27 12:00'` | `interval '1 day 15:00'`
`*` | `interval '1 hour' * double precision '3.5'` | `interval '03:30'`
`/` | `interval '1 hour' / double precision '1.5'` | `interval '00:40'`

表 9-26. 日付/時刻関数

関数名 | 戻り値型 | 説明 | 例 | 結果
--- | --- | --- | --- | ---
``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`
``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`(`timestamp`)` | `boolean` | タイムスタンプが有限(無限ではない)かどうかのテスト | `isfinite(timestamp '2001-02-16 21:28:30')` | `true`
``isfinite`(`interval`)` | `boolean` | 時間間隔が有限かどうかのテスト | `isfinite(interval '4 hours')` | `true`
``localtime`` | `time` | 本日の時刻。項9.9.4を参照。 |  |
``localtimestamp`` | `timestamp` | 日付と時刻。項9.9.4を参照。 |  |
``now`()` | `timestamp with time zone` | 現在の日付と時刻(`current_timestamp`と同じ)。 項9.9.4を参照。 |  |
``timeofday()`` | `text` | 現在の日付と時刻。項9.9.4を参照。 |  |

これらの関数に加え、`OVERLAPS` SQL演算子がサポートされています。

    ( start1, end1 ) OVERLAPS ( start2, end2 )
    ( start1, length1 ) OVERLAPS ( start2, length2 )

この式は、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

## 9.9.1. `EXTRACT`, `date_part`

    EXTRACT (field FROM source)

`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です。 この定義に納得できなければ、苦情をバチカンローマ聖パウロ大聖堂のローマ法王に伝えてください。

  PostgreSQLリリース8.0以前では、世紀の番号付けの慣習に従っていませんでした。 単に年を100で除算したものを返していました。

`day`

  (月内の)日付フィールド (1 - 31)

      SELECT EXTRACT(DAY FROM TIMESTAMP '2001-02-16 20:38:40');
      Result: 16

`decade`

  年フィールドを10で割ったもの

      SELECT EXTRACT(DECADE FROM TIMESTAMP '2001-02-16 20:38:40');
      Result: 200

`dow`

  曜日（0〜6、日曜日が0、`timestamp`の値のみで使用可）

      SELECT EXTRACT(DOW FROM TIMESTAMP '2001-02-16 20:38:40');
      Result: 5

  `extract`関数の曜日指定番号は`to_char`関数の番号と異なる点に注意してください。

`doy`

  年内での通算日数（1〜365/366）（`timestamp`の値のみ使用可）

      SELECT EXTRACT(DOY FROM TIMESTAMP '2001-02-16 20:38:40');
      Result: 47

`epoch`

  `date`型と`timestamp`型の値において、1970-01-01 00:00:00からの秒数（負の数の場合もあり）。 `interval`型の値ではその時間間隔における秒の合計

      SELECT EXTRACT(EPOCH FROM TIMESTAMP WITH TIME ZONE '2001-02-16 20:38:40-08');
      Result: 982384720

      SELECT EXTRACT(EPOCH FROM INTERVAL '5 days 3 hours');
      Result: 442800

  以下に、この経過秒数をタイムスタンプ値に変換する方法を示します。

      SELECT TIMESTAMP WITH TIME ZONE 'epoch' + 982384720 * INTERVAL '1 second';

`hour`

  時のフィールド(0 - 23)

      SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 20:38:40');
      Result: 20

`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日から始まります。

  PostgreSQLリリース8.0以前では、ミレニアムの番号付けの慣習に従っていませんでした。 単に年フィールドを1000で割った値を返していました。

`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)(`timestamp`の値に対してのみ)

      SELECT EXTRACT(QUARTER FROM TIMESTAMP '2001-02-16 20:38:40');
      Result: 1

`second`

  端数を含んだ秒フィールド(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

`timezone`

  秒単位のUTCからの時間帯オフセット。 正の値はUTCより東の時間帯に対応し、負の値はUTCより西の時間帯に対応。

`timezone_hour`

  時間帯オフセットの時の成分

`timezone_minute`

  時間帯オフセットの分の成分

`week`

  その日の年間通算での週を計算します。 (ISO 8601の)定義では、その年の1月4日の週を第1週とします。 (ISO-8601では、週は月曜日から始まるとしています。) つまり、年の最初の木曜日がある週がその年の第1週となります。 (`timestamp`の値のみ)

      SELECT EXTRACT(WEEK FROM TIMESTAMP '2001-02-16 20:38:40');
      Result: 7

`year`

  年フィールド。 `0 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

## 9.9.2. `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`
`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

## 9.9.3. `AT TIME ZONE`

`AT TIME ZONE`構文を使用することにより、タイムスタンプを異なる時間帯に変換することができます。 表9-27にその種類を示します。

表 9-27. `AT TIME ZONE` の種類

式 | 戻り値 | 説明
--- | --- | ---
``timestamp without time zone` AT TIME ZONE `zone`` | `timestamp with time zone` | 与えられた時間帯のローカル時間をUTCに変換します。
``timestamp with time zone` AT TIME ZONE `zone`` | `timestamp without time zone` | UTCを与えられた時間帯のローカル時間に変換します。
``time with time zone` AT TIME ZONE `zone`` | `time with time zone` | 時間帯に関係なくローカル時間を変換します。

上記の式では、設定する時間帯`zone`は、(`'PST'`のような)テキスト文字列、または(`INTERVAL '-08:00'`のような)時間間隔で指定することができます。 テキストの場合、表B-4に示したゾーン名を利用することができます。 （表B-6内の一般的な名前を使用できればもっと便利でしょうが、これはまだ実装されていません。）

以下に例を示します(ローカルな時間帯を`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-8)に置き換えられます。 2番目の例では、EST(UTC-5)に指定されたタイムスタンプが使用され、それがMST(UTC-7)でのローカル時間に変換されています。

関数`timezone`(`zone`, `timestamp`)は、SQL準拠の構文``timestamp` AT TIME ZONE `zone``と等価です。

## 9.9.4. 現在の日付/時刻

以下の関数は、現在の日付および/または時間を取得するための関数です。

    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`関数では、精度のパラメータをオプションで与えることができ、それに合わせて秒フィールドの端数桁を丸める結果をもたらします。 精度のパラメータがない場合、結果は使用可能な最大精度で出力されます。

> 注意: PostgreSQL 7.2より前までは、精度パラメータは実装されておりませんでした。 そして結果は常に整数による秒となりました。

以下にいくつか例を示します。

    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

`now()`関数は`CURRENT_TIMESTAMP`と等価のPostgreSQLに於ける因習です。

同時に`timeofday()`関数があって、歴史的理由により`timestamp`の値ではなく`text`型の文字列を返します。

    SELECT timeofday();
    Result: Sat Feb 17 19:07:32.000126 2001 EST

`CURRENT_TIMESTAMP`と、それに関連する関数は、全て現在のトランザクションが開始された時間を返すことを理解することは重要です。 この値は、トランザクションが実行されている間は変化しません。 これは、次の機能を検討した結果です。 単一トランザクションで、"current"時間を一貫性を持った表現を行なうことができるようにすることを目的とし、このため、同一トランザクションで何回変更を行なっても同一のタイムスタンプを生成します。 `timeofday()`は、壁時計時刻を返し、トランザクションが実行されている間にも増加します。

> 注意: 他の多くのデータベースシステムでは、これらの値をより頻繁に増加させます。

全ての日付/時刻データ型は同時に`now`という現在の日付と時刻を特定する特殊なリテラル値を受け付けます。 従って、下記の3つの実行結果は全て同じものとなります。

    SELECT CURRENT_TIMESTAMP;
    SELECT now();
    SELECT TIMESTAMP 'now';

> ティップ: テーブルを作成する時、`DEFAULT`句を指定するのに3番目の形式を使おうとは思わないでしょう。 定数が解析された時、システムが`now`を`timestamp`に変換するので、デフォルト値としてテーブルが作成された時刻が使われます。 最初の2つの形式は関数呼び出しのためデフォルト値が使用されるまで評価されません。 ですから、これらの関数は列の挿入時間をデフォルトとする、望ましい振舞いをします。

### 注意

[1] | オペレーティングシステムでうるう秒が実装されている場合は 60 まで

前のページ | ホーム | 次のページ
データ型書式設定関数 | 上に戻る | 幾何関数と演算子