php array arrangements - php

Hi i convert an collections of string comma separated 0 1 5, 2 3 15, 4 18 20 into an array using this functions as follow:
$openHrs = explode(",", $openHrs['open_hours']);
The end result are as follow:
Array ( [0] => 0 1 5 [1] => 2 3 15 [2] => 4 18 20 )
In this array 0 1 5 means Mon 1 am 5 am and 4 18 20 means Thur 6 pm 8 pm, so first digit represent weekday rest 2 digits represent hours in 24hrs format, now how can i output the existing array into this format?
Array ( [0] => Mon 1 am 5 am [1] => Tue 3 am 3 pm [2] => Thur 6 pm 8 pm )
Thanks

I would use array_map to get a filtered version. You can create dates using mktime() and format them using date(). I believe this should be the solution:
$filtered = array_map(function($incoming) {
$parts = explode(' ', $incoming);
return
date('D', mktime(0,0,0,1, $parts[0])) . ' ' .
date('g a', mktime($parts[1])) . ' ' .
date('g a', mktime($parts[2]));
}, $openHrs);

For the weekday, I suggest:
$weekday=array('Mon','Tue','Wed','Thu','Fri','Sat','Sun');
foreach ($openHours As &$openHour) {
$foo = explode(' ',$openHour);
$openHour=$weekday[$foo].' '. // <-- write yourself a nice function to convert 24h to 12h, maybe there's something like this in PHP already?
}

Try this:
// This will be used for the week days
$weekdays = array('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
// Loop through each date
foreach($openHrs as &$temp) {
// Separate the numbers
$temp = explode(" ", $temp);
// Change from a 24 hrs clock to a 12 hrs clock
$temp[1] = $temp[1] > 12 ? $temp[1] - 12 . 'pm' : $temp[1] . 'am';
$temp[2] = $temp[2] > 12 ? $temp[2] - 12 . 'pm' : $temp[2] . 'am';
// Update the element
$temp = $weekdays[$temp[0]] . ' ' . $temp[1] . ' ' . $temp[2];
}

I would explode each Arrayelement again with a whitespace as Delimiter so you have a better array structure:
Array ( [0] => Array(0, 1, 5), [1] => Array(1, 3, 3) [2] => Array(4, 18, 18) )
If you have this structure there are probably several approaches. There might be a solution with date() and timestamps but Iam honestly not to sure about that. An other solution would be. Define another array with the Weekdays.
$weekdays = array("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun");
Then you can use the numbers that you have as index for that array to output the correct weekday.
The hours can you output with a little selfmade function ala:
function twentyFourHourToAmPM($number) {
if ($number > 12) {
return ($number - 12)." pm";
} else {
return $number." am";
}
}
Output everything should then work like this:
foreach ($openHrs as $key => $value) {
echo $weekdays[$value[0]]." ".twentyFourHourToAmPM($value[1])." - ".twentyFourHourToAmPM($value[2]);
}

Related

Count months from a date to December then count months from January the following year to December that same year, then from January to end date

I have a start_date of 1/10/2018, and an end_date of 1/8/2020, the difference between the two dates in months is 22, that is 1 year 10 months, now, I want to create tables that terminate at the end of each year as follows:
table 1
column_heading will be "1/10/2018 - 31/12/2018"
and the row will be "2 months"
table 2
column_heading will be "1/1/2019 - 31/12/2019"
and the row will be "12 months"
table 3
column_heading will be "1/1/2020 - 1/8/2020"
and the row will be "8 months"
I would like to loop something, maybe the difference between the dates to create the number of tables necessary, if the two dates exist within the same year it will only create 1 table, or 2 if it enters the next year, I am using laravel and carbon to manipulate the dates.
Thank you in anticipation of your help.
Something like this
Here's one way. Note that I had to convert the format of your dates to YYYY-mm-dd in order to use PHP date functions. In the end you'll get an array and it's easy for you to transform the final dates into the format you desire. You can test it here: https://www.tehplayground.com/lvuTdWl91TeItEQC
The code:
<?php
// example code
$s = "1/10/2018";
$e = "1/08/2020";
// reassemble so we can use the date functions YYYY-mm-dd
$s = implode("-", array_reverse(explode("/", $s)) );
$e = implode("-", array_reverse(explode("/", $e)) );
// get the parts separated
$start = explode("-",$s);
$end = explode("-",$e) ;
$iterations = ((intVal($end[0]) - intVal($start[0])) * 12) - (intVal($start[1]) - intVal($end[1])) ;
$sets=[$start[0] => array("start" => $s, "end" => "", "months" => 0)];
$curdstart= $curd = $s;
$curyear = date("Y", strtotime($s));
for($x=1; $x<=$iterations; $x++) {
$curdend = date("Y-m-d", strtotime($curd . " +{$x} months"));
$curyear = date("Y", strtotime($curdend));
if (!isset($sets[$curyear])) {
$sets[$curyear]= array("start" => $curdend, "end" => "", "months" => 0);
}
$sets[$curyear]['months']++;
$sets[$curyear]['end'] = date("Y-m-", strtotime($curdend)) . "31";
}
die(print_r($sets,1));
$mctr = 0 ;
The output:
Array
(
[2018] => Array
(
[start] => 2018-10-1
[end] => 2018-12-31
[months] => 2
)
[2019] => Array
(
[start] => 2019-01-01
[end] => 2019-12-31
[months] => 12
)
[2020] => Array
(
[start] => 2020-01-01
[end] => 2020-08-31
[months] => 8
)
)

How to count days of year PHP to create day range array wrapping past day 365 to day 1

I have a database table with content for each day of the year and I'm trying to return the current day and the next 9 days to my PHP app.
Day 1 = Lorem ipsum
Day 2 = Lorem ipsum
Day 3 = Lorem ipsum
Day 365 = Lorem ipsum
I have a basic function that gets the current day of year in PHP and creates an array of the subsequent 10 days:
$today = date(z);
$subsequent_days = 9;
$days_arr = range($today, $today+$subsequent_days);
Example: If today is 12/27, the day number is 360, the resulting array is (360, 361, 362, 363, 364, 365, 366, 367, 368, 369)
The problem I'm trying to solve is that when I feed that array into my database query to get the current and upcoming 9 days, if the current date is less than 10 days from the end of the year (as in the example above) then it only returns me that many days back.
What I'm looking for is a simple/clean way to have the days_arr stop at 365 and restart at 1 to complete the 10 values in the returned array.
So the end result I'm looking for is: (360, 361, 362, 363, 364, 365, 1, 2, 3, 4)
You can just use the modular operator:
<?php
$ten_days = function($from) {
for(
$range = [], $i = 0;
$i<10;
$range[] = ($from + $i) % 365, $i++
);
return $range;
};
var_export($ten_days(360));
Output:
array (
0 => 360,
1 => 361,
2 => 362,
3 => 363,
4 => 364,
5 => 0,
6 => 1,
7 => 2,
8 => 3,
9 => 4,
)
Note: This is assuming a year of 365 days, 0 indexed. You will have to adjust for leap years.
You can adjust the for loop above for 1 indexed days:
for(
$range = [], $i = -1;
$i<9;
$range[] = ($from + $i) % 365 + 1, $i++
);
A simple solution can be achieved using modulo % operator. Using range() is convenient, but doesn't give you the flexibility of using modulo. Not sure if you need to account for leap years, so adding it as an arg:
<?php
$day_seq = function($start, $isleap) {
// Convert human's 1-indexed day to zero-indexed day
$start--;
$numdays = $isleap ? 366 : 365;
// Build 10-day sequence, adding 1 to re-calibrate to human's 1-indexed counting
for($seq = [], $i = 0; $i<10; $i++) {
$seq[] = (($start + $i) % $numdays) + 1;
}
return $seq;
};
print_r($day_seq(360,0));
Output:
Array
(
[0] => 360
[1] => 361
[2] => 362
[3] => 363
[4] => 364
[5] => 365
[6] => 1
[7] => 2
[8] => 3
[9] => 4
)

how to sum time value in array in php

i am fetching a data from my database according to client id. client id work time is different like:
00:15:00
00:20:00
etc.
this is not an array
i make this as dynamic array
$time[] = $alltime;
result showing this:
Array
(
[0] => 00:20:00
[1] => 00:15:00
[2] => 00:20:00
[3] => 00:20:00
[4] => 00:55:00
[5] => 00:05:00
)
i want to sum all time.
i tried many times and many way but output not showing according to time.
please help
Here's one way to get the sum, using strtotime to convert the times to seconds. Note that since strtotime produces a timestamp relative to the Unix Epoch, you need to subtract the start of the day (strtotime('00:00')) from each value to get the number of seconds in the time:
$time = array
(
'00:20:00',
'00:15:00',
'00:20:00',
'00:20:00',
'00:55:00',
'00:05:00'
);
$time_in_secs = array_map(function ($v) { return strtotime($v) - strtotime('00:00'); }, $time);
$total_time = array_sum($time_in_secs);
$hours = floor($total_time / 3600);
$minutes = floor(($total_time % 3600) / 60);
$seconds = $total_time % 60;
echo "Total time is "
. str_pad($hours, 2, '0', STR_PAD_LEFT)
. ":" . str_pad($minutes, 2, '0', STR_PAD_LEFT)
. ":" . str_pad($seconds, 2, '0', STR_PAD_LEFT) . "\n";
Output:
Total time is 02:15:00
Demo on 3v4l.org
You could also simplify the code by using array_reduce to compute $total_time instead of array_map and array_sum:
$total_time = array_reduce($time, function ($c, $v) { return $c + strtotime($v) - strtotime('00:00'); }, 0);
Alternate demo

Add Days from Input Type Date and Input Type Duration PHP Excluding Weekends + MYSQL National Holiday

I need to add days (input type number + input type date) but the result must be an array so I can INSERT one after another into the Database.
Here's the code (After HTML Form submitted):
<?php
$start_date = '2017-12-22';
$duration = '3';
$d = new DateTime($start_date);
$t = $d->getTimestamp();
// loop for X days
for($i=0; $i <= $duration; $i++){
// add 1 day to timestamp-
$addDay = 86400;
// get what day it is next day
$nextDay = date('w', ($t + $addDay));
// if it's Saturday or Sunday get $i-1
if($nextDay === 6 || $nextDay === 7) {
$i --;
}
// modify timestamp, add 1 day
$t = $t + $addDay;
$d->setTimestamp($t);
$day_off = $d->format( 'Y-m-d' ). "<br />";
echo $day_off;
$query = "INSERT SQL";
}
?>
From echo $day_off result I get:
2017-12-23
2017-12-24
2017-12-25
2017-12-26
Instead of 23, 24, 25, 26. I need to get the result below:
2017-12-22
2017-12-25
2017-12-26
2017-12-27
22 is the input date, start from 25 because 23 and 24 are Sat and Sun and weekends need to be excluded.
How can I achieve this result? I've been searching on the net but unfortunately, I couldn't find what I needed.
#C. Geek answer made it to works, but I have a more complex question here, since my account are not eligible to ask more question so I'll ask here.
So here's what I've tried so far (with #C. Geek answer) :
<?php
// loop for X days
for($i=0; $i < $duration; $i++){
$d = strtotime("$start_date +$i weekdays");
$t = strftime("%Y-%m-%d",$d);
$day_off[] = $t;
foreach($day_off as $dayoff) {
$data_holiday = mysqli_fetch_array(mysqli_query($con, "SELECT * FROM `holiday_master_data` WHERE `date` = '$dayoff' "));
}
$holiday[] = $data_holiday['date'];
$date = array_diff($day_off, $holiday);
$dayoff_ = $holiday;
?>
Start date : 2017-12-29
Duration : 5 days
From print_r($day_off); I'm getting this result :
Array ( [0] => 2017-12-29 ) Array ( [0] => 2017-12-29 [1] => 2018-01-01 ) Array ( [0] => 2017-12-29 [1] => 2018-01-01 [2] => 2018-01-02 )
And from print_r($holiday); I'm getting this result :
Array ( [0] => ) Array ( [0] => [1] => 2018-01-01 ) Array ( [0] => [1] => 2018-01-01 [2] => ) Array ( [0] => [1] => 2018-01-01 [2] => [3] => ) Array ( [0] => [1] => 2018-01-01 [2] => [3] => [4] => )
The national date fetched from database is 2018-01-01 with 5 looping result, the final date result I need to make are 29 Dec, 02 Jan 03 Jan and 04 Jan, 05 Jan.
Any help will be much appreciated.
Thanks.
https://stackoverflow.com/a/4261223/6288442
If you are limiting to weekdays use the string weekdays.
echo date ( 'Y-m-j' , strtotime ( '3 weekdays' ) );
This should jump you ahead by 3 weekdays, so if it is Thursday it will
add the additional weekend time.
Source: http://www.php.net/manual/en/datetime.formats.relative.php
As for formatting:
http://php.net/manual/en/function.strftime.php
string strftime ( string $format [, int $timestamp = time() ] )
If you need more help with writing the code than these, please do tell in a comment
Here is my full answer:
$start_date = '2017-12-22';
$duration = 3;
$arr=null;
for($i=0; $i <= $duration; $i++){
$d = strtotime("$start_date +$i weekdays");
$t = strftime("%Y-%m-%d",$d);
$arr[]=$t;
}
Get the holidays before the looping, then in the loop, check if date is in_array before adding it to $arr.
e.g.
$start_date = '2017-12-22';
$data_holiday = mysqli_fetch_array(mysqli_query($con, "SELECT * FROM `holiday_master_data` WHERE YEAR(`date`) BETWEEN YEAR('$start_date') AND YEAR('$start_date')+1 "));
$holidays =
$duration = 3;
$arr=null;
for($i=0; $i <= $duration; $i++){
$d = strtotime("$start_date +$i weekdays");
$t = strftime("%Y-%m-%d",$d);
if(!in_array($t,$data_holiday))
$arr[]=$t;
}
FINALLY!! After several hours I fixed everything. Here's the code how I manage to skip (Sun and Monday) and also Skip the Holiday's fetched from the database (based on #C.Geek answers + several tweaking):
<?php
include 'conn.php';
$start_date = mysqli_real_escape_string($con, $_POST['start_date']);
$duration = mysqli_real_escape_string($con, $_POST['duration']);
// loop for X days
for($i=0; $i <= $duration; $i++){
$d = strtotime("$start_date +$i weekdays");
$t = explode(", ", strftime("%Y-%m-%d", $d));
foreach ($t as $date) {
$to_encode = array("date" => $date);
$date_where = $to_encode['date'];
$data_holiday = mysqli_fetch_array(mysqli_query($con, "SELECT `date` AS '0' FROM `holiday_master_data` WHERE DATE(`date`) BETWEEN DATE('$date_where') AND DATE('$date_where') + 1 GROUP BY `id` "));
$encode_holiday = array("date" => $data_holiday[0]);
break;
}
$holiday = array_unique($encode_holiday);
$dayoff = array_diff($t, $holiday);
foreach($dayoff as $date) {
$query = mysqli_query($con, "INSERT INTO ");
if ($query) {
echo "<script>alert('Absence Saved'); window.location ='document.php' </script>";
} else {
echo "<script>alert('Gagal'); window.location ='document.php' </script>";
}
}
}
?>
Hope this helps anyone seeking the same problem I had.
Cheers.

Traversing arrays php

I was wondering if there is a better solution to loop through an array from mid to end then from start to mid. Particularly for an associative array.
So for example if there is an associative array with the keys
$dow = array(Mon => etc, Tue => etc, Wed => etc, Thr => etc .. to .. Sun => etc).
I would start searching the array from Thurs to find the next day with something specific which could be anyday but happens to be on Tues, I usually iterate from Thurs (by index) to Sunday then, reset and start again from Monday to Wed and find the target when reaching Tues.
I count the index via an id and when it reaches 6 reset the id to 0
$id = 3 // Found day is Thursday id
//Loop function starts here
$id++; // start search from one day above found day
if ($id >= 6){ //when reaching Sunday
$id = 0 // start search from monday
}
// check array here for that specific thing
So the question is to ask if there is a more simple solution than this, ie split array from index thursday to sunday and add it onto the beginning of the array and then do the loop without having to count an index or if there are any other solutions without using the count index.
You can try with array_splice:
$array = array(1,2,3,4,5,6,7);
$lastDays = array_splice($array, 3);
$firstDays = $array;
print_r(array('first days' => $firstDays, 'last days' => $lastDays));
If the day is not in $lastDays (use a boolean like $matchFound) then you would search in $firstDays.
Or just use with array_merge:
$array = array(1,2,3,4,5,6,7);
$array = array_merge(array_splice($array, 3), $array);
print_r($array);
where output is:
Array
(
[0] => 4
[1] => 5
[2] => 6
[3] => 7
[4] => 1
[5] => 2
[6] => 3
)
and then you can search with a foreach.
maybe a foreach would be more efficient. hope this helps.
$id = 3 // Found day is Thursday id
$i =0;
//Loop function starts here
foreach($dow as $idx)
if($id == $i):
else if($i > $id):
endif;
if($i == count($dow)){$i=0;}else{$i++;}
endforeach;
<?php
$dow = array("mon","tue","wed","thu","fri","sat","sun");
$pick_a_day = 2; // user input; NON zero based. monday = 1
$pick_a_day--; // make it zero based to use in code
foreach($dow as $inc => $an_element )
{
echo $dow[($pick_a_day+(count($dow))) % (count($dow))]." - loop number:".($inc+1)."\n";
$pick_a_day++;
}
?>
output
tue - loop number:1
wed - loop number:2
thu - loop number:3
fri - loop number:4
sat - loop number:5
sun - loop number:6
mon - loop number:7
Maybe not the best solution, but a solution:
function half($array) {
$h = sizeof($array) / 2;
$a1 = array_splice($array, $h);
$a2 = array_splice($array, 0);
$res = array_merge($a1, $a2);
return $res;
}
$dow = array('Mon' => 'etc1', 'Tue' => 'etc2', 'Wed' => 'etc3', 'Thr' => 'etc4', 'Fri' => 'etc5', 'Sat' => 'etc6', 'Sun' => 'etc7');
$b = half($dow);
Now you can go through with a foreach, or how would you like. Result of $b:
Array
(
[Thr] => etc4
[Fri] => etc5
[Sat] => etc6
[Sun] => etc7
[Mon] => etc1
[Tue] => etc2
[Wed] => etc3
)

Categories