1/200 «с потолка». просто на примере США. по логике модели у них через пару недель должны закончиться резервы популяции. по кривой заражения это явно не так.
Представьте, что у вас первая зарплата в компании 15 февраля. Так же рассуждать будете? ;) Сдвиг на месяц не предполагает привяки к половинам и каким-либо другим частям месяца — это всегда либо то же число, что и в прошлом месяце, либо максимальное дата месяца, если число в месяце отсутствует.
Почему нельзя определить месяц? Это единичный интервал, для которого год и столетие кратные. Выразить эти интервалы в днях нельзя, но это не мешает их определению.
Начнём с того, что не всегда. Второй момент, мы оперируем с разными величинами — датами и интервалами. Последние, в довершение всего, ещё и могут быть выражены в величинах, однозначно не приводимых друг к другу. А как называть/обозначать эту операцию — дело десятое.
В операциях с месяцами основная ошибка — это попытка «взвесить» месяц в днях, что по определению невозможно, да и в корне неверно. Чтобы избежать неоднозначности, этого делать не нужно. В этом плане, очень правильно эта математика реализована, например, в PostgreSQL. Чтобы понять логику прибавления месяцев, проще всего взять пример зарплаты. Если заплата выплачивается каждый месяц, то месяц не может быть пропущен по определению. Иными словами, при добавлении месяца к любой дате в январе должна быть дата в феврале, но никак не в марте. Отсюда правда вытекают такие порой неочевидные моменты, как например: 28/29/30/31 января + 1 месяц = 28 февраля (дата + N месяцев) - N месяцев не всегда равно дата (дата + 1 месяц) + 1 месяц не всегда равно дата + 2 месяца
и т.п.
Это неявный lateral cross join, ввиду того что функция приведения типа напрямую не применима на функцию, возвращающую множество. На самом деле, можно было обойтись без этого, заменив
эту часть запроса
from generate_series(start_time::date, stop_time::date, '1 day')_, "timestamp"(_) period_day,
на такой вариант
from generate_series(date_trunc('day', start_time), date_trunc('day', stop_time), '1 day') period_day,
или такой вариант
from generate_series(start_time::date::timestamp, stop_time::date::timestamp, '1 day') period_day,
чтобы функция generate_series сразу возвращала timestamp. Это бы ещё и облегчило запрос. Но… хорошая мысля приходит опосля. :)
тут в идеале бы ещё знать, как представлен календарь праздников и рабочих уикендов, так как параметрически их вряд ли передают в запрос. задача была бы более приближена к реальной, а так решение выглядит несколько искусственно.
Это лишь вопрос синтаксиса запроса, по использованию join'ов я с Вами согласен. Join тут не был использован исключительно из соображений компактности. Для конкретно этого случая второй запрос можно заменить на эквивалентный вариант с использованием явных join'ов:
select date, step + 1
from params
cross join cycle
join date(date1 + interval * step) on date <= date2
Другого варианта на чистом sql, кроме как рекурсивно прокрутить цикл, сходу в голову не пришло, но Ваше решение можно сделать несколько более изящным:
with recursive params as (
select date('2018-01-31') date1, date('2018-05-31') date2, "interval"('1 month')
),
cycle as (
select date1 result, 1 step from params
union all
select date, step + 1 from params, cycle, date(date1 + interval * step)
where date <= date2
)
select result from cycle
Можно вспомнить относительно недавнюю комету Хейла-Боппа. Подобные кометы — явление, конечно, достаточно редкое, но не в рамках периодов порядка столетий. А Больших комет за столетие может быть и больше десятка.
Там вопрос о расширении группы томов. К тому же ответ приведён неточный. Физический том можно не создавать — он будет создан неявно vgextend, если его нет.
28/29/30/31 января + 1 месяц = 28 февраля
(дата + N месяцев) - N месяцев
не всегда равнодата
(дата + 1 месяц) + 1 месяц
не всегда равнодата + 2 месяца
и т.п.