Laravel automatically adding time to date - php

I seem to have a problem with my Laravel application, and I can't for the life of me figure out whats going on.
I have a simple date field in my MySQL database, its data type is just date, and for this example the value is 2020-08-13, but for some reason, when I try to access the date, it adds a timestamp on the end, minuses 1 day and throws a Carbon trailing data error.
It is definitely this date, because when I soft delete it, the error disappears.
As an example, the error for this date is
Carbon\\Carbon::rawCreateFromFormat('Y-m-d', '2020-08-12T23:0...', NULL)
So as you can see, it's removing a day and trying to format at 11pm the night before?
I have had similar issues to this before where Laravel was adding 0000-00-00 to the date, so I had to remove it in my accessor, but now that its throwing 11pm, my string replace doesn't work anymore. I can obviously just change the string replacer to look for 11pm, but I don't want to have to fix this every time the format changes.
My accessor code is as follows
public function getDateAttribute($value){
//String replace and remove the time from the value if it exists
$value = str_replace(' 00:00:00', '', $value);
return Carbon::CreateFromFormat('Y-m-d', $value)->format('d/m/Y');
}
Has anyone had an error like this before, or have any idea whats going on?

Before Laravel 7, dates would be serialized to a format like the following :
2019-12-02 20:01:00
But, Laravel 7 uses a new date serialization format when using the toArray or toJson method on Eloquent models, with ISO-8601 date format. This ISO-8601 dates are always expressed in UTC, like this :
2019-12-02T20:01:00.283041Z
If you would like to keep using the previous behavior you can override the serializeDate() method on your model, add this into your model :
use DateTimeInterface;
protected function serializeDate(DateTimeInterface $date)
{
return $date->format('Y-m-d H:i:s');
}

first define you column to $dates property on your model :
$dates=['date']
then specify your date format by accessor :
public function getDateAttribute($value){
return $val->format('d/m/Y');
}

public function getDateAttribute($value){
// return 2020-08-17
$date = date('Y-m-d',strtotime($value));
return $date;
}
Make sure of the config file. You will find there a function of local time that can change its value from UTC to the local time of your country
config / app.php
'timezone' => 'Asia/Riyadh',

it's removing a day and trying to format at 11pm the night before
That's clearly a timezone shift (you're likely in GMT+1) and this is a shift to GMT+0 (UTC).
You should not trim the time to force "00:00:00" because this will only work in 1 timezone (there is no worldwide-midnight-moment, there is a different midnight moment in each timezone for each day), while your app now or later may handle multiple timezones. You should rather save the timezone ("Europe/London" for instance) in an other DB column and so you'll keep the complete information and when retrieving your date, you can calculate on the fly the midnight from (before) this date-time according to the user timezone.

Related

Carbon time format

I save the user photo with Carbon in laravel 9
$user->photo_verified_at = Carbon::now()->timestamp;
But I get this output from database:
Error Message : ORA-01843: not a valid month
Position : 42
Statement : update "USERS" set "PHOTO_VERIFIED_AT" = :p0, "USERS"."UPDATED_AT" = :p1 where "ID" = :p2
Bindings : [1672340645,2022-12-29 19:04:05,25]
If you a look at the data for created_at and updated_at in the database, they have the following format:
29/12/22 18:30:43,000000000
How is it possible to set Carbon to return in that format?
Carbon::now()->timestamp->format('dd/mm/yy H:i:s')
it returns
Error: Call to a member function format() on int
You should be fine with just Carbon::now() or now() (it is a helper function calling Carbon::now())
I am not exactly sure what you are storing there, if it is a timestamp that is literally a number, for example, 13102321 (just a made up number from me), it is the seconds that literally passed since a known date (I think it is January 1st, 1970 or something like that).
So, if you exactly want that fomat, it is as easy as reading the documentation, it will state that you can use the normal PHP's Date format:
$formatedString = now()->format('d/m/Y H:i:s,u000');
You have to add 3 more 0, as it has 9 0, that is nano seconds, super weird, but it is exactly the format you want...
You can also try out just using now() or any method that returns a literal Carbon object, it can or cannot work, depends how you have your model's attribute casted/declared.

Laravel saving data with Carbon::now() is formatted differently to created_at

I'm working with a Laravel project and time zones (I know time zones are a pain), and what's occurred to be is that one of my custom columns in my table, the column called last_checked which is stored as a timestamp appears to be formatted differently from the created_at, and it means that my time zone parsing isn't parsing the date at all for the user's time zone.
Here's what I mean...
When storing a record, I set the date and time:
$uptimeMonitor = Monitors::where('id', $monitor['id'])
->get()
->first();
$uptimeMonitor->last_checked = Carbon::now();
$uptimeMonitor->save();
But when I retrieve the result, looking in my network request, I'm seeing this format:
2021-04-05 11:46:54
But when I look at both the created_at and updated_at columns, they're in this format:
2021-04-05T10:01:16.000000Z
So the question here is, what am I doing wrong with saving my data? Both formats seem to be visually shown the same in the database, but for some strange reason, the first example isn't parsing correctly.
Carbon uses the default DateTime PHP object, so use the date_default_timezone_set() function, for example: date_default_timezone_set('UTC');
or you define it AppServiceProvider App/Providers/AppServiceProvider.php
public function boot()
{
date_default_timezone_set('UTC');
}
Or you can use setTimezone of carbon method
echo Carbon::now()->setTimezone('UTC')->format('H:i');
Try this
$uptimeMonitor = Monitors::where('id', $monitor['id'])
->get()
->first();
$uptimeMonitor->last_checked = Carbon::now()->setTimezone('UTC')->format('Y-m-d H:i:s');
$uptimeMonitor->save();
Note my default app timezone is UTC just find your default timezone
and set it in `setTimezone('UTC');
You need to add all the datetime properties in your $casts model protected member:
https://laravel.com/docs/8.x/eloquent-mutators#date-casting
All is OK in your DB, it's just Laravel model has to know it's a date to format with the full ISO-8601 string in your JSON.
Side note, you still should have "UTC" as your default in config/app.php, it does not prevent from having any timezone handling for particular cases, or to handle users timezone, on the contrary.
If your dates output string as GMT+1 by default, it's very likely a configuration mistake.

Date from API call not being accepted in Laravel as a dateTime field

I am getting dates from an API call. The date is formatted in this way
2017-10-19T15:30:00
I want to store this date in my MYSQL database using Laravel Database Migration, currently I am using
$table->dateTime('datetime');
When I store it using a dateTime field as above, all I get is
0000-00-00 00:00:00
When I use a timestamp format, I don't get accurate dates, I just get the current time and date.
How can I solve this? Any help would be appreciated, and please let me know if you want further information.
Luckily, Laravel uses the Carbon class, which makes things a lot easier to modify dates. In your case, you want to do this:
Carbon::createFromFormat('Y-m-d\TH:i:s', $date);
There are two ways you can implement it: you can modify it before you save it to your database, or you can add a mutator on your model.
public function setDatetimeAttribute($value)
{
$this->attributes['datetime'] = Carbon::createFromFormat('Y-m-d\TH:i:s', $value);
}
You may want to build in some validation to see which format the date/time is in before you try to convert it.
in the model you should put:
protected $dates = ['datetime'];
Use Carbon
$dt = Carbon::parse('1975-05-21 22:23:00.123456');
to save:
$model = new Model;
$model->date = $dt; // you can use the carbon object directly
$model->save();

Carbon in Laravel 4 InvalidArgumentException - Unexpected data found. Trailing data

I'm trying to get an Eloquent query result for DB::raw("DATE_FORMAT(created_at, '%m-%d-%Y %r') AS created_at") but each time I get this exception from Carbon:
InvalidArgumentException
Unexpected data found. Trailing data
If I change it to just created_at instead of employing MySQL's DATE_FORMAT() function, then it gets the data without issue.
I've not only done this sort of date formatting without issue before, but I checked every field in the database table (there are only 10 for this seed) and each is a standard valid date, so I'm wondering why Carbon is pitching a fit.
Running this in Laravel 4.1.
In an Eloquent query result (model) every date field is a carbon object, it means, if you query a model which contains any timestamp field like created_at, updated_at (basically created using timestamps() during migration) and deleted_at, Laravel converts them to a Carbon object and you may use any public methods of Carbon, for example:
$user = User::find(1);
// '2014-04-20 19:02:09' will become 'Apr 20, 2014'
$user->created_at->toFormattedDateString();
So, you may directly use any public method of Carbon on a timestamp field available in a model. If you try this:
dd($user->created_at);
Then the output will be:
object(Carbon\Carbon)[456]
public 'date' => string '2014-04-20 19:02:09' (length=19)
public 'timezone_type' => int 3
public 'timezone' => string 'UTC' (length=3)
So, if you want to format a date, you may use:
// outputs like: 'Sunday 20th of April 2014 07:02:09 PM'
$user->created_at->format('l jS \\of F Y h:i:s A')
Update:
If you want to change this behavior, means that, if you want tell Laravel that, which fields should be converted automatically to Carbon object then you may override that by creating a method in your model like:
public function getDates()
{
// only this field will be converted to Carbon
return array('updated_at');
}
To totally disable date mutations, simply return an empty array from the getDates method. For more details, check Date Mutators on Laravel website.
I realise the original question refers to MySQL but I had the same error with MSSQL. The problem turned out to be that MSSQL's datetime column type has a precision of .001 seconds but I was setting my model's format to no precision:
protected function getDateFormat()
{
return 'Y-m-d G:i:s';
}
By using the newer DateTime2 column type and turning off the precision, I fixed the error. I.e.
datetime2(0)
You could instead change the format in getDateFormat, of course.
If it helps anyone else, I got the same error when attempting to copy a date.
$user->last_login = Carbon::now();
if ($user->first_login < Carbon::createFromDate(2000, 1, 1)) {
// This is the users first login
$user->first_login = $user->last_login; // FAILS!
}
Turns out Laravel casts the value of $user->last_login to a DateTime+Timezone string. It's no longer a Carbon object.
You could fix the error by using copies of a single Carbon object (example below), or by setting up mutators (setters) on the underlying model.
$now = Carbon::now();
$user->last_login = $now;
if ($user->first_login < Carbon::createFromDate(2000, 1, 1)) {
// This is the users first login
$user->first_login = $now;
}

PHP using Laravel 4 and Carbon will not print out a DateTime field from my Database

I am building a PHP application with Laravel 4.
I am getting errors when I try to print out a DateTime record from the Database though.
{{ $user->created_at }}
Gives me this error
InvalidArgumentException
Trailing data
open: E:\Server\htdocs\projects\timeclock\www\vendor\nesbot\carbon\src\Carbon\Carbon.php
Very frustrating!
An example value from that Database field is: 2013-08-31 20:50:25.
You are missing the milisecond data on the time stamp, you need to use:
Carbon::createFromFormat('Y-m-d H:i:s.u', $value)->format('d/m/Y H:i:s');
You have to format it:
{{ $user->created_at->format('h:i:s') }}
The PHP docs has a list of all the codes available to use as a format.
I have the same issue.
And I found that this is caused by my timestamp data in database.
2013-12-13 22:40:50.561709 <- this one will cause the issue.
2013-12-13 22:40:50 <- this one will not.
Timestamp value with millisecond causes this issue.
Column which is converted to Carbon object can not have millisecond timestamp.(default: created_at, updated_at).
http://readouble.com/laravel/4/2/0/en/eloquent.html#date-mutators
If Carbon Object is not necessary, you can disallow auto-converting.
class SomeModel extends Eloquent {
public function getDates()
{
return array();
}
}
But it also make Carbon methods(ex:->format()) unavailable. You have to format timestamps in other way.

Categories