$yearData = [2016,2017,2018,2019,2020,2021,2022];
$monthDay = '02-29';
foreach($yearData as $ayKey=>$ayVal){
$tempDateData = _isDateValid($ayVal.'-'.$monthDay);
$sDate = [];
if($ayKey == 0){
$sDate = $ayVal.'-'.$monthDay;
}else{
$sDate = $ayVal.'-'.date('m-d',strtotime($ayVal.'-'.$tempDateData[$ayVal]['e_m']." +1 day"));
}
$dateData = [];
$res[] = _isDateValid($sDate);
}
print_r($res);
/**
* 算出一年时间的日期跨度,支持闰年2月29日情况的筛选
* eg: 2016年2月29日-2027年2月28日
* @param [type] $date [description]
* @param array $formats [description]
* @return boolean [description]
*/
function _isDateValid($date, $formats = ['Y-m-d']){
$unixTime = strtotime($date);
if(!$unixTime) { //无法用strtotime转换,说明日期格式非法
list($y, $m, $d) = explode('-', $date);
$tempDate1 = date('Y-m-d',strtotime(date("$y-m-d", strtotime("$date"))));
$unixTime = strtotime($tempDate1);
}
//校验日期合法性
foreach ($formats as $format) {
if(date($format, $unixTime) == $date) {
list($y) = explode('-',$date);
$timeDate = strtotime($date);
return ["$y"=>['s_m'=>date("m-d",$timeDate),'e_m'=>date("m-d",strtotime($date." +1 year -1 day"))]];
}else{
//不合法日期进行转换
list($y, $m, $d) = explode('-', $date);
$tempDate2 = date('Y-m-d',strtotime(date("$y-m-d", strtotime("$date"))));
return _isDateValid($tempDate2);
}
}
return [];
}
![]()
/**
* 服务:将时间段按天进行分割
* @param int $startDate @起始日期
* @param int $endDate @结束日期
* @return array $timesInlineArray
*/
function _dateSegmentation($startDate, $endDate)
{
if(!_isTimestamp((int)$startDate) || !_isTimestamp((int)$endDate)){
return;
}
//如果为空,则从今天的0点为开始时间
$startDate = date('Y-m-d H:i:s',$startDate);
//如果为空,则以明天的0点为结束时间(不存在24:00:00,只会有00:00:00)
$endDate = date('Y-m-d H:i:s',$endDate);
//between 查询 要求必须是从低到高
if($startDate > $endDate){
$ttt = $startDate;
$startDate = $endDate;
$endDate = $ttt;
}
$timeS = strtotime($startDate);
$timeE = strtotime($endDate);
$secondsInaDay = 86400;
//生成中间时间点数组(时间戳格式、日期时间格式、日期序列)
$timesInlineArray = array();
$timesInlineArray[0] = $timeS; //初始化第一个时间点
if(date('Y-m-d',$timeS) != date('Y-m-d',$timeE)){
/**
* A.取开始时间的第二天凌晨0点
* B.用结束时间减去A
* C.用B除86400取商,取余
* D.用A按C的商循环+86400,取得分割时间点,如果C没有余数,则最后一个时间点 与 循环最后一个时间点一致
*/
$ATemp = date('Y-m-d 00:00:00',$timeS+$secondsInaDay);
$A = strtotime($ATemp);
$B = $timeE-$A;
//商舍去法取整
$CQuotient = floor($B/$secondsInaDay);
//余数
$CRemainder = fmod($B,$secondsInaDay);
$timesInlineArray[1] = $A;
for($increaseTime = $A,$cCountT = 1;$cCountT <= $CQuotient;$cCountT++)
{
$increaseTime += $secondsInaDay;
$timesInlineArray[] = $increaseTime;
}
}
return $timesInlineArray;
}
function _isTimestamp($timestamp) {
if(strtotime(date('Y-m-d H:i:s',$timestamp)) === $timestamp) {
return $timestamp;
} else return false;
}
![]()
/**
* 算出N个数的最大公约数
* 最大公约数求法:
* 以三个数,其实很简单,就是求取前两个数的最大公约数,
* 再求这个最大公约数和第三个数的最大公约数,
* 最后得出的那个数就是这三个数的最大公约数
*/
$a = [10,20,50];
$n = count($a);
$cc = '';
for ($i=0; $i <= $n-1; $i++) {
if($i == 0){
$cc = maxCommonDivisor($a[$i], $a[$i+1]);
}else if($i == $n-1){
$cc = maxCommonDivisor($cc, $a[$i]);
}else{
$cc = maxCommonDivisor($cc, $a[$i+1]);
}
}
/**
* 辗转相除法:又名欧几里德算法。辗转相除法的核心就是不断的让两个数做除法运算。
* 其原理基于两个整数的最大公约数等于其中较小的数和两数的相除余数的最大公约数。
**/
function maxCommonDivisor($x,$y){
$a = $b = $temp = '';
$a = $x;
$b = $y;
//如果a<b,则调换位置
if ($a < $b){
$temp = $a;
$a = $b;
$b = $temp;
}
//当a除以b的余数不等于0,将较小的数取出来除以余数
while($a % $b != 0){
$c = $a % $b;
$a = $b;
$b = $c;
}
return $b;
}
//创建多级目录
function Directory( $dir ){
return is_dir ( $dir ) or Directory(dirname( $dir )) and mkdir ( $dir , 0777);
}