как получить следующую дату за день месяца - PullRequest
0 голосов
/ 25 октября 2018

спасибо за чтение, это ситуация

У меня есть current_date и день месяца, поэтому мне нужно знать, какой будет следующая дата для этого дня месяца, учитывая, что какой-то месяцне имеет 30 и 31.

Пример:

  • current_date = '2018-09-24'
  • day_of_week = 31

Ожидаемый результат: '2018-12-31'

В настоящее время у меня есть это:

create or replace function next_diff(vals int[], current_val int) returns int as 
$$
declare v int;
declare o int := vals[1];
begin
    foreach v in array vals loop
    if current_val >= o and current_val < v then
       return v - current_val;
    end if;
    o := v;
    end loop;
    return vals[1] - current_val;
end;
$$ language plpgsql;

и это:

create or replace function next_day_of_month(days_of_month int[], curr_date date) returns date as 
$$
declare cur_dom int := extract(day from curr_date);
declare next_diff int := next_diff(days_of_month, cur_dom);
begin
    if next_diff < 0 then
    curr_date := curr_date + '1 months'::interval;
    end if;
    curr_date := curr_date + (next_diff || 'days')::interval;
    return curr_date;
end;
$$ language plpgsql;

но для этого звонка:

select next_day_of_month(array[31], '2018-09-24');

я получаю:

"2018-10-01"

Дополнительный пример

Если у меня есть это значение

  • current_date = '2018-02-01'
  • day_of_week = 31

я будунужен следующий месяц с 31-м, но я не могу получить «2018-02-31», потому что в феврале нет 31-го, тогда я должен получить «2018-02-31», потому что у марта 31-е.

Заключение

если месяц не имеет указанного дня, должен игнорировать месяц и переходить ко следующем.

спасибо за все

Финальный метод

Используя ответ Карлоса Гомеса, я создаю эту функцию PostgreSQL и отлично работаю:

create or replace function next_day_date(curr_date date, day_of_month int) returns date as 
$$
declare next_day date;
begin
    SELECT next_day_date into next_day FROM (
      SELECT make_date_nullable(EXTRACT(year from n.month)::int, EXTRACT(month from n.month)::int, day_of_month) AS next_day_date
      FROM (
        SELECT generate_series(curr_date, curr_date + '3 months'::interval, '1 month'::interval) as month
          ) n
      ) results
      WHERE results.next_day_date IS NOT NULL and results.next_day_date > curr_date  LIMIT 1;
      return next_day;
end;
$$ language plpgsql;

просто добавьте другой фильтр в пункт where and results.next_day_date > curr_date, чтобы предотвратить получение тех же или предыдущих значений на указанную дату

Спасибо всем за помощь

Затем, Карлос, вы лучший

Gracias carlos eres el mejor:)

1 Ответ

0 голосов
/ 25 октября 2018

Ваши примеры на самом деле не совпадают, но я думаю, что я знаю, для чего вы пытаетесь решить (ваш первый примерный результат должен быть '2018-10-31', поскольку в октябре 31 день, а ваш второй примерный результат должен быть ''2018-03-31' ).Кажется, что, учитывая дату и день месяца, вы хотите найти следующий месяц, который имеет этот день месяца.Чтобы сделать это, я бы сделал следующее:

Эта функция просто оборачивает make_date , чтобы она возвращала ноль, так как она выдает исключение, если данная дата выходит за пределы (например, февраль).30).

CREATE OR REPLACE FUNCTION make_date_nullable(year int, month int, day int)
RETURNS date as $$
BEGIN
  RETURN make_date(year, month, day);
EXCEPTION WHEN others THEN RETURN null;
END;
$$ language plpgsql;

Этот SELECT сначала генерирует следующие три месяца, начиная с текущего, затем создает дату из них с помощью предоставленного вами day_of_month и, наконец, получает первый, который не равен нулю (существует согласно postgresql.

SELECT next_day_date FROM (
  SELECT make_date_nullable(EXTRACT(year from n.month)::int, EXTRACT(month from n.month)::int, day_of_month) AS next_day_date
  FROM (
        SELECT generate_series(current_date, current_date + '3 months'::interval, '1 month'::interval) as month
      ) n
  ) results
  WHERE results.next_day_date IS NOT NULL LIMIT 1;

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...