一次工作日的获取技巧记录
前言
工作日的获取还是比较常见的,比如银行和跨境电商的交易,有时候在教育的行业也会有用到,由于我们不知道每一年那一天是节假日,有时候涉及调休等等又要上班比较麻烦,所以这里干脆做一次记录,以后用到的时候可以直接把表拿来做参考,希望这次的笔记能对读者有所帮助。
注意,本文使用的是PostgreSql数据库,使用其他的数据库需要略微的修改sql的内容。
日期表的设计
日期表的设计不是固定的,下面的内容其实都是供参考使用。
字段名称 |
类型 |
是否为空 |
描述 |
calendar_id |
varchar(255) |
M |
主键 |
calendar_year |
varchar(10) |
M |
年 |
calendar_month |
varchar(10) |
M |
月 |
calendar_date |
varchar(10) |
M |
日 |
day_of_week |
varchar(10) |
M |
自然周的第几天 |
day_of_month |
varchar(10) |
M |
月的第几天 |
week_of_year |
varchar(10) |
M |
年的第几个自然周 |
month_of_year |
varchar(10) |
M |
年的第几月 |
quarter_of_year |
varchar(10) |
M |
年的第几季 |
is_end_month |
varchar(10) |
M |
是否月末 |
is_end_quarter |
varchar(10) |
M |
是否季末 |
is_end_halfayear |
varchar(10) |
M |
是否半年末 |
is_end_year |
varchar(10) |
M |
是否年末 |
operator_id |
varchar(50) |
M |
操作人ID |
operator_name |
varchar(50) |
M |
操作人名称 |
operate_date |
timestamp |
M |
操作时间 |
res_attr1 |
varchar(40) |
O |
预留字段1 |
res_attr2 |
varchar(40) |
O |
预留字段2 |
res_attr3 |
varchar(40) |
O |
预留字段3 |
res_attr4 |
varchar(40) |
O |
预留字段4 |
数据入库模板
当然还是针对PostgreSql数据库使用,下面使用了数据库入库的sql,入库之后可以看到一年的数据内容。
下面的select insert
语句来讲数据入库,当然我们需要先根据上面的数据表构建相关的数据表才行
INSERT INTO sa_calendar_table(
calendar_id,
calendar_year,
calendar_month,
calendar_date,
day_of_week,
day_of_month,
week_of_year,
month_of_year,
quarter_of_year,
is_end_month,
is_end_quarter,
is_end_halfayear,
is_end_year,
operator_id,
operator_name,
operate_date,
res_attr1,
res_attr2,
res_attr3,
res_attr4,
is_work_day
)
SELECT
a.calendar_id,
a.calender_year,
a.calender_month,
a.calendar_date,
a.day_of_week,
a.day_of_month,
a.week_of_year,
a.month_of_year,
a.quarter_of_year,
a.is_end_month,
a.is_end_quarter,
a.is_end_halfayear,
a.is_end_year,
a.operator_id,
a.operator_name,
a.operator_date,
a.res_attr1,
a.res_attr2,
a.res_attr3,
a.res_attr4,
a.is_work_day
FROM (
SELECT
gen_random_uuid() as calendar_id,
to_char(tt.day, 'yyyy') as calender_year,
to_char(tt.day, 'yyyy-mm') as calender_month,
to_char(tt.day, 'yyyy-mm-dd') as calendar_date,
extract(DOW FROM tt.day) as day_of_week,
to_char(tt.day, 'dd') as day_of_month,
extract(MONTH FROM tt.day) as month_of_year,
extract(WEEK FROM tt.day) as week_of_year,
extract(QUARTER FROM tt.day) as quarter_of_year,
CASE WHEN tt.day = date_trunc('month',tt.day + interval'1 month') - interval '1 day' THEN 'Y' ELSE 'N' END as is_end_month,
CASE WHEN tt.day = date_trunc('quarter',tt.day + interval '3 month') - interval '1 day' THEN 'Y' ELSE 'N' END as is_end_quarter,
CASE WHEN tt.day = date_trunc('year',tt.day) + interval '6 month' - interval '1 day'THEN 'Y' ELSE 'N' END as is_end_halfayear,
CASE WHEN tt.day= date_trunc('year',tt.day) + interval '12 month' - interval '1 day'THEN 'Y' ELSE 'N' END as is_end_year,
'b8617d3d-d2c9-4a2a-93ba-5b2d8b700cb0' as operator_id,
'admin' as operator_name,
cast(CURRENT_DATE AS TIMESTAMP) as operator_date,
null as res_attr1,
null as res_attr2,
null as res_attr3,
null as res_attr4,
CASE WHEN extract(DOW FROM tt.day) = 6 THEN 'N' WHEN extract(DOW FROM tt.day) = 0 THEN 'N' ELSE 'Y' END as is_work_day
FROM (
select generate_series(
(SELECT (date_trunc('year', now()) + interval '1 year' )::date as next_year_first_date) ,
(SELECT (SELECT (date_trunc('year', now()) + interval '2 year')::date -1 as last_year_last_date)), '1 d'
) as day
) as tt
) as a;
案例:获取几天前工作日
由于个人使用的经验也不是十分丰富,所以这里记录个人最近接触到的一个使用案例,下面的案例是使用row_number()
来获取多少个日之前的工作日,根据下面的sql语句我们可以轻松完成多少个日之前的工作日,默认会按照当前的日期作为分水岭,如果在当天之前的日期,则为负数,如果是当前天数之后的内容,则为正数。
select * from
(
select - ROW_NUMBER () OVER (ORDER BY t.calendar_date desc) as add_day,t.calendar_date from sa_calendar_table t where t.calendar_year = '2021'
and t.calendar_date < cast(CURRENT_DATE as VARCHAR) and t.is_work_day = 'Y'
union
select ROW_NUMBER () OVER (ORDER BY t.calendar_date) -1 as add_day,t.calendar_date from sa_calendar_table t where t.calendar_year = '2021'
and t.calendar_date >= cast(CURRENT_DATE as VARCHAR) and t.is_work_day = 'Y'
) mm ORDER BY calendar_date
运行效果这里就不进行展示了,无非就是前一天工作日为-1,后一天工作日为+1等等的内容。
问题收集
如果出现ERROR: function gen_random_uuid() does not exist
的代码,可以执行下面的sql语句实现。
CREATE EXTENSION pgcrypto;
如果再postgresql中会有如下的类似报错:
# SELECT gen_random_uuid();
ERROR: function gen_random_uuid() does not exist
LINE 1: select gen_random_uuid();
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
# CREATE EXTENSION pgcrypto;
CREATE EXTENSION
# SELECT gen_random_uuid();
gen_random_uuid
--------------------------------------
19a12b49-a57a-4f1e-8e66-152be08e6165
(1 row)
总结
算是一次简单的总结,希望对于读者有帮助
写在最后
本次主要为一次个人的时间记录。