I am trying to remove exactly 1 year from every date of an array.
Here is the original $periods array
Array ( [0] => 2020-06-01 [1] => 2020-07-01 [2] => 2020-08-01 [3] => 2020-09-01 [4] => 2021-01-01 [5] => 2022-01-01 [6] => 2022-06-01 [7] => 2022-08-01 [8] => 2022-10-01 [9] => 2023-04-01 )
I tried
foreach ($periods as $p) {
date_sub($p,date_interval_create_from_date_string("1 year"));
echo date_format($p,"Y-m-d"). '<br>';
}
It doesn't return anything...
Any pointers would be appreciated.
First set your array values datatype to string => "2020-06-01" , and try this code:
foreach ($periods as $period) {
// convert date string to date model object
$periodDate = date_create($period);
// subtract date string from coverted date string
date_sub($periodDate,date_interval_create_from_date_string("1 year"));
// covert subtracted date object to readable date fromat
echo date_format($periodDate,"Y-m-d");
}
You can transform dates using next code:
$res = array_map(
// convert source string to time, subtract 1 year interval
// and convert to 'Y-m-d' format in singe function
fn($p) => date('Y-m-d', strtotime("-1 year", strtotime($p))),
$periods
);
run PHP online
Related
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
)
)
Please sort the below array by its index(date). I want to sort the below array by ASC order by its date. After sorting the first one will be 2020-06-29 and its array, then 2020-06-30, I have tried more sorting mechanism but it could not solve the issue. Please help me to sort out this issue
Array(
[2020-07-01] => Array
(
[0] => Array
(
[slot] => 09:00 AM-11:00 AM
[is_available] => 1
[slot_id] => 29
)
)
[2020-06-29] => Array
(
[0] => Array
(
[slot] => 02:16 AM-02:16 AM
[is_available] => 1
[slot_id] => 14
)
)
[2020-06-30] => Array
(
[0] => Array
(
[slot] => 09:00 AM-06:00 PM
[is_available] => 1
[slot_id] => 15
)
)
[2020-07-02] => Array
(
[0] => Array
(
[slot] => 10:00 AM-05:00 PM
[is_available] => 1
[slot_id] => 35
)
)
[2020-07-03] => Array
(
[0] => Array
(
[slot] => 10:00 AM-03:00 PM
[is_available] => 1
[slot_id] => 36
)
)
)
Try ksort
here is a short example :
<?php
$fruits = array("d"=>"lemon", "a"=>"orange", "b"=>"banana", "c"=>"apple");
ksort($fruits);
foreach ($fruits as $key => $val) {
echo "$key = $val\n";
}
?>
https://www.php.net/manual/en/function.ksort.php
EDIT :
Since ksort seems to not be working, you should use uksort.
function date_compare($a, $b)
{
$t1 = strtotime($a);
$t2 = strtotime($b);
return $t1 - $t2;
}
uksort($data, 'date_compare');
here is a working example :
https://repl.it/repls/FoolhardyDrabPolygon
Step 1 : Create a function which accepts two dates ( strings ) as parameters, this function returns 1 if first date is greater than the second, it returns -1 if second date > first date or 0 if date's are equal. Working of functions starts from Step 2.
Step 2 : Toeknize the strings to get respective year, month and day of the two dates respectively. [ see : https://www.php.net/manual/en/book.tokenizer.php ]
Step 3 : If first date's year > second date's year, return 1 . If second date's year > first date's year return -1, if they are equal proceed to Step 4.
Step 4 : If first date's month > second date's month, return 1 . If second date's month > first date's month return -1, if they are equal proceed to Step 5.
Step 5 : If first date's day > second date's day, return 1 . If second date's day > first date's day return -1, if they are equal return 0.
Now use php's usort function and pass your function in it
[see : https://www.php.net/usort ]
I have an input array which contains arrays of day and time data:
$temp = Array
(
[0] => Array
(
[day] => Tuesday
[time] => 07:44 pm - 08:44 pm
)
[1] => Array
(
[day] => Tuesday
[time] => 04:00 am - 04:25 am
)
[2] => Array
(
[day] => Sunday
[time] => 04:00 am - 04:25 am
)
[3] => Array
(
[day] => Sunday
[time] => 04:00 am - 04:25 am
)
[4] => Array
(
[day] => Friday
[time] => 04:00 am - 04:25 am
)
[5] => Array
(
[day] => Friday
[time] => 04:00 am - 04:25 am
)
)
Now I want to group the common times display as one element and if the time is the same for more than one day then it's should display one entry. So what is the best way to achieve the desired result without making this too complex?
Array
(
[0] => Array
(
[day] => Tuesday
[time] => 04:00 am - 04:25 am & 07:44 pm - 08:44 pm
)
[1] => Array
(
[day] => Friday & Sunday
[time] => 04:00 am - 04:25 am
)
)
Here it's what I have done:
$final = [];
foreach ($temp as $val) {
$final[strtolower($val['day'])][] = $val['time'];
}
foreach ($final as $k => $v) {
sort($v);
$v = array_unique($v);
$last = array_pop($v);
$final[$k] = [
'day' => $k,
'time' => count($v) ? implode(", ", $v) . " & " . $last : $last,
];
}
There are 4 basic steps:
Remove duplicate rows.
Sort all rows by day (via lookup) ASC, then time (as a string) ASC.
Store joined time values using day values as temporary keys.
Store joined day values using joined time values as temporary keys.
Code: (Demo)
$array=[
['day'=>'Tuesday','time'=>'07:44 pm - 08:44 pm'],
['day'=>'Tuesday','time'=>'04:00 am - 04:25 am'],
['day'=>'Sunday','time'=>'04:00 am - 04:25 am'],
['day'=>'Sunday','time'=>'04:00 am - 04:25 am'],
['day'=>'Friday','time'=>'04:00 am - 04:25 am'],
['day'=>'Friday','time'=>'04:00 am - 04:25 am']
];
$array=array_unique($array,SORT_REGULAR); // remove exact duplicate rows
$order=array_flip(['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']); // lookup array
usort($array,function($a,$b)use($order){ // sort by day name ASC then time ASC
if($order[$a['day']]==$order[$b['day']]){
return $a['time']<=>$b['time']; // 2nd sort criteria: time string
}
return $order[$a['day']]<=>$order[$b['day']]; // 1st sort criteria: day name via lookup array
});
foreach($array as $row){
if(!isset($temp[$row['day']])){
$temp[$row['day']]=$row['time']; // store time for first occurring day
}else{
$temp[$row['day']].=" & {$row['time']}"; // join times (for pre-existing day) as they are found
}
}
foreach($temp as $day=>$times){
if(!isset($result[$times])){
$result[$times]=['day'=>$day,'time'=>$times]; // store first occurring day and time using time as temp key
}else{
$result[$times]['day'].=" & $day"; // join day names as they are found
}
}
var_export(array_values($result)); // optionally remove the temporary keys
Output:
array (
0 =>
array (
'day' => 'Tuesday',
'time' => '04:00 am - 04:25 am & 07:44 pm - 08:44 pm',
),
1 =>
array (
'day' => 'Friday & Sunday',
'time' => '04:00 am - 04:25 am',
),
)
Here is another version that doesn't call array_unique(), but I don't like it as much because it does iterated sort() calls and generates a deeper temporary array.
foreach($array as $row){
$temp[$row['day']][$row['time']]=$row['time']; // remove duplicates and group by day
}
$order=array_flip(['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']); // lookup array
uksort($temp,function($a,$b)use($order){
return $order[$a]<=>$order[$b]; // sort by day name via lookup array
});
foreach($temp as $day=>$times){
sort($times); // sort time elements ASC
$time_key=implode(' & ',$times); // join the day's time elements
if(!isset($result[$time_key])){ // if first occurrence of the time string
$result[$time_key]=['day'=>$day,'time'=>$time_key]; // store data using time string as temp key
}else{
$result[$time_key]['day'].=" & {$day}"; // concatenate new day to day element
}
}
var_export(array_values($result));
I have some date, like:
20 November 06:10
12 November 08:12
10 October 13:23
There all in the past 6 months, Now I want to strtotime() them, but they are all un complete (lack of year), how to make some process so that I could strtotime() them?
Try this:
$dates = array("10 October 13:23", "12 November 08:12", "10 October 13:23");
foreach($dates as $d){
$exploded = explode(" ", $d);
$newDate = array_slice($exploded, 0,2,true)+array(2=>"2012")+array(3 => $exploded[2]);
//print_r($newDate);
$time = strtotime(implode($newDate));
echo $time."<br/>";
}
The output i got is:
1349868180
1352704320
1349868180
The logic is:
You lack the year, so I exploded the dates into an array to slice them, insert the year (the +array(2=>"2012") part) and glue them again with implode, and then run the strtotime.
This work only for this year, so you can use this logic to add the year to all your dates, or in the future there will be absolutely no way to filter dates from different years.
I added the dates into an array for loop through all of them, you can use the loop other ways, depending on where you have all your dates stored. For example if they are in a database you can include the script in the while($row = mysqli_fetch_assoc($result)) part where $d would be $row['date'] instead.
You should use the DateTime class and its createFromFormat and getTimeStamp methods instead of strtotime.
print_r(date_parse_from_format("d F H:i", '20 November 06:10'));
gives you:
Array
(
[year] =>
[month] => 11
[day] => 20
[hour] => 6
[minute] => 10
[second] => 0
[fraction] =>
[warning_count] => 0
[warnings] => Array
(
)
[error_count] => 0
[errors] => Array
(
)
[is_localtime] =>
)
I have an array like this:
Array
(
[0] => stdClass Object
(
[Start] => 08:00
[dayName] => Tuesday
[dayID] => 2
[courseName] => Math
)
[1] => stdClass Object
(
[Start] => 10:00
[dayName] => Tuesday
[dayID] => 2
[courseName] => Geography
)
[2] => stdClass Object
(
[Start] => 14:00
[dayName] => Tuesday
[dayID] => 2
[courseName] => Science
)
[3] => stdClass Object
(
[Start] => 10:00
[dayName] => Thursday
[dayID] => 4
[courseName] => Math
)
[4] => stdClass Object
(
[Start] => 18:00
[dayName] => Friday
[dayID] => 5
[courseName] => History
)
)
What I want to do is , I want to compare the daya nd time now to the values in the array. For example lets assume that it is 7:00 am and it is Tuesday. Then I want to get the Object[0]. But if it is 11:00 o'clock then i need to get the Object[2] which starts at 14:00 on Tuesday.
It it is Tuesday and 16:00 o'clock then i need Object[3] .
If it is a weekend then i need the beginning of the week which is Tuesday at 08:00 with the Math Course.
I tried to get that using key => value but I mixed up.
How can I compare the Day and then time and in case there is a Course on that combination just pick it up if not just continue checking.
regards
littleblue
function getObject($array){
$timeNow = date('U'); // time now
$oneHour = $timeNow+3600; // time now + 1 hour
foreach($array as $num => $one){ // loop in each $array
$date = strtotime($one->Start); // convert start time to timestamp
if($date >= $timeNow && $date < $oneHour && date('l', $date) == $one->dayName){ // if all criteria met
return $array[$num]; // return that object
}
}
return array('no data'); // if no criteria is met return no data.
}
$course = getObject($yourArray);
echo $course->courseName;
You can mix the use of DateTime and a simple min search :
$myCourse = null;//initialisation
$myCourseDate =null;
$now = new DateTime;
foreach($array as $course){
//get the date from the datas
$date = DateTime::createFromFormat('l h:i',$course->dayName.' '.course->start);
if($now < $date && ($myCourseDate === null || $myCourseDate > $date)){
$myCourse = $course;
$myCourseDate = $date;
}
}
//at the end of the loop, you've got the expected course