how can I find the next closest hour in php
so for example if current time is 4:15 the next hour will be 5, etc
$dateString = 'Tue, 13 Mar 2012 04:48:34 -0400';
$date = new DateTime( $dateString );
echo $date->format( 'H:i:s' );
gives me the time from the string and I want to expand on that and get the next closest hour
$nextHour = (intval($date->format('H'))+1) % 24;
echo $nextHour; // 5
Here we go:
<?php
echo date("H:00",strtotime($date. " + 1hour "));
?>
Can you just take pieces (hours, minutes, seconds) and get the next hour?
$dateString = 'Tue, 13 Mar 2012 04:48:34 -0400';
$date = new DateTime( $dateString );
echo $date->format( 'H:i:s' );
echo "\n";
$nexthour = ($date->format('H') + ($date->format('i') > 0 || $date->format('s') > 0 ? 1 : 0)) % 24;
echo "$nexthour:00:00";
Supply any eligible date() to:
function roundToNextHour($dateString) {
$date = new DateTime($dateString);
$minutes = $date->format('i');
if ($minutes > 0) {
$date->modify("+1 hour");
$date->modify('-'.$minutes.' minutes');
}
return $date;
}
<?php
$dateString = 'Tue, 13 Mar 2012 04:48:34 -0400';
$date = new DateTime( $dateString );
$date->modify('+1 hour');
echo $date->format('H:i:s').PHP_EOL;
// OR
echo date('H:i:s', strtotime($dateString) + 60 * 60).PHP_EOL;
As I just needed something similar (next full hour) here my solution:
$now = time();
$nextFullHour = date(DATE_ATOM, $now + (3600 - $now % 3600));
By replacing the 3600 e.g. with 60 you get the next full minute...
You can also replace the $now with any other timestamp if you do not need it relative to the current time.
That is my solution:
$dateTime = new \DateTime();
$dateTime->add(new \DateInterval('PT1H'))
->setTime($dateTime->format('H'), '00');
Nobody else used this one so I figured I'd drop it here, simplest one I saw above for an actual timestamp, not just the hour itself.
$now = ''; // empty uses current time, or you can insert a datetime string
$next_hour = date( 'Y-m-d H:00:00', strtotime( $now . ' +1 hour' ) );
try it for current time, if you need put second argument to date function
<?php echo date('H')+1; ?>
very nice stuff
One more:
$current_datetime = new DateTimeImmutable();
$next_full_hour_datetime = $current_datetime
->modify(
sprintf(
'+%d seconds',
3600 - ($current_datetime->getTimestamp() % 3600)
)
);
A little late to this party, but here's a more flexible function to round up a dateTime object by any interval in minutes. You pass in your dateTime object and a rounding interval in minutes, so for an hour you'd just pass in 60, etc.
public function round_up_time( $datetime, $rounding_interval ) {
// get total minutes from the start of the day
$minutes = ( intval( $datetime->format( 'H' ) ) * 60 ) + ( intval( $datetime->format( 'i' ) ) );
// round up the minutes based on the interval we are rounding to
$rounded_minutes = ( intval( $minutes / $rounding_interval ) + 1 ) * $rounding_interval;
// reset our dateTime to the very start of the day
$datetime->setTime( 0, 0 );
// then increase the dateTime by the rounded minutes value
$datetime->modify( '+ ' . $rounded_minutes . ' minutes' );
}
To get the next closest full hour in DateTime:
$date = new DateTime('+1 hour'); //set the next hour
$date->setTime($date->format('H'), '00', '00'); //keep the next hour, set minutes to 00 and seconds to 00
Related
While using strtotime function , if i am giving +48 day i am not sure whether is working fine or not ?
<?php
date_default_timezone_set('Asia/Kolkata');
$Seconds = 8604800 ;
$At = "2018-11-28 12:16:19";
echo date('Y-m-d H:i:s',strtotime("+48 day",strtotime($tAt)));
?>
strtotime expects the first parameter to be a valid time string. You are providing the number of seconds. Try -
echo $requestValidTill = date('Y-m-d H:i:s',strtotime("+$resetPasswordDurationInSeconds SECONDS",strtotime($requestAt)));
Output
2018-12-05 12:16:19
strtotime()
Working code
if you have PHP 5.3+ you can use the following lines of code
$requestAt = "2018-11-28 12:16:19";
$resetPasswordDurationInSeconds = 604800 ; //60 * 60 * 24 * 7 ( +7 days in seconds )
$date = new DateTime($requestAt );
$date->add(new DateInterval('PT'.$resetPasswordDurationInSeconds.'S')); // adds 604800 secs
echo date('Y-m-d H:i:s', $date->getTimestamp());
Your just need to add seconds in strtotime
<?php
$requestAt = strtotime("2018-11-28 12:16:19");
$requestAt += 604800;
echo date('Y-m-d H:i:s', $requestAt);
?>
Live Demo
I have a time string in UNIX format . I need to round that string to closest interval of 30 minutes.
For eg: I have time as 9:20 AM than it should round it to 9:30 AM.
If minutes are greater than 30 like 9:45 AM it should round to 10:00 AM.
I have tried this so far:
$hour = date('H', $ltdaytmfstr);
$minute = (date('i', $ltdaytmfstr)>30)?'00':'30';
echo "$hour:$minute";
$ltdaytmfstr is time string in unix format.
Any suggestions? It would be better if I can get the value returned in UNIX format .
You should try this: This will round it to the nearest half an hour.
Use ceil function.
<?php
$rounded = date('H:i:s', ceil(strtotime('16:20:34')/1800)*1800);
echo $rounded;
?>
Output: 16:30:00
http://codepad.org/4WwNO5Rt
If you use DateTime:
$dt = new \DateTime;
$diff = $dt
->add(
//This just calculates number of seconds from the next 30 minute interval
new \DateInterval("PT".((30 - $dt->format("i"))*60-$dt->format("s"))."S")
);
echo $dt->getTimestamp();
I guess this is what you are looking for
function round_timestamp($timestamp){
$hour = date("H", strtotime($timestamp));
$minute = date("i", strtotime($timestamp));
if ($minute<15) {
return date('H:i', strtotime("$hour:00") );
} elseif($minute>=15 and $minute<45){
return date('H:i', strtotime("$hour:30") );
} elseif($minute>=45) {
$hour = $hour + 1;
return date('H:i', strtotime("$hour:00") );
}
}
echo round_timestamp("11:59");
// 00:00
echo round_timestamp("10:59");
// 11:00
Since UNIX time is in seconds, you can just transform it to 30 minute units, round, and convert back to seconds.
$timestamp = time();
$rounded = round($timestamp / (30 * 60)) * 30 * 60
You can also use floor() or ceil() to round up or down if needed.
How do I calculate the difference between two dates in hours?
For example:
day1=2006-04-12 12:30:00
day2=2006-04-14 11:30:00
In this case the result should be 47 hours.
The newer PHP-Versions provide some new classes called DateTime, DateInterval, DateTimeZone and DatePeriod. The cool thing about this classes is, that it considers different timezones, leap years, leap seconds, summertime, etc. And on top of that it's very easy to use. Here's what you want with the help of this objects:
// Create two new DateTime-objects...
$date1 = new DateTime('2006-04-12T12:30:00');
$date2 = new DateTime('2006-04-14T11:30:00');
// The diff-methods returns a new DateInterval-object...
$diff = $date2->diff($date1);
// Call the format method on the DateInterval-object
echo $diff->format('%a Day and %h hours');
The DateInterval-object, which is returned also provides other methods than format. If you want the result in hours only, you could to something like this:
$date1 = new DateTime('2006-04-12T12:30:00');
$date2 = new DateTime('2006-04-14T11:30:00');
$diff = $date2->diff($date1);
$hours = $diff->h;
$hours = $hours + ($diff->days*24);
echo $hours;
And here are the links for documentation:
DateTime-Class
DateTimeZone-Class
DateInterval-Class
DatePeriod-Class
All these classes also offer a procedural/functional way to operate with dates. Therefore take a look at the overview: http://php.net/manual/book.datetime.php
$t1 = strtotime( '2006-04-14 11:30:00' );
$t2 = strtotime( '2006-04-12 12:30:00' );
$diff = $t1 - $t2;
$hours = $diff / ( 60 * 60 );
To provide another method for DatePeriod when using the UTC or GMT timezone.
Count Hours https://3v4l.org/Mu3HD
$start = new \DateTime('2006-04-12T12:30:00');
$end = new \DateTime('2006-04-14T11:30:00');
//determine what interval should be used - can change to weeks, months, etc
$interval = new \DateInterval('PT1H');
//create periods every hour between the two dates
$periods = new \DatePeriod($start, $interval, $end);
//count the number of objects within the periods
$hours = iterator_count($periods);
echo $hours . ' hours';
//difference between Unix Epoch
$diff = $end->getTimestamp() - $start->getTimestamp();
$hours = $diff / ( 60 * 60 );
echo $hours . ' hours (60 * 60)';
//difference between days
$diff = $end->diff($start);
$hours = $diff->h + ($diff->days * 24);
echo $hours . ' hours (days * 24)';
Result
47 hours (iterator_count)
47 hours (60 * 60)
47 hours (days * 24)
Count Hours with Daylight Savings https://3v4l.org/QBQUB
Please be advised that DatePeriod excludes an hour for DST but does not add another hour when DST ends. So its usage is subjective to your desired outcome and date range.
See the current bug report
//set timezone to UTC to disregard daylight savings
date_default_timezone_set('America/New_York');
$interval = new \DateInterval('PT1H');
//DST starts Apr. 2nd 02:00 and moves to 03:00
$start = new \DateTime('2006-04-01T12:00:00');
$end = new \DateTime('2006-04-02T12:00:00');
$periods = new \DatePeriod($start, $interval, $end);
$hours = iterator_count($periods);
echo $hours . ' hours';
//DST ends Oct. 29th 02:00 and moves to 01:00
$start = new \DateTime('2006-10-28T12:00:00');
$end = new \DateTime('2006-10-29T12:00:00');
$periods = new \DatePeriod($start, $interval, $end);
$hours = iterator_count($periods);
echo $hours . ' hours';
Result
#2006-04-01 12:00 EST to 2006-04-02 12:00 EDT
23 hours (iterator_count)
//23 hours (60 * 60)
//24 hours (days * 24)
#2006-10-28 12:00 EDT to 2006-10-29 12:00 EST
24 hours (iterator_count)
//25 hours (60 * 60)
//24 hours (days * 24)
#2006-01-01 12:00 EST to 2007-01-01 12:00 EST
8759 hours (iterator_count)
//8760 hours (60 * 60)
//8760 hours (days * 24)
//------
#2006-04-01 12:00 UTC to 2006-04-02 12:00 UTC
24 hours (iterator_count)
//24 hours (60 * 60)
//24 hours (days * 24)
#2006-10-28 12:00 UTC to 2006-10-29 12:00 UTC
24 hours (iterator_count)
//24 hours (60 * 60)
//24 hours (days * 24)
#2006-01-01 12:00 UTC to 2007-01-01 12:00 UTC
8760 hours (iterator_count)
//8760 hours (60 * 60)
//8760 hours (days * 24)
your answer is:
round((strtotime($day2) - strtotime($day1))/(60*60))
The easiest way to get the correct number of hours between two dates (datetimes), even across daylight saving time changes, is to use the difference in Unix timestamps. Unix timestamps are seconds elapsed since 1970-01-01T00:00:00 UTC, ignoring leap seconds (this is OK because you probably don't need this precision, and because it's quite difficult to take leap seconds into account).
The most flexible way to convert a datetime string with optional timezone information into a Unix timestamp is to construct a DateTime object (optionally with a DateTimeZone as a second argument in the constructor), and then call its getTimestamp method.
$str1 = '2006-04-12 12:30:00';
$str2 = '2006-04-14 11:30:00';
$tz1 = new DateTimeZone('Pacific/Apia');
$tz2 = $tz1;
$d1 = new DateTime($str1, $tz1); // tz is optional,
$d2 = new DateTime($str2, $tz2); // and ignored if str contains tz offset
$delta_h = ($d2->getTimestamp() - $d1->getTimestamp()) / 3600;
if ($rounded_result) {
$delta_h = round ($delta_h);
} else if ($truncated_result) {
$delta_h = intval($delta_h);
}
echo "Δh: $delta_h\n";
//Calculate number of hours between pass and now
$dayinpass = "2013-06-23 05:09:12";
$today = time();
$dayinpass= strtotime($dayinpass);
echo round(abs($today-$dayinpass)/60/60);
<?
$day1 = "2014-01-26 11:30:00";
$day1 = strtotime($day1);
$day2 = "2014-01-26 12:30:00";
$day2 = strtotime($day2);
$diffHours = round(($day2 - $day1) / 3600);
echo $diffHours;
?>
$day1 = "2006-04-12 12:30:00"
$day1 = strtotime($day1);
$day2 = "2006-04-14 11:30:00"
$day2 = strtotime($day2);
$diffHours = round(($day2 - $day1) / 3600);
I guess strtotime() function accept this date format.
Unfortunately the solution provided by FaileN doesn't work as stated by Walter Tross.. days may not be 24 hours!
I like to use the PHP Objects where possible and for a bit more flexibility I have come up with the following function:
/**
* #param DateTimeInterface $a
* #param DateTimeInterface $b
* #param bool $absolute Should the interval be forced to be positive?
* #param string $cap The greatest time unit to allow
*
* #return DateInterval The difference as a time only interval
*/
function time_diff(DateTimeInterface $a, DateTimeInterface $b, $absolute=false, $cap='H'){
// Get unix timestamps, note getTimeStamp() is limited
$b_raw = intval($b->format("U"));
$a_raw = intval($a->format("U"));
// Initial Interval properties
$h = 0;
$m = 0;
$invert = 0;
// Is interval negative?
if(!$absolute && $b_raw<$a_raw){
$invert = 1;
}
// Working diff, reduced as larger time units are calculated
$working = abs($b_raw-$a_raw);
// If capped at hours, calc and remove hours, cap at minutes
if($cap == 'H') {
$h = intval($working/3600);
$working -= $h * 3600;
$cap = 'M';
}
// If capped at minutes, calc and remove minutes
if($cap == 'M') {
$m = intval($working/60);
$working -= $m * 60;
}
// Seconds remain
$s = $working;
// Build interval and invert if necessary
$interval = new DateInterval('PT'.$h.'H'.$m.'M'.$s.'S');
$interval->invert=$invert;
return $interval;
}
This like date_diff() creates a DateTimeInterval, but with the highest unit as hours rather than years.. it can be formatted as usual.
$interval = time_diff($date_a, $date_b);
echo $interval->format('%r%H'); // For hours (with sign)
N.B. I have used format('U') instead of getTimestamp() because of the comment in the manual. Also note that 64-bit is required for post-epoch and pre-negative-epoch dates!
Carbon could also be a nice way to go.
From their website:
A simple PHP API extension for DateTime. http://carbon.nesbot.com/
Example:
use Carbon\Carbon;
//...
$day1 = Carbon::createFromFormat('Y-m-d H:i:s', '2006-04-12 12:30:00');
$day2 = Carbon::createFromFormat('Y-m-d H:i:s', '2006-04-14 11:30:00');
echo $day1->diffInHours($day2); // 47
//...
Carbon extends the DateTime class to inherit methods including diff(). It adds nice sugars like diffInHours, diffInMintutes, diffInSeconds e.t.c.
This function helps you to calculate exact years and months between two given dates, $doj1 and $doj. It returns example 4.3 means 4 years and 3 month.
<?php
function cal_exp($doj1)
{
$doj1=strtotime($doj1);
$doj=date("m/d/Y",$doj1); //till date or any given date
$now=date("m/d/Y");
//$b=strtotime($b1);
//echo $c=$b1-$a2;
//echo date("Y-m-d H:i:s",$c);
$year=date("Y");
//$chk_leap=is_leapyear($year);
//$year_diff=365.25;
$x=explode("/",$doj);
$y1=explode("/",$now);
$yy=$x[2];
$mm=$x[0];
$dd=$x[1];
$yy1=$y1[2];
$mm1=$y1[0];
$dd1=$y1[1];
$mn=0;
$mn1=0;
$ye=0;
if($mm1>$mm)
{
$mn=$mm1-$mm;
if($dd1<$dd)
{
$mn=$mn-1;
}
$ye=$yy1-$yy;
}
else if($mm1<$mm)
{
$mn=12-$mm;
//$mn=$mn;
if($mm!=1)
{
$mn1=$mm1-1;
}
$mn+=$mn1;
if($dd1>$dd)
{
$mn+=1;
}
$yy=$yy+1;
$ye=$yy1-$yy;
}
else
{
$ye=$yy1-$yy;
$ye=$ye-1;
$mn=12-1;
if($dd1>$dd)
{
$ye+=1;
$mn=0;
}
}
$to=$ye." year and ".$mn." months";
return $ye.".".$mn;
/*return daysDiff($x[2],$x[0],$x[1]);
$days=dateDiff("/",$now,$doj)/$year_diff;
$days_exp=explode(".",$days);
return $years_exp=$days; //number of years exp*/
}
?>
In addition to #fyrye's very helpful answer this is an okayish workaround for the mentioned bug (this one), that DatePeriod substracts one hour when entering summertime, but doesn't add one hour when leaving summertime (and thus Europe/Berlin's March has its correct 743 hours but October has 744 instead of 745 hours):
Counting the hours of a month (or any timespan), considering DST-transitions in both directions
function getMonthHours(string $year, string $month, \DateTimeZone $timezone): int
{
// or whatever start and end \DateTimeInterface objects you like
$start = new \DateTimeImmutable($year . '-' . $month . '-01 00:00:00', $timezone);
$end = new \DateTimeImmutable((new \DateTimeImmutable($year . '-' . $month . '-01 23:59:59', $timezone))->format('Y-m-t H:i:s'), $timezone);
// count the hours just utilizing \DatePeriod, \DateInterval and iterator_count, hell yeah!
$hours = iterator_count(new \DatePeriod($start, new \DateInterval('PT1H'), $end));
// find transitions and check, if there is one that leads to a positive offset
// that isn't added by \DatePeriod
// this is the workaround for https://bugs.php.net/bug.php?id=75685
$transitions = $timezone->getTransitions((int)$start->format('U'), (int)$end->format('U'));
if (2 === count($transitions) && $transitions[0]['offset'] - $transitions[1]['offset'] > 0) {
$hours += (round(($transitions[0]['offset'] - $transitions[1]['offset'])/3600));
}
return $hours;
}
$myTimezoneWithDST = new \DateTimeZone('Europe/Berlin');
var_dump(getMonthHours('2020', '01', $myTimezoneWithDST)); // 744
var_dump(getMonthHours('2020', '03', $myTimezoneWithDST)); // 743
var_dump(getMonthHours('2020', '10', $myTimezoneWithDST)); // 745, finally!
$myTimezoneWithoutDST = new \DateTimeZone('UTC');
var_dump(getMonthHours('2020', '01', $myTimezoneWithoutDST)); // 744
var_dump(getMonthHours('2020', '03', $myTimezoneWithoutDST)); // 744
var_dump(getMonthHours('2020', '10', $myTimezoneWithoutDST)); // 744
P.S. If you check a (longer) timespan, which leads to more than those two transitions, my workaround won't touch the counted hours to reduce the potential of funny side effects. In such cases, a more complicated solution must be implemented. One could iterate over all found transitions and compare the current with the last and check if it is one with DST true->false.
$diff_min = ( strtotime( $day2 ) - strtotime( $day1 ) ) / 60 / 60;
$total_time = $diff_min;
You can try this one.
// Create two new DateTime-objects...
$date1 = new DateTime('2006-04-12T12:30:00');
$date2 = new DateTime('2006-04-14T11:30:00');
// The diff-method returns difference in days...
$diffInDays = $date2->diffInDays($date1);
// The diff-method returns difference in hours...
$diffInHours = $date2->diffInHours($date1);
// The diff-method returns difference in mintes...
$diffInMinutes = $date2->diffInMinutes($date1);
The second part of the answer from #fidi doesn't factor in months/years.
$date1 = new DateTime('2006-04-12T12:30:00');
$date2 = new DateTime('2010-04-14T11:30:00');
$diff = $date2->diff($date1);
$hours = $diff->h;
$days = intval($diff->format('%a'));
$hours = $hours + ($days*24);
echo $hours;
This is working in my project. I think, This will be helpful for you.
If Date is in past then invert will 1.
If Date is in future then invert will 0.
$defaultDate = date('Y-m-d');
$datetime1 = new DateTime('2013-03-10');
$datetime2 = new DateTime($defaultDate);
$interval = $datetime1->diff($datetime2);
$days = $interval->format('%a');
$invert = $interval->invert;
To pass a unix timestamp use this notation
$now = time();
$now = new DateTime("#$now");
So I have a script that does multiple checks for 32, 48 and 72 hours ago.
Basically I check my database for entries that are at least x hours old.
Now this works fine like this:
$date = date('Y-m-d H:i:s',strtotime('-32 hours'));
$q = "SELECT * FROM `table` WHERE `date` <= '".$date."'";
Now I want this to exclude weekends. I know you can use weekdays within strtotime to get this effect however this doesn't work for hours.
For 48 hours it's easy because I can simply do the following:
echo date('Y-m-d H:i:s',
strtotime(date("Y-m-d H:i:s").
" -2 weekdays ".
date('H:i:s')));
For 72 hours it's also easy because it's 3 days. However 32 hours poses a problem because it's ±1.3 days.
In conclusion, how do I get the datetime of 32 hours ago excluding weekends.
Use strtotime as you had initially:
$time = strtotime('-32 hours');
Then do the weekend/weekday calculation manually.
// If the day is Sunday or Saturday subtract a full day.
while (date('w', $time) % 6 == 0) {
$time = strtotime('-1 day', $time);
}
$date = date('Y-m-d H:i:s', $time);
I am not sure if this is correct or the best way to do it but something like:
function getDateBackExcludingWeekend( $hours ) {
$now = time();
$secondsBack = $hours * 3600;
$actual = $now - $secondsBack;
$monday = strtotime("last monday");
if( $actual < $monday ) {
$diff = ($secondsBack - ($now - $monday));
$backthen = ($monday - 172800 /* two days */) - $diff;
return date("Y-m-d H:i:s", $backthen);
}
return date("Y-m-d H:i:s", $actual);
}
Why not just remove two days and add 16 hours semi-manually to make up for it?
$DateTMP = date('Y-m-d h:i:s',(strtotime(date(Y-m-d)." -2 weekdays") + (60 * 60 * 16)));
How do I calculate the difference between two dates in hours?
For example:
day1=2006-04-12 12:30:00
day2=2006-04-14 11:30:00
In this case the result should be 47 hours.
The newer PHP-Versions provide some new classes called DateTime, DateInterval, DateTimeZone and DatePeriod. The cool thing about this classes is, that it considers different timezones, leap years, leap seconds, summertime, etc. And on top of that it's very easy to use. Here's what you want with the help of this objects:
// Create two new DateTime-objects...
$date1 = new DateTime('2006-04-12T12:30:00');
$date2 = new DateTime('2006-04-14T11:30:00');
// The diff-methods returns a new DateInterval-object...
$diff = $date2->diff($date1);
// Call the format method on the DateInterval-object
echo $diff->format('%a Day and %h hours');
The DateInterval-object, which is returned also provides other methods than format. If you want the result in hours only, you could to something like this:
$date1 = new DateTime('2006-04-12T12:30:00');
$date2 = new DateTime('2006-04-14T11:30:00');
$diff = $date2->diff($date1);
$hours = $diff->h;
$hours = $hours + ($diff->days*24);
echo $hours;
And here are the links for documentation:
DateTime-Class
DateTimeZone-Class
DateInterval-Class
DatePeriod-Class
All these classes also offer a procedural/functional way to operate with dates. Therefore take a look at the overview: http://php.net/manual/book.datetime.php
$t1 = strtotime( '2006-04-14 11:30:00' );
$t2 = strtotime( '2006-04-12 12:30:00' );
$diff = $t1 - $t2;
$hours = $diff / ( 60 * 60 );
To provide another method for DatePeriod when using the UTC or GMT timezone.
Count Hours https://3v4l.org/Mu3HD
$start = new \DateTime('2006-04-12T12:30:00');
$end = new \DateTime('2006-04-14T11:30:00');
//determine what interval should be used - can change to weeks, months, etc
$interval = new \DateInterval('PT1H');
//create periods every hour between the two dates
$periods = new \DatePeriod($start, $interval, $end);
//count the number of objects within the periods
$hours = iterator_count($periods);
echo $hours . ' hours';
//difference between Unix Epoch
$diff = $end->getTimestamp() - $start->getTimestamp();
$hours = $diff / ( 60 * 60 );
echo $hours . ' hours (60 * 60)';
//difference between days
$diff = $end->diff($start);
$hours = $diff->h + ($diff->days * 24);
echo $hours . ' hours (days * 24)';
Result
47 hours (iterator_count)
47 hours (60 * 60)
47 hours (days * 24)
Count Hours with Daylight Savings https://3v4l.org/QBQUB
Please be advised that DatePeriod excludes an hour for DST but does not add another hour when DST ends. So its usage is subjective to your desired outcome and date range.
See the current bug report
//set timezone to UTC to disregard daylight savings
date_default_timezone_set('America/New_York');
$interval = new \DateInterval('PT1H');
//DST starts Apr. 2nd 02:00 and moves to 03:00
$start = new \DateTime('2006-04-01T12:00:00');
$end = new \DateTime('2006-04-02T12:00:00');
$periods = new \DatePeriod($start, $interval, $end);
$hours = iterator_count($periods);
echo $hours . ' hours';
//DST ends Oct. 29th 02:00 and moves to 01:00
$start = new \DateTime('2006-10-28T12:00:00');
$end = new \DateTime('2006-10-29T12:00:00');
$periods = new \DatePeriod($start, $interval, $end);
$hours = iterator_count($periods);
echo $hours . ' hours';
Result
#2006-04-01 12:00 EST to 2006-04-02 12:00 EDT
23 hours (iterator_count)
//23 hours (60 * 60)
//24 hours (days * 24)
#2006-10-28 12:00 EDT to 2006-10-29 12:00 EST
24 hours (iterator_count)
//25 hours (60 * 60)
//24 hours (days * 24)
#2006-01-01 12:00 EST to 2007-01-01 12:00 EST
8759 hours (iterator_count)
//8760 hours (60 * 60)
//8760 hours (days * 24)
//------
#2006-04-01 12:00 UTC to 2006-04-02 12:00 UTC
24 hours (iterator_count)
//24 hours (60 * 60)
//24 hours (days * 24)
#2006-10-28 12:00 UTC to 2006-10-29 12:00 UTC
24 hours (iterator_count)
//24 hours (60 * 60)
//24 hours (days * 24)
#2006-01-01 12:00 UTC to 2007-01-01 12:00 UTC
8760 hours (iterator_count)
//8760 hours (60 * 60)
//8760 hours (days * 24)
your answer is:
round((strtotime($day2) - strtotime($day1))/(60*60))
The easiest way to get the correct number of hours between two dates (datetimes), even across daylight saving time changes, is to use the difference in Unix timestamps. Unix timestamps are seconds elapsed since 1970-01-01T00:00:00 UTC, ignoring leap seconds (this is OK because you probably don't need this precision, and because it's quite difficult to take leap seconds into account).
The most flexible way to convert a datetime string with optional timezone information into a Unix timestamp is to construct a DateTime object (optionally with a DateTimeZone as a second argument in the constructor), and then call its getTimestamp method.
$str1 = '2006-04-12 12:30:00';
$str2 = '2006-04-14 11:30:00';
$tz1 = new DateTimeZone('Pacific/Apia');
$tz2 = $tz1;
$d1 = new DateTime($str1, $tz1); // tz is optional,
$d2 = new DateTime($str2, $tz2); // and ignored if str contains tz offset
$delta_h = ($d2->getTimestamp() - $d1->getTimestamp()) / 3600;
if ($rounded_result) {
$delta_h = round ($delta_h);
} else if ($truncated_result) {
$delta_h = intval($delta_h);
}
echo "Δh: $delta_h\n";
//Calculate number of hours between pass and now
$dayinpass = "2013-06-23 05:09:12";
$today = time();
$dayinpass= strtotime($dayinpass);
echo round(abs($today-$dayinpass)/60/60);
<?
$day1 = "2014-01-26 11:30:00";
$day1 = strtotime($day1);
$day2 = "2014-01-26 12:30:00";
$day2 = strtotime($day2);
$diffHours = round(($day2 - $day1) / 3600);
echo $diffHours;
?>
$day1 = "2006-04-12 12:30:00"
$day1 = strtotime($day1);
$day2 = "2006-04-14 11:30:00"
$day2 = strtotime($day2);
$diffHours = round(($day2 - $day1) / 3600);
I guess strtotime() function accept this date format.
Unfortunately the solution provided by FaileN doesn't work as stated by Walter Tross.. days may not be 24 hours!
I like to use the PHP Objects where possible and for a bit more flexibility I have come up with the following function:
/**
* #param DateTimeInterface $a
* #param DateTimeInterface $b
* #param bool $absolute Should the interval be forced to be positive?
* #param string $cap The greatest time unit to allow
*
* #return DateInterval The difference as a time only interval
*/
function time_diff(DateTimeInterface $a, DateTimeInterface $b, $absolute=false, $cap='H'){
// Get unix timestamps, note getTimeStamp() is limited
$b_raw = intval($b->format("U"));
$a_raw = intval($a->format("U"));
// Initial Interval properties
$h = 0;
$m = 0;
$invert = 0;
// Is interval negative?
if(!$absolute && $b_raw<$a_raw){
$invert = 1;
}
// Working diff, reduced as larger time units are calculated
$working = abs($b_raw-$a_raw);
// If capped at hours, calc and remove hours, cap at minutes
if($cap == 'H') {
$h = intval($working/3600);
$working -= $h * 3600;
$cap = 'M';
}
// If capped at minutes, calc and remove minutes
if($cap == 'M') {
$m = intval($working/60);
$working -= $m * 60;
}
// Seconds remain
$s = $working;
// Build interval and invert if necessary
$interval = new DateInterval('PT'.$h.'H'.$m.'M'.$s.'S');
$interval->invert=$invert;
return $interval;
}
This like date_diff() creates a DateTimeInterval, but with the highest unit as hours rather than years.. it can be formatted as usual.
$interval = time_diff($date_a, $date_b);
echo $interval->format('%r%H'); // For hours (with sign)
N.B. I have used format('U') instead of getTimestamp() because of the comment in the manual. Also note that 64-bit is required for post-epoch and pre-negative-epoch dates!
Carbon could also be a nice way to go.
From their website:
A simple PHP API extension for DateTime. http://carbon.nesbot.com/
Example:
use Carbon\Carbon;
//...
$day1 = Carbon::createFromFormat('Y-m-d H:i:s', '2006-04-12 12:30:00');
$day2 = Carbon::createFromFormat('Y-m-d H:i:s', '2006-04-14 11:30:00');
echo $day1->diffInHours($day2); // 47
//...
Carbon extends the DateTime class to inherit methods including diff(). It adds nice sugars like diffInHours, diffInMintutes, diffInSeconds e.t.c.
This function helps you to calculate exact years and months between two given dates, $doj1 and $doj. It returns example 4.3 means 4 years and 3 month.
<?php
function cal_exp($doj1)
{
$doj1=strtotime($doj1);
$doj=date("m/d/Y",$doj1); //till date or any given date
$now=date("m/d/Y");
//$b=strtotime($b1);
//echo $c=$b1-$a2;
//echo date("Y-m-d H:i:s",$c);
$year=date("Y");
//$chk_leap=is_leapyear($year);
//$year_diff=365.25;
$x=explode("/",$doj);
$y1=explode("/",$now);
$yy=$x[2];
$mm=$x[0];
$dd=$x[1];
$yy1=$y1[2];
$mm1=$y1[0];
$dd1=$y1[1];
$mn=0;
$mn1=0;
$ye=0;
if($mm1>$mm)
{
$mn=$mm1-$mm;
if($dd1<$dd)
{
$mn=$mn-1;
}
$ye=$yy1-$yy;
}
else if($mm1<$mm)
{
$mn=12-$mm;
//$mn=$mn;
if($mm!=1)
{
$mn1=$mm1-1;
}
$mn+=$mn1;
if($dd1>$dd)
{
$mn+=1;
}
$yy=$yy+1;
$ye=$yy1-$yy;
}
else
{
$ye=$yy1-$yy;
$ye=$ye-1;
$mn=12-1;
if($dd1>$dd)
{
$ye+=1;
$mn=0;
}
}
$to=$ye." year and ".$mn." months";
return $ye.".".$mn;
/*return daysDiff($x[2],$x[0],$x[1]);
$days=dateDiff("/",$now,$doj)/$year_diff;
$days_exp=explode(".",$days);
return $years_exp=$days; //number of years exp*/
}
?>
In addition to #fyrye's very helpful answer this is an okayish workaround for the mentioned bug (this one), that DatePeriod substracts one hour when entering summertime, but doesn't add one hour when leaving summertime (and thus Europe/Berlin's March has its correct 743 hours but October has 744 instead of 745 hours):
Counting the hours of a month (or any timespan), considering DST-transitions in both directions
function getMonthHours(string $year, string $month, \DateTimeZone $timezone): int
{
// or whatever start and end \DateTimeInterface objects you like
$start = new \DateTimeImmutable($year . '-' . $month . '-01 00:00:00', $timezone);
$end = new \DateTimeImmutable((new \DateTimeImmutable($year . '-' . $month . '-01 23:59:59', $timezone))->format('Y-m-t H:i:s'), $timezone);
// count the hours just utilizing \DatePeriod, \DateInterval and iterator_count, hell yeah!
$hours = iterator_count(new \DatePeriod($start, new \DateInterval('PT1H'), $end));
// find transitions and check, if there is one that leads to a positive offset
// that isn't added by \DatePeriod
// this is the workaround for https://bugs.php.net/bug.php?id=75685
$transitions = $timezone->getTransitions((int)$start->format('U'), (int)$end->format('U'));
if (2 === count($transitions) && $transitions[0]['offset'] - $transitions[1]['offset'] > 0) {
$hours += (round(($transitions[0]['offset'] - $transitions[1]['offset'])/3600));
}
return $hours;
}
$myTimezoneWithDST = new \DateTimeZone('Europe/Berlin');
var_dump(getMonthHours('2020', '01', $myTimezoneWithDST)); // 744
var_dump(getMonthHours('2020', '03', $myTimezoneWithDST)); // 743
var_dump(getMonthHours('2020', '10', $myTimezoneWithDST)); // 745, finally!
$myTimezoneWithoutDST = new \DateTimeZone('UTC');
var_dump(getMonthHours('2020', '01', $myTimezoneWithoutDST)); // 744
var_dump(getMonthHours('2020', '03', $myTimezoneWithoutDST)); // 744
var_dump(getMonthHours('2020', '10', $myTimezoneWithoutDST)); // 744
P.S. If you check a (longer) timespan, which leads to more than those two transitions, my workaround won't touch the counted hours to reduce the potential of funny side effects. In such cases, a more complicated solution must be implemented. One could iterate over all found transitions and compare the current with the last and check if it is one with DST true->false.
$diff_min = ( strtotime( $day2 ) - strtotime( $day1 ) ) / 60 / 60;
$total_time = $diff_min;
You can try this one.
// Create two new DateTime-objects...
$date1 = new DateTime('2006-04-12T12:30:00');
$date2 = new DateTime('2006-04-14T11:30:00');
// The diff-method returns difference in days...
$diffInDays = $date2->diffInDays($date1);
// The diff-method returns difference in hours...
$diffInHours = $date2->diffInHours($date1);
// The diff-method returns difference in mintes...
$diffInMinutes = $date2->diffInMinutes($date1);
The second part of the answer from #fidi doesn't factor in months/years.
$date1 = new DateTime('2006-04-12T12:30:00');
$date2 = new DateTime('2010-04-14T11:30:00');
$diff = $date2->diff($date1);
$hours = $diff->h;
$days = intval($diff->format('%a'));
$hours = $hours + ($days*24);
echo $hours;
This is working in my project. I think, This will be helpful for you.
If Date is in past then invert will 1.
If Date is in future then invert will 0.
$defaultDate = date('Y-m-d');
$datetime1 = new DateTime('2013-03-10');
$datetime2 = new DateTime($defaultDate);
$interval = $datetime1->diff($datetime2);
$days = $interval->format('%a');
$invert = $interval->invert;
To pass a unix timestamp use this notation
$now = time();
$now = new DateTime("#$now");