Laravel - different formats for date/time query - laravel

I am learning Laravel and I have some small problem on controllers - when I use DB, the query returns date time without timezone but if I use model, the query returns full datetime.
public function test($switch)
{
//return "YYYY-MM-DDThh:mm:ss.000000Z"
if ($switch) return Position::select('id','created_at')->orderBy('id')->get();
// return "YYYY-MM-DD hh:mm:ss"
return DB::table('positions')->select('id','created_at')->orderBy('id')->get();
}
Why? What I need to dof I want "YYYY-MM-DDThh:mm:ss.000000Z" on both cases?
Thanks for solution.
thanks for advice

You should use the DB::raw
The following statement will convert the datetime value created_at from +00:00 timezone to +10:00 timezone.
You can try this
return DB::table('positions')->select(DB::raw('id',CONVERT_TZ('created_at','+00:00','+10:00'))->orderBy('id')->get();
you can set your timezone that you wants to convert it

They are the same data, probably just different classes of date and you can always format your date. Laravel utilizes Carbon date library which is excellent and should be used primarily.
If you try to print out your date class with get_class() for Eloquent Position created_at, you probably got Carbon and DB::table('positions') created_at, you probably got DateTime and that's why the value looks different (but you still got the same date).
If you want to convert your DateTime to Carbon, you can do
$newDate = new \Carbon\Carbon($position->created_at)

Thanks Anurat,
I realized this fact shortly after sending the previous question.
... but there is another 'issue' - both times are my local time - time in "YYYY-MM-DDThh:mm:ss.000000Z" is not UTC time as I expected.
I changed my function:
public function test($switch = false)
{
$data = Position::selectRaw('id, created_at, UNIX_TIMESTAMP(created_at) unix')->orderBy('id')->get();
foreach ($data as $d) {
$conv = new \DateTime($d->created_at);
$d->conv = intval($conv->format('U'));
$d->diff = $d->conv - $d->unix;
}
return $data;
}
... and result is
0
id 1
created_at "2021-03-18T12:36:59.000000Z"
unix 1616067419
conv 1616071019
diff 3600
As you see, the difference is 1 hour (as my timezone offset). Where is a problem?
Thanks.

Related

Correct time-zone for carbon on many records

So i'm trying to set correct time-zone on Carbon::today() for getting all of the results created for this day.
Let's explain a little bit more.
I have a command that archive the Notes when created_at column is today, so I get all Notes that are created today and check them in foreach based on Building model timezone
Database structure:
Buildings:
-id
-name
-timezone
Notes:
-id
-name
-created_at
-updated_at
-building_id (reference id on buildings)
My code:
$notes = Note::where('archived', null)
->whereDate('created_at',Carbon::today())
->get();
foreach($notes as $note) {
// Set the current timezone
date_default_timezone_set($note->building->timezone)
$note->update([
'archived' =>1,
'archived_at'=>Carbon::now()
]) // update archive status etc...
}
I want Carbon::today() to be with the current timezone of the record building.
I've tried with query something like that but still the issue is not solved:
select
*
from
`notes`
inner join `buildings` on `notes`.`building_id` = `buildings`.`id`
where
date(`notes`.`created_at`) = CONVERT_TZ('NOW()', 'UTC', `building`.`timezone`);
Is there any way to do that? Thanks. :)
date_default_timezone_set is as the name says for the default, you should not change the default timezone multiple times during the same process.
Actually it should just always stay UTC so you easily scale and share it outside, then you can simply get now or today for a given timezone:
Carbon::today($note->building->timezone)
Carbon::now($note->building->timezone)
But a better solution is to have also your dates stored as UTC in your DB, so you convert created_at from timezone to UTC instead of converting NOW from UTC to building.timezone, it would a better approach for data consistency in your DB.

Laravel Carbon allow trailing data at Postgresql Timestamp

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

How to add minutes to to a date in laravel

There are few ways that I can do this using PHP but I could not find a way to do that using laravel specific way.
I have a time that is coming from database in below format: Y:M:s
ex: 05:15:00
This is what I want to do:
add 30 minutes to that date, according to above example result should be: 05:45:00
Below is my current code and I want to add 30min to $endTime:
//get database value according to selected date
$allocatedDateQuery = DB::table('appointments')->where('date', $request->date)->get();
//loop throug every record to get time
foreach ($allocatedDateQuery as $value) {
$time = $value->time;
$endTime = $time;
}
I just got a perfect solution from here.
Use Carbon extention to simply acheive that.
What you have to do is parse your time to Carbon object and then you can use addMinutes() to do that and then you can format() if you want:
foreach ($allocatedDateQuery as $value) {
$time = Carbon::parse($value->time);
$endTime = $time->addMinutes(30);
$allocateValidateMessage .= Carbon::parse($value->time)->format('H:i') . ' - ' . $endTime->format('H:i') . ' ';
}
Usually I use php's date, you can give this a try
Date("Y:M:s", strtotime("30 minutes", strtotime($value->time))
That is converting your time into a string, adding 30minutes to it and converting it to the date format of your desire
Since you said you are grabbing the date from the database I am assuming you are also using Eloquent to query from the database.
You can use Eloquent Mutator Method in your Database Modal Class to mutate the data like this:
public function getAppointmentsAttribute($value) {
return Date("Y:M:s", strtotime("30 minutes", strtotime($value->time)));
}
You can even add another attribute without mutating the original value using Attribute assignments as well. This method caches your query and reduces database calls. Since you do not need to run local loops on the record your code is much cleaner.

Converting String Values into Date using Carbon Laravel

The sql field type is VARCHAR, I am saving date and time from an API. The format that I get is 2018-04-28T22:17:41+05:30. Now I need to convert this using carbon to get a format like 04 April 2018 and timings. I couldn't convert varchar filed value into date format which I needed.
And the expected format should be passed to view, I did that using ( $ticket->dateOfIssue and it's giving this - 018-04-28T22:17:41+05:30 ). But as I said, I need the expected format (which is 04 April 2018, time ).
You should either use Accessor on your model or set the datetime format on your model. The example of the former is:
use Carbon/Carbon; before your class declaration
public function getDateOfIssueAttribute($value) {
return Carbon::parse($value)->format('d M Y , H:m:s');
}
When ever you retrieve this model anywhere you already have it in the format you set in your accessor.
Here is an example to parse the date
Carbon::parse('2018-04-28T22:17:41+05:30')->format('dd MM YYYY');
Moreover, do not forget to import the Carbon namespaces on the top
You try
use use Carbon\Carbon; // on top
$time = Carbon::parse('2018-04-28T22:17:41+05:30')->format('d M Y'); //28 Apr 2018
Good luck
This is the exact format for date and time. First of all include carbon library in your controller
use Carbon\Carbon;
class abc extend Controller
{
public function cancell()
{
$ticket = Booking::all()->where('status', '=', 'CANCELLED');
$dateOfIssue=$ticket->dateOfIssue;
$time = Carbon::parse($dateOfIssue)->format('d M Y , H:m:s');
return view('Admin.Tickets.cancelledTickets')->with('ticket', $ticket);
}
}
If you have multiple records then you can use loop for that
Please try ,
\Carbon\Carbon::parse('2018-04-28T22:17:41+05:30')->format('d- M- Y');
the output is 28- Apr- 2018
using sql
DATE_FORMAT(mydate, '%d-%M-%Y')

how to select one month back records from data base in laravel

how select one month back records from current date from database in laravel. I am trying this code.
This is controller code.
class LoginHistoryController extends Controller {
public function index()
{
$login_history = LoginHistory::where('login_date','BETWEEN', '(CURDATE() -
INTERVAL 10 DAY) AND CURDATE()' )->get();
}
}
but i am getting error.
I will have a approach something like this. First I will calculate the date like
$today = date('Y-m-d');
$date = date_create($today);
date_sub($date, date_interval_create_from_date_string("30 days"));
$beforeOneMonth = date_format($date, "Y-m-d");
You should have the intended value in $beforeOneMonth by now. Now you can compare it in anyway you like whether you use IN operator or >=. For eg.
$login_history = LoginHistory::where('login_date','>=', $beforeOneMonth)->get();
Give it a try. If you are storing date in some other format, you can do your own tricks to format the date and do the thing
Another way to do it would be with whereRaw:
$login_history = LoginHistory::whereRaw(
'login_date BETWEEN (CURDATE() - INTERVAL 10 DAY) AND CURDATE()'
)->get();
Note that whereRaw has the side effect of making your code less portable since you're using SQL that might be specific to your database server. But sometimes you just can't do what you would like using the query builder.

Resources