successdav's avatar

Adding dates to array without formating returns wrong date

The function below returns two same dates (Carbon intances)

  public function generatePaymentDates(){
        $dates      = [];
        $start_date = $this->getRepaymentCycleStartDate(); // get the start date of the loan
        $duration   = $this->duration; // Get the loan tenor duration e.g. 2

        for ($i = 1; $i <= $duration; $i++) {
            $date = match($this->category->duration_period) {
                'Years' => $start_date->addYears(1),
                'Months' => $start_date->addMonths(1),
                'Weeks' => $start_date->addWeeks(1),
            };

            $dates[] = $date;
        }

        return $dates;
    }

The $dates array holds two dates (Cabon instances) but both dates are thesame. and when I add format('y M d') like this.

$dates[] = $date->format('y M d');

I get the proper dates, that's two different dates. however, I don't want it formatted.

0 likes
3 replies
Sinnbeck's avatar
Sinnbeck
Best Answer
Level 102

Carbon is mutable. That means you change the object every time. Do a copy

            $date = match($this->category->duration_period) {
                'Years' => $start_date->copy()->addYears(1),
                'Months' => $start_date->copy()->addMonths(1),
                'Weeks' => $start_date->copy()->addWeeks(1),
            };
1 like
Sinnbeck's avatar

Or

$date = $start_date->copy();
match($this->category->duration_period) {
                'Years' => $date->addYears(1),
                'Months' => $date->addMonths(1),
                'Weeks' => $date->addWeeks(1),
            }; 
webrobert's avatar

and, for kicks here is fun refactor...

$start_date = CarbonImmutable::parse($this->getRepaymentCycleStartDate()); 
$duration   = $this->duration; 

$dates = Collection::times($duration, fn($count) => match($this->category->duration_period) {
   'Years' => $start_date->addYears($count),
   'Months' => $start_date->addMonths($count),
   'Weeks' => $start_date->addWeeks($count),
});
1 like

Please or to participate in this conversation.