Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP Sorting Array by Time & finding the closest matches to X numbers

My goal here is not to save any items to a database, but to just display a live stream.

I am pulling an RSS feed from Huffington Post

http://www.huffingtonpost.com/section/front-page/feed

I have a WordPress array (PHP) of the most recent 50 articles from the Huff.

$rss = fetch_feed($feed_url);

I want my RSS feed to ONLY display X total unique posts per day. To make it simple, I was just going to display the post that is closest to intervals of 24 / X.

For demonstration let's go with 3. The feed would spit out posts published closest to 8, 16 (2 PM), and 24 (midnight) or (0, 8, and 16).

In PHP, how do I sort an object array by a published time variable and then find the closest post to that time? Right now I'm doing a very roundabout way that currently isn't even working.

Here's my current logic:

if(function_exists('fetch_feed')) {

    $rss = fetch_feed(get_field('feed_url'));
    if(!is_wp_error($rss)) : // error check
        $maxitems = $rss->get_item_quantity(50); // number of items at 50
        $rss_items = $rss->get_items(0, $maxitems);
    endif;
    // display feed items ?>
    <h1><?php echo $rss->get_title(); ?></h1>
<?php
$coutner = 0;
$daily_max = 3; //how many unique feeds to display per day
$display_interval = floor(24 / $daily_max); //simple way to make even intervals
$posting_time = array(); //to store the times to post
foreach(range(0, $daily_max-1) as $i) {
    $posting_time[$i] = $display_interval * $i;
}

$post_interval = 0;
$date = new DateTime();
$today = date("G"); //getting the current day's hour

$time_adjust = $today / $display_interval;

//adjust the posting times order so that its circular
while($today > $posting_time[0]){
$hold = array_pop($posting_time);
echo '<p>hold: ' . $hold;
array_unshift($posting_time,$hold);
}
$accessing = array_pop($posting_time);
?>
    <dl>
    <?php if($maxitems == 0){ echo '<dt>Feed not available.</dt>';}

else{ 

foreach ($rss_items as $item) : ?>

<?php
 //as soon as the first item is newer than post time, output it & count that time slot as being filled
$rss_item_hour = $item->get_date('G');
if($rss_item_hour > $accessing){ ?>
        <dt>
            <a href="<?php echo $item->get_permalink(); ?>" 
            title="<?php echo $item->get_date('j F Y @ G'); ?>">
            <?php echo $item->get_title(); ?>
            </a>
        </dt>
        <dd>
            <?php echo $item->get_description(); ?>
        </dd>
<p>
<?php echo $item->get_date('j F Y | G'); 
?>
</p>
<?php $coutner = $coutner + 1;
$accessing = array_pop($posting_time);
                               } 
else{echo '<p>else';} ?>

    <?php endforeach; ?>
    </dl>
<?php }} ?>

The main error right now is that sometimes the circular shifting of while($today > $posting_time[0]){ goes on infinitely. And the loop never seems to go as planned.

like image 334
jonbon Avatar asked Jan 29 '26 20:01

jonbon


1 Answers

I tried to build a solution based on the approach that you took and made it much simpler. There are a number of edge cases that should be considered, and I will explain those later, but I think that it will still achieve the basic goal of your app as is, but I did make some assumptions.

...
<?php

    $counter = 0;
    $daily_max = 3; //how many unique feeds to display per day
    $display_interval = floor(24 / $daily_max); //simple way to make even intervals
    $posting_time = array(); //to store the times to post

    // Create a list of time intervals largest to smallest ex. [16, 8, 0]
    foreach(range($daily_max-1, 0) as $i) {
        $posting_time[] = $display_interval * $i;
    }

?>
    <dl>
        <?php 
            if($maxitems == 0){ 
                echo '<dt>Feed not available.</dt>';

            }
            else{ 

                foreach ($rss_items as $item){
                    if(count ($posting_time) == 0){
                        break;
                    }  

                    //as soon as the first item is older than the most current post time, output it & count that time slot as being filled
                    $rss_item_hour = $item->get_date('G');

                    if($rss_item_hour < $posting_time[0]){ 
        ?>

                        <dt>
                            <a href="<?php echo $item->get_permalink(); ?>" 
                                title="<?php echo $item->get_date('j F Y @ G'); ?>">
                                <?php echo $item->get_title(); ?>
                            </a>
                        </dt>
                        <dd>
                            <?php echo $item->get_description(); ?>
                        </dd>

                        <p>
                            <?php echo $item->get_date('j F Y | G'); ?>
                        </p>

        <?php 
                            $counter++;
                            array_pop($posting_time);
                    } 
                    else{
                        // Debug message
                    }
                }
            }

        ?>
    </dl>
...

Ok, so since I don't have access to your fetch_feed data, this is untested, but I am happy to update if there are bugs.

What this will do is pick posts that are roughly broken up by the interval that you specify, but it does not do any checking to determine how close they are to those boundaries. For example, if the latest post is at 16:01, it will be skipped in favor of the first post that comes before 16:00, which may be at say, 9:00. Then it will look for the first post that is before 8:00, which may be at 7:59, so then you will have two posts that are really close in time. Or if there are no posts between 16:00 and 8:00, the first post displayed may be at 7:30, and then the very next post, maybe at 7:28 will also get displayed (since it is now the first post available before 8).

My assumption was that you are less concerned about the exact spacing and are more interested in 'thinning' out the volume of posts a little, which this should achieve and is hopefully suitable for your application.

As I said, I am happy to help you refine it if you have something specific in mind.

like image 77
i-man Avatar answered Feb 01 '26 13:02

i-man



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!