Home > Enterprise >  PHP How to get first and last day of a week based on date range
PHP How to get first and last day of a week based on date range

Time:09-13

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);

Online Demo

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.

  •  Tags:  
  • php
  • Related