Кину 5 копеек по поводу работы с датами. Да это зло. Работа с датами в современном API это
самый большой технический долг начиная с Unix, когда дата представлялась секундами с 1970 года
в виде DWORD. Я не встречал ни одного языка программирования и ни одной DBMS где изначально
была-бы какая-то очень строгая и математичная концепция работы с временем. Везде были ограничители
в основном завязанные на примитивные типы либо на строки вариативной длины. В Java например
долгое время экплуатировался тип java.util.Date который сегодня считается дыркой (мутабельность)
и неточным и его заменяют на java.time.* семейство типов. Параллельно с ним где-то в космосе
висит java.sql.Date который декларирован в интерфейсах JDBC как основа для БД. С ним-же и работают
все драйвера реляционных бд.
По поводу вычислений на application tier. В последнее время DBMS девальвировали. И в основном
используются в микросервисах как хранилище таблиц без особой логики. В этом есть свои смыслы.
Например удобнее тестировать и хранить 100% кода в языках Java/Node/C#. Это создает гомогенность
языка в проекте. В противном случае логику пришлось бы неизбежно резать на 2 слоя и хранить
половину в application и другую половину деплоить через flyway/liquibase в БД при этом еще и
не забыть тестировать 100% совместимость тех-же функций для работы дат-времени (никто
кстати невкурсе что в Oracle год может быть 9999 а java.util.Date мне удалось сгенерировать
такую Aug 17 09:12:55 EET 292 278 994. .. оптимистичненько доживем до 290 миллионов
лет хотя проблема comparison этих типов остается) Стандарты ISO помогают но они скорее
декларируют намерения сохранить нужное значение. Вот и если вы новичек - то я гарантирую
что вы словите кайф в попытке в Java разобраться в проекте какой тип дат вам брать. И еще
помножите это все на типы данных БД (их там будет 4 штуки обычно. Парочка для зональных
и парочка для локальных).
Использовать или нет функции PG? Ответ - it depends. В некоторых случаях оптимизатор не видит
индекса если ты делаешь неявный кастинг из строки в дату например. Я тут не уверен надо проверять.
Но есть старая админская поговорка. Плохой execution plan - проверь типы данных в предикатах.
Беда реально существует для Spark/Databricks и даже включена в учебный план. По крайней мере int/Long
различается на уровне Catalyst-optimizer. Вобщем если вы - лентяй то можете лупить строки вместо дат
и надеятся что SQL машина правильно интерпретирует. Если вы хотите быть точным то делайте CAST или
to_date с явным описаловом YYYY-MM и т.д.
Еще один поинт в части где хранить логику. Это я пишу просто для кругозора. Чтобы топик
не циклился вокруг Постгреса а люди видели пошире. В классических БД данные качаются
к клиенту. Тоесть делаете SELECT * из миллирад строк - и этот миллиард будет прокачан до конца
когда вы читаете резалт-сет по сети. Такова парадигма. Или курсор. Но суть таже. А в BigData данные
лежат на месте но к ним "ходит" код. Вот такой метафизический парадокс. Сами понимаете что
тут получается что встроенных функций даже как бы ... и нет. Подчеркиваю разницу.