skip to Main Content

I have a 2d array of jobs and each job contains a start time, an end time which is always 60 minutes after the start time, then an "add" value which is the number of minutes until the next job should start.

I need to adjust all rows so that each start time is the previous job’s end time plus its "add" time.

Here is a sample array:

[
    [
        'id' => 9,
        'needed_at' => '2023-02-26 03:31:04',
        'ended_at' => '2023-02-26 04:31:04',
        'add' => 20
    ],
    [
        'id' => 6,
        'needed_at' => '2023-02-26 04:51:04',
        'ended_at' => '2023-02-26 05:51:04',
        'add' => 30
    ],
    [
        'id' => 7,
        'needed_at' => '2023-02-26 09:21:04',
        'ended_at' => '2023-02-26 10:21:04',
        'add' => 30
    ]
]

My desired result:

[
    [
        'id' => 9,
        'needed_at' => '2023-02-26 03:31:04',
        'ended_at' => '2023-02-26 04:31:04',
        'add' => 20
    ],
    [
        'id' => 6,
        'needed_at' => '2023-02-26 04:51:04',
        'ended_at' => '2023-02-26 05:51:04',
        'add' => 30
    ],
    [
        'id' => 7,
        'needed_at' => '2023-02-26 06:21:04',  # changed based on id 6 data
        'ended_at' => '2023-02-26 07:21:04',   # changed based on new need_at time of this row
        'add' => 30                            # not actually used because no next job
    ]
]

What I have tried is:

foreach ($jobs as $k => $j) {
    $s = $k+1;
    $date = new DateTimeImmutable($j->ended_at);
    $add = $j->add;
    $date_new = $date->modify('+'.$add.' minutes');
    $needed_at = $date_new->format('Y-m-d H:i:s');
    $data['needed_at'] = $needed_at;
    
    $date2 = new DateTimeImmutable($needed_at);
    $ended_at = $date2->modify('+60 minutes');
    $data['ended_at'] = $ended_at->format('Y-m-d H:i:s');
    $d[]=[
        'id' => $jobs[$s]->id,
        'needed_at' => $needed_at,
        'ended_at' => $data['ended_at'],
        'add' => $add
    ];
}

It is not working. Is it possible to use first iteration modified data into second iteration?

2

Answers


  1. Since the first element of the array will not change we excluded from the loop.

    Two elements are important to get the expected output : ended_at and add, then after each iteration those variables will take the current values and so on

    $format = 'Y-m-d H:i:s';
    
    $ended_at = $jobs[0]['ended_at'];
    $add = $jobs[0]['add'];
    
    $d[0] = $jobs[0];
    foreach($jobs as $k => $j){
           if ($k < 1) continue;
           
           $ended_at = DateTimeImmutable::createFromFormat($format, $ended_at);
           
           $ended = $ended_at->modify('+'.$add.' minutes');
           $needed = $ended->modify('+60 minutes');
           
           $ended = $ended->format($format);
           $needed = $needed->format($format);
           
           $d[]=array(
             'id' => $jobs[$k]['id'],
             'needed_at' => $ended,
             'ended_at' => $needed,
             'add' => $jobs[$k]['add']
           );
           
           $ended_at = $needed;
           $add = $jobs[$k]['add'];
           
    }
    
    print_r($d);
    

    Demo here

    Login or Signup to reply.
  2. For a direct and concise way to create contiguous datetime stamps across all rows in your data, use a single loop, modify the rows by reference, declare a single datetime object, then bump or save the the datetime stamp as needed.

    There is no need to waste/double memory by building a completely new output array.

    Code: (Demo)

    $format = 'Y-m-d H:i:s';
    foreach ($jobs as &$row) {
        $dt ??= new DateTime($row['needed_at']);  // declare if not yet declared
        $row['needed_at'] = $dt->format($format); // save in desired format
        $dt->modify('+ 60 minutes');              // bump by duration in minutes
        $row['ended_at'] = $dt->format($format);  // save in desired format
        $dt->modify("+ {$row['add']} minutes");   // bump by gap in minutes in preparation for next row
    }
    
    var_export($jobs);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search