所以我存储了用户的生日和月份。我发送生日优惠,这些优惠以不同的间隔到期,即“生日后的天数”。
我已经成功构建了公式(下面是它的一部分)但是我遇到了这个问题:
('2015-10-10'::date >= make_date(2015, users.birth_month, users.birth_day)
...
如果用户于2月29日出生,则make_date
会针对无效年份(ERROR: date field value out of range: 2015-02-29
)提出异常
我怎样才能优雅地处理这个? (我有其他方法可以解决这个问题,但是他们要求我为闰年提供特殊待遇)
答案 0 :(得分:1)
这可以通过结合使用make_date
和interval
PostgreSQL功能(有关更多信息,请参见https://www.postgresql.org/docs/9.6/functions-datetime.html)来实现。
技巧是确保make_date
中的日期始终有效。通过使用每月的第一天,然后使用interval
(减去1天)来增加所需的天数(同时避免出现ERROR: date field value out of range
错误),可以轻松实现这一目标。
通过创建一个小表users
来举例说明:-
create table users (
id serial primary key,
birth_day integer,
birth_month integer
);
...并在其中填充一些数据...
insert into users (birth_day, birth_month) values
(1, 2),
(28, 2),
(29, 2),
(30, 2),
(31, 2);
如果年份为2015
,则可以运行以下查询:-
select birth_day,
birth_month,
make_date(2015, birth_month, 1) + (birth_day - 1) as birthday
from users;
╔═══════════╦═════════════╦══════════════╗
║ birth_day ║ birth_month ║ birthday ║
╠═══════════╬═════════════╬══════════════╣
║ 1 ║ 2 ║ "2015-02-01" ║
║ 28 ║ 2 ║ "2015-02-28" ║
║ 29 ║ 2 ║ "2015-03-01" ║ <---- wrapped to march 1st
║ 30 ║ 2 ║ "2015-03-02" ║
║ 31 ║ 2 ║ "2015-03-03" ║
╚═══════════╩═════════════╩══════════════╝
但是,如果年份为2016
(le年),则为:-
select birth_day,
birth_month,
make_date(2016, birth_month, 1) + (birth_day - 1) as birthday
from users;
╔═══════════╦═════════════╦══════════════╗
║ birth_day ║ birth_month ║ birthday ║
╠═══════════╬═════════════╬══════════════╣
║ 1 ║ 2 ║ "2016-02-01" ║
║ 28 ║ 2 ║ "2016-02-28" ║
║ 29 ║ 2 ║ "2016-02-29" ║
║ 30 ║ 2 ║ "2016-03-01" ║ <---- wrapped to march 1st
║ 31 ║ 2 ║ "2016-03-02" ║
╚═══════════╩═════════════╩══════════════╝
感谢
a_horse_with_no_name
指出如果需要的话,您不需要使用interval
-只需添加即可,即+ ((birth_day - 1) || ' days')::interval
可以简化为+ (birth_day - 1)
答案 1 :(得分:0)
好的,我已经为02-29岁的生日添加了一个特例。这可以解决我的问题,但我非常希望听到其他建议。
('2015-10-10'::date >=
case when users.birth_month = 2 and users.birth_day = 29 make_date(2015,2, 28)
else make_date(2015, users.birth_month, users.birth_day)
end
)
在这种情况下,用户将失去一天(我可以通过3月1日让他们赢得一天),但你明白了这一点=)