I am trying to make a little script which shows range of hours between 11:00 and 17:00. 11:00 is start point and 17:00 is end point. So far i have made this:
<?php
// Defining hours
$now = "13:00"; // <- my time now
$start_time = "11:00"; // start point
$end_time = "17:00"; // end point
// Convert to timestamps
$begin = strtotime($start_time);
$end = strtotime($end_time);
// Display range
while($begin <= $end) {
echo date("H:i", $begin)." </br />";
$begin = strtotime('1 hour', $begin);
}
?>
And it successfully output of range between start and end points:
11:00
12:00
13:00
14:00
15:00
16:00
17:00
My goal is to make this script show range of hours from 13:00 (my time) if actual time is more than start time (11:00). Something like this:
11:00 hidden
12:00 hidden
13:00
14:00
15:00
16:00
17:00
Can someone suggest how to make it?
In this case simply use this:
$present = strtotime($now);
if($present > $begin){
$begin = $present;
}
but what you need if say $now = 18:00 or beyond this.
In this case this code show nothing.
I think you can simplify your whole solution. Instead of using time operations, why don't you simply increase a variable from current hour or 11 to 17. To determine $begin simply use max(), like this:
$begin = max(date('H'), 11);
$end = 17;
while($begin <= $end) {
echo $begin . ':00<br>';
$begin++;
}
I have added small bits as #user1234 suggested and now it works as i wanted. Here is the full code for reference to others.
<?php
// Defining hours
$now = "13:00"; // <- my time now
$start_time = "11:00"; // start point
$end_time = "17:00"; // end point
// Convert to timestamps
$actual = strtotime($now);
$begin = strtotime($start_time);
$end = strtotime($end_time);
// Added this to see if actual time is more than start time - creadit user1234
if($actual > $begin) {
$begin = $actual;
}
// Added this to see if actual time is more than 17:00
if($actual > $end) {
echo "Try tomorrow";
}
// Display ranges accordingly.
while($begin <= $end) {
echo date("H:i", $begin)." </br />";
$begin = strtotime('1 hour', $begin);
}
?>
Anyone is welcome to test and use if needed.
Related
Users are allowed to pick a time for delivery up until the closing time of the store which can be 1am.
The list should should show all times up to 1am even if it is after midnight.
example 1: User arrives at 18:00 they see 18:00, 18:30, 19:00 and so on up until 00:30, 01:00
example 2: user arrives at 00:10 should see
00:30, 01:00 not
01:00, 01:30, 02:00, 02:30 etc because after midnight has become a has become a new day/date.
I am getting 30 minute time intervals between two times, it is fine as long as both times are in the same day e.g. 17:00 and 23:00. If the end time is past midnight I am not able to get the intervals so 17:00 to 01:00 doesn't give any intervals.
I understand 01:00 is another day but not quite sure how to fix it using a dynamic date. I keep thinking current day +1 will be fine unless it is after mindight then it will be an extra day if that makes sense.
Here's my code:
$timestamp = time() + 60*60;
$earliest = date("h:i ",$timestamp);
$period = new DatePeriod(
new DateTime($earliest),
new DateInterval('PT30M'),
new DateTime('01:00')
);
foreach ($period as $date) {
echo '<option value="">'.$date->format("H:i").'</option>';
}
Because 24:00 works as 00:00 I tried 25:00 but that didn't work. Any help appreciated!
UPDATE: following the answer below coverted to dynamic date, if I use date like:
$start = date('Y-m-d H:i');
$startdate = date('Y-m-d');
$end = date('Y-m-d', strtotime($startdate . ' +1 day'))." 01:00";
$period = new DatePeriod(
DateTime::createFromFormat('Y-m-d H:i','2020-04-03 17:00'),
new DateInterval('PT30M'),
DateTime::createFromFormat('Y-m-d H:i','2020-04-04 01:00')
);
After midnight it's another day added on which is problematic.
You also have to mention exact dates and not just time as 01:00. Because this way, it assumes the current date and hence you really can't have a time period between 17:00 and 01:00 on the same day. Below is how you would do it:
<?php
$period = new DatePeriod(
DateTime::createFromFormat('Y-m-d H:i','2020-04-03 17:00'),
new DateInterval('PT30M'),
DateTime::createFromFormat('Y-m-d H:i','2020-04-04 01:00')
);
foreach ($period as $date) {
echo $date->format("H:i"),PHP_EOL;
}
Demo: https://3v4l.org/5sj9Z
Update:
Since you have only times and not dates, you create DateTime objects, compare them, add 1 day to end time if it's smaller and then loop over the intervals using DatePeriod
<?php
$times = [
['18:00','01:00'],
['17:00','23:00'],
['00:10','01:00']
];
foreach($times as $time){
$start_time = DateTime::createFromFormat('H:i',$time[0]);
$end_time = DateTime::createFromFormat('H:i',$time[1]);
if($end_time < $start_time){
$end_time->add(new DateInterval('P1D'));
}
$period = new DatePeriod(
$start_time,
new DateInterval('PT30M'),
$end_time
);
echo $start_time->format('Y-m-d H:i:s'),' ',$end_time->format('Y-m-d H:i:s'),PHP_EOL;
foreach ($period as $date) {
echo $date->format("H:i"),PHP_EOL;
}
echo PHP_EOL;
}
Demo: https://3v4l.org/Ldpst
You can lose the whole timestamp calculation and have it all handled by DateTime:
// here we get the next round delivery time
$nextAvailableHalfHour = getNextHalfHourMark();
$todayMidnight = new DateTime('today'); // this creates today with time 00:00:00
$todayOneOclock = new DateTime('today 01:00'); // this creates today with time 01:00:00
// this condition says if we're now between midnight and 1 o'clock, use today
// otherwise use tomorrow
$endDate = $nextAvailableHalfHour >= $todayMidnight && $nextAvailableHalfHour <= $todayOneOclock
? $todayOneOclock
: new DateTime('tomorrow 01:00'); // create specific time tomorrow
$period = new DatePeriod(
$nextAvailableHalfHour,
new DateInterval('PT30M'),
$endDate
);
/**
* Gets the next available time with round half hour (:00 or :30).
*/
function getNextHalfHourMark(): DateTime
{
$now = new DateTime(); // create current date and time
$currentMinutes = (int) $now->format('i');
// if we are between :00 and :30
if ($currentMinutes > 0 && $currentMinutes < 30) {
// set to :30 minutes of current hour
$now->setTime($now->format('H'), 30);
// else if we are between :30 and :00
} elseif ($currentMinutes > 30 && $currentMinutes <= 59) {
// set to :00 minutes of next hour
$now->setTime($now->format('H') + 1, 00);
}
return $now;
}
The tomorrow and today strings are enabled by relative formats.
I am trying to make a function in Laravel 5.6
I have a $start_time, $end_time and $duration variables.
I would like to get time slots from the start time until end time, in $duration periods, for example:
$duration = 30 min
$start_time = 9:00 am
$end_time = 9:00 pm
Results:
-9:00 - 9:30
-9:30 - 10:00
-10:00 - 10:30
.... etc
Also, I would like to not show the slot where time overlaps with appointments in my database.
$starttime = '9:00'; // your start time
$endtime = '21:00'; // End time
$duration = '30'; // split by 30 mins
$array_of_time = array ();
$start_time = strtotime ($starttime); //change to strtotime
$end_time = strtotime ($endtime); //change to strtotime
$add_mins = $duration * 60;
while ($start_time <= $end_time) // loop between time
{
$array_of_time[] = date ("h:i", $start_time);
$start_time += $add_mins; // to check endtie=me
}
$new_array_of_time = array ();
for($i = 0; $i < count($array_of_time) - 1; $i++)
{
$new_array_of_time[] = '' . $array_of_time[$i] . ' - ' . $array_of_time[$i + 1];
}
If you are using Laravel there is a dependency for times&dates called Carbon I'm sure you've heard of.
all you have to do is importing it like that:
use Carbon\Carbon;
Then we can see what will we do by this dependency, we just create a time then add minutes to it according to duration, that is what you want to.
$start_time = Carbon::createFromTime(9, 0, 0); // hours, minutes, seconds
$end_time = Carbon::createFromTime(21, 0, 0);
$time = $start_time;
$time_slots = array();
while($time < $end_time){
$time = $time->addMinutes(30);
$time_slots[] = $time;
}
This array will have the time slots you want and you can manipulate them whatever you like.
You can also look at this links below:
Documentation: https://github.com/briannesbitt/Carbon
String formats for Carbon: http://carbon.nesbot.com/docs/#api-formatting
I would like to calculate some times. I need to know how many worktime hours are between a call entry and now regarding on the worktimes.
for example:
call stored yesterday 15:00
worktime ends: 18:00
worktime begins: 08:00
now: 10:00
So i need to know the age my call has during the working hours:
call stored >> worktime end: 3h
worktimebegin >> now: 2h
age: 5h
I would like to use php DateTime.
How would you proceed?
I think this can help you out:
//workdays till 18:00 and start 08:00
function calculateWorkHours(DateTime $Start, DateTime $End) {
//validate given parameters
if ($Start > $End) throw new Exception('$Start date cannot be later than $End date');
$hours = 0;
do {
//get the current hour
$currentHour = $Start->format('H');
//while the $currenthour is lower then 18 and higher than 7
if($currentHour < 18 && $currentHour >= 8) {
$hours++;
}
$Start->modify('+1 hour');
} while($End > $Start);
return $hours;
}
$Start = new DateTime('yesterday 150000');
$End = new DateTime('100000');
echo calculateWorkHours($Start, $End); //returns 5
$Start = new DateTime('yesterday 060000');
$End = new DateTime('120000');
echo calculateWorkHours($Start, $End); //returns 14
$Start = new DateTime('-2 days 150000');
$End = new DateTime('100000');
echo calculateWorkHours($Start, $End); //return 15
I'm having problems working through how I would build times that increment by a given multiple. I would like to have a function that would take 3 params, (start, end, offset) and that would give me an output:
The following function would take a start time of 0900, a stop time of 1200 and increment by multiples of 30 minutes.
Would someone please get me started in the right direction? I thought to use to mktime for this but I couldn't get it to work.
myfunction(9, 12, 30)
output:
9:00 am
9:30 am
10:00 am
10:30 am
11:00 am
11:30 am
12:00 am
Function:
function myfunction($start, $end, $step){
$start *= 3600; // 3600 seconds per hour
$end *= 3600;
$step *= 60; // 60 seconds per minute
for($i = $start; $i <= $end; $i += $step)
echo date('h:i a', $i), '<br />';
}
Output:
09:00 am
09:30 am
10:00 am
10:30 am
11:00 am
11:30 am
12:00 pm // You put am here in desired output
// ,but I think you really wanted pm
Codepad
strtotime is another useful function for dealing with dates and times in PHP.
The PHP Manual's function reference is a great place to start when looking for how to do things yourself and taking advantage of built in functions. From that page if you do a search for 'time' you'll find the Date/Time extension which is built in to PHP. You'll see there are many functions available for dealing with date's and time's in PHP.
I would use the time to create a dateTime object. You can format your output using just the time parts, so the day portion is irrelevant. Then you can use standard functions for adding time intervals (some of them are discussed in this question). Just loop over the time addition until the end time is reached or exceeded.
This will also take care of all sorts of special cases that you'd otherwise have to handle on your own, such as AM/PM conversion and start times later than the end time (which will just wrap around to the next day).
<?php
function intervals($start, $end, $interval)
{
$start_date = strtotime($start.':00:00');
$end_date = strtotime($end.'00:00');
$current_date = $start_date;
while($current_date <= $end_date)
{
echo $current_date;
$current_date = strtotime('+ '.intval($interval).' minute', $current_date);
}
}
?>
I guess something like this, is what you looking for.. (untested)
this is my idea
function myfunction($start, $end, $min_increm) {
//just get a datetime do not matter the date
$date = new DateTime('2000-01-01');
//move to start hour, add 9 hour
$start_date = $date->add(new DateInterval(PT{$start}H));
$end date_date = $date->add(new DateInterval(PT{$end}H));
while($date <= $end_date)
//increment minutes and print
echo($date->add(new DateInterval(PT{$min_increm}M))->format("H:m"));
}
Starting with a date in this format: 2011-05-01 09:00:00, how can I create an array that contains all office hours (09:00 to 17:00) for all working days of the year (so excluding all Saturday and Sundays). What I want to arrive to is something like this:
2011-05-01 09:00:00
2011-05-01 10:00:00
2011-05-01 11:00:00
2011-05-01 12:00:00
2011-05-01 13:00:00
2011-05-01 14:00:00
2011-05-01 15:00:00
2011-05-01 16:00:00
2011-05-01 17:00:00
//next day, starting at 09:00 and ending at 17:00
2011-05-02 09:00:00
...
2011-05-02 17:00:00
//until the last day of the year from 09:00 to 17:00
2011-12-31 09:00:00
...
2011-12-31 17:00:00
The start date will be the first of the current month at with 09:00 as time and the very last date (last element of the array) will always be 17:00 on the last day of the year.
Again, weekends should be excluded.
Pseudocode idea:
I thought of something like strtotime($start, "+1 one hour") with a check for "if smaller than 17:00" but it doesn't seem to be that simple.
How about this:
$start = strtotime('2011-05-01');
$end = strtotime('2011-12-31');
$times = array();
for ($i = $start; $i <= $end; $i += 24 * 3600)
{
if (date("D", $i) == "Sun" || date("D", $i) == "Sat")
{
continue;
}
for ($j = 9; $j <= 17; $j++)
{
$times []= date("Y-m-d $j:00:00", $i);
}
}
The outer loop iterates through all the days in the given time period. In the outer loop, we check to see if the day is either Saturday or Sunday (a weekend), and if it is, we skip that day. If it's not a weekend, we loop through all the valid hours, adding the full date and time to the array as we go.
Some tips:
date("G", $some_timestamp) gives you the hour of the day in 24-hour format
date("N", $some_timestamp) gives you the day of the week, 1 (for Monday) through 7 (for Sunday)
Take a look at the php manual for date.
Edit: You can pick any start timestamp and add 3600 to add one hour, if your hour is greater than 17, you can add a bigger step to go right to the next morning, same for a weekend, and just do a while ($timestamp < $end_timestamp) {}
I'd encourage you to use the wonderful DateTime class and its related classes. Here, you can make good use of DatePeriod:
<?php
$now = new DateTime('today'); // starting time 0.00 this morning
$endOfYear = new DateTime('31 December this year 23:00'); // end time
$interval = new DateInterval('PT1H'); // frequency -- every hour
$times = array();
foreach (new DatePeriod($now, $interval, $endOfYear ) as $datetime) {
// $datetime is a DateTime object for the hour and time in question
$dow = $datetime->format('w'); // 0 is Sunday
if (($dow == '0') || ($dow == '6')) {
continue; // miss Saturday and Sunday out
}
$time = $datetime->format('G'); // hour without leading 0
if (($time < '9') || ($time > '17')) {
continue;
}
$times[] = $datetime->format('r'); // output format
}
var_dump($times);
Obviously there are various aspects of this that you can configure, especially the output format. Depending on your purpose, you may prefer to put the DateTime objects themselves into the array.
$datetime = new DateTime(); // Set your start date here
do { // Iterate over .. dont know, a long time?
do { // Iterate over the week ...
$datetime->setTime(9,0,0);
do { // Iterate over the hours ...
echo $datetime->format('c') . PHP_EOL; // Do something with $datetime here
$datetime->add(new DateInterval('PT1H'));
} while ($datetime->format('G') < 18); // .. till < 18
$datetime->add(new DateInterval('P1D')); // next day
} while (!in_array($datetime->format('w'), array('0','6'))); // until we hit sunday or saturday
$datetime->add(new DateInterval('P2D')); // next monday
} while (true); // replace with your "end" expression
Currently untested.
You can use the common interval-strings (like 1 hour and so on) too http://php.net/dateinterval.createfromdatestring
You could calculate your dates with two nested loops and generate the string with date().
I would just loop through all dates, incremented by hour, from now until the end of the year, as follows (pseudocode, obviously):
for n = now until end of year
if (date(n) is between 9:00 and 17:00) AND (if date(n) is not sat or sun)
add to array
end if
increment n by 1 hour
end
Here is a solution which should be reasonably fast since it uses no string comparisons and has only two function calls inside the loops:
function hours()
{
$start = mktime(0, 0, 0, date('n'), 1, date('Y'));
$end = mktime(0, 0, 0, 1, 1, date('Y') + 1);
$wday = date('w', $start);
$result = array();
for ($t = $start; $t < $end; $t += 3600 * 24) {
if (($wday > 0) && ($wday < 6)) {
for ($hour = 9; $hour <= 17; $hour++) {
$result[] = date('Y-m-d', $t) . sprintf(' %02d:00:00', $hour);
}
}
$wday = ($wday + 1) % 7;
}
return $result;
}