How to get the nearest expiration date, - php

I have this array string :
[
{"expiration": "0000-00", "quantity": -50},
{"expiration": "2023-02", "quantity": 100},
{"expiration": "2022-03", "quantity": 50}
]
how to get the nearest expiration date, means here I need to get the third one 2022-03 and ignore others & also ignore the date that comes with 0000-00
my code:
$minDate = "";
foreach (json_decode($row['items']) as $item) {
if ($item->expiration != "0000-00") {
$minDate = min($item->expiration);
}
}
dd($minDate);

You can try something like this: -
$arr = getNearestExp($row['items']);
print_r($arr);
/**
*To get the Nearest Expiration date
*#input json array of expiration & quantity as
*per the question
*/
function getNearestExp($items){
$items = json_decode($items); // convert the items to json object
$itemArr = [];
foreach($items as $item) {
// exclude the '0000-00' expiration
if($item->expiration != '0000-00'){
$itemArr[strtotime($item->expiration)] = (array)$item;
}
}
// sort the out put array to ASC order to get the smallest value 1st
ksort($itemArr);
// Re indexing the array to proper index keys
$itemArr= array_values($itemArr);
// return the first value of the array
return $itemArr[0];
}

min(), require two values (or more) and return the lowest value. In your case you gave only one. Then, min() cannot compare strings.
You can use several arrays functions such as array_column(), array_filter(), sort() and reset() (Less verbose, but could be less efficient with large data) to achieve this :
$data = json_decode('[
{"expiration": "0000-00", "quantity": -50},
{"expiration": "2023-02", "quantity": 100},
{"expiration": "2022-03", "quantity": 50}
]');
// extract 'expiration', remove '0000-00'
$data = array_filter(array_column($data, 'expiration'), fn($item) => $item != '0000-00');
sort($data);
var_dump(reset($data)); // string(7) "2022-03"
demo (3v4l.org)

Here is another way.
<?php
//Enter your code here, enjoy!
$json = "[{\"expiration\": \"0000-00\", \"quantity\": -50},{\"expiration\": \"2023-02\", \"quantity\": 100},{\"expiration\": \"2022-03\", \"quantity\": 50}]";
$array = json_decode($json);
$currentDate = date_create_from_format('Y-m-d', date("Y-m-d"));
$daysDiff = 365;
$nearest = "";
for($i = 0; $i<count($array); $i ++) {
$v = $array[$i];
$d = explode("-",$v->expiration);
if(checkdate(intval($d[1]),1,intval($d[0]))) {
$date =date_create_from_format('Y-m-d',$d[0]."-".$d[1]."-1");
$dateDiff = (array)date_diff($currentDate, $date);
if($dateDiff["days"] < $daysDiff ) {
$daysDiff = $dateDiff["days"];
$nearest = $v;
}
}
}
var_dump($nearest)
?>
Bit more low key (it's been a while since I've done php)

Related

PHP - get closest date from array

I want to get closest date from $search_date if is not same values in $array['date']. If is same value in $array['date'] I want all array.
Format date is 'Y-m-d'.
Example 1:
$search_date = '2022-12-08';
$array = [{"price":"200","date":"2022-12-12"},{"price":"50","date":"2022-12-10"},{"price":"100","date":"2022-12-10"}]
Return should be: [{"price":"50","date":"2022-12-10"},{"price":"100","date":"2022-12-10"}]
Example 2:
$search_date = '2022-12-08';
$array = [{"price":"200","date":"2022-12-08"},{"price":"50","date":"2022-12-09"},{"price":"100","date":"2022-12-11"}]
Return should be: [{"price":"200","date":"2022-12-08"}]
Example 3:
$search_date = '2022-12-08';
$array = [{"price":"200","date":"2022-12-10"},{"price":"100","date":"2022-12-10"},{"price":"50","date":"2022-12-11"}]
Return should be: [{"price":"200","date":"2022-12-10"},{"price":"100","date":"2022-12-10"}]
Example 4:
$search_date = '2022-12-08';
$array = [{"price":"200","date":"2022-12-08"},{"price":"100","date":"2022-12-08"},{"price":"50","date":"2022-12-08"}]
Return should be: [{"price":"200","date":"2022-12-08"},{"price":"100","date":"2022-12-08"},{"price":"50","date":"2022-12-08"}]
Thank you!
This code calculates the distance in days between $search and each record. It assumes that you want to find closest distance in both future and past.
<?php
/*
Question Author: Catalin Iamandei
Question Answerer: Jacob Mulquin
Question: PHP - get closest date from array
URL: https://stackoverflow.com/questions/74598442/php-get-closest-date-from-array
Tags: php, arrays, laravel, date, php-carbon
*/
$search = '2022-12-10';
$searchObj = new DateTime($search);
$records = json_decode('[{"price":"200","date":"2022-12-10"},{"price":"100","date":"2022-12-10"},{"price":"50","date":"2022-12-11"}]', true);
$distances = [];
foreach ($records as $index => $record) {
$recordObj = new DateTime($record['date']);
$daysDiff = $searchObj->diff($recordObj)->format("%r%a");
$distances[$index] = abs($daysDiff);
}
$minimumDiff = min($distances);
$output = [];
foreach ($distances as $index => $distance) {
if ($distance == $minimumDiff) {
$output[] = $records[$index];
}
}
echo json_encode($output, JSON_PRETTY_PRINT);
Yields:
[
{
"price": "50",
"date": "2022-12-09"
},
{
"price": "100",
"date": "2022-12-11"
}
]
If you only want to search for closest dates in the future, you need to remove the abs() function and then remove all negative entries in the $distances array before using min().
If you want to search for a specific value in your array have you tried
array_search($value, $array);
By this you can search for a specific value in your array
If you want to search the lowest value
try to for looping your array and check if the array is lower than the previous index and if the for loop has ended you have the lowest date
$lowest_date = null;
for ($i = 0; count($i); $i++) {
if ($array['date'] < $lowest_date) {
$lowest_date = $array['date'];
}
}
you dont have mentioned what todo with prior dates, eg. searching for '2022-12-07', how to tread 2022-12-06 and 2022-12-08, as the difference both is 1. You can calculate the datediff for each entry, get the min datediff and output elements with this datediff. eg :
<?php
$SearchDate = new DateTimeImmutable('2022-12-08');
$array = array ('{"price":"200","date":"2022-12-12"}',
'{"price":"50","date":"2022-12-10"}',
'{"price":"100","date":"2022-12-10"}');
$laResult = array();
foreach($array as $jsonO) {
$json = json_decode($jsonO);
$CompareDate = new DateTimeImmutable($json->{'date'});
$interval = date_diff($SearchDate, $CompareDate);
$laThis['date'] = $json->{'date'};
$laThis['diff'] = $interval->format('%a');
$laThis['origin'] = $jsonO;
$laResult[] = $laThis;
}
$min_diff = min( array_column( $laResult, 'diff') );
echo 'nearestDiff:'. $min_diff .PHP_EOL;
foreach($laResult as $laSingleResult) {
if($laSingleResult['diff'] == $min_diff) {
echo $laSingleResult['origin'] .PHP_EOL;
}
}

How to add time which is coming from database in laravel

[
{"duration":"00:01:46"},
{"duration":"00:01:23"},
{"duration":"00:01:56"},
{"duration":"00:03:20"},
{"duration":"00:05:41"},
{"duration":"00:02:08"}
]
[
{"duration":"00:01:32"},
{"duration":"00:03:31"},
{"duration":"00:05:56"},
{"duration":"00:03:56"},
{"duration":"00:03:47"},
{"duration":"00:03:38"},
{"duration":"00:02:26"}
]
This is the duration which is coming from my database column duration and now i want to add/sum of these all so i can display it.
Use DateTime, its add method with DateInterval.
<?php
$a = '[
{"duration":"00:01:46"},
{"duration":"00:01:23"},
{"duration":"00:01:56"},
{"duration":"00:03:20"},
{"duration":"00:05:41"},
{"duration":"00:02:08"}
]';
$b = '[
{"duration":"00:01:32"},
{"duration":"00:03:31"},
{"duration":"00:05:56"},
{"duration":"00:03:56"},
{"duration":"00:03:47"},
{"duration":"00:03:38"},
{"duration":"00:02:26"}
]';
$dataA = json_decode($a);
$dataB = json_decode($b);
function sum(array $data): string {
$sum = new DateTime('00:00');
$start = new DateTime('00:00');
foreach ($data as $row) {
$parts = explode(':', $row->duration);
$start->add(new DateInterval(sprintf('PT%sH%sM%sS', $parts[0], $parts[1], $parts[2])));
}
return $start->diff($sum)->format('%H:%I:%S');
}
var_dump(sum($dataA));
var_dump(sum($dataB));
Output:
string(8) "00:16:14"
string(8) "00:24:46"
Note: you would have to display also days if your duration sums to more than 24 hours.

Php - Sum up the numbers in an array one by one

I have an array;
$arr=array(1100,3150,4430,4430,5170,7450,7450,7450,8230);
I want to show them in graph. I want my Y-Axis as my elements of that array and X-Axis as sum up the numbers until that element. (x1,x1+x2,x1+x2+x3,...)
My graph will be;
Y-Axis : 1100,3150,4430,4430,5170,7450,7450,7450,8230
X-Axis : 1100,4250,8680,13110,18280,25730,33180,40630,48860
But I have no idea about how to do that. Is there anyone who can help me with it ? Thanks.
My entire code:
<?php
echo " ".'<br>'.'<br>';
$arr=array(1100,3150,4430,4430,5170,7450,7450,7450,8230);
$arrtotal=0;
for($i=0; $i<=8; $i++)
{
if ($arr[$i]<100) {
$arr[$i]=$arr[$i];
}
else
{
$arr[$i]=$arr[$i]/1000;
$arr[$i]=(string)$arr[$i];
}
}
function calculate($arr, $output){
switch($output){
case 'mean':
$count = count($arr)+1;
$sum = array_sum($arr);
$total = $sum / $count;
break;
case 'median':
rsort($arr);
$middle = (count($arr) / 2)+1;
$total = $arr[$middle-1];
break;
case 'mode':
$v = array_count_values($arr);
arsort($v);
foreach($v as $k => $v){$total = $k; break;}
break;
}
return $total;
}
function sd_square($x, $total) { return pow($x - $total,2); }
function sd($arr) {
return sqrt(array_sum(array_map("sd_square", $arr, array_fill(0,count($arr), (array_sum($arr) / count($arr)) ) ) ) / (count($arr)-1) );
}
echo ' '.'<br>';
echo "Values: ";
echo json_encode($arr).'<br>';
echo 'Mean: '.calculate($arr, 'mean').'<br>';
echo 'Median: '.calculate($arr, 'median').'<br>';
echo 'Mode: '.calculate($arr, 'mode').'<br>';
echo "Standart Derivation: ".sd($arr);
?>
<!DOCTYPE HTML>
<html>
<head>
<script>
window.onload = function () {
var data = <?php echo json_encode($arr, JSON_NUMERIC_CHECK); ?>;
data = data.map(function (row, index) {
return {
x: index,
y: row
};
});
var chart = new CanvasJS.Chart("chartContainer", {
title: {
text: "Analysis"
},
axisY: {
title: "Variables"
},
data: [{
type: "line",
dataPoints: data
}]
});
chart.render();
}
</script>
</head>
<body>
<div id="chartContainer" style="height: 250px; width: 50%;"></div>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
</body>
</html>
In this code my X-Axis is (0,1,2,3,4,5,6,7,8) and I don't want that.
I'm sorry if I couldn't explain well, English is not my native language.
The simplest way is just to loop over the values, adding the current array value to the previous output value to create the new output value. You can then convert that into an array of [x => y] values using array_combine:
$arr=array(1100,3150,4430,4430,5170,7450,7450,7450,8230);
$out = array($arr[0]);
for ($i = 1; $i < count($arr); $i++) {
$out[$i] = $out[$i-1] + $arr[$i];
}
$arr = array_combine($out, $arr);
print_r($arr);
Output:
Array (
[1100] => 1100
[4250] => 3150
[8680] => 4430
[13110] => 4430
[18280] => 5170
[25730] => 7450
[33180] => 7450
[40630] => 7450
[48860] => 8230
)
Demo on 3v4l.org
to get that one array into 2 arrays of graph co-ordinates, you can do this:
$x = array();
$y = array();
$running_total = 0;
for($i = 0; $i < count($arr); $i++){
$y[$i] = $arr[$i];
$running_total += $arr[$i];
$x[$i] = $running_total;
}
This will give you two arrays; array $x that contains a list of your X-coordinates, and $y, that gives you a list of your Y-coordinates; and you will still have access to your original $arr array, should you need to do further calculations on it. Based on your question, I think that will get you what you need.
However, if you are saying you want 1 array where the X co-ordinates are the array indexes, and the value is the array value itself, for example $y[3150] = 4250, then that is impossible; because you have duplicates in your original list, you cannot use those values as array indexes without ending up overwriting them.
(At least, not without making each array value an array itself, but that is taking things an order of magnitude above where is probably necessary)
Calculating the running total and storing the data as key-value pairs can be achieved with a foreach() and zero function calls.
Although perhaps a little unorthodox, it is valid syntax to use the "addition assignment" operator as the key of the output array. This updates the $previous value and supplies the calculated value as the key.
Code: (Demo)
$arr = [1100,3150,4430,4430,5170,7450,7450,7450,8230];
$result = [];
$previous = 0;
foreach ($arr as $value) {
$result[$previous += $value] = $value;
}
var_export($result);
// same result as #Nick's answer

Using array_sum() filtered from another array

$type=array("debit", "credit", "credit", "credit", "debit");
$amount=array(20,30,40,50,60);
how to array_sum all debit values or all credit values?
expected result:
debit= 20+60 = 80
credit=30+40+50 =120
I've tried to filter it then use array_sum but not working.
function filterDebit($finddebit){
return ($finddebit == "debit");
}
$finaldebit = array_filter($type, 'filterDebit');
echo array_sum($finaldebit);
You can't quite get the sum that way because you aren't actually doing anything with the array of amounts, but you've already gotten pretty close.
You can use array_intersect_key to find the entries in $amount that match the keys in your filtered $types array.
echo array_sum(array_intersect_key($amount, $finaldebit));
If it's possible, I think it would be better to address this problem at some earlier point, so the two sets of associated values don't end up in separate arrays like this, especially if the two arrays came from a database, which would be able to handle this filtering/aggregation more efficiently, but since I don't know the source of the arrays, I don't have a suggestion for that.
Simply you can do like this without any complex logic: (Explanation inline)
$type = array('debit', 'credit', 'credit', 'credit', 'debit');
$amount = array(20, 30, 40, 50, 60);
$sum = array_fill_keys(array_unique($type), 0); // initialize the empty associative array with possible keys from $type array
foreach ($type as $key => $t) {
$sum[$t] += $amount[$key]; // Sum up the values based on keys
}
print_r($sum);
Prints:
Array
(
[debit] => 80
[credit] => 120
)
Note: Make sure your both arrays hold right values. Since both are different there might be some discrepancies if values don't match!
You may go with #Don't Panic's answer, or do it by hand with a for loop
function sumType($type, $amount, $key){
$sum = 0;
for($i = 0; $i < sizeOf($type); $i++){
if ($type[$i] == $key){
$sum += $amount[$i];
}
}
return $sum;
}
$type=array("debit", "credit", "credit", "credit", "debit");
$amount=array(20,30,40,50,60);
echo sumType($type, $amount, 'debit'); // 80
echo sumType($type, $amount, 'credit'); // 120
#Don't Panic is more concrete, but you can do something like this as well.
<?php
$type=array("debit", "credit", "credit", "credit", "debit");
$amount=array(20,30,40,50,60);
function filter_price($types, $amount, $type){
if($type == 'debit'){
$key = 'debit';
}else{
$key = 'credit';
}
$sum = 0;
foreach($types as $index->$type){
if($type == $key){
$sum += $amount[$index];
}
}
return $sum;
}
echo filter_price($type, $amount, 'debit');
echo filter_price($type, $amount, 'credit');
Here's a possibly convoluted way of doing it - not only for debit, but for any unique value in $type:
foreach(array_unique($type) as $flag) {
$i = -1;
${'sum_'.$flag} = array_reduce($amount, function($carry, $item) use($type, &$i, $flag) {
$i++;
return $carry += $type[$i] == $flag ? $item : 0;
}, 0);
}
echo $sum_debit; //80
echo $sum_credit; //120
$types=array("debit", "credit", "credit", "credit", "debit");
$amount=array(20,30,40,50,60);
function getSum ($type, $typeArr, $amountArr) {
$sum = 0;
$r = array_keys($typeArr, $type);
foreach ($r as $idx) {
$sum = $sum + (int)$amountArr[$idx];
}
return $sum;
}
Simply loop over one of the arrays and access the corresponding element in the other array using the current iteration's index. To prevent a Warning while trying to add a value to a result group that hasn't been declared yet, use the null coalescing operator to default the value to 0 before adding the new value.
Code: (Demo)
$types = ["debit", "credit", "credit", "credit", "debit"];
$amounts = [20,30,40,50,60];
$result = [];
foreach ($types as $i => $type) {
$result[$type] = ($result[$type] ?? 0) + $amounts[$i];
}
var_export($result);
Output:
array (
'debit' => 80,
'credit' => 120,
)

how I should compare my data to an array json

I'm having a hard time in comparing day to array
this is my array:
array:2 [
0 => {
"id": 1
"time_in": "08:00:00"
"time_out": "17:00:00"
"days": "["tuesday","thursday","saturday"]"
}
1 => {
"id": 2
"time_in": "09:00:00"
"time_out": "18:00:00"
"days": "["monday","wednesday","friday"]"
}
]
note: days are json data from database
and I have this variable day
$day = 'friday';
I just want to get the array data with 'friday' in their days
please help me on my code I just don't know how I should manipulate it
or what code I will use to get it
I expect to have this output:
$day = 'friday';
1 => {
"id": 2
"time_in": "09:00:00"
"time_out": "18:00:00"
"days": "["monday","wednesday","friday"]"
}
because it has friday in its day
you can use in_array() function, which searches an array for a specific value.
for search $day="friday", i declare another array as $b and put filtering value into it.
Try this:
$array = array(array("id"=>"1","time_in"=>"08:00:00","time_out"=>"17:00:00","days"=>'["tuesday","thursday","saturday"]'),
array("id"=>"2","time_in"=>"09:00:00","time_out"=>"18:00:00","days"=>'["monday","wednesday","friday"]'));
$day = "friday";
$b = array();
foreach ($array as $val) {
if (in_array($day,$val['days'])) {
$b[] = $val;
}
}
print_r($b);
let's say that your JSON data is defined as $json:
$json_array = json_decode($json);
$result = [];
foreach($json_array as $arr){
if(in_array($day,$arr->days)){
$result[] = $arr;
}
}
use in_array to find data in array
foreach($your_array as $obj){
if(in_array($day, $obj->days)){
return $obj;
}
}
<?php
// the day you want
$day = 'friday';
// decode json to php array
$days = json_decode($yourJSONArrayFromDatabase, true);
for ($i=0; $i < count($days); $i++)
{
if (in_array($day, $days[$i]['days'])) {
echo json_encode($days[$i]);
break;
}
}

Categories