I have to check if the current daytime falls in a specific range. I looked up the internet and found several similar solutions like this one:
$now = date("His");//or date("H:i:s")
$start = '130000';//or '13:00:00'
$end = '170000';//or '17:00:00'
if($now >= $start && $now <= $end){
echo "Time in between";
}
else{
echo "Time outside constraints";
}
If both conditions have to be true, how can this bis achieved when we assume that $start is 06:00:00 and $end is 02:00:00.
If we make the assumption that it is 01:00:00, in this case the first condition can't be true.
Has anybody an idea to handle this problem differently?
Thanks!
Naturally, you'd have to account for date in your comparisons.
<?php
$start = strtotime('2014-11-17 06:00:00');
$end = strtotime('2014-11-18 02:00:00');
if(time() >= $start && time() <= $end) {
// ok
} else {
// not ok
}
If you need to check whether or not the time frame rolls over midnight
function isWithinTimeRange($start, $end){
$now = date("His");
// time frame rolls over midnight
if($start > $end) {
// if current time is past start time or before end time
if($now >= $start || $now < $end){
return true;
}
}
// else time frame is within same day check if we are between start and end
else if ($now >= $start && $now <= $end) {
return true;
}
return false;
}
You can then get whether or not you are within that time frame by
echo isWithinTimeRange(130000, 170000);
date_default_timezone_set("Asia/Colombo");
$nowDate = date("Y-m-d h:i:sa");
//echo '<br>' . $nowDate;
$start = '21:39:35';
$end = '25:39:35';
$time = date("H:i:s", strtotime($nowDate));
$this->isWithInTime($start, $end, $time);
function isWithInTime($start,$end,$time) {
if (($time >= $start )&& ($time <= $end)) {
// echo 'OK';
return TRUE;
} else {
//echo 'Not OK';
return FALSE;
}
}
Cannot comment due to low reputation, but #DOfficial answer is great but be aware of inconsistency in comparision.
Original
// if current time is past start time or before end time
if($now >= $start || $now < $end){
Should be imho
// if current time is past start time or before end time
if($now >= $start || $now <= $end){
Related
I have two timestamps, which possibly can be any date and time. I want to get all minutes, which were on Sunday.
For a better understanding: The start and and end timestamp represent a date and time where an employee starts his work and finish his work. I want to get the minutes in sum, which the employee worked on a Sunday.
Here is my code:
function get_sunday_hours_from_timestamps($startTimestamp, $endTimestamp) {
$start = new DateTime();
$start->setTimestamp($startTimestamp);
$end = new DateTime();
$end->setTimestamp($endTimestamp);
$workedMinutes = 0;
$current = clone $start;
while ($current <= $end) {
$next = clone $current;
$next->modify('next day');
if ($current->format('w') == 0) {
$dayStart = ($current < $start) ? $start : $current;
$dayEnd = ($next > $end) ? $end : $next;
$diff = $dayEnd->diff($dayStart);
$minutes = $diff->days * 1440 + $diff->h * 60 + $diff->i;
$workedMinutes += $minutes;
}
$current = $next;
}
return $workedMinutes / 60;
// return $workedMinutes;
}
Thank you for your input. I was able to solve the problem. Hope this helps anybody else.
function get_sunday_hours_from_timestamps($startTimestamp, $endTimestamp) {
$totalMinutes = 0;
$startDay = strtotime("midnight", $startTimestamp);
$endDay = strtotime("tomorrow", $endTimestamp) - 1;
for ($currentDay = $startDay; $currentDay <= $endDay; $currentDay = strtotime("+1 day", $currentDay)) {
if (date("l", $currentDay) == "Sunday") {
$start = max($startTimestamp, $currentDay);
$end = min($endTimestamp, strtotime("tomorrow", $currentDay) - 1);
$totalMinutes += ($end - $start) / 60;
}
}
return round($totalMinutes / 15) * 0.25;
}
Warning: The solution below is highly inefficient and extremely slow, especially for large time periods as input. It only serves to illustrate a naive approach in an easily readable form. You can use this as a starting point, but use it wisely!
A very naive approach to your problem (count sunday minutes in a given time period) could be: Iterate over every minute in you period, check if that minute is on a sunday and count those minutes.
In PHP that could look like this:
function isSunday(DateTimeInterface $dateTime) {
return $dateTime->format('w') == 0;
}
function countSundayMinutes(DateTime $start, DateTime $end): int
{
if ($start >= $end) {
throw new LogicException('end must be > start!');
}
$sundayMinutes = 0;
$current = clone $start;
while ($current < $end) {
if (isSunday($current)) {
$sundayMinutes++;
}
$current = $current->add(DateInterval::createFromDateString('1 minute'));
}
return $sundayMinutes;
}
echo countSundayMinutes(new DateTime('2023-01-02 00:00'), new DateTime('2023-01-03 00:00')), PHP_EOL; // 0: total 24h, not on sunday
echo countSundayMinutes(new DateTime('2023-01-01 12:00'), new DateTime('2023-01-01 13:00')), PHP_EOL; // 60: total 60 minutes, thereof 60 on sunday
echo countSundayMinutes(new DateTime('2022-12-31 23:00'), new DateTime('2023-01-01 01:00')), PHP_EOL; // 60: total 12 minutes, thereof 60 on sunday
echo countSundayMinutes(new DateTime('2022-12-31 00:00'), new DateTime('2023-01-03 00:00')), PHP_EOL; // 1440: total 72h, thereof 24h (1440 minutes) on sunday
But i'm sure you'll be able to add many optimizations to that algorithm, e.g. you could check first if the given period includes any sundays at all...
I want to run my code from 21:00 to 08:00, for example. But my code does not work properly because when the clock reaches 24:00 (00:00), my code gets confused and cannot set 01:00. check 00:00 because it is a 24-hour clock.
I need this code for the dark mode of the site, so that my site will be in dark mode between a desired hour, for example, from 10 pm to 6 am.
Note: I may specify any hour for this task and I do not choose just one hour. For example, I may choose 21:00 to 3:00 am. It is random because the hours are chosen by my clients and I do not know what hours they choose. !!!
Can you guide me to make my code work correctly in 24 hours if I specify any hour?
$hour = date('H');
//$hour = 23;
if( $hour > 22 && $hour < 8) {
echo "Good night";
}else{
echo "Good Morning";
}
You can use the modulo operator to handle the 24-hour clock.
$start_hour = 21;
$end_hour = 8;
$current_hour = date('H');
// handle the 24-hour cycle
$current_hour = $current_hour % 24;
if($current_hour >= $start_hour || $current_hour < $end_hour) {
echo "Good night";
} else {
echo "Good morning";
}
This way it will work for any hours range you choose, as long as the start hour is greater than or equal to the end hour.
For HH:MM:
$start_time = "21:00";
$end_time = "08:00";
$current_time = date('H:i');
$start_hour = (int)substr($start_time, 0, 2);
$start_minute = (int)substr($start_time, 3, 2);
$end_hour = (int)substr($end_time, 0, 2);
$end_minute = (int)substr($end_time, 3, 2);
$current_hour = (int)substr($current_time, 0, 2);
$current_minute = (int)substr($current_time, 3, 2);
// handle the 24-hour cycle
$current_hour = $current_hour % 24;
if(($current_hour > $start_hour || ($current_hour == $start_hour && $current_minute >= $start_minute)) || ($current_hour < $end_hour || ($current_hour == $end_hour && $current_minute < $end_minute))) {
echo "Good night";
} else {
echo "Good morning";
}
When you reverse the intervals (21:00 to 08:00 vs 08:00 to 21:00) you also need to reverse the logic:
If $start < $end, you need to check $current >= $start && $current <= $end
Otherwise, $current >= $start || $current <= $end
You'll also want to consider minutes and seconds as well. For that, you can pass a full properly formatted H:M:S string and convert everything to the same unit so comparisons make sense. It's easier to see if you create a dedicated functions that do only one thing:
// Error checking omitted for brevity
function hmsToSeconds(string $hms): int
{
[$h, $m, $s] = array_pad(preg_split('/[^\d]+/', $hms), 3, 0);
return 3600 * $h + 60 * $m + $s;
}
function inRange(string $start, string $end, string $current = null): bool
{
if ($current === null) {
$current = date('H:i:s');
}
$start = hmsToSeconds($start);
$end = hmsToSeconds($end);
$current = hmsToSeconds($current);
if ($start < $end) {
return $current >= $start && $current <= $end;
}
return $current >= $start || $current <= $end;
}
if (inRange('21:00:00', '8:00:00')) {
echo 'Good night';
} else {
echo 'Good morning';
}
Demo
Needless to say, since we're doing this on the server we're using server clock, so it may or may nor make sense for the user. If you know the user's time zone, you can take it into account when calculating current time.
$start = '22:00:00';
$end = '08:00:00';
$now = Carbon::now('UTC');
How can I check if the time of $now is within the timerange?
There are several ways to achieve that by using Carbon. One of the easiest ways is using createFromTimeString and between methods:
$now = Carbon::now();
$start = Carbon::createFromTimeString('22:00');
$end = Carbon::createFromTimeString('08:00')->addDay();
if ($now->between($start, $end)) {
// ¯\_(ツ)_/¯
}
Try this:
$time = Carbon::now();
$morning = Carbon::create($time->year, $time->month, $time->day, 8, 0, 0); //set time to 08:00
$evening = Carbon::create($time->year, $time->month, $time->day, 18, 0, 0); //set time to 18:00
if($time->between($morning, $evening, true)) {
//current time is between morning and evening
} else {
//current time is earlier than morning or later than evening
}
The true in $time->between($morning, $evening, true) checks whether the $time is between and including $morning and $evening. If you write false instead it checks just if it is between the two times but not including.
Actually, you could leave true away because it is set by default and not needed.
Check here for more information on how to compare dates and times with Carbon.
$start = '22:00:00';
$end = '08:00:00';
$now = Carbon::now('UTC');
$time = $now->format('H:i:s');
if ($time >= $start && $time <= $end) {
...
}
Should do it, but doesn't take date into consideration
You can reverse check algorithm.
<?php
$pushChannel = "general";
$now = Carbon::now();
$start = Carbon::createFromTime(8, 0);
$end = Carbon::createFromTime(22, 0);
if (!$now->between($start, $end)) {
$pushChannel = "silent";
$restrictStartTime = Carbon::createFromTime(22, 0, 0); //carbon inbuild function which will create todays date with the given time
$restrictEndTime = Carbon::createFromTime(8, 0, 0)->addDays(1); //this will create tomorrows date with the given time
$now = Carbon::now();
if($now->gt($restrictStartTime) && $now->lt($restrictEndTime)) {
.....
}
Please Try below code,
$start = '22:00:00';
$end = '08:00:00';
$now = Carbon::now('UTC');
$nowTime = $now->hour.':'.$now->minute.':'.$now->second;
if(strtotime($nowTime) > strtotime($start) && strtotime($nowTime) < strtotime($end) ) {
echo 'YES';
} else {
echo 'NO';
}
What Chris is trying to point out is if the endtime crosses over midnight then you must account for that.
This is not the cleanest way to do it but here is a method that seems to work.
private function isNowBetweenTimes($timezone, $startDateTime, $endDateTime) {
$curTimeLocal = Carbon::now($timezone);
$startTime = $curTimeLocal->copy();
$startTime->hour = $startDateTime->hour;
$startTime->minute = $startDateTime->minute;
$endTime = $curTimeLocal->copy();
$endTime->hour = $endDateTime->hour;
$endTime->minute = $endDateTime->minute;
if ($endTime->lessThan($startTime))
$endTime->addDay();
return ($curTimeLocal->isBetween($startTime, $endTime));
}
This example only cares about the hour and minutes and not the seconds but you can easily copy that as well. The key to this is comparing start and end time before comparing them to the current time and add a day to end time if end time is less than start time.
For complete solution which supports all start and end time range you can use bitwise XOR.
/*
* must using hours in 24 hours format e.g. set 0 for 12 pm, 6 for 6 am and 13 for 1 pm
*/
private $startTime = '0';
private $endTime = '6';
$currentHour = \Carbon\Carbon::now()->hour;
$start = $this->startTime > $this->endTime ? !($this->startTime <= $currentHour) : $this->startTime <= $currentHour;
$end = $currentHour < $this->endTime;
if (!($start ^ $end)) {
//Do stuff here if you want exactly between start and end time
}
an updated version of #AliN11's answer taking into account ranges accross two days or in the same day
$now = now();
$start = Carbon::createFromTimeString('22:00');
$end = Carbon::createFromTimeString('08:00');
if ($start > $end) {
$end = $end->addDay();
}
if ($now->between($start, $end)||$now->addDay()->between($start, $end)) {
//add statements
}
<?php
$now = date("H");
if ($now < "20") {
echo "Have a good day!";
}
Try this :
$start = 22; //Eg. start hour
$end = 08; //Eg. end hour
$now = Carbon::now('UTC');
if( $start < $now->hour && $now->hour < $end){
// Do something
}
#AliN11's (currently top) answer is good, but doesn't work as one would immediately expect, after midnight it just breaks, as raised in the comments by #Sasha
The solution is to reverse the logic, and check if the time is not between the inverse hours.
Here is an alternative that works as one would expect:
$now = Carbon::now();
$start = Carbon::createFromTimeString('08:00');
$end = Carbon::createFromTimeString('22:00');
if (! $now->between($start, $end)) {
// We're all good
}
Yes, the midnight plays a vital role in time duration. We can find now() being the given time range as follows:
$now = Carbon::now();
$start = Carbon::createFromTime('22', '00');
$end = Carbon::createFromTime('08', '00');
if ($start->gt($end)) {
if ($now->gte($start)) {
$end->addDay();
} elseif ($now->lte($end)) {
$start->subDay();
} else {
return false;
}
}
return $now->between($start, $end);
I have a case where a box of text should not be shown between two times for example 20 and 01 (24-hour clock), but it should also work, when i choose not to show the box betweem 20 and 22 for example.
But if I have:
$start = "20";
$end = "01";
$now = date('H');
if($now > $start AND $now < $end) {
echo "DONT SHOW THE BOX";
} else {
echo "SHOW THE BOX";
}
How can I convert the numbers, can I use mktime() even if I don't have a date? Because the box should be activated every day in that time range.
You don't want to show the box between 20:00 to 01:00
Currently your logic is kinda messed up in if($now > $start AND $now < $end).
If you expect $start = 20 and $end = 1, Then what kind of value is $now that might be MORE than 20 AND LESS than 1.
Your if statement logic will always go to ELSE whatever the value of $now is.
But there's another workaround to switch the logic like this.
You want to show the box between 02:00 to 19:00
Instead of the other way around.
So you can do this,
$start = "20";
$end = "01";
$now = date('H');
if ($now > $end && $now < $start)
{
echo "SHOW THE BOX";
}
else
{
echo "DON'T SHOW";
}
Update 1:
Now, you don't want to show the box between 20:00 to 22:00
You can do the vice versa or which is your current logic. Like,
$start = "20";
$end = "22";
$now = date('H');
if ($now >= $start && $now <= $end)
{
echo "DON'T SHOW";
}
else
{
echo "SHOW THE BOX";
}
Update 2:
If the $start or $end varies, you can always wrap them in another if condition. Like,
if ($start > $end)
{
if ($now > $end && $now < $start)
{
echo "SHOW THE BOX";
}
else
{
echo "DON'T SHOW";
}
}
else if ($start < $end)
{
if ($now >= $start && $now <= $end)
{
echo "DON'T SHOW";
}
else
{
echo "SHOW THE BOX";
}
}
The code isn't very pretty, but I think this is what you are after?
define('START_TIME', 6);
define('END_TIME', 1);
$startTime = new DateTime();
$startTime->setTime(START_TIME, 0);
$endTime = clone $startTime;
if (START_TIME > END_TIME) {
$endTime->modify('+1 day');
}
$endTime->setTime(END_TIME, 0);
$currentTime = new DateTime();
if ($currentTime > $startTime && $currentTime < $endTime) {
echo 'Show box';
} else {
echo 'Don\'t show box';
}
You can alter the hours to decide the start/end hour for when to show/hide. If the ending hour is a lower hour than the starting hour then it will presume the ending hour should be the next day.
It could potentially be cleaned up a bit, but I'll leave that in your hands if it is what you're after.
date_default_timezone_set("Europe/Stockholm");
$setdate = ['14-05-2022','15-05-2022','16-05-2022'];
print_r($setdate)."<br>";
foreach ($setdate as $value) {
$date= date("d-m-Y");
if($date == $value){
// echo "set Data For Product";
// die();
}
}
I have been trying to figure out how to get between a day of week and time...I found this snippet of code:
function isBetween($from, $till, $input) {
$f = DateTime::createFromFormat('!H:i', $from);
$t = DateTime::createFromFormat('!H:i', $till);
$i = DateTime::createFromFormat('!H:i', $input);
if ($f > $t) $t->modify('+1 day');
return ($f <= $i && $i <= $t) || ($f <= $i->modify('+1 day') && $i <= $t);
};
and I have managed to get it to check between two times and see if current matches using:
if (isBetween('22:30','02:00','23:00')){
echo "true";
}
However I tried doing this
if (isBetween('22:30','02:00',date('H:i')){
but that just broke the site, I lack experience handling time and I basically want to check between 11pm monday to 2pm tuesday or 11pm monday to 5pm saturday and it has to do this check no matter what day of the year/month meaning I want it to be dynamic not static..
I've also tried:
if (date('H') < 14)
but it was very simplistic and I didn't know how to get something as complex as both date and hour+seconds
your missing 1 more closing )
if (isBetween('22:30','02:00',date('H:i'))){
You can just do like this:
function isBetween($from, $till, $input) {
$f = date('H:i', strtotime($from));
$fd= date('l', strtotime($from));
$t = date('H:i', strtotime($till));
$td= date('l', strtotime($till));
$i = date('H:i', strtotime($input,'+8 hours'));
$id= date('l', strtotime($input));
$days = array('Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday');
if(array_search($fd,$days)<array_search($id,$days) && array_search($td,$days)>array_search($id,$days)){
return true;
}elseif(array_search($fd,$days)==array_search($id,$days) && $f<$i){
return true;
}elseif(array_search($td,$days)==array_search($id,$days) && $t<$i){
return true;
}
return false;
};
$from = 'Wednesday 12:00';
$till = 'Saturday 23:00';
$input = 'Friday 12:23';
if(isBetween($from,$till,$input)){
echo "True";
}else{
echo "not";
}
output = true;