PHP - Hours difference is not accurate using DateTime object - php

I am trying to get difference in hours between two dates using PHP DateTime object but the result is not accurate. One date is the current date time and second is the event date which comes from database. I don't understand on what logic the hours difference is calculated.
Here's my code:
<?php
$date1 = new DateTime();
$date2 = new DateTime("2018-09-04 20:37:06");
$interval = $date2->diff($date1);
echo "<pre>";
print_r($interval);
echo "</pre>";
echo $interval->format('%a Day and %h hours');
?>
Output:
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 0
[h] => 3
[i] => 14
[s] => 13
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 1
[days] => 0
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
0 Day and 3 hours
The script is executed at 08:53 PM (India) i.e. 20:53:00 but the difference is 3 hours. Don't know why?

For Indian time this should help :-
<?php
$timezone = new DateTimeZone('Asia/Kolkata');
$date1 = new DateTime('now', $timezone);
$date2 = new DateTime("2018-09-04 20:37:06", $timezone);
$interval = $date2->diff($date1);
echo "<pre>";
print_r($interval);
echo "</pre>";
echo $interval->format('%a Day and %h hours');
?>
Just use the DateTimeZone('Zone') and it should set the new date to the zone where you are.

Related

PHP DateTime->diff() doesn't work correctly

I met an interesting case, related to the diff() method of DateTime class.
If I try to calculate difference between two dates in months like
$datetime1 = new \DateTime('June 2019');
$datetime2 = new \DateTime('July 2019');
$interval = $datetime1->diff($datetime2);
echo $interval->format('%m');
, as result I get 0.
Why does this happen?
Print_r's:
$datetime1:
DateTime Object ( [date] => 2019-06-01 00:00:00.000000
[timezone_type] => 3 [timezone] => Europe/Berlin )
$datetime2:
DateTime Object ( [date] => 2019-07-01 00:00:00.000000
[timezone_type] => 3 [timezone] => Europe/Berlin )
$interval:
DateInterval Object ( [y] => 0 [m] => 0 [d] => 30 [h] => 0 [i] => 0 [s] => 0 [f] => 0
[weekday] => 0 [weekday_behavior] => 0 [first_last_day_of] => 0
[invert] => 0 [days] => 30 [special_type] => 0 [special_amount] => 0
[have_weekday_relative] => 0 [have_special_relative] => 0 )
There is big inconsistency with timezone and date handing in PHP
This appears to be a bug (in so far as the datetime format is forced to a GMT* offset, according to this comment).
*(but forcing to GMT seems inconsistent with the results established by the code below)
Setting the server timezone value to any timezone does not effect this script timezone anomaly.
Below are two cases showing what happens in different time zones:
Case 1:
The following code will output a list of results for each time zone:
$tzList = DateTimeZone::listIdentifiers(DateTimeZone::ALL);
print "Current Zone:". print_r(ini_get('date.timezone'),true)."<br>\n<BR>\n";
foreach($tzList as $tzRow) {
$tz = new DateTimeZone($tzRow);
//$tz = null;
$datetime1 = new \DateTime('June 2019', $tz);
$datetime2 = new \DateTime('July 2019', $tz);
$interval = $datetime1->diff($datetime2, false);
echo $interval->format('%a %m') . PHP_EOL. " :: ";
print print_r($datetime1->getTimezone(),true)."<BR>";
}
The result of this list output shows a high (~60%) rate of 0 and the rest of 1 month .
Please see here: http://sandbox.onlinephpfunctions.com/code/b18ba13deb94d112b12630a12265363fb6c7670b
Case 2:
Setting the timezone AFTER creating the object, results in a consistent answer (albeit incorrect)
$tzList = DateTimeZone::listIdentifiers(DateTimeZone::ALL);
print "Current Zone:". print_r(ini_get('date.timezone'),true)."<br>\n<BR>\n";
foreach($tzList as $tzRow) {
//$tz = new DateTimeZone($tzRow);
$tz = null;
$datetime1 = new \DateTime('June 2019', $tz);
$datetime2 = new \DateTime('July 2019', $tz);
$datetime1->setTimezone(new DateTimeZone($tzRow));
$datetime2->setTimezone(new DateTimeZone($tzRow));
$interval = $datetime1->diff($datetime2, false);
echo $interval->format('%a %m') . PHP_EOL. " :: ";
print print_r($datetime1->getTimezone(),true)."<BR>";
}
This output's generated here all all 30 days out; but all 0 months difference.
See code here: http://sandbox.onlinephpfunctions.com/code/7bcc62f4e36f41df71b9cb928de75a53f233d9fd
So it's your choice if you want to use sometimes correct results or universally incorrect rbut consistent results, by setting when you establish the Timezone value in the DateTime objects.
Possible Solution:
If the server timezone is correctly set to UTC "correct" timezone (that naturally returns "1" month in Case 1, then CASE 2 above works consistently across all time zones given to the DateTime objects.
The problem is in your timezone.
There is a post explaining about it here.
See this example:
<?php
echo "----- Europe/Berlin -----\n";
date_default_timezone_set('Europe/Berlin');
$datetime1 = new \DateTime('June 2019');
$datetime2 = new \DateTime('July 2019');
print_r($datetime1);
print_r($datetime2);
$interval = $datetime1->diff($datetime2);
print_r($interval);
echo "%m = " . $interval->format('%m') . PHP_EOL;
echo "%a = " . $interval->format('%a') . PHP_EOL;
echo "%s = " . $interval->format('%s') . PHP_EOL;
echo "\n\n\n----- America/Sao_Paulo -----\n";
date_default_timezone_set('America/Sao_Paulo');
$datetime1 = new \DateTime('June 2019');
$datetime2 = new \DateTime('July 2019');
print_r($datetime1);
print_r($datetime2);
$interval = $datetime1->diff($datetime2);
print_r($interval);
echo "%m = " . $interval->format('%m') . PHP_EOL;
echo "%a = " . $interval->format('%a') . PHP_EOL;
echo "%s = " . $interval->format('%s') . PHP_EOL;
And the output:
$ php date_diff.php
----- Europe/Berlin -----
DateTime Object
(
[date] => 2019-06-01 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
DateTime Object
(
[date] => 2019-07-01 00:00:00.000000
[timezone_type] => 3
[timezone] => Europe/Berlin
)
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 30
[h] => 0
[i] => 0
[s] => 0
[f] => 0
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 30
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
%m = 0
%a = 30
%s = 0
----- America/Sao_Paulo -----
DateTime Object
(
[date] => 2019-06-01 00:00:00.000000
[timezone_type] => 3
[timezone] => America/Sao_Paulo
)
DateTime Object
(
[date] => 2019-07-01 00:00:00.000000
[timezone_type] => 3
[timezone] => America/Sao_Paulo
)
DateInterval Object
(
[y] => 0
[m] => 1
[d] => 0
[h] => 0
[i] => 0
[s] => 0
[f] => 0
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 30
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
%m = 1
%a = 30
%s = 0
In my timezone $interval->format('%m'); is 1.
You can set timezone on your dates to calculate the difference between them.
$datetime1 = new \DateTime('June 2019', new DateTimeZone('UTC'));
$datetime2 = new \DateTime('July 2019', new DateTimeZone('UTC'));
$interval = $datetime1->diff($datetime2);
print_r($interval);
echo "%m = " . $interval->format('%m') . PHP_EOL;
$ php date_diff.php
DateInterval Object
(
[y] => 0
[m] => 1
[d] => 0
[h] => 0
[i] => 0
[s] => 0
[f] => 0
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 0
[days] => 30
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
%m = 1
Can you try it by adding a timezone?
$timezones = [
'UTC',
'Europe/Berlin',
'America/Belize',
'Asia/Hong_Kong',
];
foreach ($timezones as $timezone) {
$tz = new DateTimeZone($timezone);
$datetime1 = new \DateTime('June 2019', $tz);
$datetime2 = new \DateTime('July 2019', $tz);
$interval = $datetime1->diff($datetime2);
echo str_pad($timezone, 20, ' ').' '.$interval->format('months: %M, day: %D, days: %a') . PHP_EOL;
}
Result:
UTC months: 01, day: 00, days: 30
Europe/Berlin months: 00, day: 30, days: 30
America/Belize months: 01, day: 00, days: 30
Asia/Hong_Kong months: 00, day: 30, days: 30

Calculate time difference in php

I am trying to calculate time different between 3 different dates
1. Start date
2. End date
3 current date
I have been researching on how to calculation but couldn't find any exact example.
Any assistance in resolving this would be appreciated.
function getweekSartEndDate($date){
$cur_date = strtotime($date); // Change to whatever date you need
// Get the day of the week: Sunday = 0 to Saturday = 6
$dotw = date('w', $cur_date);
if($dotw>1){
$pre_monday = $cur_date-(($dotw-1)*24*60*60);
$next_sunday = $cur_date+((7-$dotw)*24*60*60);
}
else if($dotw==1){
$pre_monday = $cur_date;
$next_sunday = $cur_date+((7-$dotw)*24*60*60);
}
else if($dotw==0){
$pre_monday =$cur_date - (6*24*60*60);;
$next_sunday = $cur_date;
}
$date_array = array();
$date_array['weekStart'] = $pre_monday;
$date_array['weekEnd'] = $next_sunday;
return $date_array;
}
The above is the example code i got so far, and i was able to get the start and end dates of a week as seen below:
$weekStart = date('Y-m-d H:i:s', $weekInfo['weekStart']);
$weekEnd = date('Y-m-d H:i:s', $weekInfo['weekEnd']);
My challenges is how to get the time difference in 'Y-m-d H:i:s' date format from the current time.
You can use
$currentDate = date('Y-m-d H:i:s');
$currentDate = new DateTime($currentDate);
$leaveDate = new DateTime($leaveFrom);
$difference = $currentDate->diff($leaveDate);
You will get result as follow
DateInterval Object ( [y] => 0 [m] => 0 [d] => 0 [h] => 0 [i] => 0 [s] => 0 [f] => 0 [weekday] => 0 [weekday_behavior] => 0 [first_last_day_of] => 0 [invert] => 0 [days] => 0 [special_type] => 0 [special_amount] => 0 [have_weekday_relative] => 0 [have_special_relative] => 0 )
You need basic knowledge on how to do number comparisons in PHP.
Convert your date strings to a UNIX-timestamp with strtotime
$d = strtotime("19/10/2016 14:48:21");
// 1519646232
When the dates are in UNIX-timestamp format, it's easy to compare them with any regular comparison operators as int numbers.
EDIT
Difference in seconds:
$diffBetweenStartAndNow = strtotime( $date_array['weekStart'] ) - time();
$diffBetweenEndAndNow = strtotime( $date_array['weekEnd'] ) - time();

How to calculate time difference between SQL time and PHP time

I have set times in SQL in this format: 2016-01-03 12:13:26.
I would like to calculate the number of hours and minutes (if hours<1) going from NOW() to that particular SQL time.
I've been looking at all the different threads here but I can't seem to grasp how to convert PHP different time formats to SQL's.
This is the code I've been using, but this will only give me back hours up to 12, and minutes also. Don't know how to use it with days.
$now = date("d/m/Y h:i:s");
$commentime = strtotime($SQLTIME);
$timetocomment = $now - $commentime;
For instance, this code will yield "12 hours ago" for data I posted 24 hours ago to SQL.
How can I do it? Thank you.
This is my suggestion to use date() in this format date("Y-m-d h:i:s"). Than you will get the complete difference in an array.
function dateDifference($date_1 ,$date_2)
{
$datetime1 = date_create($date_1);
$datetime2 = date_create($date_2);
$interval = date_diff($datetime1, $datetime2);
return $interval;
}
$now = date("Y-m-d h:i:s");
$sqlTime = "2016-01-03 12:13:26";
$DateDiffArr = dateDifference($now,$sqlTime);
echo "<pre>";
print_r($DateDiffArr);
Result Is:
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 0
[h] => 22
[i] => 45
[s] => 55
[weekday] => 0
[weekday_behavior] => 0
[first_last_day_of] => 0
[invert] => 1
[days] => 0
[special_type] => 0
[special_amount] => 0
[have_weekday_relative] => 0
[have_special_relative] => 0
)
In resultant array, you can get the all difference as you need like in years, months, days, minutes, seconds etc.

I want to find difference between these two date with days,hours and minutes

I want to find difference between these two date with days,hours and minutes.
$date1 = "27-09-2014 05:00 AM";
$date2 = "29-09-2014 03:00 PM";
From PHP Version > 5 below new date/time functions added to get difference:
$datetime1 = new DateTime("2010-06-20");
$datetime2 = new DateTime("2011-06-22");
$difference = $datetime1->diff($datetime2);
echo 'Difference: '.$difference->y.' years, '
.$difference->m.' months, '
.$difference->d.' days';
print_r($difference);
Result as below:
Difference: 1 years, 0 months, 2 days
DateInterval Object
(
[y] => 1
[m] => 0
[d] => 2
[h] => 0
[i] => 0
[s] => 0
[invert] => 0
[days] => 367
)
I'm not sure whether I get your question right, but shouldn't the following work?
$datetime1 = new DateTime('27-09-2014');
$datetime2 = new DateTime('29-09-2014');
$datetime1->setTime(05, 00);
$datetime2->setTime(15, 00);
$interval = date_diff($datetime1, $datetime2);
echo $interval->format('%a Day and %h hours'
DateTime::diff

PHP Finding how many hours of a timespan is within another timespan

I am trying to find a way to determine whether a timespan is partially or fully within another timespan. For example:
I have time entries of:
Monday 18:30:00 to Tuesday 05:00:00,
Monday 23:00:00 to Tuesday 05:00:00,
Monday 20:00:00 to Tuesday 08:00:00,
Monday 00:00:00 to Tuesday 08:00:00,
and need to find, for each one, how much of the time is within a timespan of 22:00:00 to 06:00:00. The output would need to be:
07:00:00,
06:00:00,
08:00:00,
06:00:00.
What you're looking for is DateTime::diff which returns an instance of an DateInterval
Here a little example:
$d1 = new DateTime("Monday 18:30:00");
$d2 = new DateTime("Tuesday 05:00:00");
$limit1 = new DateTime("Monday 22:00:00");
$limit2 = new DateTime("Tuesday 06:00:00");
$within1 = $d1->getTimestamp() < $limit1->getTimestamp() ? $limit1 : $d1;
$within2 = $d2->getTimestamp() < $limit2->getTimestamp() ? $d2 : $limit2;
$interval = $within1->diff($within2);
print_r($interval);
print_r($interval);
outputs:
DateInterval Object
(
[y] => 0
[m] => 0
[d] => 0
[h] => 7
[i] => 0
[s] => 0
[invert] => 0
[days] => 0
)
You can either read this attributes directly or you can use the DateInterval::format()

Categories