I am creating a Laravel application. Earlier I used to design the database with the datetime datatypes for created_at and updated_at, but a friend of mine suggested me that I should use timestamp instead of datetime because it's good with different timezones.
Is this a good idea to use timestamp instead of datetime format? Will there be any performance issues? If "No" then how can we change the default format of timestamps from datetime to timestamp globally in a laravel application.
For example (default):
$model->created_at = "yyyy-mm-dd h:i-s";
$model->updated_at = "yyyy-mm-dd h:i-s";
Integer timestamp:
$model->created_at = 1523246567;
$model->updated_at = 1523246567;
Unfortunately, I'm not able to answer your first two questions, but Laravel does provide an easy way to change the format your dates are stored in.
The Date Mutators documentation says that one can set the $dateFormat property on your model like this:
/**
* The storage format of the model's date columns.
*
* #var string
*/
protected $dateFormat = 'U';
The 'U' format would be "Seconds since the Unix Epoch." More formats are available in the php date documentation.
You would also need to change your model's migration. Replace $table->timestamps(); with $table->unsignedInteger('created_at'); and $table->unsignedInteger('updated_at');.
To use a specific date format "globally", i.e. for all of your models, you could either set the date format on a base model and let all of your models inherit that model, or use a trait. See this question for an example.
Related
Im trying to import softDelete to current project. In migration file i added:
$table->softDeletes();
In model. I got this:
protected $dateFormat = 'U';
But deleting not working as i expected.
Invalid datetime format: 1292 Incorrect datetime value: '1579188678' for column 'deleted_at'
So my question is how can i use deleted_at as unix time or how to use deleted_at column as timestamp when protected $dateFormat = 'U'; this was still exist. Thanks in advance.
Since you want to use the Unix timestamp as format, you can't use the ->sofDeletes() and ->timestamps() methods in migration, you need to set them yourself as integers
$table->integer('created_at')->nullable();
$table->integer('updated_at')->nullable();
$table->integer('deleted_at')->nullable();
I have some timestamp records on the DB that have trailing milliseconds at the timestamp and some not have. How to allowing that trailing data (millisecond) in carbon? Is this possible?
Here's the sample of my data
I can't always change the data manually because there are some other services using the same database and sometimes storing timestamp with trailing milliseconds.
As you are using Postgres, your timestamp probably has TIME WITH TIMEZONE
Example: "2018-04-19 07:01:19.929554".
In Such case have to add a date Mutator to your Model.
In your Model add this field for date mutator:
protected $dateFormat = 'Y-m-d H:i:sO';
Alternate Solution:
As you have a mix of timestamps with and without milliseconds I suggest you try this solution using Laravel field mutators:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Parse the created at field which can optionally have a millisecond data.
*
* #param string $created_at
* #return Carbon::Object
*/
public function getCreatedAtAttribute($created_at)
{
// Try to remove substring after last dot(.), removes milliseconds
$temp = explode('.', $created_at);
// If created_at had milliseconds the array count would be 2
if(count($temp) == 2) {
unset($temp[count($temp) - 1]); // remove the millisecond part
} else {
$temp = [$created_at]; // created_at didnt have milliseconds set it back to original
}
return Carbon::parse(implode('.', $temp))->format('Y-m-d H:i:s')
}
}
I have observed in Laravel, storing datetime in database ignores
millisecond field, probably depends on version and db server type.
Also Laravel has whereData() and whereTime() query builders but we
need something like whereDateTimeTz() in all cases.
I recommend storing datetime as unix timestamps in database.
From user timezone convert to GMT and save it to db as millis-timestamp
Carbon::parse('date', 'user_timezone')->setTimezone('GMT')->getPreciseTimestamp(3);
While displaying just convert the db timestamp (GMT) back to user timezone including DST status.
Laravel 7 provides better date parsing by falling back to Carbon::parse if the recevied timestamp from the database doesn't match the expected $dateFormat.
PR: https://github.com/laravel/framework/pull/30628
There is a way to set the default date format of input dates in a model?
I need to create a model with data received in JSON format and date are formatted as Y-m-dTH:i:sP, but date in the DB are stored in the default Y-m-d H:i:s format. I added all the date fields in the $dates property of the model, but now when i create the model setting all the params in the constructor, like this:
$model = new Model($params);
I get a Carbon conversion error (InvalidArgumentException) because it tries to create a Carbon object from the Y-m-d H:i:s format.
I know Date mutators, but if i set
protected $dateFormat = "Y-m-d\TH:i:sP";
it creates the Carbon object correctly but i get an error while storing in the DB, because it tries to store the record with that format.
Is there a standard way to achieve what I need without converting the date format on each date param?
//date format = Y-m-dTH:i:sP
$date = '2011-09-16T11:38:23-05:00';
$new_date = date_format(date_create($date), 'Y-m-d H:i:s');
I store in my database a date format like this:
2017-02-22 16:55:40
I added it to my database like this:
Carbon::now();
I need to check if 4 hours passed since this date.
How I can do this? I couldn't figure out how I can convert this format into Carbon or timestamp.
If you are using Laravel and the date is a Carbon instance from a Model you have access to the whole Carbon API.
You can use the Difference API of Carbon for this specific purpose.
echo $model->thedate->diffInHours($now, false);
If your model does not threat the date as a carbon instance you can cast it by adding the date to the dates array of the current model like so
protected $dates = [
'field_name',
];
Check out Date casting for more information
Update with an explicit example
$user = User::first();
// This will return the difference in hours
$user->created_at->diffInHours(Carbon\Carbon::now(), false);
You can convert it to a Carbon object with:
Carbon::parse('2017-02-22 16:55:40');
How to get only date on database column, I have difficulties using Carbon on controller:
$data['nowUser'] = User::where('date', Carbon::today()->toDateString())->get();
Date column looks like this in the database:
That is a DATETIME column, so there's no need for additional formatting the Carbon instance. However you need to use whereDate if you want the fetch all users for which the date column contains today's date:
$data['nowUser'] = User::whereDate('date', '=', Carbon::today())->get();
Because when you pass Carbon::today() to the Query Builder method, the __toString method will be automatically called and return a DATETIME string with the format from Carbon::DEFAULT_TO_STRING_FORMAT, which is exactly that MySQL format Y-m-d H:i:s.