获取指定月份的所有星期,星期日至星期六的星期
Get all weeks of specified month, weeks from Sun-Sat
编辑
我直接在下面尝试了这段代码。已经接近了,但仍然没有找到从每个月的第一个星期日到第一个星期六的星期,然后从星期日到星期六之后的每个星期,直到最后一个星期日到月底。
function get_weeks($month, $year) {
$weeks = array();
$date = DateTime::createFromFormat('mY', $month.$year);
$date->modify('first day of this month');
$end = clone $date;
$end->modify('last day of this month');
$interval = DateInterval::createFromDateString('1 week');
$period = new DatePeriod($date, $interval, $end);
$counter = 1;
foreach ($period as $dt) {
$end_of_week = clone $dt;
$end_of_week->modify('this Saturday');
$weeks[] = sprintf("Week %u: %s - %s",
$counter,
$dt->format('Y-m-d'),
$end_of_week->format('Y-m-d')
);
$counter++;
}
return $weeks;
}
$weeks = get_weeks('08', '2020');
print_r($weeks);
它打印:
Array
(
[0] => Week 1: 2020-08-01 - 2020-08-01
[1] => Week 2: 2020-08-08 - 2020-08-08
[2] => Week 3: 2020-08-15 - 2020-08-15
[3] => Week 4: 2020-08-22 - 2020-08-22
[4] => Week 5: 2020-08-29 - 2020-08-29
)
但它应该打印:
Array
(
[0] => Week 1: 2020-08-01 - 2020-08-01 //correct for this month since 1st day of month and 1st Saturday of this month just happen to be on the same day
[1] => Week 2: 2020-08-02 - 2020-08-08
[2] => Week 3: 2020-08-09 - 2020-08-15
[3] => Week 4: 2020-08-16 - 2020-08-22
[4] => Week 5: 2020-08-23 - 2020-08-29
[5] => Week 6: 2020-08-30 - 2020-08-31 //last Sunday until end of month
)
原版POST
我的目标是提取指定月份的指定周数的时间戳数据。我在周日开始我的一周,在周六结束。因此,我试图将特定月份中每周的所有时间戳集中在一起,以便我可以将其绘制出来,显示每周的总小时数。但首先我需要为那个月指定的每个星期的开始和结束。我能够为特定一周的每个工作日执行此操作,但 week/month 设置对我来说太复杂了。
这是我的:
function task_range_month_week($monthweek, $cap_start_raw, $cap_end_raw) {
$start = new DateTime(date('Y-m-d',$cap_start_raw));
$end = new DateTime(date('Y-m-d',$cap_end_raw+86399));
$interval = DateInterval::createFromDateString('1 week');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
//just make it return the values for only a single (specified) week of the month
//if ($dt->format("N") == $monthweek) {
$cap_start = strtotime($dt->format("Y-m-d 00:00:00"));
$cap_end = strtotime($dt->format("Y-m-d 23:59:59"));
//}
}
然后我会像这样调用函数,其中 $cap_start_raw
和 $cap_end_raw
是月份的开始和结束日期,$monthweek
是指定的周数(1-6 ).因此,我正在尝试获取该特定周的周日至周六(或该月的任何部分工作日)的时间。
然后 $cap_start
和 $cap_end
将是指定周范围内的输出。
我想用这个调用那个函数:
//get the 1st week of August 2020, Sun 00:00:00 - Sat 11:59:59 (or whatever days of the month are still in this week)
task_range_month_week(1, 1596240000, 1598918399)
//this would output the 2 new timestamps for that week(1)
//$cap_start = 1XXXXXXXXX;
//$cap_end = 1XXXXXXXXX;
//get the 2nd week of August 2020, Sun 00:00:00 - Sat 11:59:59 (or whatever days of the month are still in this week)
task_range_month_week(2, 1596240000, 1598918399)
//this would output the 2 new timestamps for that week(2)
//$cap_start = 1XXXXXXXXX;
//$cap_end = 1XXXXXXXXX;
etc...
我认为它与 $dt->format()
部分有关,但不确定如何让它工作。
预期输出将 return $cap_start 和 $cap_end 时间戳值。
另一种说法是...
...它 return 是预期输出范围的新开始和结束时间戳。我为每个星期调用 task_range_month_week() 函数,我希望找到单个星期的开始和结束( $cap_start, $cap_end 输出)。因此,由于 2020 年 8 月的日子跨越 6 个不同的日历周,我将调用该函数 6 次,在本月的情况下,每次调用 $monthweek 指定 1-6。然后在该月的第 1 周的情况下,新的输出范围将在该月 1 日的 00:00:00 处具有 $cap_start,并且由于 $cap_end 恰好下降在星期六,也就是我想结束我的几周(从星期天开始)的时候,它应该在同一天在 23:59:59 输出 $cap_end。然后下一周将从周日到周六,依此类推,直到找到该月所有一周的开始和结束时间,第一周和最后一周的范围只有最大截止时间,即月份开始和结束时间。
如果我将它设置为“1 天”而不是“1 周”,并取消注释 if ($dt->format("N") == $monthweek)
那么当我执行指定周的几天时它会起作用,我已经为该图表设置了这些天。但是如何使其适用于周设置?
有什么想法吗?
我有一个函数可以根据特定月份和年份中的特定周数 (1-6),将周开始日期和结束日期作为 DateTime 对象数组提供。函数returns出错时为NULL。
function datesWeekInMonth(int $monthWeekNumber, int $month, int $year):?array {
//week from Sun to Sat !
$sat = date_create('first Sat of '.$year.'-'.$month);
if($monthWeekNumber < 1 OR $sat === false) return NULL;
if($monthWeekNumber == 1) return [date_create($year.'-'.$month.'-01'),$sat];
$lastDayOfMonth = date_create('last Day of '.$year.'-'.$month);
for($i=1;$i<$monthWeekNumber;$i++) {
$sun = (clone $sat)->modify('+1 Day');
$sat->modify('next Sat');
}
if($sun > $lastDayOfMonth) return NULL;
return [$sun,min($sat,$lastDayOfMonth)];
}
用法示例:
$result = datesWeekInMonth(3,8,2020); //third week of August 2020
var_dump($result);
/*
array(2) {
[0]=>
object(DateTime)#4 (3) {
["date"]=>
string(26) "2020-08-09 00:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
[1]=>
object(DateTime)#1 (3) {
["date"]=>
string(26) "2020-08-15 00:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
}
*/
我决定从算术的角度而不是日期时间的角度来完成这项任务。
也许有一种我没有考虑过的优雅的日期时间对象变异技术,但我不认为我的 function-call-light 方法是可怕的。
我相信我的变量命名将通过我的脚本提供足够的逻辑指导,但实际上我将给定一周的开始和结束日期增加 variable/calulated 数量,并在所有代表了整个月的天数。
代码:(Demo)
function get_weeks($month, $year) {
$weeks = [];
$ym = $year . '-' . $month;
$final = date('t', strtotime($ym));
$firstSat = date('d', strtotime("first Saturday of $ym"));
$d = 1;
$weekNo = 0;
do {
$weekEnd = $d === 1 ? $firstSat : min($final, $d + 6);
$weeks[] = sprintf(
"Week %d: %s-%02d - %s-%02d",
++$weekNo,
$ym,
$d,
$ym,
$weekEnd
);
$d = $weekEnd + 1;
} while ($weekEnd < $final);
return $weeks;
}
foreach (['01','02','03','04','05','06', '07', '08', '09', '10', '11', '12'] as $month) {
echo var_export(get_weeks($month, '2020'), true) . "\n";
}
输出:
array (
0 => 'Week 1: 2020-01-01 - 2020-01-04',
1 => 'Week 2: 2020-01-05 - 2020-01-11',
2 => 'Week 3: 2020-01-12 - 2020-01-18',
3 => 'Week 4: 2020-01-19 - 2020-01-25',
4 => 'Week 5: 2020-01-26 - 2020-01-31',
)
array (
0 => 'Week 1: 2020-02-01 - 2020-02-01',
1 => 'Week 2: 2020-02-02 - 2020-02-08',
2 => 'Week 3: 2020-02-09 - 2020-02-15',
3 => 'Week 4: 2020-02-16 - 2020-02-22',
4 => 'Week 5: 2020-02-23 - 2020-02-29',
)
array (
0 => 'Week 1: 2020-03-01 - 2020-03-07',
1 => 'Week 2: 2020-03-08 - 2020-03-14',
2 => 'Week 3: 2020-03-15 - 2020-03-21',
3 => 'Week 4: 2020-03-22 - 2020-03-28',
4 => 'Week 5: 2020-03-29 - 2020-03-31',
)
array (
0 => 'Week 1: 2020-04-01 - 2020-04-04',
1 => 'Week 2: 2020-04-05 - 2020-04-11',
2 => 'Week 3: 2020-04-12 - 2020-04-18',
3 => 'Week 4: 2020-04-19 - 2020-04-25',
4 => 'Week 5: 2020-04-26 - 2020-04-30',
)
array (
0 => 'Week 1: 2020-05-01 - 2020-05-02',
1 => 'Week 2: 2020-05-03 - 2020-05-09',
2 => 'Week 3: 2020-05-10 - 2020-05-16',
3 => 'Week 4: 2020-05-17 - 2020-05-23',
4 => 'Week 5: 2020-05-24 - 2020-05-30',
5 => 'Week 6: 2020-05-31 - 2020-05-31',
)
array (
0 => 'Week 1: 2020-06-01 - 2020-06-06',
1 => 'Week 2: 2020-06-07 - 2020-06-13',
2 => 'Week 3: 2020-06-14 - 2020-06-20',
3 => 'Week 4: 2020-06-21 - 2020-06-27',
4 => 'Week 5: 2020-06-28 - 2020-06-30',
)
array (
0 => 'Week 1: 2020-07-01 - 2020-07-04',
1 => 'Week 2: 2020-07-05 - 2020-07-11',
2 => 'Week 3: 2020-07-12 - 2020-07-18',
3 => 'Week 4: 2020-07-19 - 2020-07-25',
4 => 'Week 5: 2020-07-26 - 2020-07-31',
)
array (
0 => 'Week 1: 2020-08-01 - 2020-08-01',
1 => 'Week 2: 2020-08-02 - 2020-08-08',
2 => 'Week 3: 2020-08-09 - 2020-08-15',
3 => 'Week 4: 2020-08-16 - 2020-08-22',
4 => 'Week 5: 2020-08-23 - 2020-08-29',
5 => 'Week 6: 2020-08-30 - 2020-08-31',
)
array (
0 => 'Week 1: 2020-09-01 - 2020-09-05',
1 => 'Week 2: 2020-09-06 - 2020-09-12',
2 => 'Week 3: 2020-09-13 - 2020-09-19',
3 => 'Week 4: 2020-09-20 - 2020-09-26',
4 => 'Week 5: 2020-09-27 - 2020-09-30',
)
array (
0 => 'Week 1: 2020-10-01 - 2020-10-03',
1 => 'Week 2: 2020-10-04 - 2020-10-10',
2 => 'Week 3: 2020-10-11 - 2020-10-17',
3 => 'Week 4: 2020-10-18 - 2020-10-24',
4 => 'Week 5: 2020-10-25 - 2020-10-31',
)
array (
0 => 'Week 1: 2020-11-01 - 2020-11-07',
1 => 'Week 2: 2020-11-08 - 2020-11-14',
2 => 'Week 3: 2020-11-15 - 2020-11-21',
3 => 'Week 4: 2020-11-22 - 2020-11-28',
4 => 'Week 5: 2020-11-29 - 2020-11-30',
)
array (
0 => 'Week 1: 2020-12-01 - 2020-12-05',
1 => 'Week 2: 2020-12-06 - 2020-12-12',
2 => 'Week 3: 2020-12-13 - 2020-12-19',
3 => 'Week 4: 2020-12-20 - 2020-12-26',
4 => 'Week 5: 2020-12-27 - 2020-12-31',
)
编辑
我直接在下面尝试了这段代码。已经接近了,但仍然没有找到从每个月的第一个星期日到第一个星期六的星期,然后从星期日到星期六之后的每个星期,直到最后一个星期日到月底。
function get_weeks($month, $year) {
$weeks = array();
$date = DateTime::createFromFormat('mY', $month.$year);
$date->modify('first day of this month');
$end = clone $date;
$end->modify('last day of this month');
$interval = DateInterval::createFromDateString('1 week');
$period = new DatePeriod($date, $interval, $end);
$counter = 1;
foreach ($period as $dt) {
$end_of_week = clone $dt;
$end_of_week->modify('this Saturday');
$weeks[] = sprintf("Week %u: %s - %s",
$counter,
$dt->format('Y-m-d'),
$end_of_week->format('Y-m-d')
);
$counter++;
}
return $weeks;
}
$weeks = get_weeks('08', '2020');
print_r($weeks);
它打印:
Array
(
[0] => Week 1: 2020-08-01 - 2020-08-01
[1] => Week 2: 2020-08-08 - 2020-08-08
[2] => Week 3: 2020-08-15 - 2020-08-15
[3] => Week 4: 2020-08-22 - 2020-08-22
[4] => Week 5: 2020-08-29 - 2020-08-29
)
但它应该打印:
Array
(
[0] => Week 1: 2020-08-01 - 2020-08-01 //correct for this month since 1st day of month and 1st Saturday of this month just happen to be on the same day
[1] => Week 2: 2020-08-02 - 2020-08-08
[2] => Week 3: 2020-08-09 - 2020-08-15
[3] => Week 4: 2020-08-16 - 2020-08-22
[4] => Week 5: 2020-08-23 - 2020-08-29
[5] => Week 6: 2020-08-30 - 2020-08-31 //last Sunday until end of month
)
原版POST
我的目标是提取指定月份的指定周数的时间戳数据。我在周日开始我的一周,在周六结束。因此,我试图将特定月份中每周的所有时间戳集中在一起,以便我可以将其绘制出来,显示每周的总小时数。但首先我需要为那个月指定的每个星期的开始和结束。我能够为特定一周的每个工作日执行此操作,但 week/month 设置对我来说太复杂了。
这是我的:
function task_range_month_week($monthweek, $cap_start_raw, $cap_end_raw) {
$start = new DateTime(date('Y-m-d',$cap_start_raw));
$end = new DateTime(date('Y-m-d',$cap_end_raw+86399));
$interval = DateInterval::createFromDateString('1 week');
$period = new DatePeriod($start, $interval, $end);
foreach ($period as $dt) {
//just make it return the values for only a single (specified) week of the month
//if ($dt->format("N") == $monthweek) {
$cap_start = strtotime($dt->format("Y-m-d 00:00:00"));
$cap_end = strtotime($dt->format("Y-m-d 23:59:59"));
//}
}
然后我会像这样调用函数,其中 $cap_start_raw
和 $cap_end_raw
是月份的开始和结束日期,$monthweek
是指定的周数(1-6 ).因此,我正在尝试获取该特定周的周日至周六(或该月的任何部分工作日)的时间。
然后 $cap_start
和 $cap_end
将是指定周范围内的输出。
我想用这个调用那个函数:
//get the 1st week of August 2020, Sun 00:00:00 - Sat 11:59:59 (or whatever days of the month are still in this week)
task_range_month_week(1, 1596240000, 1598918399)
//this would output the 2 new timestamps for that week(1)
//$cap_start = 1XXXXXXXXX;
//$cap_end = 1XXXXXXXXX;
//get the 2nd week of August 2020, Sun 00:00:00 - Sat 11:59:59 (or whatever days of the month are still in this week)
task_range_month_week(2, 1596240000, 1598918399)
//this would output the 2 new timestamps for that week(2)
//$cap_start = 1XXXXXXXXX;
//$cap_end = 1XXXXXXXXX;
etc...
我认为它与 $dt->format()
部分有关,但不确定如何让它工作。
预期输出将 return $cap_start 和 $cap_end 时间戳值。
另一种说法是...
...它 return 是预期输出范围的新开始和结束时间戳。我为每个星期调用 task_range_month_week() 函数,我希望找到单个星期的开始和结束( $cap_start, $cap_end 输出)。因此,由于 2020 年 8 月的日子跨越 6 个不同的日历周,我将调用该函数 6 次,在本月的情况下,每次调用 $monthweek 指定 1-6。然后在该月的第 1 周的情况下,新的输出范围将在该月 1 日的 00:00:00 处具有 $cap_start,并且由于 $cap_end 恰好下降在星期六,也就是我想结束我的几周(从星期天开始)的时候,它应该在同一天在 23:59:59 输出 $cap_end。然后下一周将从周日到周六,依此类推,直到找到该月所有一周的开始和结束时间,第一周和最后一周的范围只有最大截止时间,即月份开始和结束时间。
如果我将它设置为“1 天”而不是“1 周”,并取消注释 if ($dt->format("N") == $monthweek)
那么当我执行指定周的几天时它会起作用,我已经为该图表设置了这些天。但是如何使其适用于周设置?
有什么想法吗?
我有一个函数可以根据特定月份和年份中的特定周数 (1-6),将周开始日期和结束日期作为 DateTime 对象数组提供。函数returns出错时为NULL。
function datesWeekInMonth(int $monthWeekNumber, int $month, int $year):?array {
//week from Sun to Sat !
$sat = date_create('first Sat of '.$year.'-'.$month);
if($monthWeekNumber < 1 OR $sat === false) return NULL;
if($monthWeekNumber == 1) return [date_create($year.'-'.$month.'-01'),$sat];
$lastDayOfMonth = date_create('last Day of '.$year.'-'.$month);
for($i=1;$i<$monthWeekNumber;$i++) {
$sun = (clone $sat)->modify('+1 Day');
$sat->modify('next Sat');
}
if($sun > $lastDayOfMonth) return NULL;
return [$sun,min($sat,$lastDayOfMonth)];
}
用法示例:
$result = datesWeekInMonth(3,8,2020); //third week of August 2020
var_dump($result);
/*
array(2) {
[0]=>
object(DateTime)#4 (3) {
["date"]=>
string(26) "2020-08-09 00:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
[1]=>
object(DateTime)#1 (3) {
["date"]=>
string(26) "2020-08-15 00:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(13) "Europe/Berlin"
}
}
*/
我决定从算术的角度而不是日期时间的角度来完成这项任务。
也许有一种我没有考虑过的优雅的日期时间对象变异技术,但我不认为我的 function-call-light 方法是可怕的。
我相信我的变量命名将通过我的脚本提供足够的逻辑指导,但实际上我将给定一周的开始和结束日期增加 variable/calulated 数量,并在所有代表了整个月的天数。
代码:(Demo)
function get_weeks($month, $year) {
$weeks = [];
$ym = $year . '-' . $month;
$final = date('t', strtotime($ym));
$firstSat = date('d', strtotime("first Saturday of $ym"));
$d = 1;
$weekNo = 0;
do {
$weekEnd = $d === 1 ? $firstSat : min($final, $d + 6);
$weeks[] = sprintf(
"Week %d: %s-%02d - %s-%02d",
++$weekNo,
$ym,
$d,
$ym,
$weekEnd
);
$d = $weekEnd + 1;
} while ($weekEnd < $final);
return $weeks;
}
foreach (['01','02','03','04','05','06', '07', '08', '09', '10', '11', '12'] as $month) {
echo var_export(get_weeks($month, '2020'), true) . "\n";
}
输出:
array (
0 => 'Week 1: 2020-01-01 - 2020-01-04',
1 => 'Week 2: 2020-01-05 - 2020-01-11',
2 => 'Week 3: 2020-01-12 - 2020-01-18',
3 => 'Week 4: 2020-01-19 - 2020-01-25',
4 => 'Week 5: 2020-01-26 - 2020-01-31',
)
array (
0 => 'Week 1: 2020-02-01 - 2020-02-01',
1 => 'Week 2: 2020-02-02 - 2020-02-08',
2 => 'Week 3: 2020-02-09 - 2020-02-15',
3 => 'Week 4: 2020-02-16 - 2020-02-22',
4 => 'Week 5: 2020-02-23 - 2020-02-29',
)
array (
0 => 'Week 1: 2020-03-01 - 2020-03-07',
1 => 'Week 2: 2020-03-08 - 2020-03-14',
2 => 'Week 3: 2020-03-15 - 2020-03-21',
3 => 'Week 4: 2020-03-22 - 2020-03-28',
4 => 'Week 5: 2020-03-29 - 2020-03-31',
)
array (
0 => 'Week 1: 2020-04-01 - 2020-04-04',
1 => 'Week 2: 2020-04-05 - 2020-04-11',
2 => 'Week 3: 2020-04-12 - 2020-04-18',
3 => 'Week 4: 2020-04-19 - 2020-04-25',
4 => 'Week 5: 2020-04-26 - 2020-04-30',
)
array (
0 => 'Week 1: 2020-05-01 - 2020-05-02',
1 => 'Week 2: 2020-05-03 - 2020-05-09',
2 => 'Week 3: 2020-05-10 - 2020-05-16',
3 => 'Week 4: 2020-05-17 - 2020-05-23',
4 => 'Week 5: 2020-05-24 - 2020-05-30',
5 => 'Week 6: 2020-05-31 - 2020-05-31',
)
array (
0 => 'Week 1: 2020-06-01 - 2020-06-06',
1 => 'Week 2: 2020-06-07 - 2020-06-13',
2 => 'Week 3: 2020-06-14 - 2020-06-20',
3 => 'Week 4: 2020-06-21 - 2020-06-27',
4 => 'Week 5: 2020-06-28 - 2020-06-30',
)
array (
0 => 'Week 1: 2020-07-01 - 2020-07-04',
1 => 'Week 2: 2020-07-05 - 2020-07-11',
2 => 'Week 3: 2020-07-12 - 2020-07-18',
3 => 'Week 4: 2020-07-19 - 2020-07-25',
4 => 'Week 5: 2020-07-26 - 2020-07-31',
)
array (
0 => 'Week 1: 2020-08-01 - 2020-08-01',
1 => 'Week 2: 2020-08-02 - 2020-08-08',
2 => 'Week 3: 2020-08-09 - 2020-08-15',
3 => 'Week 4: 2020-08-16 - 2020-08-22',
4 => 'Week 5: 2020-08-23 - 2020-08-29',
5 => 'Week 6: 2020-08-30 - 2020-08-31',
)
array (
0 => 'Week 1: 2020-09-01 - 2020-09-05',
1 => 'Week 2: 2020-09-06 - 2020-09-12',
2 => 'Week 3: 2020-09-13 - 2020-09-19',
3 => 'Week 4: 2020-09-20 - 2020-09-26',
4 => 'Week 5: 2020-09-27 - 2020-09-30',
)
array (
0 => 'Week 1: 2020-10-01 - 2020-10-03',
1 => 'Week 2: 2020-10-04 - 2020-10-10',
2 => 'Week 3: 2020-10-11 - 2020-10-17',
3 => 'Week 4: 2020-10-18 - 2020-10-24',
4 => 'Week 5: 2020-10-25 - 2020-10-31',
)
array (
0 => 'Week 1: 2020-11-01 - 2020-11-07',
1 => 'Week 2: 2020-11-08 - 2020-11-14',
2 => 'Week 3: 2020-11-15 - 2020-11-21',
3 => 'Week 4: 2020-11-22 - 2020-11-28',
4 => 'Week 5: 2020-11-29 - 2020-11-30',
)
array (
0 => 'Week 1: 2020-12-01 - 2020-12-05',
1 => 'Week 2: 2020-12-06 - 2020-12-12',
2 => 'Week 3: 2020-12-13 - 2020-12-19',
3 => 'Week 4: 2020-12-20 - 2020-12-26',
4 => 'Week 5: 2020-12-27 - 2020-12-31',
)