I have a field in my DB which has a time stamp using moment js. The result is like so.
["2018-02-11 11:30:17","2018-02-11 11:20:17","2018-02-11 11:10:17"]
But when i return created_at colum from db the array is given like so:
[{"date":"2018-02-11 11:40:17.000000","timezone_type":3,"timezone":"Asia\/Karachi"},{"date":"2018-02-11 11:40:31.000000","timezone_type":3,"timezone":"Asia\/Karachi"},{"date":"2018-02-11 11:40:40.000000","timezone_type":3,"timezone":"Asia\/Karachi"}]
So how can i take two column dates in a format where carbon can understand? I want the "starttime" column to compare with "created_at". Is this achievable? Here is my code so far:
$cleanStart = Clean::pluck('starttime')->toArray();
$cleanFinish = Clean::pluck('created_at')->toArray();
$from = Carbon::parse($cleanStart);
$to = Carbon::parse($cleanFinish);
$diff_in_hours = $to->diffInHours($from);
return $diff_in_hours;
But it gives me an error:
Type error: DateTime::__construct() expects parameter 1 to be string, array given
Also how can i give the array to carbon.
So finally here is the thing i tried:
$cleanCollection = Clean::get(['starttime','created_at']);
foreach($cleanCollection as $cleanObj){
$startTime = Carbon::parse($cleanObj->starttime);
$diff = $cleanObj->created_at->diffInseconds($startTime);
}
echo $diff;
But when ever i refresh the page, the value changes in seconds. and if another record is added, it adds up again.
Pluck will give you an array of all of the start times from your result set which is why you're passing an array into parse. You're actually getting all of the start times and all of the created ats then trying to compare all to all, effectively.
You either need to get a single result,
Like
$clean = Clean::first();
$from = Carbon::parse($clean->starttime);
$to = Carbon::parse($clean->created_at);
$diff_in_hours = $to->diffInHours($from);
Or if you wanted it for each row you'd have to iterate over them and do much the same
Clean::all()->each(function ($clean) {
$from = Carbon::parse($clean->starttime);
$to = Carbon::parse($clean->created_at);
$diff_in_hours = $to->diffInHours($from); // for this row
});
The other thing you could do is put an accessor on your Clean model to help you out with this
public function getDiffInHoursAttribute()
{
$from = Carbon::parse($this->starttime);
$to = Carbon::parse($this->created_at);
return $to->diffInHours($from);
}
Then
echo Clean::first()->diffInHours;
Or
foreach(Clean::all() as $clean) {
echo $clean->diffInHours;
}
Also, if you add the following to your model, Eloquent will automatically parse the strings into Carbon objects so you can skip the need for Carbon::parse() in your code
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = [
'starttime'
];
Try adding protected $dates to your Clean model, like this:
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = [
'created_at',
'updated_at'
];
As you can read from the comments inside the code, put all of the columns that should be converted to dates inside, this will help you achieve date manipulations easier.
EDIT 1:
$start = new Carbon($cleanStart['date'], $cleanStart['timezone']);
$finish = new Carbon($cleanFinish['date'], $cleanFinish['timezone']);
Then you can compare like this:
var_dump($start->eq($finish)); //Is start date same as finish date
var_dump($start->ne($finish)); //Is start date not same as finish date
var_dump($start->gt($finish)); //Is start date greater than finish date
var_dump($start->gte($finish)); //Is start date greater than or equal to finish date
var_dump($start->lt($finish)); //Is start date less than finish date
var_dump($start->lte($finish)); //Is start date less than or equal to finish date
EDIT 2:
In order for the code underneath to work, you must initialize $start and $finish dates as in EDIT 1
$ago = $start->diffForHumans($finish, true); //2 days OR 3 weeks OR 1 hour
Related
i want to make time slot between the start time and end time and show the disponibility of the user but i get this error : strtotime() expects parameter 1 to be string, array given
this is the controller :
$model=doc::findOrFail($ID);
$ReturnArray = array ();// Define output
$StartTime = strtotime ($model->Lun_mat_de) ; //Get Timestamp
$EndTime = strtotime ($model->Lun_mat_a); //Get Timestamp
$duration = '60';
$AddMins = $duration * 15;
//Run loop
while ($StartTime <= $EndTime) {
$ReturnArray[] = date ("G:i", $StartTime);
$StartTime += $AddMins; //Endtime check
}
return view ('/rendezvous',['go'=> $model],['jaja'=>$ReturnArray] );
this is the view :
<div class="div1" ></div>
#foreach($jaja as $ja)
<button class="btn btn-info"> {{$ja}} </button> </br>
#endforeach
this is the model :
protected $table = 'doctor' ;
protected $casts = [
'Lun_mat_de' =>'array',
'Lun_apres_a' =>'array',
];
The value $model->Lun_mat_de is an array variable type rather than a string, as expected.
From Comments:
what does print_r($model->Lun_mat_de) show?
["8:30","12h30"]
Right, that is an array, which of these values do you want to be turned into a time value?
Lun_mat_de' and 'Lun_mat_a'
No, You have told me that $model->Lun_mat_de gives you an array of two values, you need to choose which of these two values you want the PHP function strtotime to work on. 8:30 or 12h30?
oh sorry yes 8:30
Ok,
So to get the strtotime function to work on 8:30 you would put:
$StartTime = strtotime ($model->Lun_mat_de[0]); //8:30
To get the strtotime function to work on the other value, the 12h30 then you would reference the other array value:
$StartTime = strtotime ($model->Lun_mat_de[1]); //12h30
(I assume here the array is integer keyed)
Recommended Reading:
Please read the PHP Manual entry on array, string types as well as the function strtotime.
Also you should actually probably be using the DateTime function going forward.
You defined in you model casts Lun_mat_de => array so $model->Lun_mat_de always returns you an array. so strtotime ($model->Lun_mat_de) will crash. fix the casts field
I need to compare two dates and find which date is greater.
$actual_date = Carbon::createFromFormat('d-m-Y',$night_out->actual_return_date);
$expected_date = Carbon::createFromFormat('d-m-Y', $night_out->expected_return_date);
$days = $expected_date->diffInDays($actual_date); // gives the days count only
Thanks in Advance!
You can use carbon method greaterThan()
if($actual_date->greaterThan($expected_date)){
// logic here
}
Carbon is an extension of datetime and inherits all properties of the base class. DateTime objects and thus carbon objects are directly comparable. Special comparison methods are not needed for this case.
if($actual_date > $expected_date){
// do something
}
If only the date which is greater is needed, you can do that
$max_date = max($actual_date , $expected_date);
Note: $ max_date is an object reference of $actual_date or $expected_date. You can get a copy with the copy () method or use clone.
$max_date = max($actual_date , $expected_date)->copy();
Use gt function for that:
$actual_date = Carbon::createFromFormat('d-m-Y',$night_out->actual_return_date);
$expected_date = Carbon::createFromFormat('d-m-Y', $night_out->expected_return_date);
if($expected_date->gt($actual_date)){
return $expected_date; //Max date
} else {
return $actual_date; //Min date
}
OR:
You need to find a greater date from two dates using max and array_map function like:
$actual_date = Carbon::createFromFormat('d-m-Y',$night_out->actual_return_date);
$expected_date = Carbon::createFromFormat('d-m-Y', $night_out->expected_return_date);
// store dates value into an array to find the max date.
$date = array();
$date['actual_date'] = $actual_date;
$date['expected_date'] = $expected_date;
$max = max(array_map('strtotime', $date));
echo date('d-m-Y', $max);
I need to retrieve all items of a particular type with Doctrine, where the 'date' field is stored as DateTime. Which means I'm working with the PHP DateTime object as well.
I need to do two things overall: if given a month and year, retrieve all records for that month and year; and if not given a month and year, retrieve all records for this month.
I've been looking at using BETWEEN statements in the Doctrine Query Builder, but can't figure out how to cleanly extract the month and year from PHP DateTime objects created 'now' so that the time portion of DateTime doesn't affect the query. I also can't see a way of just setting the day portion of the Date in DateTime to be 01 either, without affecting the month and year.
I thought this would be a fairly standard task but can't find a solution. Any help appreciated.
EDIT:
Found a hacky way to get the dates for between, but Doctrine is returning an empty array. Using the following code
/**
* Returns feed for month and year
*/
public function getMonthYearFeed($month, $year)
{
// Create two times at the start of this month and next month
$startDate = \DateTime::createFromFormat('d-n-Y', "01-".$month."-".$year);
$startDate->setTime(0, 0 ,0);
$endDate = \DateTime::createFromFormat('d-n-Y', "01-".($month+1)."-".$year);
$endDate->setTime(0, 0, 0);
$notes = $this->em->getRepository('AppBundle:Note')->createQueryBuilder('n')->where('n BETWEEN :start AND :end')->setParameter('start', $startDate->format('Y-m-d H:i:s'))->setParameter('end', $endDate->format('Y-m-d H:i:s'))->getQuery()->getResult();
return $notes;
}
Putting something like this in your Repository should get you started. I haven't tested it aside from the 'last day of this month' bit which seems to work fine.
/**
* #param int $month
* #param int $year
*
* #return object[]
*/
public function findByDate($year = null, $month = null)
{
if ($month === null) {
$month = (int) date('m');
}
if ($year === null) {
$year = (int) date('Y');
}
$startDate = new \DateTimeImmutable("$year-$month-01T00:00:00");
$endDate = $startDate->modify('last day of this month')->setTime(23, 59, 59);
$qb = $this->createQueryBuilder('object');
$qb->where('object.date BETWEEN :start AND :end');
$qb->setParameter('start', $startDate->format('Y-m-d H:i:s'));
$qb->setParameter('end', $endDate->format('Y-m-d H:i:s'));
return $qb->getQuery()->getResult();
}
Very importand moment. Use data type of setParameter.
Like this for symfony.
use Doctrine\DBAL\Types\Type;
$query->setParameter('start', $startDate, Type::DATETIME);
This appears to be working, although I will definitely need to modify the way I construct the dates (and move the function into the repo). I had originally forgotten the '.date' bit of DQL, and there was no need to output the DateTime object as a format.
// Create two times at the start of this month and next month
$startDate = \DateTime::createFromFormat('d-n-Y', "01-".$month."-".$year);
$startDate->setTime(0, 0 ,0);
$endDate = \DateTime::createFromFormat('d-n-Y', "01-".($month+1)."-".$year);
$endDate->setTime(0, 0, 0);
$notes = $this->em->getRepository('AppBundle:Note')->createQueryBuilder('n')->where('n.date BETWEEN :start AND :end')->setParameter('start', $startDate)->setParameter('end', $endDate)->getQuery()->getResult();
// $notes = $this->em->getRepository('MrshllSiteBundle:Note')->findByDate();
return $notes;
I need to change the shiftdate variable after 05:30 AM. Since i need to generate data from past 24 hrs starting 05:31 AM to Next day 05:30 AM. I tried like this, but its giving previous day every time. Please help.
I want $shiftdate to use in my sql query;
Code:
<?php
if(date('H:i')>="00:00" || date('H:i')<"05:30"){
$shiftdate= date('Y-m-d',strtotime(date('Y-m-d'))-24*60*60);
}
else if(date('H:i')>"05:30" || date('H:i')<"00:00")
{
$shiftdate=date('Y-m-d');
}
echo $shiftdate;
?>
You can't just compare string like "05:30" as a number and hope for the best. You need to compare numerical value of the hour and then numerical value of the minute.
You have a race in between the first if and the else if
Also the else if doesn't cover it completely, so if it hit's the sweetspot, you can end up with $shiftdate being NULL.
Make it a function with protoype shiftdate_type_whatever_it_is fn_name(int hour, int minute);. This way you can simply unit test the function for different (think boundary) values of the date("H:i");
You can use the DateTime classes for this and encapsulate your check into a function:-
/**
* #param DateTime $checkTime
* #return string
*/
function getShiftDate(DateTime $checkTime)
{
$shiftDate = (new DateTime())->setTimestamp($checkTime->getTimestamp());
$hours = (int)$checkTime->format('H');
$minutes = (int)$checkTime->format('i');
$totalMins = $hours * 60 + $minutes;
if($totalMins < 330){
$shiftDate->modify('yesterday');
}
return $shiftDate->format('Y-m-d');
}
var_dump(getShiftDate(new DateTime()));
Obviously the input to the function may need to be modified as I don't know how you get your date/time, but that won't be a problem. Post a comment if you need help with that.
I have a basic table which captures time and attendance.
I'm trying to out put the total hours on site, from my eloquent query:
$attendance = DB::table('staff_attendances')
->whereBetween('in_date', array($date1, $date2))->where('staff_id', $ID)->select('first_name', 'last_name', 'in_date', 'out_date', 'in_time', 'out_time')->get();
I get the following back in json.
[{"first_name":"TestFirst","last_name":"TestLast","in_date":"2016-01-30","out_date":"2016-01-30","in_time":"11:40:34","out_time":"12:41:10"},
{"first_name":"TestFirst","last_name":"TestLast","in_date":"2016-01-30","out_date":"2016-01-30","in_time":"13:02:27","out_time":"14:02:32"}]
Which method would be best to out put total hours on site?
I've tried using carbon with the following:
$startTime = Carbon::parse($attendance->in_time);
$finishTime = Carbon::parse($attendance->out_time);
$totalDuration = $finishTime->diffInHours($startTime);
But I get "Trying to get property of non-object"
Carbon is a class which extends DateTime class. It should deal with date and/or time. But it looks like your parse call don't return a Carbon instance. So I advise you to use a full date format ("Y-m-d H:i:s") as in the following example :
<?php
$totalDuration = 0;
foreach($attendance as $aAttendance){
$startTime = Carbon::parse($aAttendance->in_date.' '.$aAttendance->in_time);
$finishTime = Carbon::parse($aAttendance->out_date.' '.$aAttendance->out_time);
$totalDuration += intval($finishTime->diffInHours($startTime));
}
?>
With the foreach instruction you will go through all the attendances and do the sum of all diffInHours returns in the variable $totalDuration.