This question already has answers here:
Calculating the difference between two times using php, and then adding it to a total of time type
(2 answers)
Closed 9 years ago.
Hi I have values stored in MSSQL database as time(7)
job_start
job_end
I am trying to work out the difference between these two times using php, i have the folowing code
$start = $model->job_start;
$end = $model->job_end;
$diff = date( "h:i:s", strtotime($end) - strtotime($start) ) ;
echo $diff ;
However the output is
03:06:00
Rather than
00:06:00
By the way the difference is 6 minutes (360 seconds), can anyone help get this in the right format so i can save it ?
This question has been marked as a duplicate, however it is a different question as this addresses a specific timezone question when using the date function. And has been answered as such.
EDIT
The code i have marked answered the question i asked however I am trying to add an extra calculation as follows
$start = $model->job_start;
$end = $model->job_end;
$total = $model->customer->total_time;
//adding time difference to total time used for that customer
$dt = strtotime($total) + strtotime($end) - strtotime($start);
$hours = floor($dt / 3600);
$minutes = floor($dt / 60) - $hours * 60;
$seconds = $dt - $hours * 3600 - $minutes * 60;
// Padded values
$hours = str_pad($hours, 2, STR_PAD_LEFT, '0');
$minutes = str_pad($minutes, 2, STR_PAD_LEFT, '0');
$seconds = str_pad($seconds, 2, STR_PAD_LEFT, '0');
$output = "{$hours}:{$minutes}:{$seconds}" ;
//display
echo '<br> Start time : '. $start;
echo '<br> End time : '. $end;
echo '<br> total time + time difference : '. $output;
echo '<br> Total time for Customer : '. CHtml::encode($model->customer->total_time);
I am trying to add the difference between the total times to a total time variable
However when output is echoed i get this display
Start time : 11:45:00.0000000
End time : 12:45:00.0000000
total time + time difference : 382015:00:00
Total time for Customer : 09:00:00.0000000
Note that the total time + time difference has extra digits before it , its probably a simple mistake on my part but I can't see it , any help would be appreciated
Why not do this in the database
SELECT TIMESTAMPDIFF(SECOND, job_start, job_end);
Its faster and it is clearer for others to see what you are trying to do.
First of all, date gives date since Unix epoch (1970-01-01 00:00:00) so the odd three hour difference you see there is your timezone. You need to parse the hours, minutes and seconds separately.
<?php
$end = '2013-07-30 23:27:00';
$start = '2013-07-30 21:23:56';
$dt = strtotime($end) - strtotime($start);
$hours = floor($dt / 3600);
$minutes = floor($dt / 60) - $hours * 60;
$seconds = $dt - $hours * 3600 - $minutes * 60;
// Padded values
$hours = str_pad($hours, 2, STR_PAD_LEFT, '0');
$minutes = str_pad($minutes, 2, STR_PAD_LEFT, '0');
$seconds = str_pad($seconds, 2, STR_PAD_LEFT, '0');
$output = "{$hours}:{$minutes}:{$seconds}";
Related
I am creating a timesheet whereby it shows expected and actual hours.
The durations are saved like the below
23:15 - 23 hours and 15 mins
25:45 - 25 hours and 45 mins
I need to work out the difference in hours and mins between the two (extra hours worked)
I have tried the below
$acutal=='23:15';
$expected=='25:45';
$start_time = new DateTime("1970-01-01 $acutal:00");
$time = $start_date->diff(new DateTime("1970-01-01 $expected:00"));
This does work, however when the hours are over 24:00 it throws an error (obviously because it's reading it as time)
Uncaught exception 'Exception' with message 'DateTime::__construct():
Failed to parse time string (1970-01-01 25:45:00)
Is there another way to do this?
You could check if the number of hours are greater than 24, and if so, add a day, and remove 24 hours.
$actual='23:15';
$expected='25:45';
$day = 1;
list($hrs, $min) = explode(':', $expected);
if ($hrs > 24) { $day += 1; $hrs -= 24; }
$start_time = new DateTime("1970-01-01 $actual:00");
$time = $start_time->diff(new DateTime("1970-01-$day $hrs:$min:00"));
echo $time->format('%hh %Im');
Output:
2h 30m
Please also note that == is used to compare, not to assign.
You can also change the if ($hrs > 24) by while(), if there is 48 hours or more.
edit
As pointed out by #CollinD, if the time exceed the number of days of the month, it will fail. Here is another solution:
$actual='23:15';
$expected='25:45';
list($hrs, $min) = explode(':', $actual);
$total1 = $min + $hrs * 60;
list($hrs, $min) = explode(':', $expected);
$diff = $min + $hrs * 60 - $total1;
$start_time = new DateTime();
$expected_time = new DateTime();
$expected_time->modify("+ $diff minutes");
$time = $start_time->diff($expected_time);
echo $time->format('%hh %Im');
You can do it manually by keeping track of the number of minutes worked - this will be exact and will also allow you to show negative differences.
<?php
// get the difference in H:mm between two H:mm
function diff_time($actual, $expected) {
$diff_mins = mins($actual) - mins($expected);
return format_mins($diff_mins);
}
// convert a HH:mm to number of minutes
function mins($t) {
$parts = explode(':', $t);
return $parts[0] * 60 + $parts[1];
}
// convert number of minutes into HH:mm
function format_mins($m) {
$mins = $m % 60;
$hours = ($m - $mins) / 60;
// format HH:mm
return $hours . ':' . sprintf('%02d', abs($mins));
}
var_dump(diff_time('23:15', '25:45'));
var_dump(diff_time('25:15', '23:45'));
This outputs:
string(5) "-2:30"
string(4) "1:30"
.. first, 2:30 less than expected, for the second 1:30 more than expected.
You can try using datetime functions but it seems a lot more straightforward to me to treat the times as string, use split or explode to get hours and minutes, convert to integers, get the difference in minutes and convert it back to hours and minutes (integer divide by 60 and remainder).
$t1=explode(':',$expected);
$t2=explode(':',$actual);
$d=60*($t1[0]-$t2[0])+t1[1]-t2[1];
$result=str_pad(floor($d/60),2,'0',STR_PAD_LEFT).':'.str_pad($d%60,2,'0',STR_PAD_LEFT);
I'm currently working with a timekeeping system which computes the sum of the basic hours of the week and deduct certain time if there's a late record.
Given that the employee has a total hours rendered for this week is 45 hours (45:00), and he she/has a total late record for that week of 50 minutes (00:50),
Using, PHP. How can I deduct the late record to the total hours rendered without converting time to decimal? The desired output for the above sample is 44:10 since 00:50 is deducted to 45:00.
I see so your goal is to subtract durations ex.
45:00 - 00:50 = 44:10
1: Create a function that convert them into hours
function convertToHours($duration) {
$duration = explode(':',$duration);
$hours+= (int)$duration[0];
$hours+= (int)$duration[1] / 60;
return $hours;
}
2: Create a funciton thats convert from seconds to duration hours:seconds
function secondsToDuration($seconds) {
$H = floor($seconds / 3600);
$i = ($seconds / 60) % 60;
$s = $seconds % 60;
return sprintf("%02d:%02d:%02d", $H, $i, $s);
}
Convert them into hours using function created
$duration1 = convertToHours("25:00");
$duration2 = convertToHours("00:50");
Then subtract them
$difference = $duration1 - $duration2;
Lastly use the created method which convert them back into duration
$duration = secondsToDuration($difference * 3600);
See Demo here
Hope it helps you
You can convert the string to a date and get the difference.
$d1 = "00:45:00";
$d2 = "00:00:50";
date_default_timezone_set("utc");
$fakedate = '01/01/2017';
$d1 = $fakedate . ' ' . $d1;
$d2 = $fakedate . ' ' . $d2;
$dt1 = new DateTime($d1);
$dt2 = new DateTime($d2);
$diff = $dt1->diff($dt2);
echo $diff->format("%H:%I:%S");
The output will be: 00:44:10
I have two integers that are $hours = 74 and $minutes = 20, the format I need to get them in is following: hours and minutes (without any spacing) in percentage of one hour. So in this case the final result should be 7433.
Just to make it more clear if the two numbers would be $hours = 74 and $minutes = 30, the final result should be 7450.
I have been trying to look for similar functions, but without any success.
Any help or guidance is much appreciated.
So really what you are looking for is $result = $hours . floor($minutes/60*100); ?
Or if you need the leading zeroes: $result = str_pad($hours,2,'0') . str_pad(floor($minutes/60*100),2,'0');
Save yourself the pain of coming up with code that handles cases where the value of $minutes >= 60 by using the DateTimeInterface objects. I admit, they may seem overkill in this situation, but they are very sturdy and reliable. Plus, if ever you'd want to add days, weeks, months, years or seconds to this code, the DateTimeInterface classes are already equipped for the job:
$now = new DateTime();
$comp = clone $now;
//2 identical datetime instances
//add hours + minutes to either one
$comp->add(
sprintf(
'PT%dH%dM',
$hours,
$minuts
)
);
//get difference in seconds
$diff = $comp->getTimeStamp() - $now->getTimeStamp();
//or echo, I used printf to limit the number of decimals to 2
printf(
'%.2f hours difference'
$diff/3600 //1 hour === 3600 seconds
);
Just browse the DateTime docs, and other classes/interfaces like DateInterval and others implementing the DateTimeInterface.
Just for completeness, here's how I'd set about doing this "manually"
$decimalT = $hours + floor($minutes/60) + ($minutes%60)/60
//add hours in case $minutes>= 60
//floor($minutes/60);
//get remainder minutes, converted to decimal hours
//($minutes%60)/60;
printf(
'%d hours + %d seconds == %.2f hours',
$hours,
$minutes,
$decimalT
);
Use this snippet of code:
$hours = 74;
$minutes = 20;
$totalMinutes = $hours * 60 + $minutes;
$percentage = floor(($totalMinutes * 100) / 60);
var_dump($percentage);
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Converting Seconds to HH:MM:SS
I have an integer as a number of seconds. I want to convert that integer into into hours/minutes/seconds like this:
1:45:32
If the number of seconds equates to less than one hour then it should return the string:
45:32
If the number of minutes is less than 10 it should return the string formatted like this:
3:25
And finally if the number of seconds equate to less than 1 minute, it should return the following:
0:04
What is the best way to do this in PHP?
The simpelst approch would be
if($seconds < 3600){
$format = 'i:s';
}else{
$format = 'G:i:s';
}
echo date($format, $seconds);
EDIT: this wouldnt fix your minutes < 10 problem.
you could handle the minutes by itself. like
$time = ($seconds >= 3600) ? date('G', $seconds).':' : '';
$time .= intval(date('i',$seconds)).':'.date('s', $seconds);
<?php
$seconds = (1*60 + 45)*60 + 32; // 1:45:32
define("SECONDS_IN_HOUR", 3600);
define("SECONDS_IN_MINUTE", 60);
// hours
if ($seconds >= SECONDS_IN_HOUR)
{
print floor($seconds/SECONDS_IN_HOUR) . ":";
$seconds = $seconds % SECONDS_IN_HOUR;
}
// minutes
if ($seconds >= SECONDS_IN_MINUTE)
{
print floor($seconds/SECONDS_IN_MINUTE) . ":";
$seconds = $seconds % SECONDS_IN_MINUTE;
}
// seconds
print $seconds;
?>
I think Rufinus is pretty close:
foreach(array(60 => ' 0:s', 3600 => 'i:s', 'G:i:s') as $val => $format)
{
if ($seconds < $val) break;
}
echo ltrim(ltrim(gmdate($format, $seconds), '0'), ' ');
This variant uses a configuration stored inside an array which associates a format string based on a time value in seconds (as key). The last element is the default format that will fall through.
Edit: Unfortunately there is no formatting code in date that allows to specify minutes w/o a leading there. Therefore the date string needs to be re-formatted to remove leading 0's occasionally. It's done with ltrim here.
function formatHMS($time) {
$s = $time % 60;
$time= floor($time/60);
$m = $time % 60;
$time= floor($time/60);
$h = floor($time);
$str = $s;
if ($m>0)
$str = "$m:$str";
if ($h>0)
$str = "$h:$str";
return $str;
}
Consider using explode() & implode() and then apply your logic of less-than & greater-than!
This question already has answers here:
Get interval seconds between two datetime in PHP?
(8 answers)
Closed last year.
HI, i have a couple of posts in my MySql database server, one of the info content in each post is the date and time in the format datetime (Ex. 2010-11-26 21:55:09) when the post was made.
So, i want to retrive the actual date and time from the SQL server with the function NOW() and calculates how many seconds or minutes or hours or days ago was post the info.
I dont know how to create this php script but i know that for sure is allready made, so thanks for any help.
you could use the date_diff() function
http://php.net/manual/en/function.date-diff.php
Something like...
<?php
$now = time();
$then = $posttime;
$diff = date_diff($now,$then);
echo $diff->format('%R%d days'); #change format for different timescales
?>
edit --
I actually solve this issue on one of my twitter apps using this function...
function time_since ( $start )
{
$end = time();
$diff = $end - $start;
$days = floor ( $diff/86400 ); //calculate the days
$diff = $diff - ($days*86400); // subtract the days
$hours = floor ( $diff/3600 ); // calculate the hours
$diff = $diff - ($hours*3600); // subtract the hours
$mins = floor ( $diff/60 ); // calculate the minutes
$diff = $diff - ($mins*60); // subtract the mins
$secs = $diff; // what's left is the seconds;
if ($secs!=0)
{
$secs .= " seconds";
if ($secs=="1 seconds") $secs = "1 second";
}
else $secs = '';
if ($mins!=0)
{
$mins .= " mins ";
if ($mins=="1 mins ") $mins = "1 min ";
$secs = '';
}
else $mins = '';
if ($hours!=0)
{
$hours .= " hours ";
if ($hours=="1 hours ") $hours = "1 hour ";
$secs = '';
}
else $hours = '';
if ($days!=0)
{
$days .= " days ";
if ($days=="1 days ") $days = "1 day ";
$mins = '';
$secs = '';
if ($days == "-1 days ") {
$days = $hours = $mins = '';
$secs = "less than 10 seconds";
}
}
else $days = '';
return "$days $hours $mins $secs ago";
}
You pass it in a unix timestamp of the time to check (the post time) and it returns the various string.
As billythekid said, you can use the date_diff() function if you are using PHP5.3+, if you are not then there are various methods. As shown by other posters. The quickest method in MySQL if you want to know the time split in to the "hours:mins:secs" hierarchy is to use the TIMEDIFF() function.
SELECT TIMEDIFF(NOW(), '2010-11-26 12:00:00');
If you want it as seconds, use the unix timestamp features in MySQL or in PHP, you can convert MySQL dates to PHP quickly using strtotime().
Usually, you do this kind of thing in a query, but MySQL isn't very good with intervals (it would be very easy with PostgreSQL). You could convert it to unix timestamp, then it would give the number of seconds between the two dates :
SELECT UNIX_TIMESTAMP() - UNIX_TIMESTAMP(your_datetime_column);
I thought about DATEDIFF, but it only returns the number of days between the two dates.
You can do it in PHP, for instance, with DateTime class :
$date1 = new DateTime();
$date2 = new Datetime('2010-11-26 12:00:00');
var_dump($date1->diff($date2));
(There's a procedural way to do this, if you're not a fan of OOP.)
This is definitely the solution I'd use if I can't do it with the RDBMS. DateTime::diff returns a DateInterval object, which contains the number of seconds, minutes, hours, days, etc. between the two dates.
You could also do it with timestamps in PHP :
$num_sec = time() - strtotime('2010-11-26 12:00:00');
Which would return the same thing as the SQL query.
An easy solution is possible from within the SQL Query:
SELECT UNIX_TIMESTAMP(NOW()) - UNIX_TIMESTAMP(post_date) AS seconds_ago FROM posts
Documentation here: MySQL Ref
I actually needed to do this in PHP myself and while billythekid's post was in the right direction it fell short. I've minimized the code though it should be clear that the second parameter is from a database with a DATETIME column type.
<?php
$interval = date_diff(date_create(date('Y-m-d H:i:s')), date_create($row1['date']));
echo $interval->format('%R%a days');
//Database: 2019-02-22
//PHP's date: 2018-07-07
//Result: +306 days
?>
A reminder of the obvious: you can also just use substr($interval->format('%R%a days'),1) if you need just the integer.