Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Carbon createFromFormat unexpected result

Tags:

php

php-carbon

::createFromFormat() results in being one month ahead:

var_dump($_GET['archive']);
var_dump(Carbon::createFromFormat('m/Y', $_GET['archive']));

Result:

string '11/2015' (length=7)
object(Carbon\Carbon)[160]
  public 'date' => string '2015-12-01 10:38:41.000000' (length=26)
  public 'timezone_type' => int 3
  public 'timezone' => string 'Europe/London' (length=13)
like image 488
leevanoetz Avatar asked Apr 08 '26 08:04

leevanoetz


2 Answers

Seems that you just got unlucky because you were testing on the 31st of the month.

However, this is (apparently) a documented feature. See: http://php.net/manual/en/datetime.createfromformat.php

If you set your format mask "correctly", it works as you'd expect.

$x = Carbon::createFromFormat   ('m/Y', '04/2009');
$y = DateTime::createFromFormat ('m/Y|', '04/2009');
dd ($x, $y);

To avoid ambiguity, the Carbon function is just a wrapper for the underlying DateTime function of PHP; I'm just aiming to prove that this is not a Carbon feature that's causing our headache.

If you test on the 31st of the month, $x above will be read as 31 April 2009 which will be displayed as 1st May.

With the pipe symbol in the mask though, all the non-declared time variables (H, i, s) are set to zero, and date variables (d, m) set to 1, so $y will always respond as you expect regardless of the day of the week.

For me testing at 17:46 in the evening of the 4th day of the month, the above code produces the following:

Carbon @1233769590 {#219 ▼
    date: 2009-02-04 17:46:30.0 Europe/London (+00:00)
}

DateTime @1233446400 {#217 ▼
    date: 2009-02-01 00:00:00.0 Europe/London (+00:00)
}

This is a really weird implementation of date/time function in my opinion. The only real-world situation that you'd want to use this function in, is if you're reading data from an external source (such as an XML "date" field).

Which programmer on earth would want their program to assume that the missing time (or in your case, day) component of the incoming data, should be taken from the runtime execution time? It's absolutely crazy bonkers.

like image 193
cartbeforehorse Avatar answered Apr 10 '26 20:04

cartbeforehorse


It seems that Carbon uses the current day if not provided. Hence

var_dump(Carbon::createFromFormat('m/Y', '10/2015'));
var_dump(Carbon::createFromFormat('m/Y', '11/2015'));

results e.g. on July 31st in

object(Carbon\Carbon)[156]
  public 'date' => string '2015-10-31 11:03:10.000000' (length=26)
  public 'timezone_type' => int 3
  public 'timezone' => string 'Europe/London' (length=13)
object(Carbon\Carbon)[138]
  public 'date' => string '2015-12-01 11:03:10.000000' (length=26)
  public 'timezone_type' => int 3
  public 'timezone' => string 'Europe/London' (length=13)

as October has 31st but "November 31st is actually December 1st".

like image 24
leevanoetz Avatar answered Apr 10 '26 21:04

leevanoetz