Paulund
2024-05-27 #laravel

Laravel Immutable Carbon Dates

In this article we're going to look at the Carbon data class in laravel and how we can change the settings of how laravel uses the class to make it immutable.

What's the problem we're trying to solve?

When you're working with dates in Laravel you will most likely be using the Carbon class. This class is a wrapper around the PHP DateTime class and provides a lot of useful methods for working with dates.

When you output the value of a carbon object you get this value.

$now = now()
= Illuminate\Support\Carbon @1716793925 {#5324
    date: 2024-05-27 08:13:50.554997 Europe/London (+01:00),
  }

You can change this object by adding or subtracting time from the object with helper helpers like ->addHour()

$now = $now->addHour()
= Illuminate\Support\Carbon @1716797621 {#5329
    date: 2024-05-27 09:13:50.554997 Europe/London (+01:00),
  }

You can add multiple hours by using the method ->addHours(4)

$now = $now->addHours(4)
= Illuminate\Support\Carbon @1716812090 {#5318
    date: 2024-05-27 13:13:50.554997 Europe/London (+01:00),
  }

But we have a problem, adding 4 hours to 8:12 should be 12:12 not 13:13. This is because the Carbon class is mutable and when you call the addHours method it changes the original object.

This can have it's advantages when you have a large process of changing the date multiple times but it can also have it' s disadvantages when you want to keep the original date.

Carbon has a method called copy that will create a new instance of the Carbon object and then you can change the new object.

$now = now()
= Illuminate\Support\Carbon @1716793925 {#5324
    date: 2024-05-27 08:13:50.554997 Europe/London (+01:00),
  }

$nowCopy = $now->copy()->addHours(4)
= Illuminate\Support\Carbon @1716812090 {#5318
    date: 2024-05-27 12:13:50.554997 Europe/London (+01:00),
  }

The other approach is to use the CarbonImmutable class which is a subclass of the Carbon class but it's immutable.

$now = Carbon\CarbonImmutable::now();
= Carbon\CarbonImmutable @1716794377 {#5341
    date: 2024-05-27 08:19:37.149971 Europe/London (+01:00),
  }

$now->addHour()
= Carbon\CarbonImmutable @1716797977 {#5394
    date: 2024-05-27 09:19:37.149971 Europe/London (+01:00),
  }

$now->addHours(4)
= Carbon\CarbonImmutable @1716808777 {#5335
    date: 2024-05-27 12:19:37.149971 Europe/London (+01:00),
  }

As you can see when we add 1 hour and then 4 hours we get the result of 4 hours not 5 hours. Now we get the expected results when working with dates.

This is a simple change to make in your application but it can have a big impact on how you work with dates in your application.

Changing the default Carbon class

If you want to change the default Carbon class to be immutable you can do this by adding the following code to your AppServiceProvider class.

use Carbon\CarbonImmutable;
use Illuminate\Support\Facades\Date;

public function boot()
{
    Date::use(CarbonImmutable::class);
}

This will change the default Carbon class to be CarbonImmutable and now all dates in your application will be immutable.

This is a simple change to make in your application but it can have a big impact on how you work with dates in your application.

Performance Implications

There are some performance implications when using the CarbonImmutable class. The CarbonImmutable class is slower than the Carbon class because it creates a new instance of the object every time you call a method that changes the date.

This is because the CarbonImmutable class is immutable and it doesn't change the original object. This can have a big impact on the performance of your application if you're working with a lot of dates.

You should consider the performance implications when deciding whether to use the CarbonImmutable class or the Carbon class in your application.

Immutable Date Casting

If you're using the Eloquent ORM in Laravel you can use the date casting to cast a date attribute to a Carbon object.

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    protected $casts = [
        'published_at' => 'date',
    ];
}

You can also make sure that this date uses the immutable Carbon class by adding the following code to your model.

class Post extends Model
{
    protected $casts = [
        'published_at' => 'immutable_date',
        'published_at' => 'immutable_datetime',
    ];
}

This will make sure that the published_at attribute is cast to an immutable Carbon object when you access it.

UpChecker

Reliable uptime monitoring and instant alerts for any website downtime.

  • Uptime Monitoring
  • Performance Monitoring
  • SSL Certificate Alerts
  • Domain Monitoring
  • DNS Checker
  • XML Sitemap Monitoring