Starting the loop cycle from current month in an array - php

I have an array with rainfall amount for each month. I am doing some calculation in a foreach loop which starts from 0 index in the array. How can I start from the current month (say 4th month) and end at third month next year? Below is the code I have in hand.
public static function getWaterLevels($params)
{
$rainfall = $params["rainfall"];
$currentTime = Carbon::now();
$currentMonth = $currentTime->month;
$volume = 0;
$demand = $params["household_number"] * 140 * 30;
$tankSize = $params["tank_capacity"];
$waterLevels = array();
foreach ($rainfall as $amount){
$runoffAmount = 0.80 * ($amount - 2) * $params["roof_area"];
$volume = $volume + ($runoffAmount - $demand);
if ($volume > $tankSize)
{
$overflow = $volume - $tankSize;
$deficit = 0;
$volume = $volume - $overflow;
}
elseif ($volume < 0)
{
$deficit = abs($volume);
$overflow = 0;
$volume = 0;
}
else
{
$overflow = 0;
$deficit = 0;
}
array_push($waterLevels, array(
"volume" => $volume,
"overflow" => $overflow,
"deficit" => $deficit
));
}
return $waterLevels;
}
In the above function, I want to start the loop at $currentMonth - 1. The structure of rainfall array is like this:
array:12 [
0 => 59
1 => 57
2 => 54
3 => 76
4 => 76
5 => 87
6 => 82
7 => 83
8 => 88
9 => 91
10 => 84
11 => 74
]

Related

Create a 12 months array from few months given

I've got this PHP array:
array(
[1528840800] => 50 // 12 June 2018 22:00:00
[1531173600] => 37 // 9 July 2018 22:00:00
[1540940400] => 44 // 30 October 2018 23:00:00
[1543532400] => 9 // 29 November 2018 23:00:00
)
How can i get a full 12 months array where remaining months value are zero?
array(
[01] => 0
[02] => 0
[03] => 0
[04] => 0
[05] => 0
[1528840800] => 50 // 12 June 2018 22:00:00
[1531173600] => 37 // 9 July 2018 22:00:00
[08] => 0
[09] => 0
[1540940400] => 44 // 30 October 2018 23:00:00
[1543532400] => 9 // 29 November 2018 23:00:00
[12] => 0
)
This not works property on the second value..
for ($i=1;$i<13;$i++) {
foreach ($array as $key => $value) {
if (date('m',$key)===sprintf('%02d', $i)) {
$fullmonths[date('d/m/Y',$key)] = $value;
break;
}else{
$fullmonths['XXXX/'.sprintf('%02d', $i).'/2018]=0;
}
}
}
Many thanks.
Just some changes to skip to the next month correctly. You can break or continue a loop on any level. If set continue 2 you starts next itteration of the for loop. Else, you will fill default value
for ($i=1;$i<13;$i++) {
foreach ($array as $key => $value) {
if (date('m',$key) === sprintf('%02d', $i)) {
$fullmonths[date('d/m/Y',$key)] = $value;
// If found skip to next month
continue 2;
}
}
$fullmonths['XX/'.sprintf('%02d', $i).'/2018'] = 0;
}
demo
Kind of what you were already doing.
If you want to re:use the original array, just change $months to $array.
$array = [
"1528840800" => 50,
"1531173600" => 37,
"1540940400" => 44,
"1543532400" => 9
];
$months = [];
for ($i=1;$i <= 12;$i++) {
foreach($array as $time => $value) {
$date = date("n", $time);
if ($date == $i) {
$months[$time] = $value;break;
} else {
$months[$i] = 0;
}
}
}
var_dump($months);
If you need Zero padding to the months, simply add str_pad() to the [$i], like these:
[str_pad($i, 2, "0", STR_PAD_LEFT)]
You can try something like this using STR_PAD_LEFT and update the key.
$mainArray=array();
$output = array('1528840800' => '50', '1531173600' => '37', '1540940400' => '44', '1543532400' => '9');
for ($i=1; $i <= 12; $i++)
{
$value = str_pad($i, 2, "0", STR_PAD_LEFT);
$mainArray[$value] = 0; //set Everykey to Zero
}
foreach ($output as $key => $value)
{
$joy = gmdate("m", $key);
$mainArray[$key]=$value; //update the key
unset($mainArray[$joy]);
}

PHP get closest time to given array of times [duplicate]

This question already has answers here:
How to get closest date compared to an array of dates in PHP
(6 answers)
Closed 3 years ago.
I have an array called $timeslots with timeslots like:
array:32 [▼
0 => "2018-12-15T12:00:00.0000000"
1 => "2018-12-15T12:15:00.0000000"
2 => "2018-12-15T12:30:00.0000000"
3 => "2018-12-15T12:45:00.0000000"
4 => "2018-12-15T13:00:00.0000000"
5 => "2018-12-15T13:15:00.0000000"
6 => "2018-12-15T13:45:00.0000000"
7 => "2018-12-15T14:15:00.0000000"
8 => "2018-12-15T14:30:00.0000000"
9 => "2018-12-15T14:45:00.0000000"
10 => "2018-12-15T15:00:00.0000000"
11 => "2018-12-15T15:15:00.0000000"
12 => "2018-12-15T15:30:00.0000000"
13 => "2018-12-15T15:45:00.0000000"
14 => "2018-12-15T16:15:00.0000000"
15 => "2018-12-15T16:45:00.0000000"
16 => "2018-12-15T17:00:00.0000000"
17 => "2018-12-15T17:30:00.0000000"
18 => "2018-12-15T17:45:00.0000000"
19 => "2018-12-15T18:30:00.0000000"
20 => "2018-12-15T18:45:00.0000000"
21 => "2018-12-15T19:15:00.0000000"
22 => "2018-12-15T19:45:00.0000000"
23 => "2018-12-15T20:15:00.0000000"
24 => "2018-12-15T20:45:00.0000000"
25 => "2018-12-15T21:00:00.0000000"
26 => "2018-12-15T21:15:00.0000000"
27 => "2018-12-15T21:30:00.0000000"
28 => "2018-12-15T21:45:00.0000000"
29 => "2018-12-15T22:00:00.0000000"
30 => "2018-12-15T22:15:00.0000000"
31 => "2018-12-15T22:30:00.0000000"
]
Also, I have a variable like:
$expected_time = 2018-12-15T18:00:00.0000000; // this can be different value, so its not unique value
$expected_time is never into array $timeslots but I need to find closest value to $expected_time... How I can do that?
How I can get the closest timeslot value from array $timeslots to $expected_time and calculate the difference in minutes?
Any idea?
As Nico mentioned in the comments, it's pretty straightforward. Just looping and calculating the time difference.
$timeslots = [...];
$expected_time = "2018-12-15T18:00:00.0000000";
$timestamp = strtotime($expected_time);
$diff = null;
$index = null;
foreach ($timeslots as $key => $time) {
$currDiff = abs($timestamp - strtotime($time));
if (is_null($diff) || $currDiff < $diff) {
$index = $key;
$diff = $currDiff;
}
}
echo $timeslots[$index];
Here is one solution fitting your requirements:
function findClosestDate($expectedDate,$dates)
{
$differenceInMinutes = null;
$expectedDate = new DateTime($expectedDate);
$expectedDateEpoch = $expectedDate->getTimestamp();
$returnIndex = -1;
for($i = 0; $i<count($dates); $i++)
{
$dateObject = new DateTime($dates[$i]);
$dateEpoch = $dateObject->getTimestamp();
$difference = abs($expectedDateEpoch-$dateEpoch);
$difference = $difference/60;
if($differenceInMinutes === null || $difference < $differenceInMinutes)
{
$differenceInMinutes = $difference;
$returnIndex = $i;
}
}
return array(
"closest" => $dates[$returnIndex],
"difference" => $differenceInMinutes
) ;
}
This makes use of the DateTime class to create a DateTime object and get the respective timestamp. The minutes are then calculated by the absolute difference between the expectedDate and the entry in the dates array. After iterating over the whole array, the closest match and the difference is returned in one array.
as your list is already sorted - u can put the element into array and use sort again - and it will be much faster then calculating the diff in each iteration.
<?php
$timeslots = [
...
];
$expected_time = "2018-12-15T18:00:00.0000000";
$counter = count($timeslots);
$timeslots = array_flip($timeslots);
$timeslots[$expected_time] = $counter;
ksort($timeslots);
while (key($timeslots) !== $expected_time) {
$prev = key($timeslots);
next($timeslots);
}
next($timeslots);
$next = key($timeslots);
$expected_time = new \DateTime($expected_time);
$closestDiff = min(($expected_time)->diff(new \DateTime($prev)), (new \DateTime($next))->diff($expected_time));
var_dump($closestDiff->i);

PHP How To Calculate Yearly Increase by Given Start and End Year

By given 2 range of year, current population and target population, how to get total population every year by using PHP?
Example:
Year | Population
2014 | 100000
2018 | 132000
On paper calculation like this:
132000 / 100000 = 1.0718
so we will get result every year (On paper):
2014 = 100000
2015 = 107187 (100000 * 1.0718)
2016 = 114890 (107187 * 1.0718)
2017 = 123147 (114890 * 1.0718)
2018 = 132000
How to hold previous year variable to get result as above?
This is my PHP code:
for($i > $start; $i < $end; $i++) {
$this->ProjectPopulation->create();
$increase = array(
'project_id' => $project_id,
'year' => $i,
'percent_increase' => $this->percentage_increase($current_population, $target_population, $year),
'population' => ??? // Problem here
);
$this->ProjectPopulation->save($increase);
}
Thanks
There are two resources I'd recommend you taking a look at:
http://php.net/manual/en/ref.math.php
and
http://www.w3schools.com/php/php_ref_math.asp
You can solve this by doing the calculation each time, but it would be faster to use a loop in order to iterate through them all.
So something like this:
$population = 100000;
$year = 2014;
//I'd print the first one out prior to the loop, or you could put an if($year == 2014) in the loop, your choice really.
for(i= 0; i < 4; i++)
{
//do calculation in here.
echo "The current years is" . $year;
$yearsCalculation = $population * 1.0718;
//then save that value for the next time around the loop.
$population = $yearsCalculation ;
echo $yearsCalculation ;
//increase years each time round loop
$year++;
}
If you then want to store it in a MySQL database you might want to have a look at this tutorial:
http://www.w3schools.com/php/php_mysql_insert.asp
Hope that helped!
Solve
private function power($current_population, $target_population, $year) {
$devide = $target_population / $current_population;
$pwrdevider = 1 / $year;
$power = pow($devide, $pwrdevider);
return $power;
}
private function percentage_increase($current_population, $target_population, $year) {
$devide = $target_population / $current_population;
$power = pow($devide, 1 / $year);
$increase = ($power - 1) * 100;
return $increase;
}
$start = 2014;
$end = 2018;
$diff = $end - $start;
for($i = 1, $data = 100000; $i <= $diff; $i++) {
$data *= $this->power(100000, 132000, $diff);
$increase = array(
'project_id' => 1,
'year' => $start += 1,
'percent_increase' => $this->percentage_increase(100000, 132000, $diff),
'population' => $data
);
print_r($increase);
}
This is my result
Array
(
[project_id] => 1
[year] => 2015
[percent_increase] => 7.1873373728262
[population] => 107187.33737283
)
Array
(
[project_id] => 1
[year] => 2016
[percent_increase] => 7.1873373728262
[population] => 114891.25293076
)
Array
(
[project_id] => 1
[year] => 2017
[percent_increase] => 7.1873373728262
[population] => 123148.87489076
)
Array
(
[project_id] => 1
[year] => 2018
[percent_increase] => 7.1873373728262
[population] => 132000
)
Thanks all

Check for overlapping times on the same date in an array?

I have an array that is produced from people wanting to reserve a time block to volunteer with our organization. I want to check to see if they chose time blocks on the same day that overlap. In my example array below the first and third elements are overlapping and I need to detect that. Any recommendation would be much appreciated:
Array
(
[0] => Array
(
[id_pc_time_blocks] => 3
[id_pc] => 2
[pc_date] => 2012-11-21
[pc_time_block] => 9:00 AM-1:00 PM
[pc_time_block_max] => 25
[pc_time_block_count] => 0
[pc_name] => Atlanta
)
[1] => Array
(
[id_pc_time_blocks] => 4
[id_pc] => 2
[pc_date] => 2012-11-21
[pc_time_block] => 1:00 PM-5:00 PM
[pc_time_block_max] => 25
[pc_time_block_count] => 10
[pc_name] => Atlanta
)
[2] => Array
(
[id_pc_time_blocks] => 6
[id_pc] => 2
[pc_date] => 2012-11-21
[pc_time_block] => 10:00 AM-2:00 PM
[pc_time_block_max] => 25
[pc_time_block_count] => 0
[pc_name] => Atlanta
)
[3] => Array
(
[id_pc_time_blocks] => 6
[id_pc] => 2
[pc_date] => 2012-11-23
[pc_time_block] => 10:00 AM-2:00 PM
[pc_time_block_max] => 25
[pc_time_block_count] => 0
[pc_name] => Atlanta
)
[4] => Array
(
[id_pc_time_blocks] => 6
[id_pc] => 2
[pc_date] => 2012-11-23
[pc_time_block] => 3:00 AM-6:00 PM
[pc_time_block_max] => 25
[pc_time_block_count] => 0
[pc_name] => Atlanta
)
)
Not recommended for HUGE arrays, but here's a quick solution. You need to break hte times into unix time stamps for comparisson
// Run down each element of the array. (I've called it MyStartArray)
$numElements = count($MyStartArray);
for ($i=0; $i<$numElements ; $i++) {
// Calculate "Start Time" and "End Time" as Unix time stamps (use mktime function) and store as another items in the array
// You can use preg_match or substr to get the values to pump into mktime() below - not writing hte whole thing for you ;)
$MyStartArray[$i]['start_time'] = mktime( ... );
$MyStartArray[$i]['end_time'] = mktime( ... );
// Now run through all the previous elements to see if a start time is before the end time, or an end time is after the start time.
if ($i > 0) {
for ($j=0; $j<$i;$j++) {
if ($MyStartArray[$i]['start_time'] < $MyStartArray[$j]['end_time'] ||
$MyStartArray[$j]['end_time'] > $MyStartArray[$j]['start_time'] ) {
echo 'CLASH';
}
}
}
}
Here is my solution for checking each date for overlapping times. The only thing is, this is for my particular scenario and does not account for overlapping years as I dont have that need for this application.
Here is my working example:
$dateIdx = 0;
foreach($timeblocks_array as $obj) {
$timeblocks_array[$dateIdx]["intDay"] = idate("z",strtotime($obj["pc_date"]));
$timeblocks_array[$dateIdx]["intStart"] = intval($obj["start_time"]);
$timeblocks_array[$dateIdx]["intEnd"] = intval($obj["end_time"]);
$mindates[] = idate("z",strtotime($obj["pc_date"]));
$dateIdx++;
}
$minDateSingle = min($mindates);
$maxDateSingle = max($mindates);
$currentDate = $minDateSingle;
$dateIdx = 0;
while ($currentDate <= $maxDateSingle) {
$hrIndex = 0;
while ($hrIndex < 24) {
$matrixArray[$dateIdx][$hrIndex]["count"] = 0;
$matrixArray[$dateIdx][$hrIndex]["intDay"] = $currentDate;
$hrIndex++;
}
// calculate counts:
$hourIdx = 0;
foreach($matrixArray[$dateIdx] as $hour){
foreach($timeblocks_array as $block) {
if ($hour["intDay"] == $block["intDay"]) {
if ($hourIdx >= $block["intStart"] && $hourIdx < $block["intEnd"]) {
$matrixArray[$dateIdx][$hourIdx]["count"] = $matrixArray[$dateIdx][$hourIdx]["count"] + 1;
$matrixArray[$dateIdx][$hourIdx]["requests"][] = $block;
}
}
}
$hourIdx++;
}
$dateIdx++;
$currentDate = $currentDate + 1;
}
//loop through the matrix array and timeblocks array to see if they intersect
foreach($matrixArray as $day) {
$hourIdx = 0;
foreach($day as $hour) {
if ($hour["count"] > 1) {
//echo $hour["intDay"]." - Overlap on Hour $hourIdx\n";
$smarty->assign('overlappingError', 1);
$error = 1;
foreach($hour["requests"] as $overlapblock) {
//echo " --> conflict: ". $overlapblock["pc_date"]." ".$overlapblock["pc_time_block"]." (".$overlapblock["intStart"]." to ".$overlapblock["intEnd"].")\n";
}
} else if ($hour["count"] == 1) {
// these are valid hours
}
$hourIdx++;
}
}
Robbie's answer did not work for me. I found the rules that needed to be in place going off his example for just dates were:
$i[start] needs to be less than and not equal to $i[stop]
$i[start] needs to greater than and not equal to $j[stop]
$j[start] needs to be less than and not equal to $j[stop]
Therefore my solution was:
$numElements = count($dates);
for ($i=0; $i<$numElements; $i++) {
$dates[$i]['start_time'] = strtotime($dates[$i]['start']);
$dates[$i]['end_time'] = strtotime($dates[$i]['end']);
if ($i > 0) {
for ($j=0; $j<$i;$j++) {
if($dates[$i]['start_time'] >= $dates[$i]['end_time'] || $dates[$i]['start_time'] <= $dates[$j]['end_time'] || $dates[$j]['start_time'] >= $dates[$j]['end_time']) {
$this->set_error(['dates_overlap']);
$this->dates_overlap = true;
break;
}
}
}
if(isset($this->dates_overlap))
break;
}

php round/ceil/floor how to make a number to Multiples of 7

Firstly poor of my mathematica. I tried to use php to make a number to Multiples of 7. the rules as below:
$num >=0;
$num = '0'; => output '7'
$num = '1'; => output '7'
$num = '6'; => output '7'
$num = '8'; => output '14'
$num = '14'; => output '14'
$num = '16'; => output '21'
$num = '20'; => output '21'
$num = '40'; => output '42'
$num = '84'; => output '84'
...
I cost many times, but I am not smart to solve this by myself. such as
echo round(($num*7-1)/7); // not a right answer.
any one is kindly help me? Thanks.
Your requirements are not consistent if the output for 0 is 7; 0 is already a multiple of 7, since 0 * 7 = 0.
echo ceil($num / 7) * 7;
Alternatively, use the modulus operator:
$m = $num % 7;
echo $m == 0 ? $num : $num - $m + 7;
Try ceil($num / 7) * 7. The code:
<?php
for ($i = 0; $i < 50; $i++) {
echo get_number($i) . "\n";
}
function get_number($num) {
return ceil($num / 7) * 7;
}
?>
Produces:
0 => 0
1 => 7
2 => 7
3 => 7
4 => 7
5 => 7
6 => 7
7 => 7
8 => 14
9 => 14
10 => 14
11 => 14
12 => 14
13 => 14
14 => 14
15 => 21
...
46 => 49
47 => 49
48 => 49
49 => 49
One possibility is to use modulo arithmetic, e.g.:
$x = $whatever;
while($x % 7 != 0){
$x++
}
echo $x; // will now be next multipe of seven >= $whatever

Categories