思路:
1、获取到查询年份内所有工作日数据数组
2、获取到查询开始日期在工作日的索引
3、计算需查询日期索引
4、获得查询日期
/*创建日期类型记录表格*/CREATE TABLE `tb_workday` (`did` int(11) NOT NULL AUTO_INCREMENT,`exact_date` varchar(32) NOT NULL COMMENT ‘具体日期:格式date("Ymd");(20170205)‘,`date_year` varchar(32) NOT NULL COMMENT ‘具体日期:格式date("Y");(2017)‘,`date_type` tinyint(2) NOT NULL COMMENT ‘日期类型:0、工作日;1、特殊工作日;2、法定节假日‘,PRIMARY KEY (`did`)) ENGINE=InnoDB AUTO_INCREMENT=829 DEFAULT CHARSET=utf8 COMMENT=‘各年工作日&法定节假日数据‘
?1 <?php ?2 ??3 class work_days ?4 { ?5 ??/** ?6 ???* 获取星期 ?7 ???* @param $date ?8 ???* @return mixed ?9 ???*/ 10 ??function get_week($date) 11 ??{ 12 ????//强制转换日期格式 13 ????$date_str = date(‘Y-m-d‘, strtotime($date)); 14 ????//封装成数组 15 ????$arr = explode("-", $date_str); 16 ????//参数赋值 17 ????//年 18 ????$year = $arr[0]; 19 ????//月,输出2位整型,不够2位右对齐 20 ????$month = sprintf(‘%02d‘, $arr[1]); 21 ????//日,输出2位整型,不够2位右对齐 22 ????$day = sprintf(‘%02d‘, $arr[2]); 23 ????//时分秒默认赋值为0; 24 ????$hour = $minute = $second = 0; 25 ????//转换成时间戳 26 ????$strap = mktime($hour, $minute, $second, $month, $day, $year); 27 ????//获取数字型星期几 28 ????$number_wk = date("w", $strap); 29 ????//获取数字对应的星期 30 ????return $number_wk; 31 ????//自定义星期数组 32 ????//$weekArr = array("星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"); 33 ????//获取数字对应的星期 34 ????//return $weekArr[$number_wk]; 35 ??} 36 ?37 ??/** 38 ???* 获取指定日期段内每一天的日期 39 ???* @param ?string $startdate 开始日期 40 ???* @param ?string $enddate ??结束日期 41 ???* @return array 42 ???*/ 43 ??function getDateFromRange($startdate, $enddate) 44 ??{ 45 ????$stimestamp = strtotime($startdate); 46 ????$etimestamp = strtotime($enddate); 47 ????// 计算日期段内有多少天 48 ????$days = ($etimestamp - $stimestamp) / 86400 + 1; 49 ????// 保存每天日期 50 ????$_list_date = array(); 51 ????for ($i = 0; $i < $days; $i++) { 52 ??????$_list_date[] = date(‘Y-m-d‘, $stimestamp + (86400 * $i)); 53 ????} 54 ????return $_list_date; 55 ??} 56 ?57 ??function curl_post($url, $data = null) 58 ??{ 59 ????$curl = curl_init(); 60 ????curl_setopt($curl, CURLOPT_URL, $url); 61 ????curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE); 62 ????curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE); 63 ????if (!empty($data)) { 64 ??????curl_setopt($curl, CURLOPT_POST, 1); 65 ??????curl_setopt($curl, CURLOPT_POSTFIELDS, $data); 66 ????} 67 ????curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); 68 ????$output = curl_exec($curl); 69 ????curl_close($curl); 70 ????return $output; 71 ??} 72 ?73 ?74 ??/** 75 ???* 更新数据库指定年份日期数据 76 ???* @param $year 77 ???* @return int 78 ???*/ 79 ??function updateDate($year) 80 ??{ 81 ????$startDate = date(‘Y-m-d‘, strtotime($year . ‘-01-01‘)); 82 ????$endDate = date(‘Y-m-d‘, strtotime(‘+1 year‘, strtotime($startDate)) - 86400); 83 ????$_list_date = self::getDateFromRange($startDate, $endDate); 84 ????$url = ‘http://api.goseek.cn/Tools/holiday‘;//自行查找的免费API 85 ????$m = M(‘tb_workday‘); 86 ????$count = 0; 87 ????foreach ($_list_date as $k => $_date) { 88 ??????$_ret = 0; 89 ??????$_date = date(‘Ymd‘, strtotime($_date)); 90 ??????$_post_data = array(‘date‘ => $_date); 91 ??????$_ret_curl = curl_post($url, $_post_data); 92 ??????$_ret_curl = json_decode($_ret_curl, true); 93 ?94 ??????//工作日 95 ??????if ($_ret_curl[‘data‘] == 0) { 96 ????????$dateData[‘exact_date‘] = $_date; 97 ????????$dateData[‘date_year‘] = $year; 98 ????????$dateData[‘date_type‘] = 0; 99 ????????$_ret = $m->add($dateData) ? 1 : 0;100 ????????unset($dateData);101 102 103 ????????//工作日 判断是否为周末104 ????????if (in_array(self::get_week($_date), array(0, 1))) {105 ??????????//特殊工作日106 ??????????$dateData[‘exact_date‘] = $_date;107 ??????????$dateData[‘date_year‘] = $year;108 ??????????$dateData[‘date_type‘] = 1;109 ??????????$_ret = $m->add($dateData) ? 1 : 0;110 ??????????unset($dateData);111 ????????}112 ??????}113 114 ??????//法定节假日115 ??????if ($_ret_curl[‘data‘] == 2) {116 ????????$dateData[‘exact_date‘] = $_date;117 ????????$dateData[‘date_year‘] = $year;118 ????????$dateData[‘date_type‘] = 2;119 ????????$_ret = $m->add($dateData) ? 1 : 0;120 ????????unset($dateData);121 ??????}122 123 ??????//休息日(周末) 暂不处理124 ??????/*if ($_ret_curl[‘data‘] == 1) {125 126 ??????}*/127 128 ??????$_ret && $count++;129 ??????unset($_date, $_post_data, $_ret_curl, $_ret);130 ????}131 ????return $count;132 ??}133 134 135 ??/**136 ???* 获取当年所有工作日 (从数据库获取,数据库无数据则先更新数据)137 ???* @param string $year 当年年份138 ???* @return array139 ???*/140 ??private function getWorkDays($year)141 ??{142 ????$m = M(‘tb_workday‘);143 ????$map[‘date_year‘] = $year;144 ????$map[‘date_type‘] = 0;145 ????$DateArray = $m->field(‘exact_date‘)->where($map)->select();146 ????if (!empty($DateArray)) {147 ??????$DateArray = array_column($DateArray, ‘exact_date‘);148 ??????return $DateArray;149 ????} else {150 ??????//更新数据库工作日数据151 ??????$ret = self::updateDate($year);152 ??????if ($ret > 0) {153 ????????return self::getWorkDays($year);154 ??????} else {155 ????????return false;156 ??????}157 ????}158 ??}159 160 ??/**161 ???* 获取开始日期后第N个工作日具体日期162 ???* @param $startdate string 计算开始日期 ?需包含年月日信息163 ???* @param $days ?????int 间隔天数164 ???* @return mixed 成功返回 对应日期,失败返回false165 ???*/166 ??public function getNextWorkDate($startdate, $days)167 ??{168 ????$year = date(‘Y‘, strtotime($startdate));169 ????$startdate = date(‘Y-m-d‘, strtotime($startdate));170 ????$workDays = $this->getWorkDays($year);171 ????$search_key = array_search(date(‘Ymd‘, strtotime($startdate)), $workDays);172 ????if ($search_key === false) {//查询日期为非工作173 ??????//获取查询日期前最近工作日174 ??????$m = M(‘tb_workday‘);175 ??????$map[‘date_year‘] = $year;176 ??????$map[‘date_type‘] = 0;177 ??????$map[‘DATE_FORMAT(`exact_date`,\‘%Y-%m-%d\‘)‘] = array(‘LT‘, $startdate);178 ??????$_search_date = $m->where($map)->order(‘`exact_date` DESC‘)->getField(‘exact_date‘);179 ??????$search_key = array_search($_search_date, $workDays);180 ??????unset($m, $map, $_search_date);181 ????}182 ????$t_key = $search_key + $days;183 ????if ($t_key <= count($workDays) - 1) {184 ??????return date(‘Y-m-d‘, strtotime($workDays[$t_key]));185 ????} else {186 ??????//查询日期已跨年187 ??????$n_days = $days - (count($workDays) - 1 - $search_key);188 ??????$next_year = $year + 1;189 ??????return $this->getNextWorkDate($next_year . ‘-01-01‘, $n_days - 1);190 ????}191 ??}192 }193 194 $startdate = ‘2018-09-28‘;195 $days = 5;196 197 $class = new work_days();198 $_date_workday = $class->getNextWorkDate($startdate, $days);199 echo $_date_workday;//2018-10-10
ThinkPHP中如何获取指定日期后工作日的具体日期
原文地址:https://www.cnblogs.com/sgm4231/p/9796832.html