How to create time range-step in array like this result - PHP - php

i need array like example if can set option for step,start,end is very better
[
[
"07:30:00",
"08:00:00",
],
[
"08:00:00",
"08:30:00",
],
....
[
"23:30:00",
"00:00:00",
],
]

The best solution I guess is:
function timeSteps($step, $start, $end){
$stepHours = substr($step, 0, 2);
$stepMinutes = substr($step, 3, 2);
$stepSeconds = substr($step, 6, 2);
$startTime = Carbon::createFromFormat('H:i:s', $start);
$endTime = Carbon::createFromFormat('H:i:s', $end);
$result = [];
while ($startTime->lt($endTime)) {
$item = [];
array_push($item, $startTime->format('H:i:s'));
$startTime->addHours($stepHours);
$startTime->addMinutes($stepMinutes);
$startTime->addSeconds($stepSeconds);
array_push($item, $startTime->format('H:i:s'));
array_push($result, $item);
}
return $result;
}
And you can call it like:
timeSteps("00:30:00", "08:00:00", "10:00:00")

If you're using Laravel then you might be better off using CarbonInterval as stated by this blog post (by Jan Östlund) : https://janostlund.com/2019-11-03/generate-time-ranges
$intervals = CarbonInterval::minutes($timeStep)->toPeriod($start, $end);
Then you will get an array of Carbon-object which you can use however you want:
foreach ($intervals as $date) {
dump($date->format('H:i'))
}

i do this in laravel and result is ok
function range($lower = 0, $upper = 86400, $step = 3600, $format = '')
{
$times = array();
if ( empty( $format ) ) {
$format = 'g:i a';
}
foreach ( range( $lower, $upper, $step ) as $increment ) {
$increment = gmdate( 'H:i', $increment );
list( $hour, $minutes ) = explode( ':', $increment );
$date = new \DateTime( $hour . ':' . $minutes );
$times[] = $date->format( $format );
}
$times = collect($times)->chunk(2)->map(function($item) {
return $item->values();
});
$new_times = [];
foreach ($times as $key=>$time){
if($key == 0){
$new_times[$key][0] = $time[0];
$new_times[$key][1] = $time[1];
}
else{
$new_times[$key][0] = Carbon::parse($time[0])->subMinutes(30*$key)->format('H:i:s');
$new_times[$key][1] = Carbon::parse($time[1])->subMinutes(30*$key)->format('H:i:s');
}
}
return $new_times;
}
and use :
range(27000, 144000, 1800, 'H:i:s');

There are few possibilities here, but this method will keep it simple...
Create a function to create your sub-array start and end times.
Then, create a range of start and end times, eg: 8:00am to midnight.
By incrementing each by 1800 seconds (half hour) you will get your result..
<?php
function timeRange( $start = 0, $end = 86400, $step = 3600, $format = 'Y-m-d H:i:s' ) {
$times = [];
foreach ( range( $start, $end, $step ) as $inc ) {
$inc = gmdate( 'H:i', $inc );
$date = new DateTime( $inc );
$times[(string) $inc] = $date->format( $format );
}
return $times;
}
$my_times = [];
$range = range(28800, 84600, 1800);
foreach($range as $seconds)
{
$start = $seconds;
$end = $seconds+1800;
$my_times[] = timeRange($seconds, $end, 1800, 'H:i:s');
}
var_dump($my_times);

Related

Php get the timestamp values grouped by months

Suppose that i have
$time1 = 1492894800 //23/04/2017
$time2 = 1503521999 //23/08/2017
I would like to get timestamps grouped by months such that
get timestamp with rangess between months preserving first and last month of $time1 and $time2 such that i should have
1 23/04/2017 to 30/04/2017
2 01/05/2017 - 31/05/2017
....... //continue full months and lastly
01/08/2017 - 23/08/2017
i have tried
$timearrays = $this->getMontTimestampRanges($time1, $time2);
public function getMontTimestampRanges($ts1, $ts2){
$start = (new DateTime(date("Y-m-d", $ts1)));
$end = (new DateTime(date("Y-m-d", $ts2)));
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($start, $interval, $end);
$timestamps = [];
foreach ($period as $dt) {
//am stuck here on how to group based on the months
..push to array
}
return $timestamps;
}
so the final array i would like it to be of the form:
$timestamps = [
0=>["from":, "to": ] //first month(april)
1=>[ ] //second month may
]
How do i go about this?
After clarifying your query on my last answer, I have decided to delete my answer and post a new answer.
$start = 1492894800; //23/04/2017
$end = 1503521999; //23/08/2017
$steps = date('Ym', $end) - date('Ym', $start);
$timestamps = array();
for($i = 0; $i <= $steps; $i++) {
$base = strtotime("+{$i} months", $start);
$timestamps[] = array(
'from' => $i == 0 ? date('Y-m-d', $start) : date('Y-m-01', $base),
'to' => $i == $steps ? date('Y-m-d', $end) : date('Y-m-t', $base)
);
// If we want timestamps
// $timestamps[] = array(
// 'from' => strtotime(date('Y-m-01', $base)),
// 'to' => strtotime(date('Y-m-t', $base))
// );
}
print_r($timestamps);
Ideone link
I edited your code
Try this:
<?php
$time1 = 1492894800 ;//23/04/2017
$time2 = 1503521999; //23/08/2017
$timearrays = getMontTimestampRanges($time1, $time2);
var_dump( $timearrays);
function getMontTimestampRanges($ts1, $ts2){
$start = new DateTime(date("Y-m-d", $ts1));
$end = new DateTime(date("Y-m-d", $ts2));
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
$timestamps = [];
$startM = $period->getStartDate()->format('m');
$endM = $period->getEndDate()->format('m');
foreach ($period as $dt) {
//am stuck here on how to group based on the months
//start
if($startM == $dt->format('m'))
{
$timestamps[] = array('start'=>$start->format('Y-m-d'),'end'=>$dt->format('Y-m-t'));
}
elseif($endM == $dt->format('m'))
{
$timestamps[] = array('start'=>$dt->format('Y-m').'-01','end'=>$end->format('Y-m-d') );
}
else
{
$timestamps[] = array('start'=>$dt->format('Y-m').'-01','end'=>$dt->format('Y-m-t'));
}
}
return $timestamps;
}
http://sandbox.onlinephpfunctions.com/code/8527e45427fd0114f1e058fffc1885e460807a0a
Hope it helps.

How to skip the dates of an array and increment date by +1?

I have written a few lines code below using PHP, Im trying to pass a date in for loop by getting No of days and incrementing the date by the no of day, for example : i have 09-12-2015 and No days is 3 then i will get output as 09-12-2015,10-12-2015,11-12-2015. Next im using other condition where i need to increment by date if already date is present in $holidy_dates array.
$need_leave_date = "09-12-2015";
$no_day = 6;
$holidy_dates = array('2015-12-11','2015-12-13');
$dates=array();
for($i = 1; $i<$no_day; $i++)
{
$leave_dates = date('Y-m-d', strtotime("+1 day", strtotime($leave_dates)));
if($holidates_dates[$i] == $leave_dates) {
$leave_dates = date('Y-m-d', strtotime("+1 day", strtotime($leave_dates)));
//array_push($dates,$leave_dates);
}
else {
array_push($dates,$leave_dates);
// continue;
}
}
//IMPLODE ALL THE DATES
$implode_dates = implode(',', $dates);
echo $implode_dates;
Example I need:
09-12-2015,10-12-2015,12-12-2015,14-12-2015,15-12-2015,16-12-2015
here available dates in $holidy_dates array are skipped.
But for me its like this:
2015-12-10,2015-12-11,2015-12-12,2015-12-13,2015-12-14
Here it will work:
$need_leave_date = "09-12-2015";
$no_day = 6;
$holidy_dates = array('2015-12-11','2015-12-13');
$dates=array();
$i = $no_day;
$date = date( 'Y-m-d', strtotime($need_leave_date) );
while ( $i != 0 )
{
if( !in_array( $date, $holidy_dates ) ) {
array_push($dates,$date);
$i--;
}
$date = date( 'Y-m-d', strtotime($date . '+1 day') );
}
$implode_dates = implode(',', $dates);
echo $implode_dates;
For multi-dimensional array:
$need_leave_date = "09-12-2015";
$no_day = 6;
$holidy_dates = array(
array( 'gh_date' => "2015-12-11"),
array( 'gh_date'=> "2015-12-13")
);
$dates=array();
$i = $no_day;
$date = date( 'Y-m-d', strtotime($need_leave_date) );
while ( $i != 0 )
{
if( !in_array_r( $date, $holidy_dates ) ) {
array_push($dates,$date);
$i--;
}
$date = date( 'Y-m-d', strtotime($date . '+1 day') );
}
$implode_dates = implode(',', $dates);
echo $implode_dates;
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
Here is the solution. Try this.
<?php
$need_leave_date = "09-12-2015";
$no_day = 6;
$holidy_dates = array('2015-12-11','2015-12-13');
$dates=array();
$i=1;
while($i<=$no_day){
if($leave_dates){
$leave_dates = date('Y-m-d', strtotime("+1 day", strtotime($leave_dates)));
}else{
$leave_dates = date('Y-m-d', strtotime($need_leave_date));
}
if(in_array($leave_dates, $holidy_dates)){
// do nothing
}else{
array_push($dates,$leave_dates);
$i++;
}
}
//IMPLODE ALL THE DATES
$implode_dates = implode(',', $dates);
echo $implode_dates;
?>
Output
2015-12-09,2015-12-10,2015-12-12,2015-12-14,2015-12-15,2015-12-16

Conversion of Date string to word issue PHP string

I am converting a string number to strtotime and then attempting to get a written date outputted. This is working to an extent but the issue is that the dates are wrong.
THE PHP
$today = date("Y-m-d");
function dateRange($start, $end) {
date_default_timezone_set('UTC');
$diff = strtotime($end) - strtotime($start);
$daysBetween = floor($diff/(60*60*24));
$formattedDates = array();
for ($i = 0; $i <= $daysBetween; $i++) {
// $tmpDate = date('Y-m-d', strtotime($start . " + $i days"));
$tmpDate = date('Y-m-d', strtotime($start . " + $i days"));
// $formattedDates[] = date('Y-m-d', strtotime($tmpDate));
$formattedDates[] = date('Y-m-d', strtotime($tmpDate));
}
return $formattedDates;
}
$start=$date_system_installed;
$end=$today;
$formattedDates = dateRange($start, $end);
foreach ($formattedDates as $dt)
{
$date = strtotime($dt);
echo date('l jS F Y',$date);
}
The outputted dates
The true dates that should be showing but in text
Where am i going wrong for this to output the correct format but incorrect dates?
Here's a date range function I wrote that generates an array of formatted dates. It uses the DateTime() functions which will give you more accurate intervals than things like 60*60/24.
/**
* Creates an array of dates between `$start` and `$end`, intervaled by a day
*
* #param string $start Start date string
* #param string $end End date string
* #param string $format Date format
* #param boolean $inclusive Whether or not to include the start and end dates
* #return array Array of dates between the two
*/
function dateRange($start = null, $end = null, $format = 'Y-m-d', $inclusive = true) {
if (empty($start) || empty($end)) {
return array();
}
$start = new DateTime($start);
$end = new DateTime($end);
if ($inclusive) {
$end = $end->modify('+1 day');
} else {
$start = $start->modify('+1 day');
}
$interval = new DateInterval('P1D');
$period = new DatePeriod($start, $interval, $end);
$daterange = array();
foreach ($period as $date) {
$daterange[] = $date->format($format);
}
return $daterange;
}
And a test case
function testDateRange() {
$results = dateRange('2012-02-20', '2012-03-01');
$expected = array(
'2012-02-20',
'2012-02-21',
'2012-02-22',
'2012-02-23',
'2012-02-24',
'2012-02-25',
'2012-02-26',
'2012-02-27',
'2012-02-28',
'2012-02-29',
'2012-03-01'
);
$this->assertEquals($expected, $results);
$results = dateRange('2012-02-24', '2012-03-01', 'M j');
$expected = array(
'Feb 24',
'Feb 25',
'Feb 26',
'Feb 27',
'Feb 28',
'Feb 29',
'Mar 1'
);
$this->assertEquals($expected, $results);
$results = dateRange('2012-02-25', '2012-03-01', 'Y-m-d', false);
$expected = array(
'2012-02-26',
'2012-02-27',
'2012-02-28',
'2012-02-29'
);
$this->assertEquals($expected, $results);
}
I ran your code - it's all ok
http://codepad.org/E18ccpxV

Function to find the dates in between 2 dates not working in PHP

I have a PHP function to find the dates coming between two dates in 'd/m/Y' format.
function dateRange($first, $last, $step = '+1 day', $format = 'd/m/Y' )
{
echo $first;
echo "<br>";
echo $last;
echo "<br>";
echo $step;
echo "<br>";
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last )
{
$dates[] = date($format, $current);
$current = strtotime($step, $current);
}
print_r($dates);
exit;
return $dates;
}
Here
$first = 20/05/2014
$last = 31/05/2014
As I have exited the function just after printing first result, It should print one date. But the date it is printing is 01/01/1970
What is wrong with this function ?
just make some change in your function
$current = strtotime(str_replace("/", "-", $first));
$last = strtotime(str_replace("/", "-", $last));
instead of
$current = strtotime($first);
$last = strtotime($last);
because strtotime cannot covert the timestamp of the date format d/m/Y. it will convert the timestamp of the date format d-m-Y
Here's how to do this using DateTime() and related classes:
function dateRange($first, $last, $step = '+1 day', $format = 'd/m/Y' )
{
$dates = array();
$start = DateTime::createFromFormat($format, $first);
$finish = DateTime::createFromFormat($format, $last);
$finish->modify($step); // make sure last date is included
$interval = DateInterval::createFromDateString($step);
$period = new DatePeriod($start, $interval, $finish);
foreach ($period as $date) {
$dates[] = $date->format($format);
}
return $dates;
}
This solves the problem you are having with your date format which will not work due to how strtotime() handles dates with slashes. It assumes m/d/Y and not d/m/Y. It will also allow you to change the format into something not acceptable to strtotime() and still work.
try to replace '/' to '-'
$first = str_replace('/', '-', '20/05/2014');
$last = str_replace('/', '-', '31/05/2014');
so code will be:-
function dateRange($first, $last, $step = '+1 days', $format = 'd/m/Y' )
{
echo $first;
echo "<br>";
echo $last;
echo "<br>";
echo $step;
echo "<br>";
$dates = array();
$current = strtotime($first);
$last = strtotime($last);
while( $current <= $last )
{
$dates[] = date($format, $current);
$current = strtotime($step, $current);
}
print_r($dates);
exit;
return $dates;
}
$first = str_replace('/', '-', '20/05/2014');
$last = str_replace('/', '-', '31/05/2014');
dateRange($first, $last, $step = '+1 day', $format = 'd/m/Y' );
output :-
20-05-2014
31-05-2014
+1 day
Array ( [0] => 20/05/2014 [1] => 21/05/2014 [2] => 22/05/2014 [3] => 23/05/2014 [4] => 24/05/2014 [5] => 25/05/2014 [6] => 26/05/2014 [7] => 27/05/2014 [8] => 28/05/2014 [9] => 29/05/2014 [10] => 30/05/2014 [11] => 31/05/2014 )

Calculate number of days,hours,minutes,seconds only working hours

I have a php function to calculate timestamp (start date) to current (end) date that will return 1hr 30min 2s format. What I want to achieve is to calculate only from 8AM to 5PM of a working day. Anything that goes beyond will not be counted. Here is the php code I have.
class duration_computation {
function duration( $time ) {
$d[0] = array(1, "s");
$d[1] = array(60, "min");
$d[2] = array(3600, "hr");
$d[3] = array(86400, "dy");
$d[4] = array(604800, "wk");
$d[5] = array(2592000, "mth");
$d[6] = array(31104000, "yr");
$numbers = array();
$result = "";
$now = time();
$time_difference = ( $now - $time );
$seconds_left = $time_difference;
for ( $i = 6; $i > -1; $i-- ) {
$numbers[$i] = intval( $seconds_left / $d[$i][0] );
$seconds_left -= ( $numbers[$i] * $d[$i][0] );
if ( $numbers[$i] != 0 ) {
$result.= abs($numbers[$i]) . "" . $d[$i][1] . (($numbers[$i]>1)?'':'') ." ";
}
}
return $result;
}
}
$duration = new duration_computation();
echo $duration->duration($trail->duration);
Forget about date(), strtotime(), time(), etc. function, use DateTime :
Use example :
$from = '2013-09-06 15:45:32';
$to = '2013-09-14 21:00:00';
echo some_func_name($from, $to);
Output :
1 day, 22 hours, 14 minutes, 28 seconds
Function :
function some_func_name($from, $to) {
$workingDays = [1, 2, 3, 4, 5]; # date format = N
$workingHours = ['from' => ['08', '00'], 'to' => ['17', '00']];
$start = new DateTime($from);
$end = new DateTime($to);
$startP = clone $start;
$startP->setTime(0, 0, 0);
$endP = clone $end;
$endP->setTime(23, 59, 59);
$interval = new DateInterval('P1D');
$periods = new DatePeriod($startP, $interval, $endP);
$sum = [];
foreach ($periods as $i => $period) {
if (!in_array($period->format('N'), $workingDays)) continue;
$startT = clone $period;
$startT->setTime($workingHours['from'][0], $workingHours['from'][1]);
if (!$i && $start->diff($startT)->invert) $startT = $start;
$endT = clone $period;
$endT->setTime($workingHours['to'][0], $workingHours['to'][1]);
if (!$end->diff($endT)->invert) $endT = $end;
#echo $startT->format('Y-m-d H:i') . ' - ' . $endT->format('Y-m-d H:i') . "\n"; # debug
$diff = $startT->diff($endT);
if ($diff->invert) continue;
foreach ($diff as $k => $v) {
if (!isset($sum[$k])) $sum[$k] = 0;
$sum[$k] += $v;
}
}
if (!$sum) return 'ccc, no time on job?';
$spec = "P{$sum['y']}Y{$sum['m']}M{$sum['d']}DT{$sum['h']}H{$sum['i']}M{$sum['s']}S";
$interval = new DateInterval($spec);
$startS = new DateTime;
$endS = clone $startS;
$endS->sub($interval);
$diff = $endS->diff($startS);
$labels = [
'y' => 'year',
'm' => 'month',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second',
];
$return = [];
foreach ($labels as $k => $v) {
if ($diff->$k) {
$return[] = $diff->$k . ' ' . $v . ($diff->$k > 1 ? 's' : '');
}
}
return implode(', ', $return);
}
This function can be shorter/better; but that is your job now ;)

Categories