首页 > 其他 > 详细

计算2个日期之间的差时

时间:2020-05-10 18:22:45      阅读:54      评论:0      收藏:0      [点我收藏+]

输入2个日期,得出2个日期之间的工时小时数:

我想到得的:

(1)看2个日期是否是同一天
如果是,直接减
(2)2个日期如果不是同一天
开始日期:
如果开始时间小于当天9点,则计算开始时间置为当日早上9点
如果开始时间大于18点,则计算开始时间置为隔天早上9点
结束日期:
如果结束日期小于当天早上9点,置为昨天晚上18点
如果结束日期大大于当天18点,置换为当天18点

利用日历表,排除非记薪日(周末和节假日,补班也计算)

问题:

没有精确处理小时的差,比如 2020-04-04 101000 与 2020-04-05 153000 ,这种我任然算2天16,如果精确到小时,感觉比较麻烦,一般请假也是以半天为单位。

日历表:

create table caltab (
  n_date int(11) not null comment 无格式日期,
  y_date date not null comment 有格式日期,
  y_year int(11) not null comment 年度,
  y_month varchar(9) collate utf8mb4_0900_as_cs not null comment 月度,
  y_day int(11) not null comment ,
  y_quarter int(11) not null comment 季度,
  y_week int(11) not null comment ,
  y_num varchar(9) collate utf8mb4_0900_as_cs not null comment 每周星期几,
  holiday_flag tinyint(1) default 0 comment 是否节假日,
  working_flag tinyint(1) default 0 comment 是否工作日,
  remark varchar(50) character set utf8mb4 collate utf8mb4_0900_as_cs default null comment 补充说明,
  primary key (n_date),
  unique key td_ymd_idx (y_date,y_month,y_day),
  unique key td_y_date_idx (y_date),
  key weekend_flag (working_flag),
  key holiday_flag (holiday_flag),
  key y_year (y_year),
  key y_month (y_month),
  key y_day (y_day)
) engine=innodb default charset=utf8mb4 collate=utf8mb4_0900_as_cs

生成表proc:

DELIMITER $$
USE devops$$
DROP PROCEDURE IF EXISTS `proc_calender_day`$$
CREATE DEFINER=`coreuser`@`%` PROCEDURE `proc_calender_day`(IN start_date DATE,IN stop_date DATE)
BEGIN
## ==================================================================================
##    让读书成为一种生活方式。就像吃喝拉撒每天必须要干的事,
## 终有一天你的举止、言谈、气质会不一样。 
##                                        —- async 
##
## Created Date: Thursday, 2020-05-09, 8:46:18 am
## copyright (c):    SZWW Tech. LTD. 
## Engineer:   async 
## Module Name:   
## Revision:   v0.01 
## Description:
##   
## Revision History : 
## Revision     editor         date         Description         
## v0.01        async          2020-01-16   File Created
## ==================================================================================
    DECLARE currentdate DATE;
    SET currentdate = start_date;
    WHILE currentdate < stop_date DO
    INSERT INTO caltab VALUES (
       YEAR(currentdate)*10000+MONTH(currentdate)*100 + DAY(currentdate),
       currentdate,
       YEAR(currentdate), -- 年度
       DATE_FORMAT(currentdate,%m), -- 月度
       DAY(currentdate), -- 当月第x天
       QUARTER(currentdate),-- 季度
       WEEKOFYEAR(currentdate), -- 第x周
       case when DATE_FORMAT(currentdate,%w)=0 then 
            when DATE_FORMAT(currentdate,%w)=1 then 
            when DATE_FORMAT(currentdate,%w)=2 then 
            when DATE_FORMAT(currentdate,%w)=3 then 
            when DATE_FORMAT(currentdate,%w)=4 then 
            when DATE_FORMAT(currentdate,%w)=5 then 
            when DATE_FORMAT(currentdate,%w)=6 then  end, -- 星期几
       CASE
         WHEN DAY(currentdate)=1 AND MONTH(currentdate)=1 THEN 1 -- 元旦
         WHEN DAY(currentdate) between 24 and 30 AND MONTH(currentdate)=1 THEN 1 -- 春节(1月24日至30日放假调休,共7天。1月19日(星期日)、2月1日(星期六)上班)
         WHEN DAY(currentdate) between 4 and 6 AND MONTH(currentdate)=4 THEN 1 -- 清明节 (4月4日至6日放假调休)
         WHEN DAY(currentdate) between 1 and 5 AND MONTH(currentdate)=5 THEN 1 -- 劳动节(5月1日至5日放假调休,共5天。4月26日(星期日)、5月9日(星期六)上班。)
         WHEN DAY(currentdate) between 25 and 27 AND MONTH(currentdate)=6 THEN 1 -- 端午节(6月25日至27日放假调休,共3天。6月28日(星期日)上班)
     WHEN DAY(currentdate) between 1 and 8 AND MONTH(currentdate)=10 THEN 1 -- 国庆,中秋节(国庆节、中秋节:10月1日至8日放假调休,共8天。9月27日(星期日)、10月10日(星期六)上班)
         ELSE 0 END,
         CASE DAYOFWEEK(currentdate) WHEN 2 THEN 1 WHEN 3 THEN 1 WHEN 4 THEN 1 WHEN 5 THEN 1 WHEN 6 THEN 1 ELSE 0 END, -- 是否工作日
         NULL);
        SET currentdate = ADDDATE(currentdate,INTERVAL 1 DAY);
    END WHILE;
    --  补班特殊处理
    update caltab set working_flag=1,remark=#补班 where y_date in(2020-01-19,2020-02-01,2020-04-26,2020-05-09,2020-06-28,2020-09-27,2020-10-10);
END$$
DELIMITER ;

 计算时间差get_wk_hour函数:

DELIMITER $$
USE `devops`$$
DROP FUNCTION IF EXISTS `get_wk_hour`$$
CREATE DEFINER=`coreuser`@`%` FUNCTION `get_wk_hour`(i_time datetime,e_time datetime) RETURNS int(11)
begin
declare v_s_time datetime;
declare v_e_time datetime;
declare v_hours int;
declare h_hours int;

set v_s_time:=i_time;
set v_e_time:=e_time;

-- 如果开始时间>结束时间,则置换位置
if v_s_time>v_e_time
then
select v_s_time,v_e_time into v_e_time,v_s_time from dual;
end if;
-- 判断开始日期是否<当天上午9点
if hour(v_s_time)<9
then
select  concat(date_format(v_s_time,%Y-%m-%d), 09:00:00) into v_s_time from dual;
elseif hour(v_s_time)>18
then
select  concat(date_add(date_format(v_s_time,%Y-%m-%d),interval 1 day), 09:00:00) into v_s_time from dual;
end if;
-- 判断结束日期是否<当天上午9点
if hour(v_e_time)<9
then
select  concat(date_add(date_format(v_e_time,%Y-%m-%d),interval -1 day), 18:00:00) into v_e_time from dual;
elseif hour(v_e_time)>18
then
select  concat(date_add(date_format(v_e_time,%Y-%m-%d),interval 0 day), 18:00:00) into v_e_time from dual;
end if;

-- 找出开始日期与结束日期之间的工时时长(单位:hour),排除周末,排除法定节假日
select count(1) into v_hours from caltab ma where holiday_flag=1
and ma.y_date between date_format(v_s_time,%Y-%m-%d) and date_format(v_e_time,%Y-%m-%d);

-- 判断开始结束日期是否为同一天
select (case when date_format(v_s_time,%Y-%m-%d)=date_format(v_e_time,%Y-%m-%d) and timestampdiff(hour,v_s_time,v_e_time)<8
       then  timestampdiff(hour,v_s_time,v_e_time)
            when  date_format(v_s_time,%Y-%m-%d)=date_format(v_e_time,%Y-%m-%d) and timestampdiff(hour,v_s_time,v_e_time)>=8
       then 8
-- 开始结束日期不在同一天,开始日期在节假日,结束日期在节假日
            when datediff(v_s_time,v_e_time) <> 0
            then (datediff(v_e_time,v_s_time)+1-v_hours)*8
           -- timestampdiff(hour,v_s_time,concat(date_format(v_s_time,%Y-%m-%d), 18:00:00))
end ) into h_hours from dual;

return h_hours;
end$$

DELIMITER ;

计算2个日期之间的差时

原文:https://www.cnblogs.com/5sdba-notes/p/12864188.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!