web-dev-qa-db-ja.com

1か月の日数を取得するにはどうすればよいですか?

私はPostgresで以下を取得しようとしています:

select day_in_month(2);

期待される出力:

28

Postgresにそれを行うための組み込みの方法はありますか?

21
mmrs151
_SELECT  
    DATE_PART('days', 
        DATE_TRUNC('month', NOW()) 
        + '1 MONTH'::INTERVAL 
        - '1 DAY'::INTERVAL
    )
_

NOW()を他の日付に置き換えます。

37
Quassnoi

スマートな「トリック」を使用して、月の最後の日付からの部分を抽出します。 Quassnoiによって示されます 。しかし、それは少し単純/高速になる可能性があります:

_SELECT extract(days FROM date_trunc('month', now()) + interval '1 month - 1 day');
_

理論的根拠

extractは標準SQLであるため、おそらく望ましいですが、内部的にはdate_part()と同じ関数に解決されます。 マニュアル:

_date_part_関数は、SQL標準関数extractと同等の従来のIngresをモデルにしています。

ただし、追加する必要があるのはasingleintervalだけです。 Postgresでは、一度に複数の時間単位を使用できます。 マニュアル:

interval値は、次の詳細構文を使用して記述できます。

_[@]__quantity unit__[__quantity unit__...] [_direction_]_

ここで、quantityは数値(おそらく署名済み)です。 unitmicrosecondmillisecondsecondminutehourdayweekmonthyeardecadecenturymillennium、またはこれらの単位の略語または複数形。

ISO8601または標準SQL形式 も受け入れられます。いずれにせよ、 再びマニュアル

内部的には、interval値は月、日、秒として保存されます。これは、1か月の日数が異なるためです。夏時間の調整が含まれる場合、1日は23時間または25時間になる可能性があります。月と日のフィールドは整数ですが、秒のフィールドには分数を格納できます。

(出力/表示は IntervalStyle の設定によって異なります。)

上記の例では、デフォルトのPostgres形式を使用しています:_interval '1 month - 1 day'_。これらも有効です(読みにくくなります):

_interval '1 mon - 1 d' -- unambiguous abbreviations of time units are allowed
_

IS0 8601形式

_interval '0-1 -1 0:0'
_

標準SQL形式

_interval 'P1M-1D';
_

すべて同じです。

6

うるう年のため、day_in_month(2)の予想出力は29になる可能性があることに注意してください。 intの代わりに日付を渡したい場合があります。

また、夏時間に注意してください。タイムゾーンを削除してください。そうしないと、月の計算が間違っている可能性があります(CET/CESTの次の例):

SELECT  DATE_TRUNC('month', '2016-03-12'::timestamptz) + '1 MONTH'::INTERVAL
      - DATE_TRUNC('month', '2016-03-12'::timestamptz) ;
------------------
 30 days 23:00:00

SELECT  DATE_TRUNC('month', '2016-03-12'::timestamp) + '1 MONTH'::INTERVAL
      - DATE_TRUNC('month', '2016-03-12'::timestamp) ;
----------
 31 days
1
Laurent B

あなたは関数を書くことができます:

CREATE OR REPLACE FUNCTION get_total_days_in_month(timestamp)
RETURNS decimal
IMMUTABLE
AS $$
  select cast(datediff(day, date_trunc('mon', $1), last_day($1) + 1) as decimal)
$$ LANGUAGE sql;
0
dr34m3r

これも同様に機能します。

WITH date_ AS (SELECT your_date AS d)
SELECT d + INTERVAL '1 month' - d FROM date_;

あるいは単に:

SELECT your_date + INTERVAL '1 month' - your_date;

これらの2つは、integerではなくintervalを返します。

0
Mark Mishyn