Carbon::createFromFormat

Parses a date string against an exact format, rejecting input that does not match.

Signature
public static function createFromFormat($format, $time, $timezone = null): ?static
  • Added in Laravel Carbon 1.0

Parameters

ParameterTypeDescription
$$formatstringA DateTime::createFromFormat() format string. Prefix with ! to reset unmatched fields to the Unix epoch instead of the current date and time; use | to reset only the trailing ones.
$$timestringThe value to read. It must match the format exactly, including separators and any literal characters.
$$timezoneoptionalDateTimeZone|string|int|null= nullTimezone the string should be read in and carried by the result. Ignored when the format itself captures an offset.

Return value

?staticA Carbon instance built from the string read through the given format.

Errors

Throws Carbon\Exceptions\InvalidFormatException when the string does not match the format, including trailing or unexpected data.

Changelog

  • PHP 2.0Parsing failures raise Carbon\Exceptions\InvalidFormatException instead of returning false the way DateTime::createFromFormat() does.

Carbon::createFromFormat() reads a string through a format you supply, so there is no guessing about whether 03/04 means March or April. It is the method to reach for on data you did not write: a CSV export, a legacy API, a form field, anything where a misread date is worse than a rejected one.

Unmatched fields are filled from now

The single biggest surprise: fields the format does not mention are taken from the current time, not zeroed. Parsing '03/04/2026' with 'd/m/Y' gives that date at the current time of day, which then leaks into equality checks and stored values. Prefix the format with ! to reset everything the format did not set, or append | to reset just the trailing fields.

It still overflows

Strictness is about the shape of the string, not the validity of the date. '31/02/2026' matches 'd/m/Y' perfectly and quietly becomes 3 March. If a real calendar date matters, compare the result back against the input with format(), or validate first with Laravel's date_format rule.

A mismatch throws InvalidFormatException rather than returning false, so wrap it in a try/catch when the input is untrusted.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Importing a CSV whose dates are written day-first as 03/04/2026.
  • Reading a legacy API that emits a fixed, non-ISO timestamp layout.
  • Accepting a date from a form field where the input mask is known.

Frequently asked questions

Why does createFromFormat with a date-only format include a time?

Any field the format does not mention is filled from the current date and time, so 'd/m/Y' leaves the clock's time of day attached. Prefix the format with an exclamation mark — '!d/m/Y' — to reset unmatched fields to zero.

Does createFromFormat reject 31 February?

No. The string matches 'd/m/Y', so the parse succeeds and the date overflows to 3 March. Use Laravel's date_format validation rule, or format the result back and compare it with the input, when calendar validity matters.

What happens when the string does not match the format?

Carbon throws Carbon\Exceptions\InvalidFormatException, unlike PHP's DateTime::createFromFormat() which returns false. Catch it when the input is untrusted, or validate before calling.

More examples

Importing day-first dates from a CSV

The second row is a perfectly valid date in a different layout, and it is refused — which is the point. Carbon::parse() would have accepted both and given two different interpretations of the same digits.

Example · php
<?php

use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException;

$rows = [
    ['ref' => 'A-1', 'due' => '03/04/2026'],
    ['ref' => 'A-2', 'due' => '2026-04-03'],
];

foreach ($rows as $row) {
    try {
        $due = Carbon::createFromFormat('!d/m/Y', $row['due']);
        echo $row['ref'], ': ', $due->toDateTimeString(), PHP_EOL;
    } catch (InvalidFormatException) {
        echo $row['ref'], ': rejected', PHP_EOL;
    }
}

// A-1: 2026-04-03 00:00:00
// A-2: rejected

Round-tripping to reject impossible dates

31/02/2026 matches the format, so createFromFormat happily overflows it to 3 March; formatting the result back and comparing catches that. This is the same check Laravel's date_format validation rule performs.

Example · php
<?php

use Carbon\Carbon;

function strictDate(string $format, string $value): ?Carbon
{
    try {
        $date = Carbon::createFromFormat('!'.$format, $value);
    } catch (Throwable) {
        return null;
    }

    return $date->format($format) === $value ? $date : null;
}

var_dump(strictDate('d/m/Y', '03/04/2026')?->toDateString()); // string(10) "2026-04-03"
var_dump(strictDate('d/m/Y', '31/02/2026'));                  // NULL

Validating before parsing

The date_format rule rejects both the wrong layout and impossible calendar dates before Carbon sees the value, so the parse itself can be written without a try/catch. The ! prefix still matters — without it the stored value would carry the request's time of day.

Example · php
<?php

use Carbon\Carbon;
use Illuminate\Http\Request;

public function store(Request $request)
{
    $validated = $request->validate([
        'starts_on' => ['required', 'date_format:d/m/Y'],
    ]);

    $startsOn = Carbon::createFromFormat('!d/m/Y', $validated['starts_on']);

    return $startsOn->toDateString();
}

Discussion

  • Be the first to comment on this lesson.