Rotate an array with weekday names as keys to start with tomorrow

Viewed 12290

I have the following array:

[
     [
         'schedules' => [
             'monday' => 1,
             'tuesday' => 1,
             'wednesday' => 1,
             'thursday' => 1,
             'friday' => 1,
             'saturday' => 0,
             'sunday' => 1,
         ]
    ]
]

I'd like to rotate the elements of this array with the first key being the tomorrow. Let's say today was Wednesday, I'd want my array to look like this:

[
     [
         'schedules' => [
             'thursday' => 1,
             'friday' => 1,
             'saturday' => 0,
             'sunday' => 1,
             'monday' => 1,
             'tuesday' => 1,
             'wednesday' => 1,
         ]
    ]
]

I already have the weekday available (e.g. a string 'thursday'). It gets passed into the function that I'm working with.

12 Answers

you can do like this to achieve this

$week = [
    'sunday',
    'monday',
    'tuesday',
    'wednesday',
    'thursday',
    'friday',
    'saturday',
];

  $day = date('w'); // weekday as integer(3 for Wednesday)

  for ($i=0; $i <= $day ; $i++) {
    array_push($week, array_shift($week));
  }

  $result = $week;

Result (if today is Wednesday):

    Array
    (
        [0] => thursday
        [1] => friday
        [2] => saturday
        [3] => sunday
        [4] => monday
        [5] => tuesday
        [6] => wednesday
    )

Try this below code. it will sort days based on current day.

    $days = array("Friday","Thursday","Wednesday","Tuesday");
    $days = array_combine($days,$days);
    
    //loop the days and check the next day
    foreach($days as $k => $dd){
        
        //check next day name & increment current date with +1
        $current_dt = date("Y-m-d",strtotime("next day", strtotime($current_dt)));
        $days_name = date("l", strtotime($current_dt));    
        
        // if day name exists in array, push in seperate array
        if(!empty($days[$days_name])){
            $arrSortedDays[] = $days_name;
        }
    }
    
    //check if currnet day fall today, push it in array to last element.
    if(!empty($days[date("l")])){
        $arrSortedDays[] = date("l");
    } 

There is already a circular order in the subarray data so there is no requirement to sort by comparing each entry against each other.

The most direct solution (that I know of) is to:

  1. Find the correct position to cut the array into two parts, then
  2. Remove the first part and reattach it after the second part.

Code: (Demo)

$newStart = 'thursday';
foreach ($array as &$entry) {
    $position = array_search(
        $newStart,
        array_keys($entry['schedules'])
    );
    if ($position) {
        $entry['schedules'] += array_splice(
            $entry['schedules'],
            0,
            $position
        );
    }
}
var_export($array);

The condition ensures that no element rotation is performed if the targeted key is not found (false) or is already in first position (0).

array_search() is efficient because it halts iterating as soon as it finds its first match.

I do not endorse any of the earlier answers which recommend:

  • uksort() -- this has greater computational complexity, not to mention the additional overhead of function calls in the custom function body.
  • looping -- iterated function calls are unnecessarily expensive and represent a less elegant / brute force technique. A loop with a break condition and no iterated function calls would not be so bad.
  • changing the OP's input data to better suit an alternative solution -- this is unnecessarily admitting defeat.

My solution happens to be suitable as a utility function because it does not rely on any date-related data/logic.

A combination of array_slice and array_merge will do the trick.

'week' => [
   'monday' => 1,
   'tuesday' => 1,
   'wednesday' => 1,
   'thursday' => 1,
   'friday' => 1,
   'saturday' => 0,
   'sunday' => 1,
         ]
// get today's index, like Wednesday will be 3
$day = date('w')

// Get the days until today
$previous = array_slice($week, 0, $day); // ["mon","tue","wed"]

// Get remaining days in week
$coming = array_slice($week, $day); //  ["thu","fri","sat","sun",]

array_merge($coming, $previous);//["thu","fri","sat","sun","mon","tue","wed"]
Related