Unix time difference in minutes gives unexpected results - php

I have the following simple code for testing:
$start_time_unix = time();
$end_time_unix = time();
$seconds_diff = $end_time_unix - $start_time_unix;
$duration = round(abs($seconds_diff/1000) / 60,2);
When i store it in MySQL (int), the results are big values like 25634 even for a few seconds. How can i get the minutes, even in fraction of minutes?? What is wrong with my code above ??

First of all int cannot store fractions, so you will probably want to use float or double instead.
But why are you dividing by 1000. $seconds_diff consists of a seconds, so dividing by 60 will give you fraction of a minute.
For example: If $seconds_diff is a value of 13 [seconds]:
$duration_in_minutes = round($seconds_diff / 60, 2);
$duration_in_milliseconds = $seconds_diff * 1000;
If it is your goal to use milliseconds then use microtime() instead of time():
http://php.net/manual/de/function.microtime.php
Recommendation
Just measure the time with microtime() and directly store the result in the database without rounding, dividing or formatting. Then later on, do the formatting when you have to output it. This will give you more precise results and more freedom.
$start_time = microtime();
…
$end_time = microtime();
$duration = $end_time - $start_time; // duration in milliseconds --> save to database
When outputting, for example:
$duration = get_duration_from_database(); // pseudo function
printf('%.2f minutes', $duration / 1000 / 60);

The time() function returns the current Unix timestamp in seconds. There is no need to divide it by 1000. Since MySQL is expecting an integer, you must round to 0 decimal places:
$seconds_diff = abs($end_time_unix - $start_time_unix);
$duration = round($seconds_diff / 60, 0);

Related

Display time with 1 zero when seconds is less or equal to 60 seconds

I'm displaying videos and I want to show the duration. Im using the following:
echo ltrim(date('i:s', $vduration), '0')
//result
5:40
But, if the video is 40 seconds only. The formula doesn't work. It shows
:40
Basically, if the video is less then 60 seconds, it should show 1 zero only (not 2), like so:
0:40
Is there a magic formula for this or do I need to use conditions to check if less or equal to 60 seconds?
Instead of date(), use printf() to format the numbers the way you wan.
$minutes = date('i', $vduration);
$seconds = date('s', $vduration);
printf("%d:%02d", $minutes, $seconds);
%d will format a number with no leading zeroes, %02d will format a number in 2 digits with leading zeroes.
A date is poorly suited to represent a time interval. The DateInterval class is better suited. The date interval format method can also represent minutes without leading zeros.
//example to create a date interval
$timeStart = date_create_from_format('!','');
$timeEnd = date_create_from_format('!i:s','00:07');
$interval = $timeStart->diff($timeEnd);
//output
echo $interval->format('%i:%S'); //0:07
If the minutes and seconds are given, a date interval can also be created directly.
$minute= 1;
$second = 40;
$interval = new DateInterval('PT'.$minute.'M'.$second.'S');

How to round an integer UP to the nearest 15 in PHP

I have the INTEGER(255) variable $duration stored with a value taken from the user. I need to round this UP to the nearest 15. I have searched all over but haven't been able to find a solution.
How may I go about doing this?
For example:
10 becomes 15
16 becomes 30
130 becomes 135
Also, how can I add $duration to a TIME variable $time to output the time after that duration?
For example, from 080000:
If $duration is 15, $time becomes 081500
If $duration is 30, $time becomes 083000
If $duration is 135, $time becomes 101500
Thank you!
You can use the simple division and addition with casting (will return the whole value without the fraction) operator as follows:
$val = 130;//or any value
$roundedVal = ((int)($val/15) + 1) * 15;
about the second question:
$time='080000';
$valHours = (int)($val/60);
$valMin = (int)($val % 60);
$time = $time + ($valHours * 10000) + ($valMin * 100);
$time = strlen($time) == 8? $time : '0' . $time;
the last row is meant or fixing the leading zero, since it's not a conventional time format.
I haven't took into consideration the seconds.

miscalculating times - strtotime, date() - PHP

Calculating time using date and strtotime functions.
$starttime = '11:55';
$endtime = '13:01'; //or '1:01'
$totaltime = date("i",strtotime($endtime) - strtotime($starttime));
I don't know why, but echo $totaltime giving 06 instead of 66
Its working fine on other time frames. i.e for 12:30, 13:30
Thanks for any help.
Your return value is formatted as a new time output (because of the date() function)
As you are only requesting the number of minutes in the formatted time, it's only returning that part.
If you want to see the hours and minutes, output using h:
$totaltime = date("H:i",strtotime($endtime) - strtotime($starttime));
This will return "01:06".
If you need the actual number of minutes between two dates (so you want 66 as outcome) then you're not looking for a formatted time-string as an outcome, but rather a regular integer holding the number of minutes. This you can calculate from your earlier calculation, like this:
// divide total seconds between these points by 60, round down.
$totalMinutes = floor ( ( strtotime($endtime) - strtotime($starttime) ) / 60 );
Because date("i") only shows minutes from 0 to 59.
PHP date manual
A possible solution:
$totaltime = (strtotime($endtime) - strtotime($starttime)) / 60;
<?php
$starttime = '11:55';
$endtime = '13:01';
echo $totaltime (strtotime($endtime) - strtotime($starttime)) / 60;
echo $totaltime = floor ((strtotime($endtime) - strtotime($starttime)) / 60);
?>

Multiple hour by a number

I have something like that for example: 01:06:22 this represents 1hour, 6minutes and 22seconds. I want to take that, and multiple it by 6 and add it to some other hour such as 04:23 which is 4AM and 23Minutes not 4hours and 23 minutes.
Basically, as a result I expect that:
01:06:22
* 6 = 6hours 38minutes canceling the remaining seconds which are 12 in this case
Now, I want to take that and append it to other hour, 04:23 in this case, so the result would be:
11:01.
I have no clue how to start and do it, unfortunately.
Any help is appriciated!
Clarifications
The time that I have to multiple by 6 will never exceed 2 hours.
All the times are in the same format.
With DateTime it is simple:
$time = '01:06:22';
$dateSeconds = new DateTime("1970-01-01 $time UTC");
$seconds = $dateSeconds->getTimestamp() * 6;
$interval = new DateInterval('PT'.$seconds.'S');
$date = new DateTime('1970-01-01 04:23:00 UTC');
$date->add($interval);
echo $date->format('H:i:s');
Other solution with strtotime and gmdate. (Similar to Suresh but working):
$date = strtotime('1970-01-01 01:06:22 UTC');
$add = strtotime('1970-01-01 04:23:00 UTC');
$date = (($date*6)+$add);
echo gmdate('H:i:s', $date);
This is a solution if you want to implement it yourself.
The thing about timecode is that it can become really heavy with the if the if conditions etc if you don't do it right.
The best Way I thought of to deal with this is to convert everything to second.
so 01:06:22 would become:
numberOfSecond = 22 + 06 * 60 + 01 * 60 * 60
How to get the 22, 06 etc from the String? You can use Regex.
What you will need:
a function to extract the different values (hours, minute, second)
a function to convert the timecode into second
a function to convert back into timecode
the functions to multiply, add etc...
You might want to create a class for it.
You can try like this:
$date = strtotime('01:06:22');
$add = strtotime('00:04:23');
$date = ($date*6)+$add;
echo date('H:i:s', $date);
Note: Code is not tested.
First of all you want to multiply a time span by a factor. The easiest way to do this is to convert the span to seconds and do a straight multiply:
$date =DateTime::createFromFormat('!H:i:s', '01:06:22', new DateTimeZone('UTC'));
$seconds = $date->getTimestamp();
This code works by pretending that the time is a moment during the Unix epoch start so that it can then get the number of seconds elapsed since the epoch (the timestamp). That number is equal to the duration of the time span in seconds. However, it is vitally important that the input is interpreted as UTC time and not as something in your local time zone.
An equivalent way of doing things (as long as the input is in the correct format) which is lower-tech but perhaps less prone to bugs would be
list($h, $m, $s) = explode(':', '01:06:22');
$seconds = $h * 3600 + $m * 60 + $s;
Now the multiplication:
$seconds = $seconds * 6;
If you want to only keep whole minutes from the time you can do so at this stage:
$seconds = $seconds - $seconds % 60;
The final step of adding the result to a given "time" is not clearly specified yet -- does the reference time contain date information? What happens if adding to it goes over 24 hours?
Self explanatory :
$initialTime = '01:06:22';
$timeToAdd = '04:23';
$initialTimeExploded = explode( ':' ,$initialTime );
$initialTimeInMintues = ( $initialTimeExploded[0] * 60 ) + $initialTimeExploded[1];
$initialTimeInMintuesMultipliedBySix = $initialTimeInMintues * 6;
$timeToAddExploded = explode( ':' ,$timeToAdd );
$timeToAddExplodedInMintues = ( $timeToAddExploded[0] * 60 ) + $timeToAddExploded[1];
$newTimeInMinutes = $initialTimeInMintuesMultipliedBySix + $timeToAddExplodedInMintues;
$newTime = floor( $newTimeInMinutes / 60 ) .':' .($newTimeInMinutes % 60);
echo $newTime;
Result :
10:59

Create 3 digit Millisecond with php

I have 13 digit number and want to create date and time with include milisecond
Example code is like this this is my php script
$mil = 1328910295939;
$seconds = $mil / 1000;
$showdate = date('Y:m:d H:i:s', $seconds) ;
echo "$showdate";
the result is like this 2012:02:10 15:44:55.xxx ===> xxx is 3 digit miliseconds that i want to show up.
and how to include with 3 digit milisecond after H:i:s
Please help me.....
How about something like this?
$mil = 1328910295939;
function toTimestamp($milliseconds)
{
$seconds = $milliseconds / 1000;
$remainder = round($seconds - ($seconds >> 0), 3) * 1000;
return date('Y:m:d H:i:s.', $seconds).$remainder;
}
echo toTimestamp($mil);
Tadaa!
It should be pretty quick too.
Also, this is the output: 2012:02:10 15:44:55.939 - why you're not using - for delimiting the date portion beats me.
Just trim off the last two characters:
substr(date('Y-m-d H:i:s.u',1328910295939), 0, -2)
Here's a function that will do it for you accurately (by rounding, not cutting off):
function getTimestamp()
{
$microtime = floatval(substr((string)microtime(), 1, 8));
$rounded = round($microtime, 3);
return date("Y-m-d H:i:s") . substr((string)$rounded, 1, strlen($rounded));
}
Explanation:
microtime() returns 2 numbers as 1 string, delimited by a space. the 2nd number is the amount of seconds since the unix epoch, and the 1st number is the amount of microseconds since the 2nd number. Basically, the first number is the amount of microseconds expressed in a 8 precision format (0.00000000) and trailing 0s are never cut off.
We round this to a precision of 3 (0.00), and cut off the leading 0, and append that to the actual timestamp.
For some reason the php doc for u, microseconds, doesn't seem to be actually supported. I get 0.000 everytime when using that method. So I resorted to microtime() as a backup solution.
$t = 1328910295939;
echo date('Y-m-d H:i:s.', substr($t, 0, -3)) . substr($t, -3);
Output: 2012-02-10 16:44:55.939 (it depends on the timezone)
Because these answers were all quite amusing in their complexity, here's yet another answer for future posterity that uses the asker's original code and doesn't treat numbers as strings.
$mil = 1328910295939;
$seconds = floor($mil / 1000);
$fraction = $mil % 1000;
$showdate = date('Y:m:d H:i:s',$seconds) . ".$fraction";
echo "$mil<br>
$seconds<br>
$fraction<br>
$showdate";
Outputs the following on a server set to the EST time zone:
1328910295939
1328910295
939
2012:02:10 16:44:55.939
Since I can't add a comment to the of #westie, and if anyone need this, I allow myself to add the missing line to his function for decimals < 100 :
$seconds = $milliseconds / 1000;
$remainder = round($seconds - ($seconds >> 0), 3) * 1000;
$remainder = sprintf("%03d", $remainder);
return gmdate('H:i:s.', $seconds).$remainder;
Note that I also use gmdate to prevent time zone issues (i suppose you would work on milliseconds for duration calculation and not date calculation)

Categories