工作中,经常会遇到需要根据节假日来进行排班、统计工作量等需求。由于每年的节假日安排不是固定的,所以在实现这些统计查询时,往往比较困难。
网上也有一些比较不错的WebService服务,可以用来提供对某个日期是否为节假日的查询。比如在下面这篇文章中
非常好用的节假日查询接口_yinfuyuan-CSDN博客blog.csdn.net
就介绍了一个不错的查询节假日安排的服务:
接口坞www.apihubs.cn
而且,这个服务接口支持将指定区间范围内的所有日期(包括节假日)的安排以JSON格式返回,例如:
https://api.apihubs.cn/holiday/get?year=2021&month=202101api.apihubs.cn
就可以返回2021年1月份的所有日期安排,格式类似:
{"year":2021,"month":202112,"date":20211231,"yearweek":202152,"yearday":365,"lunar_year":2021,"lunar_month":202111,"lunar_date":20211128,"lunar_yearday":323,"week":5,"weekend":2,"workday":1,"holiday":10,"holiday_or":10,"holiday_overtime":10,"holiday_today":2,"holiday_legal":2,"holiday_recess":2}
其中各个参数的含义如下:
year 公历年份
month 公历月份
date 公历日期
yearweek 公历一年中的第几周,注意这里的年份是ISO-8601周编号年份,始终以周一至周日为一周。如需获取7天为一周直接使用年份中的天数除7即可。
yearday 公历一年中的第几天
lunar_year 农历年份
lunar_month 农历月份
lunar_date 农历日期
lunar_yearday 农历一年中的第几天
week 星期几
weekend 是否为周末
workday 是否为工作日(包含调休在内需要上班的日子)(1-工作日,2-非工作日)
holiday 节假日,这里使用两位数字枚举表示节假日,其中特殊数字10表示非节假日,特殊数字99表示全部节假日
holiday_or 其他节假日,枚举与节假日相同,表示同一天中的另一个节日
holiday_overtime 节假日调休
holiday_today 是否为节日当天
holiday_legal 是否为法定节假日(三倍工资)
holiday_recess 是否为假期节假日(节日是否放假)
为此,本人做了一个试验模型,将该网站提供的2021年全年日期数据下载后,导入Oracle数据库,以方便实现一些与节假日相关的查询。
一、构建数据结构
1、创建如下字典表:
-- Create table
create table COMM.CALENDAR_DICT
(
year NUMBER(4) not null,
month VARCHAR2(6) not null,
day VARCHAR2(8) not null,
yearweek VARCHAR2(6),
yearday NUMBER(3),
lunar_year NUMBER(4),
lunar_month VARCHAR2(6),
lunar_date VARCHAR2(8),
lunar_yearday NUMBER(3),
week NUMBER(2),
weekend NUMBER(1),
workday NUMBER(1),
holiday NUMBER(3),
holiday_or NUMBER(3),
holiday_overtime NUMBER(3),
holiday_today NUMBER(1),
holiday_legal NUMBER(1),
holiday_recess NUMBER(1)
)
tablespace TSP_COMM
pctfree 10
initrans 1
maxtrans 255
storage
(
initial 64K
next 64K
minextents 1
maxextents unlimited
pctincrease 0
);
-- Add comments to the columns
comment on column COMM.CALENDAR_DICT.year
is '公历年份';
comment on column COMM.CALENDAR_DICT.month
is '公历月份';
comment on column COMM.CALENDAR_DICT.day
is '公历日期';
comment on column COMM.CALENDAR_DICT.yearweek
is '公历一年中的第几周,注意这里的年份是ISO-8601周编号年份,始终以周一至周日为一周。如需获取7天为一周直接使用年份中的天数除7即可。';
comment on column COMM.CALENDAR_DICT.yearday
is '公历一年中的第几天';
comment on column COMM.CALENDAR_DICT.lunar_year
is '农历年份';
comment on column COMM.CALENDAR_DICT.lunar_month
is '农历月份';
comment on column COMM.CALENDAR_DICT.lunar_date
is '农历日期';
comment on column COMM.CALENDAR_DICT.lunar_yearday
is '农历一年中的第几天';
comment on column COMM.CALENDAR_DICT.week
is '星期';
comment on column COMM.CALENDAR_DICT.weekend
is '是否为周末(星期六和星期日)';
comment on column COMM.CALENDAR_DICT.workday
is '是否为工作日(包含调休在内需要上班的日子)(1-工作日,2-非工作日)';
comment on column COMM.CALENDAR_DICT.holiday
is '节假日,这里使用两位数字枚举表示节假日,其中特殊数字10表示非节假日,特殊数字99表示全部节假日';
comment on column COMM.CALENDAR_DICT.holiday_or
is '其他节假日,枚举与节假日相同,表示同一天中的另一个节日';
comment on column COMM.CALENDAR_DICT.holiday_overtime
is '节假日调休';
comment on column COMM.CALENDAR_DICT.holiday_today
is '是否为节日当天';
comment on column COMM.CALENDAR_DICT.holiday_legal
is '是否为法定节假日(三倍工资)';
comment on column COMM.CALENDAR_DICT.holiday_recess
is '是否为假期节假日(节日是否放假)';
-- Create/Recreate primary, unique and foreign key constraints
alter table COMM.CALENDAR_DICT
add constraint PK_CALENDAR_DICT primary key (DAY)
using index
tablespace TSP_COMM
pctfree 10
initrans 2
maxtrans 255
storage
(
initial 64K
next 64K
minextents 1
maxextents unlimited
pctincrease 0
);
2、通过上面的服务网址,将2021年所有月份的日期安排的JSON格式数据下载到本地,使用PowerBuilder下的PBJSON接口,将JSON格式转换到数据窗口中,再将数据窗口中的数据插入上面的字典表。
这里,引用了大自在大神 (QQ号:781770213 QQ群:624409252) 提供的PB_Json_httpclient_crypto_ftp_20201210接口,特此鸣谢。
这样,我们就有了一张包含2021年全年日期的日历字典表,其中记录了所有2021年日期的公历、农历、节假日信息。
二、关于节假日查询的两个例子
1、两个日期之间的工作日数量
该查询可能的用途:计算两个日期之间的工作日有多少个,以方便计算工作日平均工作量。
以下查询就演示了查询2021.01.01到2021.01.10之间有多少个工作日:
select count(*)
from COMM.CALENDAR_DICT
where day >= to_char(to_date('20210101','YYYYMMDD'), 'YYYYMMDD')
and day < to_char(to_date('20210110','YYYYMMDD'), 'YYYYMMDD')
and workday = 1
;
COUNT(*)
----------
5
2、返回指定日期的X个工作日以后的日期
该查询可能的用途:按照《病案管理质量控制指标(2021年版)》要求,出院患者病历应在2个工作日内完成归档,将“出院患者病历2 日归档率”作为重要的评价指标。因此需要根据病人出院日期计算出2个工作日是哪一天。
以下查询就演示了2021.01.01往后面数6个工作日对应的日期:
select max(day)
from
( select day
from COMM.CALENDAR_DICT
where workday = 1
and day >= to_char(to_date('20210101','YYYYMMDD'), 'YYYYMMDD')
order by day
)
where rownum <= 6 ;
MAX(DAY)
--------
20210111
上述举例完全可以举一反三,根据该字典表数据,实现各种涉及公历和农历节假日的数据统计分析。且该表的数据增长速度并不快,因此对数据库不会造成较大的存储压力。
后续,本人将逐步完善,用函数或者存储过程实现涉及节假日的主要查询功能,以方便其它应用调用。
(待更新)