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);
    ?>
    
  • 相关阅读:
    Educational Codeforces Round 20 D. Magazine Ad
    Educational Codeforces Round 20 C. Maximal GCD
    紫书第三章训练2 暴力集
    Educational Codeforces Round 20 B. Distances to Zero
    Educational Codeforces Round 20 A. Maximal Binary Matrix
    紫书第三章训练1 D
    紫书第一章训练1 D -Message Decoding
    HAZU校赛 Problem K: Deadline
    Mutual Training for Wannafly Union #8 D
    紫书第三章训练1 E
  • 原文地址:https://www.cnblogs.com/rohanCh/p/11196143.html
Copyright © 2011-2022 走看看