I have a function that can return first day and last day of a week based on date range given but apparently I got some problems in the function as it will return 8 days per week in an array and how can I set the end date of a week to Sunday as now the end date is Monday.
PHP:
private function rangeWeek(string $start,string $end): array
{
$start = new DateTime($start);
$end = new DateTime($end);
$interval = new DateInterval('P1D');
$period = new DatePeriod($start, $interval, $end);
$weeks = [];
$oldWeek = null;
$weekStart = null;
foreach ($period as $date) {
$week = $date->format('W');
if ($week !== $oldWeek) {
if (null === $weekStart) {
$oldWeek = $week;
$weekStart = $date->format('Y-m-d');
} else {
$weeks[] = ['start' => $weekStart, 'end' => $date->format('Y-m-d'), 'week' => $week];
$weekStart = null;
}
continue;
}
}
$weeks[] = ['start' => $weekStart, 'end' => $end->format('Y-m-d'), 'week' => $week];
return $weeks;
}
$startDate = '2022-08-08'; //Monday
$endDate = '2022-08-23'; //Tuesday
$weeks = rangeWeek($startDate, $endDate);
print_r($weeks);
Output:
Array
(
[0] => Array //This array return 8 days per week
(
[start] => 2022-08-08 //Monday
[end] => 2022-08-15 //Monday (should be end on Sunday)
[week] => 33
)
[1] => Array
(
[start] => 2022-08-16 //Tuesday (Should be start on Monday)
[end] => 2022-08-22 //Monday (should be end on Sunday)
[week] => 34
)
[2] => Array
(
[start] => null
[end] => 2022-08-23
[week] => 34
)
)
Expected Output:
Array
(
[0] => Array
(
[start] => 2022-08-08 //Monday
[end] => 2022-08-14 //Sunday
[week] => 33
)
[1] => Array
(
[start] => 2022-08-15 //Monday
[end] => 2022-08-21 //Sunday
[week] => 34
)
[2] => Array
(
[start] => 2022-08-22 //Monday
[end] => 2022-08-23 //Tuesday
[week] => 35
)
)
CodePudding user response:
I'm adding a simple post here with a PHP method that has helped me. This method calculates the beginning and ending of a week given the year and week number
To add to the confusion, PHP's methods themselves seem confused about what the first and last day of the week are.
For example:
$new_date = new DateTime;
// returns Monday, Jan 29 2018
$new_date->setISODate(2018, 5);
// returns Sunday, Feb 4 2018
$new_date->modify('sunday this week');
// returns Sunday, Jan 28 2018
$new_date->setISODate(2018, 5 ,0);
The method below is the one I've found returns the most helpful results:
function get_first_and_last_day_of_week( $year_number, $week_number ) {
// we need to specify 'today' otherwise datetime constructor uses 'now' which includes current time
$today = new DateTime( 'today' );
return (object) [
'first_day' => clone $today->setISODate( $year_number, $week_number, 0 ),
'last_day' => clone $today->setISODate( $year_number, $week_number, 6 )
];
}
CodePudding user response:
I written a sample code.
I using monday this week
to get start of week and sunday this week
to get end of week.
<?php
function rangeWeek(string $start,string $end)
{
$start = new DateTime($start);
$end = new DateTime($end);
$interval = new DateInterval('P1D');
$period = new DatePeriod($start, $interval, $end);
$weeks = [];
$oldWeek = null;
$weekStart = null;
foreach ($period as $date) {
$week = $date->format('W');
if(!isset($weeks[$week]))
{
$weekStart = date("Y-m-d", strtotime('monday this week', strtotime($date->format('Y-m-d'))));
$weekEnd = date("Y-m-d", strtotime('sunday this week', strtotime($date->format('Y-m-d'))));
$weeks[$week] = ['start' => $weekStart, 'end' => $weekEnd, 'week' => $week];
}
}
return $weeks;
}
$startDate = '2022-08-08'; //Monday
$endDate = '2022-08-23'; //Tuesday
$weeks = rangeWeek($startDate, $endDate);
print_r($weeks);
CodePudding user response:
You don't need to keep track of the week number but rather just Mondays and Sundays as a pair like below:
Snippet:
<?php
function rangeWeek(string $start,string $end): array{
$start = new DateTime($start);
$end = new DateTime($end);
$interval = new DateInterval('P1D');
$period = new DatePeriod($start, $interval, $end);
$weeks = [];
$monday = null;
foreach ($period as $currentDay) {
if($currentDay->format('D') == 'Mon'){
$monday = $currentDay;
}else if($currentDay->format('D') == 'Sun'){
$weeks[] = [
'start' => is_null($monday) ? null : $monday->format('Y-m-d'),
'end' => $currentDay->format('Y-m-d'),
'week' => $currentDay->format('W')
];
$monday = null;
}
}
return array_merge($weeks, [[
'start' => is_null($monday) ? null : $monday->format('Y-m-d'),
'end' => $end->format('Y-m-d'),
'week' => $end->format('W')
]]);
}
$startDate = '2022-08-08'; //Monday
$endDate = '2022-08-23'; //Tuesday
$weeks = rangeWeek($startDate, $endDate);
print_r($weeks);
CodePudding user response:
Without DateInterval
, the modify method of DateTime can be used to go from the current day to the next Sunday and then to the following Monday.
function rangeWeek(string $start,string $end): array{
$dtStart = date_create($start);
$dtEnd = date_create($end);
$weeks = [];
while($dtStart <= $dtEnd){
$weeks[] = [
'start' => $dtStart->format('Y-m-d'),
'end' => min($dtEnd,$dtStart->modify('Sunday this week'))->format('Y-m-d'),
'week' => $dtStart->format('W')
];
$dtStart->modify('next Monday');
}
return $weeks;
}
$startDate = '2022-08-08'; //Monday
$endDate = '2022-08-23'; //Tuesday
$weeks = rangeWeek($startDate, $endDate);
var_dump($weeks);
Demo: https://3v4l.org/ouK2q
Using min
replaces the if queries to test if the next Sunday is after the end date. min
can be used since DateTime objects can be directly compared.