Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Carbon makes PHP date and time work more expressive, but reliable results depend on choosing the right object type, timezone, and meaning of “day.” Use CarbonImmutable when a date should not change unexpectedly, represent precise moments in UTC, and use a named region timezone for local schedules and display. Around daylight-saving changes, decide whether you mean a calendar day or exactly 24 elapsed hours.

What Carbon does—and when to use each class

Carbon builds on PHP’s native date/time classes and provides a richer API for creating, modifying, comparing, and formatting dates. Carbon extends DateTime; CarbonImmutable extends DateTimeImmutable. They expose the same methods, but their modifiers behave differently: Carbon changes the existing object, while CarbonImmutable returns a new object. Carbon’s introduction describes the library and its core types.

Class What a modifier does Use it when
Carbon Changes the existing instance and returns it Mutation is intentional and the object is not unexpectedly shared
CarbonImmutable Returns a new instance; the original remains unchanged Callers or components may share a date value and should not silently alter one another’s data

For example, adding a day to an immutable value leaves the starting value intact:

<?php
use CarbonCarbonImmutable;

$start = CarbonImmutable::parse('2026-10-04 09:00:00', 'UTC');
$tomorrow = $start->addDay(); // $start is unchanged

With mutable Carbon, assigning the result of a modifier does not protect the original variable: the object itself has already changed. Choose the class based on whether mutation is part of the intended behavior, especially when passing date objects between functions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Create dates with an explicit interpretation

Carbon can create values from date strings, integer timestamps, and PHP DateTimeInterface objects. Its documentation describes static creation helpers as a clear alternative to relying on a constructor. For reproducible code, pass a timezone when creating a value rather than relying on the machine’s default.

<?php
use CarbonCarbonImmutable;

$utcNow = CarbonImmutable::now('UTC');
$fromSeconds = CarbonImmutable::createFromTimestamp(1_601_735_792, 'UTC');
$fromMilliseconds = CarbonImmutable::createFromTimestampMs(1_601_735_792_000, 'UTC');

There is a version-sensitive default: Carbon’s documentation says createFromTimestamp() uses UTC when no timezone is supplied starting with Carbon 3; earlier versions used PHP’s default timezone. Passing the timezone explicitly avoids that change in interpretation when code runs across environments or is upgraded. See Carbon’s instantiation guide.

String parsing follows PHP’s date/time parsing rules, so a permissive parse is not a substitute for validating user input against an application’s required format. The Carbon guidance cited here does not establish strict parsing behavior across PHP versions; check the PHP version and its official documentation if your application depends on specific parsing errors or validation details.

Choose a timezone based on what the date means

A moment and a local wall-clock time are not interchangeable. Use UTC as the consistent basis for moments that need comparison or storage, then convert to a named region timezone for display. A region such as Europe/Paris applies that location’s timezone rules; a fixed offset such as +02:00 stays fixed and does not encode a city’s historical or future rule changes. Carbon’s timezone guide recommends UTC by default and changing zones when displaying a date.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
$event = CarbonImmutable::parse('2026-10-04 12:00:00', 'UTC');
$parisDisplay = $event->setTimezone('Europe/Paris');

setTimezone() preserves the instant and changes how it is represented in the new zone. In contrast, Carbon’s factory timezone setting uses shiftTimezone(), which shifts the wall-clock value into the configured zone. That distinction matters when applying per-user settings: converting an existing event for display should preserve its instant; creating a local “now” or local wall-clock value may require the factory’s shifted interpretation. Carbon explains the difference in its localization guide.

  • Precise moment: Keep the instant in UTC, then convert it for the viewer or location where it is displayed.
  • Recurring local schedule: Keep the intended region timezone with the rule—for example, 9 a.m. every Monday in Paris—so the schedule follows local civil time.
  • Location-bound travel event: Preserve the local context of each location as well as the instant. A flight’s departure and arrival occur in different zones, so local clock readings alone do not convey elapsed duration.

Carbon’s Laravel guide discusses location-specific events and viewer-local display. The appropriate database type and schema depend on the framework and database; the Carbon guidance does not prescribe a universal schema.

Distinguish calendar days from 24-hour durations

A local calendar day can be 23 or 25 hours when daylight-saving rules change the clocks. Consequently, adding one local day is not always the same operation as adding 86,400 seconds. Decide what the application’s rule means before choosing the arithmetic.

Requirement Use Resulting meaning
“Run at the same local time tomorrow” addDay() in the relevant region timezone Advance by one local calendar day, preserving the intended civil-time schedule where local rules allow
“Expire exactly 24 hours after creation” Elapsed-time arithmetic, such as addUTCDays() for a 24-hour day Advance along the UTC timeline by 24 hours
“How many calendar days apart?” Calendar-day difference in the relevant zone Compare dates in the civil calendar, not the number of full 24-hour spans

Carbon’s Carbon 3 migration guide distinguishes local calendar operations such as addDays() and diffInDays() from UTC-oriented methods such as addUTCDays() and diffInUTCDays(). Its Berlin example says March 30, 2025 lasts 23 hours: advancing one local day reaches midnight the next day, while advancing one UTC day reaches 01:00. The elapsed difference in that example is 0.95833333333333 UTC days.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The same migration guide notes that Carbon 3 changed diffIn*() behavior, including signed and fractional results where Carbon 2 code may have expected absolute integers. When upgrading, review each difference calculation and make the desired sign, absolute-value handling, and rounding or truncation explicit.

Localize output without changing other users’ settings

For translated date output, set the locale on the particular instance or use a configured Factory for a user or component. Carbon’s guide says instance-level locale() takes precedence over global settings and changes the language only for that instance. This avoids one component’s global locale change affecting unrelated Carbon values.

$localized = $event->locale('fr');
$label = $localized->isoFormat('LLLL');

Localized output can also use methods such as diffForHumans(). A factory can group settings such as locale and timezone for a particular user. Remember that its timezone setting uses shiftTimezone(); for an existing instant that should simply be shown in another zone, use setTimezone() instead. See Carbon’s localization documentation.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Keep the stored value aligned with the domain meaning

Do not force every date-related concept into the same representation. A birthday may be a calendar date without a time; a payment timestamp is a moment; a train departure is a moment associated with a station’s local timezone. Store enough context to preserve the meaning required by the application.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

For APIs that represent a moment, Carbon’s Laravel guidance demonstrates an ISO-style UTC datetime with a Z suffix. A location-specific schedule, by contrast, needs its location timezone to retain the intended civil-time rule. A viewer’s preferred timezone affects presentation, not the underlying meaning of an already-defined event.

Make date logic reproducible and easier to debug

Carbon includes testing aids for controlling “now,” which lets tests exercise relative-date logic against a known point in time. Its testing aids guide notes that real Carbon::now() uses the timezone returned by PHP’s date_default_timezone_get(). Set the intended timezone explicitly in tests rather than inheriting an environment default.

When a result looks wrong, inspect the complete timestamp, timezone name, UTC offset, and installed Carbon and PHP versions. A local wall-clock value without a zone may be ambiguous during the repeated hour when clocks move backward. Then identify whether the requirement is about a calendar date, local schedule, or elapsed seconds before changing the code.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.