Php, add and subtract timestamps, get minutes - php

I need to get different time lengths in minutes from a few timestamps that are:
starttime
endtime
starttime2nd
endtime2nd
Edit: clarification:
Each time is originally stored as a datetime string, like
"2018-02-21T19:45:13+00:00".
I take that and convert it to strtotime("2018-02-21T19:45:13+00:00");
And from that I get a timestamp : 1519242313
It doesn't seem that I can use plus or minus operators to add or subtract timestamps, like:
$length = ($endtime2nd - $starttime2nd) + ($endtime - $starttime)
Am I required to instantiate DateTime and use the "->diff" method to get a time interval?
I could get one time interval by doing this:
$date1 = new DateTime();
$date2 = new DateTime();
$starttime= $date1->setTimestamp($starttime);
$endtime= $date2->setTimestamp($endtime);
$length = $endtime->diff($starttime);
Does this mean that I need to instantiate four DateTimes to get the total length, and set four timestamps, then get the "->diff" for the two time intervals, and then add them using the "->add" method of DateTime method?
I would just like to know if there is a simpler method?

I don't think you need to instantiate DateTime and use the "->diff" method, because you already have timestamp (as i can see you are using setTimestamp)
<?php
$length = ($endtime2nd - $starttime2nd) + ($endtime - $starttime);
echo round(abs($length / 60), 2). " minute";
?>

You can get the total minuts like this.
$min = $length->d * 24 * 60;
$min = $min + $length->h * 60;
$min = $min + $length->m;

Related

Working datetime between php and mysql

I'm just want to check if my way is correct or not. I want to calculate the remaining time for an event.
There are 3 component for it.
The start datetime (in mysql datetime), which is retrieved from mysql.
The duration (minutes in integer), which is also retrieved from mysql.
The current datetime, which is retrieved from php function now().
To count:
The remaining time (in time hh:mm:ss), which is from formula (start + duration) - now
My propose code is:
$row = data->fetch_assoc();
$start = $row["start_time"]; // e.g: "2015-06-19 09:37:16"
$duration = $row["duration"]; // e.g: 60 (minutes)
$now = time(); // e.g: 1434648994
$start_dt = strtotime ($start);
$remaining = ($start_dt + $duration * 60) - $now;
echo "Remaining time: ".$remaining. " seconds."
Is this correct?
Your code now calculates time until the end of the event.
And if $start_dt is lower then $now you get negative value.

How to convert Php::DateInterval to seconds?

so, I substract two dates:
$d = $start->diff($end);
and now I want to get the date in seconds (not the second parameter). I know it can be done with a native Php function - but it only works above 1970. I know I have to somehow operate with format() method, but I dont get it...
You could access the public properties of the DateInterval class and do some math on it:
$seconds = $d->s + ($d->i * 60) + ($d->h * 3600) + ($d->d * 86400) + ($d->m * 2592000); // and so on
but once we get into the months there will be variance by +/- 2 days unless we stick to an arbitrary definition of a month as 2592000 secs (30 days).
You can also use the difference of the two UNIX timestamps from the DateTime objects (but you will end up having problems with the dates being less than year of 1970):
$seconds = $end->getTimestamp() - $start->getTimestamp();
The following seems to work, although I feel there should be a better way.
$dateIntrvl = $start->diff($end);
$days = $dateIntrvl->format('%a');
$hours = $dateIntrvl->format('%h');
$mins = $dateIntrvl->format('%i');
$secs = $dateIntrvl->format('%s');
$totalSeconds = ($days * 24 * 60 * 60) + ($hours * 60 * 60) + ($mins * 60) + $secs;
And yes, it seems to be working for dates earlier than 1970.
How about using a class DateTime / DateTimeImmutable to create current DateTime instance, then add your DateInterval $d by using the add() method, and then using the getTimestamp() method.
(new \DateTimeImmutable())->add($d)->getTimestamp()
To get number of seconds from now, just subtract time().
(new \DateTimeImmutable())->add($d)->getTimestamp() - \time()

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

get php DateInterval in total 'minutes'

I am trying to get the PHP "DateInterval" value in "total minutes" value. How to get it? Seems like simple format("%i minutes") not working?
Here is the sample code:
$test = new \DateTime("48 hours");
$interval = $test->diff(new \DateTime());
Now if I try to get the interval in total days, its fine:
echo $interval->format('%a total days');
It is showing 2 days as output, which is totally fine. What I am trying to get if to get the value in "total minutes", so I tried:
echo $interval->format('%i total minutes');
Which is not working. Any help appreciated to get my desired output.
abs((new \DateTime("48 hours"))->getTimestamp() - (new \DateTime)->getTimestamp()) / 60
That's the easiest way to get the difference in minutes between two DateTime instances.
If you are stuck in a position where all you have is the DateInterval, and you (like me) discover that there seems to be no way to get the total minutes, seconds or whatever of the interval, the solution is to create a DateTime at zero time, add the interval to it, and then get the resulting timestamp:
$timeInterval = //the DateInterval you have;
$intervalInSeconds = (new DateTime())->setTimeStamp(0)->add($timeInterval)->getTimeStamp();
$intervalInMinutes = $intervalInSeconds/60; // and so on
I wrote two functions that just calculates the totalTime from a DateInterval.
Accuracy can be increased by considering years and months.
function getTotalMinutes(DateInterval $int){
return ($int->d * 24 * 60) + ($int->h * 60) + $int->i;
}
function getTotalHours(DateInterval $int){
return ($int->d * 24) + $int->h + $int->i / 60;
}
Here is the excepted answer as a method in PHP7.2 style:
public static function getMinutesDifference(\DateTime $a, \DateTime $b): int
{
return abs($a->getTimestamp() - $b->getTimestamp()) / 60;
}
That works perfectly.
function calculateMinutes(DateInterval $int){
$days = $int->format('%a');
return ($days * 24 * 60) + ($int->h * 60) + $int->i;
}
This question is about minutes but if you want to recalculate every carry over points (like I needed to) you can use this solution suggested by #glavic in the comments on the php.net man page (simplified and turned into a function):
private function calculateCarryOverPoints(\DateInterval $dateInterval): \DateInterval
{
$from = new \DateTime;
$to = clone $from;
// Add time of dateInterval to empty DateTime object
$to = $to->add($dateInterval);
// Calculate difference between zero DateTime and DateTime with added DateInterval time
// Which returns a DateInterval object $diff with correct carry over points (days, hours, minutes, seconds etc.)
return $from->diff($to);
}

Get interval seconds between two datetime in PHP?

2009-10-05 18:11:08
2009-10-05 18:07:13
This should generate 235,how to do it ?
With DateTime objects, you can do it like this:
$date = new DateTime( '2009-10-05 18:07:13' );
$date2 = new DateTime( '2009-10-05 18:11:08' );
$diffInSeconds = $date2->getTimestamp() - $date->getTimestamp();
You can use strtotime() to do that:
$diff = strtotime('2009-10-05 18:11:08') - strtotime('2009-10-05 18:07:13')
A similar approach is possible with DateTime objects, e.g.
$date = new DateTime( '2009-10-05 18:07:13' );
$date2 = new DateTime( '2009-10-05 18:11:08' );
$diff = $date2->getTimestamp() - $date->getTimestamp();
PHP Date Time reference is helpful for things like this: PHP Date Time Functions
strtotime() is probably the best way.
$seconds = strtotime('2009-10-05 18:11:08') - strtotime('2009-10-05 18:07:13')
For those worrying about the limitations of using timestamps (i.e. using dates before 1970 and beyond 2038), you can simply calculate the difference in seconds like so:
$start = new DateTime('2009-10-05 18:11:08');
$end = new DateTime('2009-10-05 18:07:13');
$diff = $end->diff($start);
$daysInSecs = $diff->format('%r%a') * 24 * 60 * 60;
$hoursInSecs = $diff->h * 60 * 60;
$minsInSecs = $diff->i * 60;
$seconds = $daysInSecs + $hoursInSecs + $minsInSecs + $diff->s;
echo $seconds; // output: 235
Wrote a blog post for those interested in reading more.
Because of unix epoch limitations, you could have problems compairing dates before 1970 and after 2038. I choose to loose precision (=don't look at the single second) but avoid to pass trough unix epoch conversions (getTimestamp). It depends on what you are doing to do...
In my case, using 365 instead (12*30) and "30" as mean month lenght, reduced the error in an usable output.
function DateIntervalToSec($start,$end){ // as datetime object returns difference in seconds
$diff = $end->diff($start);
$diff_sec = $diff->format('%r').( // prepend the sign - if negative, change it to R if you want the +, too
($diff->s)+ // seconds (no errors)
(60*($diff->i))+ // minutes (no errors)
(60*60*($diff->h))+ // hours (no errors)
(24*60*60*($diff->d))+ // days (no errors)
(30*24*60*60*($diff->m))+ // months (???)
(365*24*60*60*($diff->y)) // years (???)
);
return $diff_sec;
}
Note that the error could be 0, if "mean" quantities are intended for diff. The PHP docs don't speaks about this...
In a bad case, error could be:
0 seconds if diff is applied to time gaps < 1 month
0 to 3 days if diff is applied to time gaps > 1 month
0 to 14 days if diff is applied to time gaps > 1 year
I prefer to suppose that somebody decided to consider "m" as 30 days and "y" as 365, charging "d" with the difference when "diff" walk trough non-30-days months...
If somebody knows something more about this and can provide official documentation, is welcome!
strtotime("2009-10-05 18:11:08") - strtotime("2009-10-05 18:07:13")
The solution proposed by #designcise is wrong when "end date" is before "start date".
Here is the corrected calculation
$diff = $start->diff($end);
$daysInSecs = $diff->format('%r%a') * 24 * 60 * 60;
$hoursInSecs = $diff->format('%r%h') * 60 * 60;
$minsInSecs = $diff->format('%r%i') * 60;
$seconds = $daysInSecs + $hoursInSecs + $minsInSecs + $diff->format('%r%s');
A simple and exact solution (exemplifying Nilz11's comment):
$hiDate = new DateTime("2310-05-22 08:33:26");
$loDate = new DateTime("1910-11-03 13:00:01");
$diff = $hiDate->diff($loDate);
$secs = ((($diff->format("%a") * 24) + $diff->format("%H")) * 60 +
$diff->format("%i")) * 60 + $diff->format("%s");

Categories