How do I get the time of the previous '4 am'? - php

I would like to get the time in seconds (standard time() format) of the previous '4 am'.
My first attempt was: mktime(4,0,0).
This works for every time of the day, except between 00:00 and 04:00, because than it will give the time of the next '4 am'.
So how do I tackle this problem?

$now = new DateTime();
$fourAm = new DateTime('today 4am');
if ($now < $fourAm) {
$time = strtotime('yesterday 4am');
} else {
$time = $fourAm->getTimestamp();
}
Where $time is the timestamp of the "last 4am", regardless of what time it currently is.
Edit:
You could also do this without the DateTime objects, but I love that suite of classes, so I usually find any reason at all to use them. :-P
$now = time();
$fourAm = strtotime('today 4am');
if ($now < $fourAm) {
$time = strtotime('yesterday 4am');
} else {
$time = $fourAm;
}

If the time you have created is in the future, subtract one day.

$date = strtotime('yesterday 4am');

Related

How to find the Time Difference between a PM time and AM time?

In my form there are 2 Time Pickers where user can select a from time and to time. It doesn't have a date associated with it. And for a report generating purpose I've to calculate the time difference between them. It works perfectly to if the From and to Time is "06:00 to 10:00" but if the from and to time is "21:00 to 02:00" I get a time difference of 19 hours. Could you please help me to fix this.
For this case "21:00 to 02:00" the time difference should be 5 hours.
This is the Code
$datetime1 = new \DateTime('09:30 PM');
$datetime2 = new \DateTime('02:00 AM');
$interval = $datetime1->diff($datetime2);
echo $interval->format('%hh');
exit;
The difference becomes negative If $totime is less than $fromtime.
DateInterval->invert == 1 indicates that. This is used with this short solution to correct the result.
$fromtime = '09:30 PM';
$totime = '02:00 AM';
$diff = date_create($fromtime)->diff(date_create($totime));
$hours = $diff->invert ? 24-$diff->h : $diff->h;
echo $hours; //5
Since you have 2 date pickers one for from time and another to time, the former will always be smaller than the latter. Hence when from time is larger than to time it means user has selected to from the next day. If we don't add a date for calculating difference, PHP will assume today's date by default. We can easily fix this by adding a condition to compare the times and prepend the dates accordingly. Below is the updated code.
<?php
$fromtime = '09:30 PM';
$totime = '02:00 AM';
$now = new \DateTime();
$today = $now->format('Y-m-d'); // Store current date
$now->add(new DateInterval('P1D')); // Add one day to current date to get next date
$nextDay = $now->format('Y-m-d'); // Store next date
if($fromtime > $totime) // If from time is bigger than to time, it means to is a next day
{
$fromdatetime = "$today $fromtime";
$todatetime = "$nextDay $totime";
}
else
{
$fromdatetime = "$today $fromtime";
$todatetime = "$today $totime";
}
$datetime1 = new \DateTime($fromdatetime);
$datetime2 = new \DateTime($todatetime);
$interval = $datetime1->diff($datetime2);
echo $interval->format('%hh');
?>

Compare 2 time which is greater without date in PHP

I am trying to get the result that which time is greater. I mean there is no date only time.
$open_time = date("g:i A", strtotime($restaurant['open_time']));
$close_time = date("g:i A", strtotime($restaurant['close_time']));
$curren_time = date("h:i");
$restaurant['open_time'] and $restaurant['close_time'] is the result from database. It is coming in 24 hour format like 22:30, 10:20.
What i want exactly.
if(($current_time > $open_time) && ($current_time < $close_time)
{
echo "Opened";
}
else
{
echo "Closed";
}
If current_time is 2:00 AM and open_time is 11:00 AM then the result should echo Closed. And like this if current_time is 1:00 PM and closed_time is 11:00 PM then the result should echo Opened. Hope i explained well. Please ask if you have any doubt in my question.
You can solve thus using 24 hour format time also. But remember you can add date but virtually not from database. You can use to get the greater time
Set correct timezone and should work.
$restaurant = [
'open_time' => '11:00',
'close_time' => '22:00'
];
$timeZone = new DateTimeZone('Europe/Warsaw');
$now = new DateTime('now', $timeZone);
$open = DateTime::createFromFormat('H:i', $restaurant['open_time'], $timeZone);
$close = DateTime::createFromFormat('H:i', $restaurant['close_time'], $timeZone);
$working_now = ($now > $open && $now < $close);
if ($working_now) {
echo 'open';
} else {
echo 'closed';
}
You can play with it in sandbox - uncomment the test line to change current time.
If it's open through midnight you might need additional logic there:
if ($open > $close) {
if ($now > $close) {
$close->modify('+1 day');
} else {
$open->modify('-1 day');
}
}
$working_now = ...

How we can get difference of time In "H:i:s" time format as given scenario?

here is scenario that i have two time as given i have only time part of datetime in 24 hour format
$start_time = "23:00:00";
$end_time = "07:00:00";
How i can calculate duration hours , if the start_time's hour part is greater then $end_time's hour.
I would just create an if, where if the start time is bigger you have to calculate 24h (base_time) minus the start time first.
$start_time = "23:00:00";
$end_time = "07:00:00";
$base_time = "24:00:00";
if ($start_time>$end_time) {
$time = $base_time-$start_time+$end_time;
} else {
$time = $start_time-$end_time;
}
Or you can also have a look here, if you also have the day format given.
The way over DateTime, as far as I know, is just possible with a date. So you could add a pseudo date infront... and then use diff :
$start_time = "23:00:00";
$end_time = "07:00:00";
$st = new DateTime("0000-00-00".$start_time);
$et = new DateTime("0000-00-01".$end_time);
$interval = $st->diff($et);
$time = $interval->format('%H:%I:%S');

Given a Unix timestamp, how to get beginning and end of that day?

I have a Unix timestamp like this:
$timestamp=1330581600
How do I get the beginning of the day and the end of the day for that timestamp?
e.g.
$beginOfDay = Start of Timestamp's Day
$endOfDay = End of Timestamp's Day
I tried this:
$endOfDay = $timestamp + (60 * 60 * 23);
But I don't think it'll work because the timestamp itself isn't the exact beginning of the day.
strtotime can be used to to quickly chop off the hour/minutes/seconds
$beginOfDay = strtotime("today", $timestamp);
$endOfDay = strtotime("tomorrow", $beginOfDay) - 1;
DateTime can also be used, though requires a few extra steps to get from a long timestamp
$dtNow = new DateTime();
// Set a non-default timezone if needed
$dtNow->setTimezone(new DateTimeZone('Pacific/Chatham'));
$dtNow->setTimestamp($timestamp);
$beginOfDay = clone $dtNow;
$beginOfDay->modify('today');
$endOfDay = clone $beginOfDay;
$endOfDay->modify('tomorrow');
// adjust from the start of next day to the end of the day,
// per original question
// Decremented the second as a long timestamp rather than the
// DateTime object, due to oddities around modifying
// into skipped hours of day-lights-saving.
$endOfDateTimestamp = $endOfDay->getTimestamp();
$endOfDay->setTimestamp($endOfDateTimestamp - 1);
var_dump(
array(
'time ' => $dtNow->format('Y-m-d H:i:s e'),
'start' => $beginOfDay->format('Y-m-d H:i:s e'),
'end ' => $endOfDay->format('Y-m-d H:i:s e'),
)
);
With the addition of extended time in PHP7, there is potential to miss a second if using $now <= $end checking with this.
Using $now < $nextStart checking would avoid that gap, in addition to the oddities around subtracting seconds and daylight savings in PHP's time handling.
Just DateTime
$beginOfDay = DateTime::createFromFormat('Y-m-d H:i:s', (new DateTime())->setTimestamp($timestamp)->format('Y-m-d 00:00:00'))->getTimestamp();
$endOfDay = DateTime::createFromFormat('Y-m-d H:i:s', (new DateTime())->setTimestamp($timestamp)->format('Y-m-d 23:59:59'))->getTimestamp();
First a DateTime object is created and the timestamp is set to the desired timestamp. Then the object is formatted as a string setting the hour/minute/second to the beginning or end of the day. Lastly, a new DateTime object is created from this string and the timestamp is retrieved.
Readable
$dateTimeObject = new DateTime();
$dateTimeObject->setTimestamp($timestamp);
$beginOfDayString = $dateTimeObject->format('Y-m-d 00:00:00');
$beginOfDayObject = DateTime::createFromFormat('Y-m-d H:i:s', $beginOfDayString);
$beginOfDay = $beginOfDayObject->getTimestamp();
We can get the end of the day in an alternate manner using this longer version:
$endOfDayObject = clone $beginOfDayOject(); // Cloning because add() and sub() modify the object
$endOfDayObject->add(new DateInterval('P1D'))->sub(new DateInterval('PT1S'));
$endOfDay = $endOfDayOject->getTimestamp();
Timezone
The timezone can be set as well by adding a timestamp indicator to the format such as O and specifying the timestamp after creating the DateTime object:
$beginOfDay = DateTime::createFromFormat('Y-m-d H:i:s O', (new DateTime())->setTimezone(new DateTimeZone('America/Los_Angeles'))->setTimestamp($timestamp)->format('Y-m-d 00:00:00 O'))->getTimestamp();
Flexibility of DateTime
We can also get other information such as the beginning/end of the month or the beginning/end of the hour by changing the second format specified. For month: 'Y-m-01 00:00:00' and 'Y-m-t 23:59:59'. For hour: 'Y-m-d H:00:00' and 'Y-m-d H:59:59'
Using various formats in combination with add()/sub() and DateInterval objects, we can get the beginning or end of any period, although some care will need to be taken to handle leap years correctly.
Relevant Links
From the PHP docs:
DateTime
date with info on the format
DateTimeZone
DateInterval
You can use a combination of date() and mktime():
list($y,$m,$d) = explode('-', date('Y-m-d', $ts));
$start = mktime(0,0,0,$m,$d,$y);
$end = mktime(0,0,0,$m,$d+1,$y);
mktime() is smart enough to wrap months/years when given a day outside the specified month (jan 32nd will be feb 1st, etc)
You could convert the time to the current data and then use the strtotime function to find the start of the day and simply add 24 hours to that to find the end of the day.
You could also use the remainder operator (%) to find the nearest day. For example:
$start_of_day = time() - 86400 + (time() % 86400);
$end_of_day = $start_of_day + 86400;
The accepted answer unfortunately breaks due to a php bug that occurs in very specific scenarios. I'll discuss those scenarios, but first the answer using DateTime. The only difference between this and the accepted answer occurs after the // IMPORTANT line:
$dtNow = new DateTime();
// Set a non-default timezone if needed
$dtNow->setTimezone(new DateTimeZone('America/Havana'));
$dtNow->setTimestamp($timestamp);
$beginOfDay = clone $dtNow;
// Go to midnight. ->modify('midnight') does not do this for some reason
$beginOfDay->modify('today');
// now get the beginning of the next day
$endOfDay = clone $beginOfDay;
$endOfDay->modify('tomorrow');
// IMPORTANT
// get the timestamp
$ts = $endOfDay->getTimestamp();
// subtract one from that timestamp
$tsEndOfDay = $ts - 1;
// we now have the timestamp at the end of the day. we can now use that timestamp
// to set our end of day DateTime
$endOfDay->setTimestamp($tsEndOfDay);
So you'll note that instead of using ->modify('1 second ago'); we instead get the timestamp and subtract one. The accepted answer using modify should work, but breaks because of php bug in very specific scenarios. This bug occurs in timezones that change daylight savings at midnight, on the day of the year that clocks are moved "forward". Here is an example you can use to verify that bug.
bug example code
// a time zone, Cuba, that changes their clocks forward exactly at midnight. on
// the day before they make that change. there are other time zones which do this
$timezone = 'America/Santiago';
$dateString = "2020-09-05";
echo 'the start of the day:<br>';
$dtStartOfDay = clone $dtToday;
$dtStartOfDay->modify('today');
echo $dtStartOfDay->format('Y-m-d H:i:s');
echo ', '.$dtStartOfDay->getTimestamp();
echo '<br><br>the start of the *next* day:<br>';
$dtEndOfDay = clone $dtToday;
$dtEndOfDay->modify('tomorrow');
echo $dtEndOfDay->format('Y-m-d H:i:s');
echo ', '.$dtEndOfDay->getTimestamp();
echo '<br><br>the end of the day, this is incorrect. notice that with ->modify("-1 second") the second does not decrement the timestamp by 1:<br>';
$dtEndOfDayMinusOne = clone $dtEndOfDay;
$dtEndOfDayMinusOne->modify('1 second ago');
echo $dtEndOfDayMinusOne->format('Y-m-d H:i:s');
echo ', '.$dtEndOfDayMinusOne->getTimestamp();
echo '<br><br>the end of the day, this is correct:<br>';
$dtx = clone $dtEndOfDay;
$tsx = $dtx->getTimestamp() - 1;
$dty = clone $dtEndOfDay;
$dty->setTimestamp($tsx);
echo $dty->format('Y-m-d H:i:s');
echo ', '.$tsx;
bug example code output
the start of the day:
2020-03-26 00:00:00, 1585173600
the start of the *next* day:
2020-03-27 01:00:00, 1585260000
the end of the day, this is incorrect. notice that with ->modify("1 second ago") the
second does not decrement the timestamp by 1:
2020-03-27 01:59:59, 1585263599
the end of the day, this is correct:
2020-03-26 23:59:59, 1585259999
Today Starting date timestamp. Simple
$stamp = mktime(0, 0, 0);
echo date('m-d-Y H:i:s',$stamp);
$start_of_day = floor (time() / 86400) * 86400;
$end_of_day = ceil (time() / 86400) * 86400;
If your need both values in the same script. It is faster to +/- 86400 seconds to one of the variables than to fire both floor and ceil. For example:
$start_of_day = floor (time() / 86400) * 86400;
$end_of_day = $start_of_day + 86400;
For anyone that have this question in the future:
Any day code
<?php
$date = "2015-04-12 09:20:00";
$midnight = strtotime("midnight", strtotime($date));
$now = strtotime($date);
$diff = $now - $midnight;
echo $diff;
?>
Current day code
<?php
$midnight = strtotime("midnight");
$now = date('U');
$diff = $now - $midnight;
echo $diff;
?>
$date = (new \DateTime())->setTimestamp(1330581600);
echo $date->modify('today')->format('Y-m-d H:i:s'); // 2012-02-29 00:00:00
echo PHP_EOL;
echo $date->modify('tomorrow - 1 second')->format('Y-m-d H:i:s'); // 2012-02-29 23:59:59
$startOfDay = new \DateTime('tomorrow');
$startOfDay->modify('-1 day');
This works for me :)
A little late to the party, but here's another easy way to achieve what you're looking for:
$timestamp=1330581600;
$format = DATE_ATOM;
$date = (new DateTime())->setTimestamp($timestamp);
// Here's your initial date, created from the timestamp above
// 2012-03-01T06:00:00+00:00
$dateFromTimestamp = $date->format($format);
// This is the beginning of the day
// 2012-03-01T00:00:00+00:00
$startOfDay = $date->setTime(0,0);
// This is the beginning of the next day
// 2012-03-02T00:00:00+00:00
$startOfNextDay = $startOfDay->modify('+1 day');
I would personally avoid using the end of the day unless it's absolutely necessary. You can, of course, use 23:59:59 but this is not the actual end of the day (there's still 1 second left). What I do is use the start of the next day as my end boundary, for example:
$start = new DateTime('2021-11-09 00:00:00');
$end = new DateTime('2021-11-10 00:00:00');
if ($someDateTime >= $start && $someDateTime < $end) {
// do something
}
If I must use the end of the day, I'd go with calculating the start of the next day and then subtracting 1 microsecond from that.
$beginOfDay = (new DateTime('today', new DateTimeZone('Asia/Tehran')))->getTimestamp();
$endOfDay = $beginOfDay + 86399;
You can set a timezone by replacing "Asia/Tehran". One day is 86400 seconds, Don't ask me why 86399, It is a whisper in my mind that says it is 86399, So I do not even want to think about its truth.

Setting a time and date and adding to it in PHP

Basically am trying to set a time and a date in PHP then set a time gap which will range between minutes, loop through between a start time and end time echoing something out for each one. Have tried loads of different ways and cant seem to figure a way to set a date and add to it.
This seems the best script I have modified so far:
$minutes = 5;
$endtime = new DateTime('2012-01-01 09:00');
$newendtime = $endtime->format('Y-m-d H:i');
$timedate = new DateTime('2012-01-01 09:00');
while($stamp < $newendtime)
{
$time = new DateTime($timedate);
$time->add(new DateInterval('PT' . $minutes . 'M'));
$timedate = $time->format('Y-m-d H:i');
echo $timedate;
}
$minutes = 5;
$endtime = new DateTime('2012-01-01 09:00');
//modified the start value to get something _before_ the endtime:
$time = new DateTime('2012-01-01 8:00');
$interval = new DateInterval('PT' . $minutes . 'M');
while($time < $endtime){
$time->add($interval);
echo $time->format('Y-m-d H:i');
}
Do everything in seconds, and use php's time(), date(), and mktime functions.
In UNIX Time, dates are stored as the number of seconds since Jan 1, 1970.
You can render UNIX Timestamps with date().
$time = time(); // gets current time
$endtime = mktime(0,0,0, 1, 31, 2012); // set jan 31 # midnight as end time
$interval = 60 * 5; // 300 seconds = 5 minutes
while($time < $endtime){
$time += $interval;
echo date("M jS Y h:i:s a",$time) . "<br>"; // echos time as Jan 17th, 2012 1:04:56 pm
}
date reference:
http://us3.php.net/manual/en/function.date.php (includes superb date format reference too)
mktime reference: http://us2.php.net/mktime
time() only gets the current time, but just for kicks n' giggles: http://us2.php.net/time
And, it's super easy to store in a database!
This function will let you add date to your existing datetime. This will also preserves HH:MM:SS
<?php
function add_date($givendate,$day=0,$mth=0,$yr=0) {
$cd = strtotime($givendate);
$newdate = date('Y-m-d h:i:s', mktime(date('h',$cd),
date('i',$cd), date('s',$cd), date('m',$cd)+$mth,
date('d',$cd)+$day, date('Y',$cd)+$yr));
return $newdate;
}
?>
Usage:
add_date($date,12,0,0);
where $date is your date.

Categories