I'm trying to generate a list of consecutive date periods by using strtotime to add 13 days to the first date like this:
$start = strtotime(date('2020-06-01'));
for($x = 1; $x<=10; $x++) // increment $x until 10
{
$period = $start - ($x * 1209600); // 1209600 is equivalent to 14 days. Multiply by $x
$period_end = date('Y-m-d', strtotime(date('Y-m-d', $period). ' + 13 days'));
echo date('Y-m-d', $period) . " - " . $period_end ."<br>";
}
The output looks like this:
2020-05-18 - 20-05-31
2020-05-04 - 20-05-17
2020-04-20 - 20-05-03
2020-04-06 - 20-04-19
2020-03-23 - 20-04-05
2020-03-09 - 20-03-22
2020-02-23 - 20-03-07
2020-02-09 - 20-02-22
2020-01-26 - 20-02-08
2020-01-12 - 20-01-25
Everything works as expected until it hits the '2020-02-23 - 20-03-07' range. It should report '2020-02-24 - 2020-03-08'
Why the shift by 1 day? Is this a bug in PHP strtotime in relation to a leap year?
Edit: This was not a leap year issue. It turned out to be a daylight savings time issue in my timezone. When DST occurred on 3/8 the time in seconds from epoch changed by an hour. This shifted my date to 1 hour earlier which ends up being a previous day.
If we add H:i to your date()'s it all becomes clear.
$start = strtotime(date('2020-06-01'));
for($x = 1; $x<=10; $x++) // increment $x until 10
{
$period = $start - ($x * 1209600); // 1209600 is equivalent to 14 days. Multiply by $x
$period_end = date('Y-m-d H:i', strtotime(date('Y-m-d H:i', $period). ' + 13 days'));
echo date('Y-m-d H:i', $period) . " - " . $period_end ."<br>\n";
}
Output:
2020-05-18 00:00 - 2020-05-31 00:00<br>
2020-05-04 00:00 - 2020-05-17 00:00<br>
2020-04-20 00:00 - 2020-05-03 00:00<br>
2020-04-06 00:00 - 2020-04-19 00:00<br>
2020-03-22 23:00 - 2020-04-04 23:00<br>
2020-03-08 23:00 - 2020-03-21 23:00<br>
2020-02-23 23:00 - 2020-03-07 23:00<br>
2020-02-09 23:00 - 2020-02-22 23:00<br>
2020-01-26 23:00 - 2020-02-08 23:00<br>
2020-01-12 23:00 - 2020-01-25 23:00<br>
r3mainer comment is correct. Add 12:00 to the start and the problem will go away.
Because of the daylight savings you remove one hour too much, it's not the leap year.
$start = strtotime(date('2020-06-01 12:00'));
https://3v4l.org/Uj2CA
I have x.
x is minutes.
I have a string start_time like: 7:00
And I have a string end_time like: 14:00
how can print a list of time with increase x minutes for each loop?
I want print something like this:
if x = 30
7:00 - 7:30
7:30 - 8:00
...
13:30 - 14:00
I try do it with math functions in php like this:
$time = '7:00';
$mm = $hh = 0;
$str = explode(":",$time);
if(($str[1]+ $x) > 60)
{
...
}
but it there a more simple method? can date function in php do it?
You can use DatePeriod together with DateInterval to achieve this.
Create two DateTime intervals with your start and end times, and a DateInterval instance with the number of minutes you need. Then, create a DatePeriod with this information, and iterate over it to show the resulting times:
<?php
$minutes = 15;
$start = "07:00";
$end = "14:00";
$startDate = DateTime::createFromFormat("H:i", $start);
$endDate = DateTime::createFromFormat("H:i", $end);
$interval = new DateInterval("PT".$minutes."M");
$dateRange = new DatePeriod($startDate, $interval, $endDate);
foreach ($dateRange as $date) {
echo $date->format("H:i")."<br>";
}
Demo
Result
07:00
07:15
07:30
07:45
08:00
08:15
08:30
08:45
09:00
09:15
09:30
09:45
10:00
10:15
// etc
You can use the DatePeriod object along with a desired DateInterval object.
Example: https://3v4l.org/lg8QW
$start = new \DateTime('07:00');
$end = new \DateTime('14:00');
$interval = new \DateInterval('PT1M'); //change to desired interval
$periods = new \DatePeriod($start, $interval, $end);
foreach ($periods as $period) {
echo $period->format('H:i') ;
}
Result:
07:00
07:01
07:02
07:03
07:04
07:05
07:06
07:07
07:08
07:09
07:10
07:11
07:12
07:13
07:14
07:15
07:16
07:17
07:18
07:19
07:20
//...
13:59
You can use DateTime object.
just like this:
<?php
$start_time = '7:00';
$date1 = DateTime::createFromFormat('H:i', $start_time);
$old = $start_time;
while (true) {
$date1->modify('+30 min');
echo $old . '-' . $date1->format('H:i').PHP_EOL;
$old = $date1->format('H:i');
if ($old == '14:00') {
break;
}
}
Output:
7:00-07:30
07:30-08:00
08:00-08:30
...
13:30-14:00
More info just see the manual here: DateTime
I tryed to display added date as 25 minutes ago, Today 5.30 PM etc.
$added_time = strtotime('1 Jan 2016 6:00 AM');
$currentTime = strtotime('1 Jan 2016 7:15 AM'); // probably uses time()
$diff = timespan($time1, $time2);
if($diff < 1 hour){ // how to check 1 hour
//display minutes ago
}
else {
//display added time
}
Conditions
if the time gap is less than 60 minute -> 25 minutes ago
If the time gap is over 60 minute But Today -> Today 6.00AM
If the time gap is over 60 minute But Yesterday -> Yesterday 6.00AM
Else exactly $added_time
How to check the condition for less than 1 hour, today and yesterday?
This is not specifically a CodeIgniter question. I am not sure exactly what you are doing, but this code will get you close.
$Added = new \DateTime(date('Y-m-d H:i:s', strtotime('1 Jan 2016 6:00 AM')));
$Current = new \DateTime(date('Y-m-d H:i:s', strtotime('1 Jan 2016 7:15 AM')));
$Diff = $Added->diff( $Current , FALSE);
$hours = $Diff->format('%H');
$mins = $Diff->format('%I');
if( $Diff->invert == true ){
echo "Some hours $hours and minutes $mins ago ";
}
else if( $Diff->invert == false ){
echo "Some hours $hours and minutes $mins into the future ";
}
References:
http://php.net/manual/en/class.datetime.php
http://php.net/manual/en/datetime.diff.php
I am slightly confused to build Time-slot logic dynamically could you please help me out.
I need to display some list of time-slot but each time slot will be of two hour. please see list inline below
00:00 02:00
02 04
04 06
06 08
08 10
10 12
12 14
14 16
16 18
18 20
20 22
22 00
Code
public function getTimeSlot(){
$custom = array();
$M = 'AM';
for($i=0;$i<=23;$i++):
$time1 = strtotime($i.':00:00');
$time2 = strtotime(($i*2).':00:00');
$diff = $time2 - $time1;
$custom[] = date('H:i:s ', $diff);
endfor;
pr($custom);
exit();
}
Your question seems vague. Is it like this?
00:00 02:00
02:00 04:00
04:00 06:00
06:00 08:00
08:00 10:00
10:00 12:00
12:00 14:00
14:00 16:00
16:00 18:00
18:00 20:00
20:00 22:00
22:00 00:00
If I would just print a simple time, I would do something like:
$start = 0; $end = 22;
$time_slot = range($start, $end, 2);
$time_slot = array_map(function($time) use ($end){
$next = ($time != $end) ? $time + 2 : 00;
$times = array(sprintf("%02s:00", $time), sprintf("%02s:00", $next));
return $times;
}, $time_slot);
foreach($time_slot as $time) {
echo "$time[0] $time[1] <br/>";
}
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;
}