Am trying to get the time difference between two days. But for certain date/time, I get wrong answers
Here is my code:
/****************************************
$start_date = new DateTime('23:58:40'); *These two still give
$end_date = new DateTime('00:00:00'); *a wrong answer
*****************************************/
$start_date = new DateTime('23:58:40');
$end_date = new DateTime('00:11:36');
$dd = date_diff($end_date, $start_date);
//Giving a wrong answer: Hours = 23, Minutes = 47, Seconds = 4
echo "Hours = $dd->h, Minutes = $dd->i, Seconds = $dd->s";
The awnser is correct. You provide two times. Without a date there is no way to know the last date is actually the next day. Just because you named the variable "end_date" doesnt mean PHP knows what you mean.
Perhaps you should include the date aswell in your request like
$start_date = new DateTime('2012-12-07 23:58:40');
$end_date = new DateTime('2012-12-08 00:11:36');
If you realy want to work with just times:
function differenceInTimes($start, $end) {
if (strtotime($start)>strtotime($end)) {
//start date is later then end date
//end date is next day
$s = new DateTime('2000-01-01 '.$start);
$e = new DateTime('2000-01-02 '.$end);
} else {
//start date is earlier then end date
//same day
$s = new DateTime('2000-01-01 '.$start);
$e = new DateTime('2000-01-01 '.$end);
}
return date_diff($s, $e);
}
$start_date = '23:58:40';
$end_date = '00:11:36';
$dd = differenceInTimes($start_date, $end_date);
echo "Hours = $dd->h, Minutes = $dd->i, Seconds = $dd->s";
//Hours = 0, Minutes = 12, Seconds = 56
Swap the arguments to date_diff
$dd = date_diff($start_date, $end_date);
Edit
After actually testing this theory it proved to be totally useless, giving the same answer.
Related
Sorry for my bad english, im trying to convert duration from given date time range in minute only. There something weird when display only %I. My final out put using variable $durationDisplayMin. How how convert in minute only?
$startDate = "2018-01-20 15:10:10";
$end_datetime = "2018-07-29 11:11:05";
$start_datetime = new DateTime($startDate);
$end_datetime = new DateTime($endDate);
$diffr = $start_datetime->diff($end_datetime);
$durationDisplayMin = $diffr->format("%I");
just found the answer:
$durationInMin = 0;
$start_datetime = new DateTime("2018-01-20 15:10:10");
$end_datetime = new DateTime("2018-07-29 11:11:05");
$Date1 = strtotime($start_datetime->format('Y-m-d H:i:s'));
$Date2 = strtotime($end_datetime->format('Y-m-d H:i:s'));
$durationInMin += round(abs($Date1 - $Date2)/ 60,2);
I want to check between two user-specified times everyday and not run some function call (i.e. "Do Not Disturb").
For example, a user set a "Do Not Disturb" time block between 10:00pm to 6:00am (next day).
FYI, no days/dates are being specified by the end-user, ONLY times. This will run consistently everyday, 7 days a week.
So between 10pm-6am (next day), any function call is ignored. This is what I've written up so far:
$now = time(); // or $now = strtotime('11:00pm'); to simulate time to test
$start = strtotime('10:00pm');
$end = strtotime('6:00am +1 day');
// alternative time block
//$start = strtotime('10:00am');
//$end = strtotime('11:00am');
//debug
//echo date('r', $now) . '<br>' . date('r', $start) . '<br>' . date('r', $end) . '<br><br>';
if($start > $now || $now > $end) {
echo 'disturb';
} else {
echo 'do not disturb';
}
But this doesn't seem to work, because once you reach midnight, it's a new day, but the $end variable is already a day ahead.
I tried putting it a day behind, but then the issue is that the value of $end ends up being lower than the value of $start, which isn't correct.
I also tried adding a day to the $now variable whenever the time reaches midnight, but the issue w/ that is, what if the $start and $end times are within the same day?
What am I missing here?
Apparently you're trying to build some kind of calendar functionality here.
If you use strtotime('10:00pm'); this will change to the timestamp of the next day after midnight.
So you need to give the variable a date
$start = strtotime('2015-02-26 10:00pm');
$end = strtotime('2015-02-27 6:00am');
Not sure how you store these time blocks, but ideally they would be stored in a database table.
If it's every day the same you could do:
$now = time(); // or $now = strtotime('11:00pm'); to simulate time to test
$start = strtotime('10:00pm');
$end = strtotime('6:00am'); // without the +1 day
if($start > $end) {
if($start > $now && $now > $end) {
echo 'disturb';
} else {
echo 'do not disturb';
}
}else{
if($now < $start || $now > $end) {
echo 'disturb';
} else {
echo 'do not disturb';
}
}
That's a nice question actually,
You can use the the relatively new object oriented way of dealing with times.
I'll link you some info as I don't have time to write an entire example
http://php.net/manual/en/datetime.diff.php
http://php.net/manual/en/class.datetime.php
http://php.net/manual/en/class.dateinterval.php
specifically from the docs :
<?php
$datetime1 = new DateTime('2009-10-11');
$datetime2 = new DateTime('2009-10-13');
$interval = $datetime1->diff($datetime2);
echo $interval->format('%R%a days');
?>
Hope it helps
I would convert to DateTime() objects instead. Then you won't get any issues with days ending.
// obviously you'll need to feed in the date as well so
// that might involve some refactoring
$now = new DateTime();
$start = new DateTime('2015-02-26 10:00');
$end = new DateTime('2015-02-27 06:00');
Now you can compare as before.
If you don't know the date and your users are only specifying time, you might need to add the date dynamically. These are just for example.
Edit: to cope with unknown days, you could dynamically generate after grabbing today:
$today = new DateTime();
$start = new DateTime($today->format('Y-m-d') . ' 10:00');
$end = new DateTime($today->format('Y-m-d') . ' 06:00');
$end->add(new DateInterval('P1D'));
I'm working on a client scheduler and my employer wants it to automatically reschedule clients each year. He wants them to keep the same day of the same week every year.
For example, a client is scheduled for May 23rd 2014. This is the fourth friday of may. Once May 23rd 2014 has passed, a appointment for the fourth friday of may in 2015 should be booked (in this case the 22nd).
I've tried various things to get this to work (such as using DateTime to advance by a year and find "previous" of whatever day of the week it was). But every model I've tried breaks down a bit after just a few years. They'll end up on like...the second Friday of the month.
Does anyone have a way to get this to work? My employer is very specific about wanting the scheduler to work this way. x.x I'd really appreciate the help if someone knows how.
Thanks for reading this!
As has already been pointed out, there may not be a 5th Friday in June, for example, so there needs to be some standard way to decide which week next year is the same week as the current one.
As it happens there is already a standard for week numbering in ISO 8601 and PHP's DateTime class has built in functionality for handling them.
My suggestion would be to schedule the next meeting for the same day in the same ISO 8601 week number the following year. The following function will do that for you:-
/**
* #param \DateTime $date Date of the original meeting
* #return \DateTime Date of the next meeting
*/
function getSameDayNextYear(\DateTime $date = null)
{
if(!$date){
$date = new \DateTime();
}
return (new \DateTime())->setISODate((int)$date->format('o') + 1, (int)$date->format('W'), (int)$date->format('N'));
}
See it working with some test code.
I'm sure you'll agree that this is the simplest way of doing it and it should see you right for the next 100 years or more :)
References DateTime and Date for formats.
I think this will do what you need. You'll need to thoroughly test it out to be sure, though.
$event = new DateTime('2014-05-18');
$dayOfWeek = $event->format('l');
if ($dayOfWeek !== 'Sunday') {
$event->modify('previous Sunday');
}
else {
$event->modify('-1 day');
}
$event->modify('+1 year');
if ($dayOfWeek !== 'Sunday' && $dayOfWeek !== $event->format('l')) {
$event->modify('next ' . $dayOfWeek);
}
echo $event->format('Y-m-d');
Demo
So changing your requirements to "add a year and find the next matching day of the week" I've come up with this:
function nextDate($date = false){
if(!$date){ $date = new DateTime(); }
$oneYear = new DateInterval('P1Y');
$dayOfWeek = $date->format('w');
$nextDate = clone $date;
$nextDate->add($oneYear);
$nextYearDayOfWeek = $nextDate->format('w');
while($nextYearDayOfWeek != $dayOfWeek){
// add a day and check again
$nextDate->add(new DateInterval('P1D'));
$nextYearDayOfWeek = $nextDate->format('w');
}
return $nextDate;
}
And my tests:
$test1 = new DateTime('5/23/2014');
$test2 = new DateTime('5/24/2014');
$test3 = new DateTime('5/25/2014');
$test4 = new DateTime('5/26/2014');
$test5 = new DateTime('5/27/2014');
$test6 = new DateTime('5/28/2014');
$test7 = new DateTime('5/29/2014');
$test8 = new DateTime('1/1/2014');
$test9 = new DateTime('12/31/2014');
$test10 = new DateTime('5/5/2040');
$nextDate1 = nextDate($test1);
$nextDate2 = nextDate($test2);
$nextDate3 = nextDate($test3);
$nextDate4 = nextDate($test4);
$nextDate5 = nextDate($test5);
$nextDate6 = nextDate($test6);
$nextDate7 = nextDate($test7);
$nextDate8 = nextDate($test8);
$nextDate9 = nextDate($test9);
$nextDate10 = nextDate($test10);
print($nextDate1->format('m/d/y'));
print('<br />');
print($nextDate2->format('m/d/y'));
print('<br />');
print($nextDate3->format('m/d/y'));
print('<br />');
print($nextDate4->format('m/d/y'));
print('<br />');
print($nextDate5->format('m/d/y'));
print('<br />');
print($nextDate6->format('m/d/y'));
print('<br />');
print($nextDate7->format('m/d/y'));
print('<br />');
print($nextDate8->format('m/d/y'));
print('<br />');
print($nextDate9->format('m/d/y'));
print('<br />');
print($nextDate10->format('m/d/y'));
Results:
05/29/15
05/30/15
05/31/15
06/01/15
06/02/15
06/03/15
06/04/15
01/07/15
01/06/16
05/11/41
Edit
I've modified the function below to find the closest day of the week instead of the next one (though it tends to just be the same as the previous one except subtracting).
function nextDate($date = false){
if(!$date){ $date = new DateTime(); }
$oneYear = new DateInterval('P1Y');
$dayOfWeek = $date->format('w');
$nextDate = clone $date;
$nextDate->add($oneYear);
$nextYearDayOfWeek = $nextDate->format('w');
$diff = $dayOfWeek-$nextYearDayOfWeek;
// if $diff is more than 3, it's faster to go the other way
if(abs($diff) > 3){
if($diff > 0){
$diff = $diff-7;
}else{
$diff = 7+$diff;
}
}
if($diff != 0){
if($diff < 0){
$nextDate->sub(new DateInterval('P'.abs($diff).'D'));
}else{
$nextDate->add(new DateInterval('P'.$diff.'D'));
}
}
return $nextDate;
}
Test results this time:
05/22/15
05/23/15
05/24/15
05/25/15
05/26/15
05/27/15
05/28/15
12/31/14
12/30/15
05/04/41
I need some help to calculate the current minutes:seconds played in a soccer match, let's suppose a soccer match have :
$schedule='2014-02-13';
$start_time1='03:00 pm';
$end_time1='03:45 pm';
$start_time2='04:00 pm';
$end_time2='04:50 pm';
$start_extra_time1='05:10 pm';
$end_extra_time1='05:30 pm';
$start_extra_time2='05:35 pm';
$end_extra_time2='06:10 pm';
And I actually my current time is "05:32 pm", how I can calculate the current played minutes:seconds or (hours:minutes:second) of the match?
I have tried many solutions, like datediff, strtotime etc... but no luck, since there is some OFF time between these dates.
Thanks so much for helping.
Here's how to do it using DateTime() and DateInterval():
<?php
$schedule='2014-02-13';
$start_time1='03:00 pm';
$end_time1='03:45 pm';
$start_time2='04:00 pm';
$end_time2='04:50 pm';
$start_extra_time1='05:10 pm';
$end_extra_time1='05:30 pm';
$start_extra_time2='05:35 pm';
$end_extra_time2='06:10 pm';
$start1 = new DateTime($start_time1);
$end1 = new DateTime($end_time1);
$firstInterval = $start1->diff($end1);
$start2 = new DateTime($start_time2);
$end2 = new DateTime($end_time2);
$secondInterval = $start2->diff($end2);
$start3 = new DateTime($start_extra_time1);
$end3 = new DateTime($end_extra_time1);
$thirdInterval = $start3->diff($end3);
$start4 = new DateTime($start_extra_time2);
$end4 = new DateTime($end_extra_time2);
$fourthInterval = $start4->diff($end4);
$baseline = new DateTime();
$accrual = clone $baseline;
$accrual->add($firstInterval);
$accrual->add($secondInterval);
$accrual->add($thirdInterval);
$accrual->add($fourthInterval);
$difference = $accrual->diff($baseline);
echo $difference->format('%h hours, %i minutes');
See it in action
All this code does is:
create DateTime() objects representing the start and end time of each time interval.
get a DateInterval() object representing the difference between the two.
create a baseline (beginning point) DateTime() object
create a DateTime() object that we add our intervals to to represent time elapsed
echo out the difference between the two
You can shorten some of this if you use PHP 5.4 or newer:
$firstInterval = (new DateTime($start_time1))->diff((new DateTime($end_time1)));
$secondInterval = (new DateTime($start_time2))->diff((new DateTime($end_time2)));
$thirdInterval = (new DateTime($start_extra_time1))->diff((new DateTime($end_extra_time1)));
$fourthInterval = (new DateTime($start_extra_time2))->diff((new DateTime($end_extra_time2)));
and
$accrual->add($firstInterval)->add($secondInterval)->add($thirdInterval)->add($fourthInterval);
I have added the solution of John, here is my code:
<?php
date_default_timezone_set("Canada/Eastern");
$date="2014-02-14 14:00:00 +00";
$start_time1='09:00 am';
$end_time1='09:45 am';
$start_time2='10:00 am';
$end_time2='10:50 am';
$start_extra_time1='';
$end_extra_time1='';
$start_extra_time2='';
$end_extra_time2='';
$start1 = new DateTime($start_time1);
$end1 = new DateTime($end_time1);
$firstInterval = $start1->diff($end1);
$start2 = new DateTime($start_time2);
$end2 = new DateTime($end_time2);
$secondInterval = $start2->diff($end2);
$start3 = new DateTime($start_extra_time1);
$end3 = new DateTime($end_extra_time1);
$thirdInterval = $start3->diff($end3);
$start4 = new DateTime($start_extra_time2);
$end4 = new DateTime($end_extra_time2);
$fourthInterval = $start4->diff($end4);
$baseline = new DateTime($date);
$baseline->setTimezone(new DateTimeZone('Canada/Eastern')); // -05
$accrual = new DateTime();
$accrual->add($firstInterval);
$accrual->add($secondInterval);
$accrual->add($thirdInterval);
$accrual->add($fourthInterval);
$difference = $accrual->diff($baseline);
echo "baseline time :\n";
var_dump($baseline);
echo "accrual time :\n";
var_dump($accrual);
print json_encode(array('response'=>$difference->format('%h hours, %i minutes, %s seconds')));
?>
The game not started yet, but it show 1 hour passed in the game, how it's possible? http://easycaptures.com/fs/uploaded/645/4891434894.png
Mysql has a bug with timediff, so use this:
Time_To_Sec($currentime) - Time_To_Sec($end_time2) As time_seconds
Also check your time format, avoid the use of strings as time or dates, format as date/time entities.
Do you know what the problem is by looking at the code?
I would be happy if you helped me:
list($from_day,$from_month,$from_year) = explode(".","27.09.2012");
list($until_day,$until_month,$until_year) = explode(".","31.10.2012");
$iDateFrom = mktime(0,0,0,$from_month,$from_day,$from_year);
$iDateTo = mktime(0,0,0,$until_month,$until_day,$until_year);
while ($iDateFrom <= $iDateTo) {
print date('d.m.Y',$iDateFrom)."<br><br>";
$iDateFrom += 86400;
}
Date of writing the same problem 2 times
October (31) for writing 2 times in history draws the ends October 30th: (
27.09.2012
28.09.2012
...
26.10.2012
27.10.2012
[[28.10.2012]]
[[28.10.2012]]
29.10.2012
30.10.2012
Your problem is because you have set time to 00:00:00, set it to 12:00:00. That is because the Daylight saving time.
Stop using date() function, use Date and Time classes.
Solution (PHP >= 5.4):
$p = new DatePeriod(
new DateTime('2012-09-27'),
new DateInterval('P1D'),
(new DateTime('2012-10-31'))->modify('+1 day')
);
foreach ($p as $d) {
echo $d->format('d.m.Y') . "\n";
}
Solution (PHP < 5.4)
$end = new DateTime('2012-10-31');
$end->modify('+1 day');
$p = new DatePeriod(
new DateTime('2012-09-27'),
new DateInterval('P1D'),
$end
);
foreach ($p as $d) {
echo $d->format('d.m.Y') . "\n";
}
You have daylight savings time issues. Adding seconds from one timestamp to another is prone to problems around these sorts of edge conditions (leap days can be problematic is well), You should get in the habit of using PHP's DateTime and DateInterval objects. It makes working with dates a snap.
$start_date = new DateTime('2012-09-27');
$end_date = new DateTime('2012-10-31');
$current_date = clone $start_date;
$date_interval = new DateInterval('P1D');
while ($current_date < $end_date) {
// your logic here
$current_date->add($date_interval);
}
My idea for solving this would be something like this;
$firstDate = "27.09.2012";
$secondDate = "31.10.2012";
$daysDifference = (strtotime($secondDate) - strtotime($firstDate)) / (60 * 60 * 24);
$daysDifference = round($daysDifference);
for ($i = 0; $i <= $daysDifference; $i++)
{
echo date("d.m.Y", strtotime('+'.$i.' day', strtotime($firstDate))) . "<BR>";
}
This should solve your problem and be much easier to read (imho). I've just tested the code, and it outputs all dates and no doubles. It also saves you from all the daylight savings inconsistencies.
I don't know where you're from, but it's likely you're hitting daylight saving changeover in your timezone (it's Nov 4th where I live - exactly one week after Oct 28th). You can not rely on a day being exactly 86400 seconds long.
If you loop incrementing with mktime, you should be fine:
list($from_day,$from_month,$from_year) = explode(".","27.09.2012");
list($until_day,$until_month,$until_year) = explode(".","31.10.2012");
$iDateFrom = mktime(0,0,0,$from_month,$from_day,$from_year);
$iDateTo = mktime(0,0,0,$until_month,$until_day,$until_year);
while ($iDateFrom <= $iDateTo)
{
print date('d.m.Y',$iDateFrom)."<br><br>";
$from_day = $from_day + 1;
$iDateFrom = mktime(0,0,0,$from_month,$from_day,$from_year);
}
Even though $from_day will likely be going well over 31, mktime will make the math conversion for you. (ie 32 days in a 31 day month = day 1 of the next month)
EDIT: sorry, I had the incrementation in the wrong place.