如何使用 plpgsql 函数将实际月份划分为 5 天

how to divide actual months to 5 days periods using plpgsql function

我需要使用 posgrees 获取每月每五天的第一天。例如,如果 no 是 2.03,那么我将得到 1.03。如果今天是 19.03,那么我会得到 15.03。我尝试使用以下 if 语句,但在今天;那天我得到了 null,我不确定为什么。也肯定有一些不太复杂的方法来完成这个操作。有什么想法吗?

create or replace function getFirstDayOfFive()
returns timestamp with time zone as $$
declare
firstDay timestamp;
begin
if (now()::date>date_trunc('month', now()::date) and now()::date < date_trunc('month', now()::date) + interval '5 day') then
    return firstDay = date_trunc('month', now()::date);
elsif (now()::date>date_trunc('month', now()::date) + interval '5 day' and now()::date < date_trunc('month', now()::date) + interval '10 day') then
    return firstDay = (date_trunc('month', now()::date) + interval '5 day')::date;
elsif (now()::date>date_trunc('month', now()::date) + interval '10 day' and now()::date < date_trunc('month', now()::date) + interval '15 day') then
    return firstDay = (date_trunc('month', now()::date) + interval '10 day')::date;
elsif (now()::date>date_trunc('month', now()::date) + interval '15 day' and now()::date < date_trunc('month', now()::date) + interval '20 day') then
    return firstDay = (date_trunc('month', now()::date) + interval '15 day')::date;
elsif (now()::date>date_trunc('month', now()::date) + interval '20 day' and now()::date < date_trunc('month', now()::date) + interval '25 day') then
    return firstDay = (date_trunc('month', now()::date) + interval '20 day')::date;
end if;
end;

$$
language plpgsql;

demo:db<>fiddle

SELECT
    make_date(                                             -- 4
        date_part('year', my_date)::int,                   -- 3
        date_part('month', my_date)::int,                     
        greatest(                                          -- 2
            floor(date_part('day', my_date) / 5) * 5,      -- 1
            1
        )::int
    )
  1. 使用 date_part() 获取当前日期的第几天。在它用 floor(day / 5) * 5
  2. 舍入到完整的倍数 5 之后
  3. 所提供的算法始终给出 5 的前一个倍数(对于 19,它给出 15,对于 6,它给出 5,...)。但是,对于 14 天,它给出了 0。所以这是一个需要处理的异常。这是在这里完成的
  4. 获取当前日期的年月部分
  5. 创建预期日期。

这个查询当然可以嵌入到一个函数中:

create or replace function getFirstDayOfFive()
returns timestamp with time zone as $$
declare
    firstDay timestamp;
begin

SELECT
    make_date(
        date_part('year', now())::int,
        date_part('month', now())::int,
        greatest(
            floor(date_part('day', now()) / 5) * 5,
            1
        )::int
    )
INTO firstDay;

RETURN firstDay;
    
end;

$$
language plpgsql;

编辑:来自评论:最后一天相同:

你必须改变:

  1. floor()ceil()
  2. greatest(..., 1)改成least(..., last day of current month)

要获得当月的最后一天,您必须使用 date_trunc('month', ...) 找到第一天,加上一个月得到下个月的第一天并从中减去一天:

demo:db<>fiddle

SELECT
    least(
        ceil(date_part('day', now()) / 5) * 5,
        date_part('day', date_trunc('month', now()) + interval '1 month - 1 day')
    )