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"));
}
Related
I'm struggling to to write a PHP function that would calculate time difference between two hours (minus the brake) and the result would be in decimal format. My inputs are strings in 24-hour format (hh:mm):
$start = '07:00'; //started at 7 after midnight
$brake = '01:30'; //1 hour and 30 minutes of brake
$finish = '15:00'; //finished at 3 afternoon
//the desired result is to print out '6.5'
example 2
$start = '19:00'; //started late afternoon
$brake = '00:30'; //30 minutes of brake
$finish = '03:00'; //finished at 3 after midnight
//the desired result is to print out '7.5'
I used to have following formula in MS Excel which worked great:
=IF(D12>=F12,((F12+1)-D12-E12)*24,(F12-D12-E12)*24) '7.5 worked hours
where
D12 - Start time '19:00
F12 - Finish time '03:00
E12 - Brake time '00:30
I tried to play with strtotime() with no luck. My PHP version is 5.4.45. Please help
To provide a solution that doesn't require as much mathematics or parsing of the time values.
Assuming the day is not known, we can also account for the offset of the finish time and start time, when the start time is late at night.
Example: https://3v4l.org/FsRbT
$start = '07:00'; //started at 7 after midnight
$break = '01:30'; //1 hour and 30 minutes of brake
$finish = '15:00'; //finished at 3 afternoon
//create the start and end date objects
$startDate = \DateTime::createFromFormat('H:i', $start);
$endDate = \DateTime::createFromFormat('H:i', $finish);
if ($endDate < $startDate) {
//end date is in the past, adjust to the next day
//this is only needed since the day the time was worked is not known
$endDate->add(new \DateInterval('PT24H'));
}
//determine the number of hours and minutes during the break
$breakPeriod = new \DateInterval(vsprintf('PT%sH%sM', explode(':', $break)));
//increase the start date by the amount of time taken during the break period
$startDate->add($breakPeriod);
//determine how many minutes are between the start and end dates
$minutes = new \DateInterval('PT1M');
$datePeriods = new \DatePeriod($startDate, $minutes, $endDate);
//count the number of minute date periods
$minutesWorked = iterator_count($datePeriods);
//divide the number of minutes worked by 60 to display the fractional hours
var_dump($minutesWorked / 60); //6.5
This will work with any time values within a 24 hour period 00:00 - 23:59. If the day the times were worked are known, the script can be modified to allow for the day to be given and provide more precise timing.
To do this, convert you string times into a unix timestamp. This is an integer number of seconds since the unix epoch (00:00:00 Coordinated Universal Time (UTC), Thursday, 1 January 1970, minus the number of leap seconds that have taken place since then). Do your math, then use the Date() function to format it back into your starting format:
<?php
$start = '19:00'; //started late afternoon
$break = '00:30'; //30 minutes of brake
$finish = '03:00'; //finished at 3 after midnight
//get the number of seconds for which we took a $break
//do this by converting break to unix timestamp, then extracting the hour and multiplying by 360
//and do the same extracting minutes and multiplying by 60
$breaktime = date("G",strtotime($break))*60*60 + date("i",strtotime($break))*60;
//get start time
$unixstart=strtotime($start);
//get finish time. Add a day if finish is tomorrow
if (strtotime($finish) < $unixstart) {
$unixfinish = strtotime('+1 day', strtotime($finish));
} else {
$unixfinish = strtotime($finish);
}
//figure out time worked
$timeworked = ($unixfinish - $unixstart - $breaktime) / 3600;
echo $timeworked;
?>
Another way, using DateTime. Basically, create 2 DateTime objects with the times of start and finish. To the start time, subtract the brake time, and the subtract from the result the end time.
You need to split the brake time in order to use modify().
<?php
$start = '07:00'; //started at 7 after midnight
$brake = '01:30'; //1 hour and 30 minutes of brake
$brakeBits = explode(":", $brake);
$finish = '15:00'; //finished at 3 afternoon
$startDate = \DateTime::createFromFormat("!H:i", $start);
$startDate->modify($brakeBits[0]." hour ".$brakeBits[1]." minutes");
$endDate = \DateTime::createFromFormat("!H:i", $finish);
$diff = $startDate->diff($endDate);
echo $diff->format("%r%H:%I"); // 06:30
Demo
What I am doing is actually iterating from 8AM to 9PM with 1 hour interval but it doesn't give me correct result. This is my code below
<?php
$date = date("08:00");
for($i=1; $i<=10; $i++)
{
$date = strtotime("+".$i." hour");
echo date('H:i A', $date);
}
?>
it starts with current time!,
Thanks for your help.
There are a few different problems to unpack here:
$date = date("08:00");
This isn't useful. date is for formatting a timestamp - you can't use it to create one from an hours:minutes string like this.
What you probably want is
$date = strtotime("08:00");
The reason this didn't cause any problems is that inside your loop you then immediately overwrite it with:
$date = strtotime("+".$i." hour");
This will create a new timestamp, but it will be relative to now, not your initial time. Saying "+1 hour" means you want a timestamp that is now + 1 hour. You can use strtotime to create a timestamp relative to another by using the second argument...
$date = strtotime("+{$i} hour", $date);
...but you're still overwriting your start value. So let's put that in a variable called $start instead:
$start = strtotime("08:00");
...
$date = strtotime("+".$i." hour", $start);
This gets you:
<?php
$start = strtotime("08:00");
for($i=0; $i<=10; $i++) {
$date = strtotime("+{$i} hour", $start);
echo date('H:i A', $date), PHP_EOL;
}
which will output:
08:00 AM
09:00 AM
10:00 AM
...
18:00 PM
It doesn't quite get you to 9PM, because that's not ten hours away from 8am, but 13. I'll leave the last part to you.
See https://eval.in/867974
Also, you might want to look at PHP's DateTime library, which gives you an object-oriented interface for working with dates & times. For a simple script like this, it's not vital.
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.
is there a way in PHP to get the next date(s) using a 4-week interval from a given date ?
Example:
My start date is Friday, Jan 03, 2014 and my interval is every 4 weeks from that date.
What I am looking for is the next date (or dates, if possible) from the current date that matches this 4-week interval.
In the above example this would be Friday, May 23, 2014 (then June 20, 2014, July 18, 2014 etc.).
I know I can get the current date as follows: $today = date('Y-m-d');
and I could probably set the start date like this: $start = date('2014-01-03');
but I don't know how to calculate the interval and how to find out the next matching date(s).
You should read up on the DateTime classes, specifically DatePeriod and DateInterval:
$start = new DateTime('2014-01-03');
$interval = DateInterval::createFromDateString('4 weeks');
$end = new DateTime('2015-12-31');
$occurrences = new DatePeriod($start, $interval, $end);
foreach ($occurrences as $occurrence) {
echo $occurrence->format('Y-m-d') . PHP_EOL;
}
DatePeriod takes a start date and a DateInterval and allows you traverse over the object to get all dates within the boundaries using the given interval. The cut off can be either a set number of cycles (so the next 10 dates) or an end date (like above), even if the end date is not one of the dates the interval falls on (it will stop below it). Or you can use an 8601 interval notation string (which sounds so much fun, huh?), but I'm pretty shaky on that.
If 4-week interval means 7 x 4 = 28 days, you can obtain the "next date" by:
$today = new DateTime();
$next_date = $today->add(new DateInterval('P28D'));
$next_next_date = $next_date->add(new DateInterval('P28D'));
$next_next_next_date = $next_next_date->add(new DateInterval('P28D'));
And if you want to calculate more "next dates", you can repeat the add() to repetitively add 28 days to your date.
Note: Beside using P28D, you can use P4W, which means 4 weeks.
While some answers may suggest using strtotime(), I find the object-oriented approach more structured. However, DateInterval is only available after PHP >= 5.3.0 (while DateTime is available after PHP >= 5.2.0)
You could use strtotime()
echo date('Y-m-d', strtotime('now +4 weeks'));
UPDATED:
$start = date('Y-m-d', strtotime('2014-01-03 +4 weeks'));
echo $start;
You could also run this in a for loop to get the next 6 or more dates. For example:
$Date = "2014-01-03";
$Int = 6;
for($i=0; $i<$Int; $i++){
$Date = date('Y-m-d', strtotime('{$Date} +4 weeks'));
echo $Date;
}
Hi Suppose I have a timestamp of "2005-10-16 13:05:41".
How would I go about creating a variable that will have a unixtime of the next time it becomes 10am from that initial point?
Would it be something like this?
$timestamp = "2005-10-16 13:05:41";
$tenAMTime = strtotime("next 10am", $timestamp);
I am guessing there is some string I can use to do this? Like "next thursday" example in the PHP documentation.
You nearly had it...
$tomorrowAt10Am = strtotime('+1 day 10:00:00', $timestamp);
Edit:
This was based on the title of your question, for the timestamp of 10am the next day. If you want to output 10am the same day for any times before 10am then you'll want to add some extra logic, as thatidiotguy suggested.
Edit2:
For some reason it won't work if you put all the logic in the same strtotime method, so I made a simple function. You could easily put this into a single line, but I left it as 2 to make it clearer:
$time1 = strtotime('-2 days 09:59:59');
$time2 = strtotime('-2 days 10:00:01');
function next_10am($time)
{
$temp = strtotime('+1 day -10 hours', $time);
return strtotime('10:00', $temp);
}
echo next_10am($time1); // Outputs: 2012-09-08 10:00:00
echo next_10am($time2); // Outputs: 2012-09-09 10:00:00
There is no way for strtotime to know whether or not 10am has already passed, so this is how I would do it:
$timestamp = strtotime("2005-10-16 13:05:41");
// Get current hour and if it is > 10 add a day
if (date('G',$timestamp) >= 10) {
$tenAMTime = strtotime("+1 day 10am", $timestamp);
}
else {
$tenAMTime = strtotime("10am", $timestamp);
}
echo date('r',$tenAMTime); // Comment this out if you want