3

In Laravel environment I have a set of times that I am adding minutes to and it is not giving me what I expect.

In the below array_map function there is some weird addMinutes happening

$d = array_map(function ($date) {
    $base = Carbon::parse($date['time']);
    return [
        'start' => $base->addMinutes(150)->toDateTimeString(),
        'end' => $base->addMinutes(190)->toDateTimeString()
    ]
}, $dates);

So 150mins is 2hrs30mins, 190mins is 3hrs10mins, so I would assume the following

2018-07-05 19.20.00 (+150 mins) -> start = 2018-07-05 21.50
                    (+190 mins) -> end   = 2018-07-05 22.30

I am actually getting

2018-07-05 19.20.00 (+150 mins) -> start = 2018-07-05 21.30
                    (+190 mins) -> end   = 2018-07-06 00.40

Can anyone see the obvious I'm missing here with the Carbon processing ? I'm quite certain it has to do with Carbon as I restructured the above array_map into a foreach and same results with the same addMinutes.

Edit:

I've just adapted this code for anyone to help diagnose by pasting the below into phpio

require 'Carbon/Carbon.php';
use Carbon\Carbon;

$dates[] = ['time' => '2018-07-05 19:20:00'];

$d = array_map(function ($date) {
    $base = Carbon::parse($date['time']);
    return [
        'start' => $base->addMinutes(150)->toDateTimeString(),
        'end' => $base->addMinutes(190)->toDateTimeString()
    ];
}, $dates);

print_r($d);

WEIRD - now the start is correct, but end is still incorrect (showing 2018-07-06 01:00:00)

yoyoma
  • 3,336
  • 6
  • 27
  • 42
  • FYI, using normal DateTime, I didn't encounter this problem: https://3v4l.org/A1qAB . Weeeeird. – Loek Jul 04 '18 at 14:35

1 Answers1

5

Take a look at this code:

return [
    'start' => $base->addMinutes(150)->toDateTimeString(),
    'end' => $base->addMinutes(190)->toDateTimeString()
]

In both situations, you're adding to $base, so you're adding 150 minutes, then an additional 190 (so a total of 340 minutes). Try using with ->copy():

return [
    'start' => $base->copy()->addMinutes(150)->toDateTimeString(),
    'end' => $base->copy()->addMinutes(190)->toDateTimeString()
]

Using the following code in phpio:

require 'Carbon/Carbon.php';
use Carbon\Carbon;

$dates[] = ['time' => '2018-07-05 19:20:00'];

$d = array_map(function ($date) {
  $base = Carbon::parse($date['time']);
  return [
    'start' => $base->copy()->addMinutes(150)->toDateTimeString(),
    'end' => $base->copy()->addMinutes(190)->toDateTimeString()
  ];
}, $dates);

print_r($d);

Gives me the following:

Array ( [0] => Array ( [start] => 2018-07-05 21:50:00 [end] => 2018-07-05 22:30:00 ) )

Tim Lewis
  • 27,813
  • 13
  • 73
  • 102
  • 1
    No problem; just a caveat when modifying a `Carbon` date :) – Tim Lewis Jul 04 '18 at 14:51
  • 1
    `->copy()` is a `Carbon` function, burried in the documentation: *"You can also create a copy() of an existing Carbon instance. As expected the date, time and timezone values are all copied to the new instance."* Most examples are found below the section https://carbon.nesbot.com/docs/#api-addsub, where all the `addXXX` and `subXXX` methods use `->copy()` prior. – Tim Lewis Jul 04 '18 at 15:00