私はPostgresで以下を取得しようとしています:
select day_in_month(2);
期待される出力:
28
Postgresにそれを行うための組み込みの方法はありますか?
_SELECT
DATE_PART('days',
DATE_TRUNC('month', NOW())
+ '1 MONTH'::INTERVAL
- '1 DAY'::INTERVAL
)
_
NOW()
を他の日付に置き換えます。
スマートな「トリック」を使用して、月の最後の日付から日の部分を抽出します。 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
は数値(おそらく署名済み)です。unit
はmicrosecond
、millisecond
、second
、minute
、hour
、day
、week
、month
、year
、decade
、century
、millennium
、またはこれらの単位の略語または複数形。
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';
_
すべて同じです。
うるう年のため、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
あなたは関数を書くことができます:
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;
これも同様に機能します。
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を返します。