0

The MySQL database stores time in Y-m-d H:i:s i.e 2000-12-32 00:00:00 format , UTC.

I am wondering if there's some way I can convert the created_at dateTime property on the $order objects returned from the database, so it would instead send a dateTime string to the client as such: 31/04/16 14:25pm and without seconds.

for($i = 0;  $i < sizeof($orders); $i++ ) { 
    $orders[$i]->created_at = $orders[$i]->created_at->format('d/m/y H:i');
}
Machavity
  • 30,841
  • 27
  • 92
  • 100
LaserBeak
  • 3,257
  • 10
  • 43
  • 73

3 Answers3

2

Welcome to Accessors and Mutators:

Proper way of doing this using Laravel is by defining an Accessor: The accessor will automatically be called by Eloquent when attempting to retrieve the value of your fields. This means that you don't have to loop over a set of objects and then convert the values, simply define an Accessor in your model and you're good to go.

Solution #1:

So for your date field add the following method to your Orders Model

public function getCreatedAtAttribute($value)
{
    return $value->format('d/m/y H:i a');
}

The name of an Accessor should be getFieldAttribute where you replace field with your corresponding column name. This way you don't have to loop over the results.

Note: do bare in mind that by doing so, you are now getting the created_at as a string not a Carbon object anymore in your model, so how can this affect you? if you're doing some comparison somewhere else, you can also use a Mutator to set the field value more on Accessors and Mutators can be found here https://laravel.com/docs/5.1/eloquent-mutators

Solution #2:

Yeap, basically loop over all of your array and do the conversion.

for($i = 0;  $i < count($orders); $i++ ) {
    $orders[$i]->created_at = $orders[$i]->created_at->format('d/m/y H:i a');
}

Update:

if you're experiencing errors like "The separation symbol could not be found" or "Unexpected data found." adjust the solutions like this:

Solution #1:

public function getCreatedAtAttribute($value)
{
    return Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $value->toDateTimeString())->format('d/m/y H:i a');
}

Solution #2:

for($i = 0;  $i < count($orders); $i++ ) {
    $orders[$i]->created_at = Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $orders[$i]->created_at->toDateTimeString())->format('d/m/y H:i a');
}
Islam Al-Rayan
  • 396
  • 2
  • 7
  • I am giving the basic loop approach a go. However it won't accept conversion to any format other than its Y-m-d H:i:s one. So for created_at->format('d/m/y H:i a') it will throw up errors such as: Carbon.php Unexpected data found.. a two digit second could not be found etc. trailing symbol .. separation could not be found etc. – LaserBeak Apr 11 '16 at 10:37
  • I've updated the answer, also the reason for the errors you isn't because Carbon doesn't allow you to format properly, it's because it really met unexpected data. – Islam Al-Rayan Apr 11 '16 at 11:57
  • Also check this SO question: http://stackoverflow.com/questions/25223958/laravel-unexpected-data-found-error-when-trying-to-change-format-of-carbon-cre – Islam Al-Rayan Apr 11 '16 at 11:58
  • Still gives me the unexpected data errors (two digit second could not be found)... then if I add the :s in the ->format argument it will then pick on the 'a' and state trailing data. So unless the input format and convert to format are identical, it gives me errors. The time in the database looks as such '2016-04-01 13:53:54', so input format looks correct ? – LaserBeak Apr 11 '16 at 12:14
  • I've updated the code in the update section to convert to a date time string first, check it. and regarding that database comment, you will probably find a cell with 0000-00-00 00:00:00 that's what causing the error by the way. if you want to fix that set the created_at null flag, and default value to null in the table structure. – Islam Al-Rayan Apr 11 '16 at 12:19
  • Same thing occurs with solution #2. Unexpected data found. A two digit second could not be found. I have confirmed all dates in the database have two digits representing seconds if that matters. – LaserBeak Apr 11 '16 at 12:26
  • how about you wrap the function in a try catch statment like this `for($i = 0; $i < count($orders); $i++ ) { try{ $orders[$i]->created_at = Carbon\Carbon::createFromFormat('Y-m-d H:i:s', $orders[$i]->created_at->toDateTimeString())->format('d/m/y H:i a');} catch(\Exception $ex){ dd($orders[$i]); } }` this way you can see the value that was passed that caused the error. – Islam Al-Rayan Apr 11 '16 at 12:30
  • It appears to give Model->fromDateTime('31/03/16 12:33 pm') , Model->asDateTime('31/03/16 12:33 pm'), Carbon::createFromFormat('Y-m-d H:i:s', '31/03/16 12:33 pm') – LaserBeak Apr 11 '16 at 12:42
  • By the looks of it createFromformat function won't work because there's in fact no seconds value in the time string for some reason. – LaserBeak Apr 11 '16 at 12:48
  • Based on the feed back I suggest you try this `for($i = 0; $i < count($orders); $i++ ) { $orders[$i]->created_at = Carbon\Carbon::createFromFormat('Y-m-d H:i', $orders[$i]->created_at->toDateTimeString())->format('d/m/y H:i a'); }` – Islam Al-Rayan Apr 11 '16 at 13:04
  • If that :s is taken off the input format in createFromFormat, Error log reads : at Carbon::createFromFormat('Y-m-d H:i', '2016-03-31 12:33:38'), if the :s is put on like before 'Y-m-d H:i:s', it states: at Carbon::createFromFormat('Y-m-d H:i:s', '31/03/16 12:33 pm') After copy pasting your last suggestion, I only get one error: Trailing data – LaserBeak Apr 11 '16 at 13:15
  • the problem is your records are inconsistent, some have the seconds and some dont, you can run a query that will update the cells that have seconds and remove them, then use the last suggested function, otherwise run a query that would set the seconds to 00 if they're not found and use the default function, this is as far as I can help :) – Islam Al-Rayan Apr 11 '16 at 13:56
  • Thanks for trying. Albeit I only have like five records I am testing with and all created_at fields are consistent with the aforementioned format, all have seconds on the end. The database wouldn't even let me enter a different format if I wanted to. – LaserBeak Apr 11 '16 at 14:08
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/108826/discussion-between-islam-al-rayan-and-laserbeak). – Islam Al-Rayan Apr 11 '16 at 14:10
0

you are right,you can format created_at time

foreach($orders as $order){
echo $order->created_at->format('d/m/y H:i a');
}
Imtiaz Pabel
  • 5,307
  • 1
  • 19
  • 24
0

Assuming $orders is an eloquent model, the created_at and updated_at attributes are automatically converted to carbon instances, so you can already run carbon methods on them.

See the docs on this topic: https://laravel.com/docs/5.2/eloquent-mutators#date-mutators

So, your code:

$orders[$i]->created_at->format('d/m/y H:i');

Should work just fine!

You could always add a helper method in your Order model to make it a bit more readable too, something like this:

public function createdAtTimeStamp()
{
    return $this->created_at->format('d/m/y H:i');
}

Then you can access it like so:

$orders[$i]->createdAtTimeStamp()
haakym
  • 12,050
  • 12
  • 70
  • 98