I have several date(strtotime) in a Variable and want the first nearest date that is after the specified date(my date) with php. what do i do?
Variable:
$varD = "1481691600,1482642000,1482037200";
my date:
1481778000 => (2016-12-15)
several date(strtotime):
1481691600 => (2016-12-14)
1482642000 => (2016-12-25)
1482037200 => (2016-12-18) //result
result:
1482037200 => (2016-12-18)
$varD = "1481691600,1482037200,1482642000";
$myDate = "1481778000";
After you explode the string of timestamps ($varD), you can filter them and return the minimum value of the result. Here is one way to do that using array_filter and min.
$comp = function($x) use ($myDate) { return $x > $myDate; };
$firstDateAfterYours = min(array_filter(explode(',', $varD), $comp));
But if you already know that the timestamps in the string will be in ascending order, it will probably be faster not to convert the whole thing to an array and sort through it. You can use strtok to go through it piece by piece and just stop as soon as you get to a timestamp larger than your target.
$ts = strtok($varD, ',');
while ($ts !== false) {
$ts = strtok(',');
if ($ts > $myDate) break;
}
$firstDateAfterYours = $ts;
Related
I am trying to make a really basic day booking system and need to return all dates within a range, and then remove selected dates from that range. I tried the following code but realised that will remove duplicates which is fine, but I also need that date to be removed too.
Can anyone suggest a good way of doing this?
In the below example I am just hoping to see:
2022-04-03T00:00:00.000000Z
2022-04-04T00:00:00.000000Z
2022-04-05T00:00:00.000000Z
$start_date = "2022-04-01";
$end_date = "2022-04-05";
$datesToRemove = [
'2022-04-01T00:00:00.000000Z',
'2022-04-02T00:00:00.000000Z'
];
$range = Carbon::parse($start_date)->toPeriod($end_date)->toArray();
$available = array_unique(array_merge($range, $datesToRemove));
return $available;
To compare it is necessary to have the compared values in the same format. I decide to morph the $datesToRemove to Carbon format. The you can use to nested loops and check with PHP in_array() function.
$start_date = "2022-04-01";
$end_date = "2022-04-05";
$datesToRemove = [
"2022-04-01T00:00:00.000000Z",
"2022-04-02T00:00:00.000000Z"
];
$range = \Carbon\Carbon::parse($start_date)->toPeriod($end_date)->toArray();
$datesToRemove2 = [];
foreach($datesToRemove as $r) {
$datesToRemove2[] = \Carbon\Carbon::parse($r);
}
$res = [];
foreach($datesToRemove2 as $index => $d1) {
if(in_array($d1, $range)) {
unset($range[$index]);
}
}
return $range;
output
{
"2":"2022-04-03T00:00:00.000000Z",
"3":"2022-04-04T00:00:00.000000Z",
"4":"2022-04-05T00:00:00.000000Z"
}
Means that
I have array like this:
arr=[
627=[
'lead_data'=>['name'=>'Name1', 'date'=>'2019-04-09']
],
500=[
'lead_data'=>['name'=>'Name2', 'date'=>'2018-05-07']
],
534=[
'lead_data'=>['name'=>'Name3', 'date'=>'2019-07-10']
],
100=[
'lead_data'=>['name'=>'Name4', 'date'=>'2019-05-12']
],
]
How can I filter this array where date is between 2019-05-01 and 2019-07-12.
So in result there will be elements with ids 534 and 100.
Or date is >= 2019-07-05 or date is <= 2019-01-01 ?
I know there is array_filter function, but cant understand how to use it in thus case? Please help, thanks
The simplest solution would to just iterate over your data like so:
<?php
$begin = date('Y-m-d', strtotime("2019-05-01"));
$end = date('Y-m-d', strtotime("2019-07-12"));
foreach($array as $key => $data)
{
$date = date('Y-m-d', strtotime($$data['date']));
if (($$data > $begin) && ($date < $end)){
unset($array[$key]);
}
}
var_dump($array);
Always make sure you check out official documentation on php.net because it usually have tons of examples and very thorough explanations.
In your case you can compare dates as strings (since they are in Y-m-d format and comparing them alphabetically will do the trick):
$filtered = array_filter($arr, function ($item) {
return ($item['lead_data']['date'] > '2019-05-01') && ($item['lead_data']['date'] < '2019-07-12');
});
By using array_filter(), and using the use keyword, you can supply variables into the filter - this can be the start- and end-dates for your limits.
When using array_filter(), the data will remain in the array if the return value inside the callback is true, otherwise it will be removed. So then compare the dates, and see if they are greater than $from, and less than $to.
$from = '2019-05-01';
$to = '2019-07-12';
$result = array_filter($arr, function ($v) use ($from, $to) {
return $v['lead_data']['date'] > $from && $v['lead_data']['date'] < $to;
});
print_r($result);
Live demo at https://3v4l.org/Cmt8H
I want sorting multidimensional array. But I must to change format value to sorting before then get back format in beginning.
This my array (multidimensional)
$db = [['1','00:01:13.145'], ['2','00:02:19.145'],
['3','00:02:13.235'], ['4','00:01:44.020'],
['5','00:02:25.035'], ['6','00:01:11.031']];
For example can help you to answer, I Know a part how to sorting array time and to get format back again:
This my array (single)
$db2 = ['00:01:13.145','00:02:19.145',
'00:02:13.235','00:01:44.020',
'00:02:25.035','00:01:11.031'];
Function to sorting this
$rep = str_replace(':','', str_replace('.','', $db2));
echo arr($rep);
function arr($array) {
$return = array();
foreach($array as $row) {
$return[] = (int)$row;
sort($return);
}
return $return;
}
The output will be
Array ( [0] => 111031 [1] => 113145 [2] => 144020 [3] => 213235 [4] => 219145 [5] => 225035 )
Second, I know how to get format again, example:
$int = 111031;
$str = substr_replace(substr_replace($int,".",-3,-3),":",-6,-6);
echo substr_replace($str,'00:0',-9,-9);
from (int)111031 the output will be 00:01:11.031
Pleas help me to solve this
This should work for you:
Here we simply use usort() to use our own custom compare function. In this function we first explode() the time by a dot, so we get the time and the milliseconds separately. After this we convert the time into a timestamp with strtotime() and multiply it by 1,000 so we can add the milliseconds to it.
With this we have converted the time into milliseconds and we can simply compare the numbers and sort by the milliseconds.
Code:
<?php
$db = [
['1','00:01:13.145'], ['2','00:02:19.145'],
['3','00:02:13.235'], ['4','00:01:44.020'],
['5','00:02:25.035'], ['6','00:01:11.031']
];
usort($db, function($a, $b){
list($timeOne, $millisecondsOne) = explode(".", $a[1]);
list($timeTwo, $millisecondsTwo) = explode(".", $b[1]);
$millisecondsOne = strtotime($timeOne) * 1000 + $millisecondsOne;
$millisecondsTwo = strtotime($timeTwo) * 1000 + $millisecondsTwo;
if($millisecondsOne == $millisecondsTwo)
return 0;
return $millisecondsOne > $millisecondsTwo ? 1 : -1;
});
print_r($db);
?>
How can I use array_push to add a timestamp and a value to a two-dimensional array with square bracket syntax?
I successfully get rows, each with a timestamp and associated value from a mysql database.
While retrieving the results, I add these times and values into an array like so:
while($row=mysqli_fetch_array($r, MYSQLI_ASSOC)){
$q1_array[$i][0]= $row["time"];
$q1_array[$i][1]= $row["val"]; // the value ("val") will either be 1 or 0 (ON or OFF)
$i++;
}
I need the final array to contain an even number of elements (which will be within a time interval of 30 minutes), so I test for that:
If the LAST array element(s?) has a timestamp and associated value of 1, I want to append at the end of the array the ending half-hour timestamp along with a 0.
if ($q1_array[sizeof($q1_array)-1][1] == 1){
//here I want to append a timestamp and value
}
On the other hand, if the FIRST element(s?) has a timestamp with associated value of 1, I want to append at the beginning of the array the starting half-hour timestamp along with a 0.
else if ($q1_array[0][1]== 1){
//here I want to append a timestamp and value
}
Really would appreciate help! Thank you!
To add a new row to the end of the array, write:
$new_row = array($timestamp, 0);
$q1_array[] = array($timestamp, 0);
To insert at the beginning of the array, use array_splice:
array_splice($q1_array, 0, 0, $new_row);
For your specific question:
//process first element
if($q1_array[0][1] == 1){
$time = roundTime($q1_array[0][0], 'start');
$newElement = array( $time, 0 );
array_unshift($q1_array, $newElement);
}
//process last element
$len = count($q1_array) - 1;
if($q1_array[$len][1] == 1){
$time = roundTime($q1_array[$len][0], 'end');
$newElement = array( $time, 0 );
array_push($q1_array, $newElement);
}
//rounding function
//$timeIn = unix timestamp, $direction = 'start' or 'end'
function roundTime($timeIn , $direction){
$tUnit = 1800; //seconds in half-hour
if ($direction == 'start'){
$output = floor($timeIn / $tUnit) * $tUnit;
} else {
$output = ceil($timeIn / $tUnit) * $tUnit;
}
return $output;
}
This works with unix timestamp format. If using MySQL datetime you'll need to convert accordingly.
I need to add a zero to the date value that is posted as the MySQL date value will be used as a directory path to show added photos. Currently the directory is saved as 2012-2-5 and the MySQL entry is 2012-02-05.
I have tried the following, however it doesn't seem to be working:
$dates = array($_POST['photos_year'], $_POST['photos_month'], $_POST['photos_day']);
foreach($dates as $date) {
if (strlen($date) == 1) {
$date = '0' . $date;
}
}
$photos->date = $dates[0] . "-" . $dates[1] . "-" . $dates[2];
I am using a for loop to create the date form, it might be easier for me to edit this however I haven't had any success:
<select name="photos_month" id="photos_month" tabindex="3">
<option value ="">- Month -</option>
<?php
for($date=01;$date<=12;$date++) {
if (isset($photos) && $date==$month) {
echo "<option value='".$date."' selected='selected'>".$date."</option>";
} else {
echo "<option value='".$date."'>".$date."</option>";
}
}
?>
</select>
You need to update the foreach to be
foreach ($dates as &$date)
Currently, $date is a new symbol and will not overwrite the value. That should fix it, but it may be nice to have the correct strings in the options too. You can use str_pad to do that.
When doing a foreach, the element variable $date is a new variable, a copy of the value from the array. You should use a key and update the original array.
foreach($dates as $key => $date) {
if (strlen($date) == 1) {
$dates[$key] = '0' . $date;
}
}
Also, you're running that code on the year, you don't want to be adding a zero to the year, only the month and day.
You could make it a little simpler by just using sprintf with a format string;
$photos_year = '2012';
$photos_month = '2';
$photos_day = '5';
$result = sprintf("%4d-%02d-%02d", $photos_year, $photos_month, $photos_day);
// $result = '2012-02-05'
Check out the string pad function http://php.net/manual/en/function.str-pad.php
Along with the array map function http://php.net/manual/en/function.array-map.php
Using these two together would allow for you to go through each part of the date(array_map) and pad the value with a 0 (using str_pad)
Code would look something like this
$dates = array_map("padString",$dates);
function padString($string) {
return str_pad($string,2,"0",STR_PAD_LEFT);
}
print_r($dates);
//Gives you Array ( [0] => 2012 [1] => 02 [2] => 05 )
use sprintf()
For example:
$date = sprintf('%02d', $_POST['photos_day']);