How to get distinct months from array containing dates - php

I have an array with dates. ie.
array(
0 => '2016-08-01',
1 => '2016-07-15',
2 => '2016-07-01'
);
I need to get the distinct months in array. ie.
array(
0 => 7,
1 => 8
);
I need it to do a foreach to show: June - Juy - August with the distinct months from the dates array. (That part I know how)

You can reformat the date using a combination of array_map, DateTime, and array_unique to achieve that result.
$arr = array(
0 => '2016-08-01',
1 => '2016-07-15',
2 => '2016-07-01'
);
$dates = array_unique(array_map(function($date) {
return DateTime::createFromFormat('Y-m-d', $date)->format('n');
}, $arr));
var_dump($dates);
array(2) {
[0]=>
string(1) "8"
[1]=>
string(1) "7"
}
Of course, it's important to note this results in two dates like 2015-08-11 and 2016-08-04 both showing up as one value in the array. So it's not entirely clear why you would want to do this, but this will meet your specified requirements.

This is the loop you need :
<?php
$arr = array( '2016-08-01',
'2016-07-15',
'2016-07-01' );
$months = array(); // EMPTY ARRAY FOR MONTHS.
foreach ( $arr as $date ) // VISIT EACH DATE IN ARRAY.
{ $mon = substr( $date,5,2 ); // EXTRACT THE MONTH DIGITS.
if ( ! in_array( $mon,$months ) ) // IF MONTH IS NOT IN ARRAY
array_push( $months,$mon ); // INSERT THE MONTH DIGITS.
}
var_dump( $months );
?>
Edit : display month name :
<?php
$arr = array( '2016-08-01',
'2016-07-15',
'2016-07-01' );
$months = array(); // EMPTY ARRAY FOR MONTHS.
foreach ( $arr as $date ) // VISIT EACH DATE IN ARRAY.
{ $mon = substr( $date,5,2 ); // EXTRACT THE MONTH DIGITS.
if ( ! in_array( $mon,$months ) ) // IF MONTH IS NOT IN ARRAY
{ array_push( $months,$mon ); // INSERT THE MONTH DIGITS.
echo date ("F",mktime( null,null,null,$mon,1 ) ); // ◄ MONTH NAME!!!
}
}
?>
Edit #2 : storing month names in array :
<?php
$arr = array( '2016-08-01',
'2016-07-15',
'2016-07-01' );
$months = array(); // EMPTY ARRAY FOR MONTHS.
foreach ( $arr as $date ) // VISIT EACH DATE IN ARRAY.
{ $mon = date("F",mktime( null,null,null,substr( $date,5,2 ),1 ) ); // EXTRACT MONTH.
if ( ! in_array( $mon,$months ) ) // IF MONTH IS NOT IN ARRAY
array_push( $months,$mon ); // INSERT MONTH NAME IN ARRAY.
}
var_dump( $months );
?>

Just use substr on each of your dates array entries to retrieve the chars 5 to 7, then store them in a new array :
$dates = array(
0 => '2016-08-01',
1 => '2016-07-15',
2 => '2016-07-01');
$months = array();
foreach ($dates as $date) {
$months[] = (int)substr($date, 5, 2);
}
$months = array_unique($months); // Remove duplicates
sort($months);

Related

Loop through array results within last hour

I have a script that queries an API and finds records within the last day.
I'd like to then loop through these results and solely get those within the last hour.
Can someone explain how I do this?
This is my array of daily results:
array(2) {
[0]=>
array(36) {
["CallRef"]=> string(10) "1234567891"
["CallStartTime"]=> string(8) "08:18:30"
}
[1]=>
array(36) {
["CallRef"]=> string(10) "1234567892"
["CallStartTime"]=> string(8) "14:04:20"
}
}
It's 14:40 here in the UK so my script should just grab the 2nd item from the array.
How about this?
$apiElements = [
['CallRef' => '1234567891', 'CallStartTime' => '08:18:30'],
['CallRef' => '1234567892', 'CallStartTime' => '14:04:20'],
];
$currentFormatted = (new DateTime())->format('H');
$startOfHour = DateTime::createFromFormat('H:i:s', $currentFormatted . ':00:00');
$endOfHour = DateTime::createFromFormat('H:i:s', $currentFormatted . ':59:59');
$callsInHour = array_filter($apiElements, function($element) use ($startOfHour, $endOfHour) {
$dt = DateTime::createFromFormat('H:i:s', $element['CallStartTime']);
return $dt >= $startOfHour && $dt <= $endOfHour;
});
Totally untested, but give it a try.
Next time, please post what code you tried...
Theres multiple ways to do this. You can get a Unix timestmap from a hour ago: strtotime('-1 hour'). You can explode the time on every : in the time and take the 2nd result from the explode result.
foreach ($array as $value){
$exploded=explode(":",$value['CallStartTime']);
if(date('H')-1>$exploded[1]){
//This means it's an hour ago.
}
}
Replace $allResults and try this:
date_default_timezone_set('UTC');
$hourAgo = strtotime(date('H:i:s')) - 3600;
foreach ($allResults as $result){
if(strtotime($result["CallStartTime"]) > $hourAgo){
var_dump($result);
}
}
More flexible solution:
First you need a function to convert time to seconds
function convertTimeToSeconds($hhmmss)
{
//correct format if needed
list($hours, $minutes, $seconds) = explode(':', $hhmmss);
return $hours * 3600 + $minutes * 60 + $seconds;
}
And then you just can use array_filter function
$now = date('H:i:s');
$nowSeconds = convertTimeToSeconds($now);
$filterFunction = function ($value) use ($nowSeconds) {
return ($nowSeconds - convertTimeToSeconds($value['CallStartTime'])) < 3600; //3600 seconds = hour
};
$filteredList = array_filter($array, $filterFunction);
All together https://3v4l.org/icAmp
I suppose you have this array
Array
(
[0] => Array
(
[CallRef] => 1234567892
[CallStartTime] => 21:04:20
)
[1] => Array
(
[CallRef] => 1234567892
[CallStartTime] => 09:08:08
)
[2] => Array
(
[CallRef] => 1234567892
[CallStartTime] => 08:11:08
)
[3] => Array
(
[CallRef] => 1234567892
[CallStartTime] => 20:59:08
)
)
And so i tried this
<?php
$arr = array(
"0" => array (
"CallRef" => 1234567892,
"CallStartTime" => "21:04:20"
),
"1" => array (
"CallRef" => 1234567892,
"CallStartTime" => "09:08:08"
),
"2" => array (
"CallRef" => 1234567892,
"CallStartTime" => "08:11:08"
),
"3" => array (
"CallRef" => 1234567892,
"CallStartTime" => "20:59:08"
)
);
//echo "<pre>";print_r($arr);die;
date_default_timezone_set('Asia/kolkata');//set your timezone
$currentTime = date('H:i:s');//getting current time
$lastHourTime = date('H:i:s', strtotime('-1 hour'));//getting last hour time
$result = array();
foreach ($arr as $singlearr){
if(strtotime($singlearr['CallStartTime']) >= strtotime($lastHourTime) && strtotime($singlearr['CallStartTime']) <= strtotime($currentTime)){
$result[] = $singlearr;
}else{
}
}
echo "<pre>";print_r($result);die;//this gives me last hour records only
Check Demo When you check demo All records which have time > last hour will return otherwise it will return empty array
May be it can help!

How To Remove Duplicate Elements from array after merging with another array in php?

I am trying to Write Program for Calculating Next 20 dates After Specifying Start date, then from 20 dates i have Exclude Weekends & Holidays(Array holidays('2016-12-13',2016-12-24)) And Result Array which includes only Working Days Excluding Saturday & Sunday, from this Result Array after Passing Holiday array(Eg:- holidays('2016-12-13',2016-12-24))), it must be Excluded from result array. i:e;
I want Expected Output Below mentioned
.
<?php
$Date=array('2016-12-01');
echo "\n <br />Start Date:-" . $Date[0] . "";
/*Code For Generating Next 20 Dates Starts*/
//$start = strtotime($s_row['schedule_start_date']);
$start = strtotime('2016-12-01');
$dates=array();
for($i = 0; $i<20; $i++)
{
array_push($dates,date('Y-m-d', strtotime("+$i day", $start)));
}
echo "\n <br /> Array Of next 20 Days/dates of Given:-";
print_r($dates);
$start=array();
$start=$dates; /*Code For Generating Next 20 Dates Ends*/
$result=array();
$start = strtotime(array_values($Date)[0]);
//$end = strtotime(array_values($Date)[30]);
$result = array();
$begin = new DateTime( '2016-12-01' );
$end = new DateTime( '' );
//$end = $end->modify( '+1 day' );
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);
foreach($daterange as $date)
{
//echo $date->format("Y-m-d") . "<br>";
if (date('N', $start) <= 5) /* 'N' number days 1 (mon) to 7 (sun) */
/*5 weekday */
{
$current = date('Y-m-d', $start); //m/d/Y
$result[$current] = '';
}
$start += 86400;
//echo "Days Without Sat Sun".$result[date($date->format("Y-m-d"))];
//echo "Days Without Sat Sun".$result2[date($current->format("Y-m-d"))];
}
echo " \n <br /> Dates Without Weekends LIKE (Excluding Saturday & Sunday):-";
print_r($result);
/*For Holiday*/
$FinalArray = array();
$holidays = array(
'2016-12-13',
'2016-12-24',
);
echo " \n <br /> Given Holiday Dates Are:-";
print_r($holidays);
$a1 = $result;
$a2 = $holidays;
$array = array_diff(array_merge($a1,$a2),array_intersect($a1,$a2));
echo "\n <br /> Output:-";
print_r($array);
?>
it Gives Output as :- Array ( [2016-12-01] => [2016-12-02] => [2016-12-05] => [2016-12-06] => [2016-12-07] => [2016-12-08] => [2016-12-09] => [2016-12-12] => [2016-12-13] => [2016-12-14] => [2016-12-15] => [2016-12-16] => [2016-12-19] => [2016-12-20] => [2016-12-21] => [2016-12-22] => [2016-12-23] => [0] => 2016-12-13 [1] => 2016-12-24 )
> But I Want Expected Output:-
Array ( [2016-12-01] => [2016-12-02] => [2016-12-05] => [2016-12-06] => [2016-12-07] => [2016-12-08] => [2016-12-09] => [2016-12-12] => [2016-12-14] => [2016-12-15] => [2016-12-16] => [2016-12-19] => [2016-12-20] => [2016-12-21] => [2016-12-22] => [2016-12-23]
You Can Notice That 2016-12-13 is Not There in Above Expected Output as in '2016-12-13', 2016-12-24 is passed as Holiday via holiday array ($holidays = array( '2016-12-13', '2016-12-24', );) i:e; if i pass any date through holidays array it should not be included in result Array(). i:e 2016-12-13 is Available in Result array as well as holiday array So While while printing Final OUTPUT:- 13th date(2016-12-13) Should not be Included in final Output. Anybody Solve this will be Appreciated Thanks in Advance.
When I have to remove duplicates from a array the function that I keep going back to is
array array_unique ( array $array [, int $sort_flags = SORT_STRING ] )
you can find the documentation Here
<?php
$input = array("a" => "green", "red", "b" => "green", "blue", "red");
$result = array_unique($input);
print_r($result);
?>
the output
Array
(
[a] => green
[0] => red
[1] => blue
)
I hope that this was able to help
I prefer to calculate all dates just in one pass. (You may skip filling $dates and $dates_mon_fri arrays if they doesn't used in output also.) There is yet another approach to avoid array_diff() and array_unique() functions. I've used an array_flip() to exchange keys with values in $holdidays array to use fast array_key_exists() function.
<?php
$start = strtotime('2016-12-01');
$holidays = [
'2016-12-13',
'2016-12-24',
];
$dates = [];
$dates_mon_fri = [];
$dates_working = [];
$flip_holidays = array_flip($holidays);
for ($i = 0; $i < 20; $i++) {
$timestamp = strtotime("+$i day", $start);
$date = date('Y-m-d', $timestamp);
$dates[] = $date;
$mon_fri = false;
if (date('N', $timestamp) <= 5) {
$dates_mon_fri[] = $date;
$mon_fri = true;
}
if ($mon_fri && !array_key_exists($date, $flip_holidays)) {
$dates_working[] = $date;
}
}
var_dump($dates);
var_dump($dates_mon_fri);
var_dump($dates_working);
You can avoid using explicit looping:
$begin = new DateTimeImmutable('2016-12-01');
$end = $begin->modify('+20 days');
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval, $end);
$allDates = iterator_to_array($daterange);
$datesExcludingWeekends = array_filter($allDates, function ($date) {
return (int) $date->format("N") < 6;
});
$datesExcludingWeekends = array_map(
'date_format',
$datesExcludingWeekends,
array_fill(1, count($datesExcludingWeekends), 'Y-m-d')
);
$holidays = [
'2016-12-13',
'2016-12-24',
];
$datesExcludingWeekendsIncludingHolidays = array_flip(array_merge(
$datesExcludingWeekends,
array_diff($holidays, $datesExcludingWeekends)
));
Here is working demo.
Also, take a look at the Carbon library. If you need some exhaustive working with dates this library can really ease your life.

WooCommerce Bookings - Comparing two timestamps with PHP on custom dates format

Using WooCommerce Bookings plugin, I'm developing a system where I have to compare two dates with PHP.
I have the next sql query to get this date:
$consulta2="SELECT meta_value FROM pwkynbjbwoocommerce_order_itemmeta WHERE meta_key='Fecha de Reserva' AND order_item_id=".$row["order_item_id"];
Fecha de Reserva give us a spanish date like septiembre 2016, or septiembre 1, 2016 (September 2016, or September 1,2016) for example.
I want to compare one date with "today", so I have tried to use this PHP code:
if (strtotime($row2["meta_value"])>time()){}
But it doesn't work.
How can I achieve this?
Thanks
Yes is it possible with this custom function where I list in an associative array the spanish month with numerical month as key, and I reorder the date to output it through strtotime() function. This function can also return the current time with 'now' as parameter.
This is the function code:
function bk_date( $date ) {
// Removing the coma (if there is a coma + a space)
$my_time = str_replace ( ',', '', $date );
// or replacing the coma by a space (if there is a coma alone without a space)
// $my_time = str_replace ( ',', ' ', $the_date );
$my_time_arr = explode( ' ', $my_time );
$my_time_count = count( $my_time_arr );
$month = $my_time_arr[0];
if ( count( $my_time_arr ) > 2 ) { // When there is the month, the day and the year
// Formating the day in 2 digits
$day = $my_time_arr[1] < 10 ? '0'.$my_time_arr[1] : $my_time_arr[1];
$year = $my_time_arr[2];
} else { // When there is the month, the day and the year
$year = $my_time_arr[1];
}
// Array of spanish month
$month_arr = array('01' => 'enero', '02' => 'febrero', '03' => 'marzo', '04' => 'abril', '05' => 'mayo', '06' => 'junio', '07' => 'julio', '08' => 'agosto', '09' => 'septiembre', '10' => 'octubre', '11' => 'noviembre', '12' => 'diciembre');
// Browse the list of month and compare (when $value match, it's replace by the index $key
foreach ( $month_arr as $key => $value ) {
if ( $month == $value ) {
$month = $key;
break;
}
}
if ( count( $my_time_arr ) > 2 )
$result = $year . '-' . $month . '-' . $day;
else
$result = $year . '-' . $month;
return $date == 'now' ? strtotime( $date ) : strtotime( $result );
}
This code goes on function.php file of your active child theme or theme.
As I don't really know if the date is like septiembre 1, 2016 or like septiembre 1,2016 (without a space after the coma), you will find a commented alternative in the code above.
My code work also for febrero, 2016 or febrero 2016 date format.
Please check that I haven't make any mistakes in the month names located in $month_arr array…
Usage:
echo bk_date($row2["meta_value"]); // display the timestamp of your spanish date.
// Comparing 2 timestamps (bk_date('now') return the "current time").
if ( bk_date($row2["meta_value"]) > bk_date('now') ) {
// do something
}

Create zero values for missing items in foreach loop

I have an application that extracts some information from mysql between two dates and returns an associative array. I am producing a graph with this information but have dates missing for the dates in the database that have no information to return. I cannot fix this on the mysql side as I only have read only access to the database.
My database method retrieves an associative array like the below:
[0] => Array
(
[number_of_calls] => 151
[total_call_time] => 00:01:30
[average_call] => 00:02:00
[DATE(calldate)] => 2016-03-18
[direction] => outbound
)
What I am hoping to do is create a daterange from my form like below:
//create data range array
$begin = new DateTime( $datefrom );
$end = new DateTime( $dateto );
$end = $end->modify( '+1 day' );
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($begin, $interval ,$end);
And then use a foreach loop to iterate through the selected dates of the daterange and pull the value from the associative array where the dates match and if not insert zero values like below:
[number_of_calls] => 0
[total_call_time] => 00:00:00
[average_call] => 00:00:00
I also need the final array to end up in date order. Can anybody help me with this please?
You can transform your $result array to use DATE(calldate) as keys.
$keys = [];
foreach ($result as $item) {
$keys[] = $item['DATE(calldate)'];
}
$result = array_combine($keys, $result);
And your array will look like that:
[2016-03-18] => Array
(
[number_of_calls] => 151
[total_call_time] => 00:01:30
[average_call] => 00:02:00
[DATE(calldate)] => 2016-03-18
[direction] => outbound
)
And you can check if date is presented by simple command:
$key = $datevalue->format('Y-m-d');
if (isset($result[$key])) {
// date exists, use it
} else {
// date not exists, create empty value
}
This is what I ended up doing
// helper function to recursively search array
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
foreach ($daterange as $datevalue) {
$key = recursive_array_search($datevalue->format('Y-m-d'), $result);
// if date is found write values from data to output array
if ($key !== False) {
$output_array[] = array("number_of_calls" => $result[$key]['number_of_calls'],
"total_call_time" => $result[$key]['total_call_time'],
"average_call" => $result[$key]['average_call'],
"DATE(calldate)" => $datevalue->format('Y-m-d'),
"direction" => "outbound" );
}
// else write zeros
else {
$output_array[] = array("number_of_calls" => "0",
"total_call_time" => "00:00:00",
"average_call" => "00:00:00",
"DATE(calldate)" => $datevalue->format('Y-m-d'),
"direction" => "outbound" );
}
}
$this->chart_data = $output_array;
}

Make an Array from another array with using implode()

I have an array.
my array:
while($rowop = mysql_fetch_array($resultop))
{
$info[] = array(
'status'=>$rowop[2],
'day' => $rowop[3],
'from'=>$rowop[4],
'to' => $rowop[5],
'mon'=>$rowop[6],
'tue' => $rowop[7],
'wed'=>$rowop[8],
'thu' => $rowop[9],
'fri'=>$rowop[10],
'sat' => $rowop[11],
'sun'=>$rowop[12]
);
}
value of $rowop[6],$rowop[7],$rowop[8],$rowop[9],$rowop[10],$rowop[11],$rowop[12] can be 'on' or 'off'. I want to show only those rows which contain 'off' value. array will be same as:
'status'=>'ok',
'day' =>'all',
'from'=>'12pm',
'to' => '8am',
'off day'=>'tue,wed,thu,sat,sun'
Any one please give me Idea.if possible give example
Try this, ( assuming your array name is $info ) :
$result = array();
foreach($info as $key=>$value){
$result[$key]['status'] = $value['status'];
$result[$key]['day'] = $value['day'];
$result[$key]['from'] = $value['from'];
$result[$key]['to'] = $value['to'];
$off=array();
foreach ($value as $k => $v) {
if($v=="off") $off[]=$k;
}
if($off) $off_days = implode (", ", $off);
$result[$key]["off day"] = $off_days;
}
print_r($result);
What about this?
$days = ['mon','tue','wed','thu','fri','sat','sun'];
for($offs=[],$i=6,$i<=12,$i++) if($rowtop[$i]=='off') $offs[]= $days[$i-6];
$info[] = array(
'status'=>$rowop[2],
'day' => $rowop[3],
'from'=>$rowop[4],
'to' => $rowop[5],
'off day' => implode(',', $offs)
);
How about following code
I didn't test it. Fix if there are any errors
$days = array('mon','tue', 'wed', 'thu', 'fri', 'sat', 'sun');
$selected = array();
$final = array();
foreach($days as $day)
{
if(isset($info[$day]))
if($info[$day] == 'off')
$selected[] = $info[$day];
}
$all_days = implode(',', $selected);
$final['status'] = $info['status'];
$final['day'] = $info['day'];
$final['from'] = $info['from'];
$final['to'] = $info['to'];
$final['off day'] = $all_days;
This can be achieved in multiple steps:
Find all keys with off status using array_filter() and store it in array $result
Remove all the "week keys", i.e. mon, tue, wed etc. using array_diff_key()
Implode $result array to get a comma-separated string, and use that to create a new array element
Code:
// find all keys with 'off' status
$status = 'off';
$result = array_keys(array_filter($info,
function($element) use ($status) {
return $element == $status;
}
));
// remove all week keys
$keys = array('mon','tue','wed','thu','fri','sat','sun');
$info = array_diff_key($info, array_flip($keys));
// create a new array item with the comma-separated key string
$info['off_days'] = implode(',', $result);
print_r($info);
Output:
Array
(
[status] => ok
[day] => all
[from] => 12pm
[to] => 8am
[off_days] => tue,wed,thu,sat,sun
)
Demo.
An example using array_filter
$days = array('mon','tue', 'wed', 'thu', 'fri', 'sat', 'sun');
while($rowp ....) { //
$offs = implode (
',',
array_keys(
array_filter(
array_intersect_key($oneRow, array_flip($days)),
function($i) {return $i == 'off'}
)
)
);
//...
}
where $oneRow is what you are filling the $info array with.
Hope it helps

Categories