简体   繁体   中英

How to write the query to get the first and last date of a January and other month's in postgresql

如何获取特定月份的首个和最后一个日期,即如果我通过特定月份的名称说三月,则应返回输出为01/03/2019和31/03/2019。(对于当前年份)

One straightforward approach, which would also work on most other databases, would be to truncate the incoming date by month to obtain the first day of that month. Then, truncate the date with one month added to it, and subtract one day, to obtain the last day of the month.

SELECT
    DATE_TRUNC('month', '2019-03-15'::date) AS date_start,
    DATE_TRUNC('month', '2019-03-15'::date + INTERVAL '1 MONTH')
        - INTERVAL '1 DAY' AS date_end;

在此处输入图片说明

Demo

From here Date LastDay

SELECT date_trunc('MONTH', dtCol)::DATE;

CREATE OR REPLACE FUNCTION last_day(DATE)
RETURNS DATE AS
$$
  SELECT (date_trunc('MONTH', $1) + INTERVAL '1 MONTH - 1 day')::DATE;
$$ LANGUAGE 'sql' IMMUTABLE STRICT;

If you want to pass value March you would have to modify the code to understand every month. I'm not sure it's worth the trouble. Anyways, here's a code to return two values (start and end of month) based on current_date . Should you wish to change the day, you could put for example '2019-04-13' in that place.

SELECT 
    date_trunc('month', current_date) as month_start
  , (date_trunc('month', current_date) + interval '1 month' - interval '1 day')::date as month_end

DATE_TRUNC function truncates the date to the precision specified in first argument, thus making the date as of first day of given month (taken from current_date in above example).

For end of month you need a bit more computation. I've always used this in production and what it does is it first truncates your date to first day of month, then adds one month and goes back one day, so that you have your end of month date (whether it's 30, 31, or special case for February during leap years).

for any month, the first day must be 1st, so it is:

make_date(2019, 3, 1)

and for any month, the last day is 1 day before the first day of next month, so it is:

make_date(2019, 4, 1)  - integer '1'

sorry, I don't have a PostgreSQL environment to test if it is correct, so please test it yourself.

and, BTW, you can find more details about date/time operators and functions here: https://www.postgresql.org/docs/current/functions-datetime.html

The conversion from month name parameter is actually rather simple. Create an array with the month names and find the position in the array of the parameter, that result becomes the month value into the make_date function with year extracted from current date and day 1. The below contains an overloaded function providing for either date or month name with optional year.

create type first_last_date as ( first_of date, last_of date); 

create or replace function first_last_of_month(date_in date)
returns first_last_date
language sql immutable strict leakproof 
as $$
    select (date_trunc('month', date_in))::date, (date_trunc('month', date_in) + interval '1 month' - interval '1 day')::date ;
$$;

create or replace function first_last_of_month( month_name_in text
                                              , year_in      integer default null
                                              ) 
returns first_last_date 
language sql immutable leakproof 
as $$
select first_last_of_month ( make_date ( coalesce (year_in, extract ('year' from now())::integer)
                                       , array_position(ARRAY['jan','feb','mar','apr','may','jun','jul','aug','sep','nov','dec']
                                                       , lower(substring(month_name_in,1,3)))
                                       ,1 ) );

$$;

-- test    
 Select first_last_of_month('March');

 Select first_last_of_month('February') y2019
      , first_last_of_month('February', 2020) y2020;

Select first_last_of_month(now()::date);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM