zoukankan      html  css  js  c++  java
  • mysql计算两个时间戳/日期间的工作日,兼容节假日

    设置起止时间参数
    set @date1='2019/01/01';
    set @date2='2019/12/31';
    
    建表
    DROP TABLE IF EXISTS `calendar`;
    CREATE TABLE `calendar` (
      `day` date DEFAULT NULL,
      `holiday` int(11) DEFAULT '0',
      `dow` int(11) DEFAULT NULL
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4;
    
    写入时间函数
    delimiter $$
        drop procedure if exists test;
        create procedure test()
        begin
            declare tday date;
            set tday=@date1;
            while (tday <= @date2) do
                insert into calendar(day) values(tday);
                set tday=date_add(tday,interval 1 day);
        end while;
    end$$
    
    调用存储过程
    call test();
    
    更新星期数据
    update calendar set dow=dayofweek(day)-1;
    update calendar set dow=7 where dow=0;
    
    使用
    SELECT COUNT(*) FROM calendar
    WHERE day BETWEEN @date1 AND @date2 
    AND ((DAYOFWEEK(day) NOT IN(1,7) AND holiday=0) or holiday=2);
    
    排除周末
    delimiter //
    drop function if exists getworkdays;
    create function getworkdays(s varchar(16),e varchar(16))
    returns varchar(16)
    begin
    DECLARE result VARCHAR(16) default '';
    set e = FROM_UNIXTIME(e,'%Y-%m-%d');
    set s = FROM_UNIXTIME(s,'%Y-%m-%d');
    select  (floor(days/7)*5 
        + days%7
        - case when 6 between wd and wd+days%7-1 then 1 else 0 end
        - case when 7 between wd and wd+days%7-1 then 1 else 0 end) into  result
    from 
    (select datediff(e,s)+1 as days, weekday(s)+1 as wd ) as a;
    RETURN result;
    end //
    
    delimiter ;
    
    ## 函数分析
    
    
    1、编写存储过程,便于测试。存储过程命名为getWorkDays(d1,d2)
    2、先求出日期d1到d2之间的天数days【使用datediff()函数】,再求出d2所在的日期为星期几【使用weekday()函数】
    3、使用floor()函数求出days中所包含的星期数为(floor(days/7)),那么工作日数就是floor(days/7)*5。
    4、最后一步就是求出零散的工作日:days%7表示的是,当前日期被7整除后的余数,这个余数就是代表零散的天数。但是我们不能将这个零散的天数全部加上,因为这个零散的天数中可能包含着周六,周末。这就是为什么我们前面计算d2是星期几的原因。
    针对上述问题,后面再接上case when()语句,其中的between wd and wd+days%7-1意思就是指周六或者周末是不是在多出来的这个零散日期里。【需要注意这里的wd是weekday(s)即开始时间的星期,笔者在这个位置坑了好久!!】
    --------------------- 
    
    以上来自:https://blog.csdn.net/liu16659/article/details/82584807 
    
    
    排除节假日
    
    delimiter //
    drop function if exists getworkdays;
    create function getworkdays(s varchar(16),e varchar(16))
    returns varchar(16)
    begin
    DECLARE result VARCHAR(16) default '';
    set e = FROM_UNIXTIME(e,'%Y-%m-%d');
    set s = FROM_UNIXTIME(s,'%Y-%m-%d');
    select count(*) into result from calendar where holiday = 0 and day between s and e
    RETURN result;
    end //
    delimiter ;
    

    注:节假日需要维护calendar表

    calendar数据录入
    <?php
    // 工作日对应结果为 0, 休息日对应结果为 1, 节假日对应的结果为 2;
    date_default_timezone_set('PRC');
    $day='2019';
    $url='http://tool.bitefu.net/jiari/vip.php?type=0&apikey=123456&d='.$day;
    $result=curlget($url);
    function curlget($url){
        $ch = curl_init();
        curl_setopt ($ch, CURLOPT_URL, $url);
        curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT,10);
        $dxycontent = curl_exec($ch);
        curl_close($ch);
        return $dxycontent;
    }
    $conn = mysqli_connect('localhost','root','');
    if(!$conn){
    	var_dump(mysqli_error());
    }
    
    $jsonDay = json_decode($result,true);
    $dayData = $jsonDay['data']['2019'];
    mysqli_select_db($conn,'efuzhou3');
    
    $sql = "select * from calendar";
    
    $res = mysqli_query($conn,$sql);
    while($row=mysqli_fetch_assoc($res)){
    	$timestamp = strtotime($row['day']);
    	$mdData = date('md',$timestamp);
    	if(isset($dayData[$mdData])){
    	    $row['holiday'] = $dayData[$mdData];
    	}
    	$sql = "update calendar set holiday = $row[holiday] where `day` = '$row[day]'";
    	mysqli_query($conn,$sql);
    	$data[] = $row;
    }
    var_dump($data);
    ?>
    
  • 相关阅读:
    Java操作excel
    (13)C++ 多态
    (12)C++ 继承
    (18)C++ string和标准模板库
    parseInt(str),parseFloat(str)
    JavaScript substring() 方法
    JavaScript遍历对象中所有元素
    JavaScript中的number跟string
    mybatis动态sql
    Android数据存储之Android 6.0运行时权限下文件存储的思考
  • 原文地址:https://www.cnblogs.com/rohanCh/p/11196143.html
Copyright © 2011-2022 走看看