问题
I Have a log reading program written in PHP. I want to calculate the time difference of any given two log lines. I found lot of code for calculating the time difference if the two times are give like
$time1='10:15:30'; and $time2='10:15:35';. here the time difference will be 5 seconds.
But here my input times will be as in the following format $time1='10:15:30:300'; and $time2='11:15:35:450';
I want a function which will receive this times as inputs and give the time difference in milliseconds.
Is there any inbuilt php function that can be utilized for this purpose ? or should we write our custom logic to split this time and then calculate the difference ?
回答1:
My suggestion would be to find the difference in seconds first between the 2 times ignoring the milliseconds part.
So say, you have
$time1='10:15:30:300'; $time2='11:15:35:450';
In this case you will see that the seconds difference = 3605 seconds. Now calculate the milliseconds difference and maybe format it as 3605.150
If the milliseconds difference is negative, reduce the second by 1.
回答2:
Two functions which may help you with your time related development and calculations are the following
function find_time_diff($t1, $t2) {
$a1 = explode(":", $t1);
$a2 = explode(":", $t2);
$time1 = (($a1[0] * 60 * 60) + ($a1[1] * 60) + ($a1[2]));
$time2 = (($a2[0] * 60 * 60) + ($a2[1] * 60) + ($a2[2]));
$diff = abs($time1 - $time2);
return $diff;
}
and my favorite... this can return in minutes, days,years and so on
function find_date_diff($start_date, $end_date, $formatreturn = 'minutes') {
list($date, $time) = explode(' ', $start_date);
if ($time == null) {
$time = '00:00:00';
}
if ($date == null) {
$date = date("Y-m-d");
}
$startdate = explode("-", $date);
$starttime = explode(":", $time);
list($date, $time) = explode(' ', $end_date);
if ($time == null) {
$time = '00:00:00';
}
if ($date == null) {
$date = date("Y-m-d");
}
$enddate = explode("-", $date);
$endtime = explode(":", $time);
$secons_dif = mktime($endtime[0], $endtime[1], $endtime[2], $enddate[1], $enddate[2], $enddate[0]) - mktime($starttime[0], $starttime[1], $starttime[2], $startdate[1], $startdate[2], $startdate[0]);
switch ($formatreturn) {
//In Seconds:
case 'seconds':
$choice = $secons_dif;
break;
//In Minutes:
case 'minutes':
$choice = floor($secons_dif / 60);
break;
//In Hours:
case 'hours':
$choice = floor($secons_dif / 60 / 60);
break;
//In days:
case 'days':
$choice = floor($secons_dif / 60 / 60 / 24);
break;
//In weeks:
case 'weeks':
$choice = floor($secons_dif / 60 / 60 / 24 / 7);
break;
//In Months:
case 'months':
$choice = floor($secons_dif / 60 / 60 / 24 / 7 / 4);
break;
//In years:
case 'years':
$choice = floor($secons_dif / 365 / 60 / 60 / 24);
break;
}
$choice;
return $choice;
}
回答3:
Try this function:
function mtime_difference($t1, $t2) {
$t1 = DateTime::createFromFormat('H:i:s:u', $t1, new DateTimezone('UTC'));
$t2 = DateTime::createFromFormat('H:i:s:u', $t2, new DateTimezone('UTC'));
$diff = $t2->diff($t1);
$seconds = $diff->h * 3600 + $diff->i * 60 + $diff->s;
$u = $t1->format('u') - $t2->format('u');
if ($u < 0) {
$seconds--;
$u = 1000000 - abs($u);
}
$u = substr(sprintf('%06d', $u), 0, 3);
return $seconds . '.' . $u;
}
echo mtime_difference('11:15:35:450', '10:15:30:300');
# 3605.150
demo
回答4:
@Glavic - small typo in your method, this line:
$u = $t1->format('u') - $t2->format('u');
should be:
$u = $t2->format('u') - $t1->format('u');
回答5:
At first, your times are written wrong. There should be decimal dot before milliseconds.
It means there will be times
10:15:30.300 and 11:15:35.450
instead
10:15:30:300 and 11:15:35:450
But in class written below you could improve pattern to it would fit your time formatting. Or change whole checking.
For similar case I had to solve very recently (reading of csv files created by smartphone/tablet app IoTools and counting milliseconds differences between times), and based on question How to get time difference in milliseconds, I prepared class that does it - but only within range of one day (24 hours).
It is not perfect (as it could get some more options) but it computes well (I hope that it does well, I have not tested it much).
For this answer, I deleted details of exceptions throwing and rewrote some constants by their values. Also I deleted annotations to make code shorter, but replaced them with descripting texts.
class DayTimeCount
{
Times are converted into milliseconds. So, these two variables may be typed as integer
.
protected $Time_Start = 0;
protected $Time_End = 0;
Also time scale may be as integer. Name of this variable may be a bit unfortunate, as it is not fully correctly saying for what purpose it is used.
protected $Time_Scale = 1;
This variable could be a constant. Its content is not changed at all.
private $TimePattern = '/(?<Hours>[0-9]{2})\:(?<Minutes>[0-9]{2})\:(?<Seconds>[0-9]{2}).(?<Milliseconds>[0-9]{0,3})/';
This function is for setting of start time (time when starts interval you need to count). After checking if time is set in correct pattern (as string corresponding pattern writen above, not integer), time is converted into milliseconds.
public function Set_StartTime($Time = NULL)
{
try
{
if( !preg_match($this -> TimePattern, $Time, $TimeUnits) )
{
throw new Exception(/* some code */);
}
}
catch( Exception $Exception )
{
$Exception -> ExceptionWarning(/* some code */);
}
$this -> Time_Start = ($TimeUnits['Hours'] * 60 * 60 * 1000) + ($TimeUnits['Minutes'] * 60 * 1000) + ($TimeUnits['Seconds'] * 1000) + $TimeUnits['Milliseconds'];
}
This function is similar to previous, but for setting of end time (time when ends interval you need to count).
public function Set_EndTime($Time = NULL)
{
try
{
if( !preg_match($this -> TimePattern, $Time) )
{
throw new Exception(/* some code */);
}
}
catch( Exception $Exception )
{
$Exception -> ExceptionWarning(/* some code */);
}
$this -> Time_End = ($TimeUnits['Hours'] * 60 * 60 * 1000) + ($TimeUnits['Minutes'] * 60 * 1000) + ($TimeUnits['Seconds'] * 1000) + $TimeUnits['Milliseconds'];
}
This function is for setting of time scale. It helps to convert milliseconds to seconds (with precision of milliseconds) or minutes or hours.
Static function Check_IsTimeScale
is my own function that works as in_array()
.
public function Set_TimeScale($Scale = 1)
{
try
{
if( !Core::Check_IsTimeScale($Scale) )
{
throw new Exception(/* some code */);
}
}
catch( Exception $Exception )
{
$Exception -> ExceptionWarning(/* some code */);
}
$this -> Time_Scale = $Scale;
}
And finally, function is for own counting of time difference. It has only three steps.
public function Execute()
{
The first one is own counting. If difference between end and start is positive number (greater than zero), it is taken as it is.
But if difference between end and start is negative (as end is after midnight and start is before midnight, for example 00:00:00.658 and 23:59:59:354), then it is needed to use additional counting. To make difference between start and full time of day - and add end time.
$Diff = $this -> Time_End - $this -> Time_Start;
if( $Diff < 0 )
{
$Diff = $this -> Time_End + (86400000 - $this -> Time_Start);
}
The second step, application of time scale. Time in milliseconds is divided by time scale. If it is divided by 1, result is (of course) the same as original number and it is no rounded. If it is divided by larger number (1000 or greater from allowed options), it is rounded to length of number used to divide it.
$Diff = round($Diff / $this -> Time_Scale, strlen($this -> Time_Scale));
Third step is returning of final result. Probably it could be merged with previous step, but now it is (at least) better readable.
return $Diff;
}
}
Function ExceptionWarning
is also my function, and can be replaced by your own one.
来源:https://stackoverflow.com/questions/21178737/time-difference-calculation-in-milliseconds-in-php