最近在做大数据统计分析需求,经常会用到一些统计,比如,周统计,环比等 ,下面我们来计算一年有多少个 自然 周,直接上代码吧:
/**
* 获取一年每周的开始日期和结束日期
* @param $year
* @return array
*/
public function get_week($year)
{
$whole_week = $this->get_big_week($year);//获取最大周数
$str = '';
for ($i = 1; $i <= $whole_week; $i++) {
$str .= $i . ',';
}
$str_arr = explode(',', rtrim($str, ','));//转成数组
$week_list = array();
foreach ($str_arr as $key => $value) {
$week = $this->get_year_month_week($year, $value);//一周的日期
$week_list[$value] = [
0 => $week[0],
1 => $week[6],
];
}
$firstWeek = $week_list[1];// 第一周
$firstWeekDay = date('d',strtotime($firstWeek[0]));
$firstYear = date('Y',strtotime($firstWeek[0]));
$endYear = date('Y',strtotime($firstWeek[1]));
$addWeek = $newWeekList = [];
if($firstWeekDay > 1){
if($firstYear != $endYear){ //跨年
$week_list[1][0]= date('Y-m-d' ,mktime(0, 0, 0, 1,1, date($year)));
$newWeekList = $week_list;
} else { //不跨年
$addWeek = [
0 => date('Y-m-d' ,mktime(0, 0, 0, 1,1, date($year))),
1 => date('Y-m-d', strtotime($firstWeek[0]) - 24 *3600),
];
$newWeekList = $this->add_week($addWeek, $week_list);
}
} else {
$newWeekList = $week_list;
}
$endWeek = end($newWeekList);// 最后一周
$endWeekYear = date('Y',strtotime($endWeek[1]));
$startWeekYear = date('Y',strtotime($endWeek[0]));
$currentYear = date('Y',time());
if($endWeekYear != $currentYear){ //跨年了
$lastday = date("Y-m-t", strtotime('next month', strtotime("{$currentYear}-11-01")));
$weekNum = count($newWeekList);
foreach($newWeekList as $key=>&$week){
if($weekNum == $key){
$week[1] = $lastday;
}
}
$endWeek[1] = date('Y-m-t', strtotime($year."-12-01"));
}
$weekNum = count($newWeekList);
$newWeekList[$weekNum][1] = date('Y-m-t', strtotime($year."-12-01"));
return $newWeekList;
}
public function add_week($addWeek, $week_list){
if(!$addWeek) return $week_list;
$newWeekList = [];
$week_list = array_merge([$addWeek],$week_list);
foreach($week_list as $key=>$week){
$newWeekList[$key+1] = $week;
}
return $newWeekList;
}
public function get_date($return, $string, $date)
{
if (empty($return)) {
$return = "Y-m-d";
}
if (empty($string)) {
$string = "now";
}
if (empty($date)) {
$date = time();
} else {
$date = strtotime(date($date));
}
if (preg_match("/month/", $string)) {
$first_day_of_month = date('Y-m', $date) . '-01';
$str_date = strtotime($first_day_of_month);
}
if (preg_match("/month/", $string)) {
$l_date = date("Y-m-d", strtotime($string, $str_date));
$day = substr(date("Y-m-d", $date), 8, 2);
if (substr($l_date, 0, 7) . '-' . date('t', strtotime(substr($l_date, 0, 7))) < substr($l_date, 0, 7) . '-' . $day) {
$l_date = substr($l_date, 0, 7) . '-' . date('t', strtotime(substr($l_date, 0, 7)));
} else {
$l_date = substr($l_date, 0, 7) . '-' . $day;
}
$l_date = date($return, strtotime($l_date));
return $l_date;
} else {
return date($return, strtotime($string, $date));
}
}
public function get_big_week($year_now)
{
$big_week = $this->get_date("W", NULL, $year_now . '-12-31');
if ($big_week == 1) {
$big_week = $this->get_date("W", NULL, $year_now . '-12-30');
}
if ($big_week == 1) {
$big_week = $this->get_date("W", NULL, $year_now . '-12-29');
}
if ($big_week == 1) {
$big_week = $this->get_date("W", NULL, $year_now . '-12-28');
}
if ($big_week == 1) {
$big_week = $this->get_date("W", NULL, $year_now . '-12-27');
}
if ($big_week == 1) {
$big_week = $this->get_date("W", NULL, $year_now . '-12-26');
}
if ($big_week == 1) {
$big_week = $this->get_date("W", NULL, $year_now . '-12-25');
}
if ($big_week == 1) {
$big_week = $this->get_date("W", NULL, $year_now . '-12-24');
}
return $big_week;
}
public function get_year_month_week($year_now, $week_now)
{
//指定年和周的日期数组
$time = new \DateTime();
$time->setISODate($year_now, $week_now, 1);
$result[] = $time->format('Y-m-d');
$time->setISODate($year_now, $week_now, 2);
$result[] = $time->format('Y-m-d');
$time->setISODate($year_now, $week_now, 3);
$result[] = $time->format('Y-m-d');
$time->setISODate($year_now, $week_now, 4);
$result[] = $time->format('Y-m-d');
$time->setISODate($year_now, $week_now, 5);
$result[] = $time->format('Y-m-d');
$time->setISODate($year_now, $week_now, 6);
$result[] = $time->format('Y-m-d');
$time->setISODate($year_now, $week_now, 7);
$result[] = $time->format('Y-m-d');
return $result;
}
/**
* 获取当前周的起止时间
* @param $currentWeek
* @param $weeklist
* @return int|string
*/
public function setCurrentWeek($currentWeek, $weeklist) {
if(!$weeklist || !$currentWeek) return 1;
$week_start = $currentWeek['week_start'];
foreach($weeklist as $key=>$week){
if($week_start == $week[0]){
return $key;
}
}
}
/*PHP获取当前日期是第几周和本周开始日期和本周结束日期*/
public function getNowTimeInfo($now) {
$str = array();
//$first =1 表示每周星期一为开始日期 0表示每周日为开始日期
$str['year'] = date('Y', strtotime($now));
$first = 1;
//当日在整年中的第几周
$str['week'] = date('W', strtotime($now));
//获取当前周的第几天 周日是 0 周一到周六是 1 - 6
$w = date('w', strtotime($now));
//获取本周开始日期,如果$w是0,则表示周日,减去 6 天
$week_start = date('Y-m-d', strtotime("$now -" . ($w ? $w - $first : 6) . ' days'));
$str['week_start'] = $week_start;
//本周结束日期
$week_end = date('Y-m-d', strtotime("$week_start +6 days"));
$str['week_end'] = $week_end;
return $str;
}
这样我们就可以获取当前是第几周,以及起止时间:
$weekFormat = new WeekFormatLogic();
$date = date("Y-m-d",time());
$currentWeek = $weekFormat->getNowTimeInfo($date);
$year = date("Y",time());
$weeklist = $weekFormat->get_week($year);
return $weekFormat->setCurrentWeek($currentWeek, $weeklist);
可以看到当前是滴29周:
起止时间为:
Array
(
[week_start] => 2021-07-12
[week_end] => 2021-07-18
)
全部周的起止时间:
Array
(
[1] => Array
(
[0] => 2021-01-01
[1] => 2021-01-03
)
[2] => Array
(
[0] => 2021-01-04
[1] => 2021-01-10
)
[3] => Array
(
[0] => 2021-01-11
[1] => 2021-01-17
)
[4] => Array
(
[0] => 2021-01-18
[1] => 2021-01-24
)
[5] => Array
(
[0] => 2021-01-25
[1] => 2021-01-31
)
[6] => Array
(
[0] => 2021-02-01
[1] => 2021-02-07
)
[7] => Array
(
[0] => 2021-02-08
[1] => 2021-02-14
)
[8] => Array
(
[0] => 2021-02-15
[1] => 2021-02-21
)
[9] => Array
(
[0] => 2021-02-22
[1] => 2021-02-28
)
[10] => Array
(
[0] => 2021-03-01
[1] => 2021-03-07
)
[11] => Array
(
[0] => 2021-03-08
[1] => 2021-03-14
)
[12] => Array
(
[0] => 2021-03-15
[1] => 2021-03-21
)
[13] => Array
(
[0] => 2021-03-22
[1] => 2021-03-28
)
[14] => Array
(
[0] => 2021-03-29
[1] => 2021-04-04
)
[15] => Array
(
[0] => 2021-04-05
[1] => 2021-04-11
)
[16] => Array
(
[0] => 2021-04-12
[1] => 2021-04-18
)
[17] => Array
(
[0] => 2021-04-19
[1] => 2021-04-25
)
[18] => Array
(
[0] => 2021-04-26
[1] => 2021-05-02
)
[19] => Array
(
[0] => 2021-05-03
[1] => 2021-05-09
)
[20] => Array
(
[0] => 2021-05-10
[1] => 2021-05-16
)
[21] => Array
(
[0] => 2021-05-17
[1] => 2021-05-23
)
[22] => Array
(
[0] => 2021-05-24
[1] => 2021-05-30
)
[23] => Array
(
[0] => 2021-05-31
[1] => 2021-06-06
)
[24] => Array
(
[0] => 2021-06-07
[1] => 2021-06-13
)
[25] => Array
(
[0] => 2021-06-14
[1] => 2021-06-20
)
[26] => Array
(
[0] => 2021-06-21
[1] => 2021-06-27
)
[27] => Array
(
[0] => 2021-06-28
[1] => 2021-07-04
)
[28] => Array
(
[0] => 2021-07-05
[1] => 2021-07-11
)
[29] => Array
(
[0] => 2021-07-12
[1] => 2021-07-18
)
[30] => Array
(
[0] => 2021-07-19
[1] => 2021-07-25
)
[31] => Array
(
[0] => 2021-07-26
[1] => 2021-08-01
)
[32] => Array
(
[0] => 2021-08-02
[1] => 2021-08-08
)
[33] => Array
(
[0] => 2021-08-09
[1] => 2021-08-15
)
[34] => Array
(
[0] => 2021-08-16
[1] => 2021-08-22
)
[35] => Array
(
[0] => 2021-08-23
[1] => 2021-08-29
)
[36] => Array
(
[0] => 2021-08-30
[1] => 2021-09-05
)
[37] => Array
(
[0] => 2021-09-06
[1] => 2021-09-12
)
[38] => Array
(
[0] => 2021-09-13
[1] => 2021-09-19
)
[39] => Array
(
[0] => 2021-09-20
[1] => 2021-09-26
)
[40] => Array
(
[0] => 2021-09-27
[1] => 2021-10-03
)
[41] => Array
(
[0] => 2021-10-04
[1] => 2021-10-10
)
[42] => Array
(
[0] => 2021-10-11
[1] => 2021-10-17
)
[43] => Array
(
[0] => 2021-10-18
[1] => 2021-10-24
)
[44] => Array
(
[0] => 2021-10-25
[1] => 2021-10-31
)
[45] => Array
(
[0] => 2021-11-01
[1] => 2021-11-07
)
[46] => Array
(
[0] => 2021-11-08
[1] => 2021-11-14
)
[47] => Array
(
[0] => 2021-11-15
[1] => 2021-11-21
)
[48] => Array
(
[0] => 2021-11-22
[1] => 2021-11-28
)
[49] => Array
(
[0] => 2021-11-29
[1] => 2021-12-05
)
[50] => Array
(
[0] => 2021-12-06
[1] => 2021-12-12
)
[51] => Array
(
[0] => 2021-12-13
[1] => 2021-12-19
)
[52] => Array
(
[0] => 2021-12-20
[1] => 2021-12-26
)
[53] => Array
(
[0] => 2021-12-27
[1] => 2021-12-31
)
)
当然了,这里计算的时候是从元旦开始计算的,起止周可能不满足7天,中间其他的周都是正常的