Support

Account

Home Forums ACF PRO Group CPT in years by using ACF date field

Solved

Group CPT in years by using ACF date field

  • I have a custom post type that I’d like to group in years (in an accordion display) by using the ACF date field. I use the following date format in my ACF and WP settings d/m/Y.
    Somehow some posts don’t end up in the correct year but in 1970. How to make sure the date formatting is working as expected?

    
      <?php
        // Retrieve the list of posts from your CPT 'accreditations' with ACF fields 'description' and 'date'
        $posts = get_posts(array(
          'post_type' => 'accreditaties',
          'posts_per_page' => -1,
        )); ?>
    
        <?php
        // Sort the posts by the 'date' field in descending order
        usort($posts, function($a, $b) {
          $dateA = get_field('acc_aanvangsdatum', $a->ID);
          $dateB = get_field('acc_aanvangsdatum', $b->ID);
          return strtotime($dateB) - strtotime($dateA);
        });
    
        // Create an associative array to group posts by year
        $groupedPosts = array();
    
        // Iterate through the sorted list of posts and assign each post to the corresponding year
        foreach ($posts as $post) {
          $date = get_field('acc_aanvangsdatum', $post->ID);
          $year = date('Y', strtotime($date));
    
          if (!isset($groupedPosts[$year])) {
            $groupedPosts[$year] = array();
          }
    
          $groupedPosts[$year][] = $post;
        }
    
    // Iterate through the grouped posts and generate the HTML markup for each year's section
    foreach ($groupedPosts as $year => $posts) {
      echo '<button class="accordion"><h4>' . $year . '</h4></button>';
      echo '<div class="panel accreditaties">'; 
      ?>
    
            <div class="grid-container">
    
                <div class="grid-item" id="grid-item-title"><p>Aanvangsdatum</p></div>
    			<div class="grid-item" id="grid-item-title"><p>Titel</p></div>
                <div class="grid-item" id="grid-item-title"><p>Status</p></div>
    			<div class="grid-item" id="grid-item-title"><p align="right">Uren</p></div>           
    
      <?php
      // Sort the posts within each year section by date in descending order
      usort($posts, function($a, $b) {
        $dateA = DateTime::createFromFormat('d/m/Y', get_field('acc_aanvangsdatum', $a->ID));
        $dateB = DateTime::createFromFormat('d/m/Y', get_field('acc_aanvangsdatum', $b->ID));
        return $dateB <=> $dateA;
      });
      
      foreach ($posts as $post) {
        $title = get_the_title($post->ID);
        $acc_aanvangsdatum = get_field('acc_aanvangsdatum', $post->ID);
        $acc_status = get_field('acc_status', $post->ID);
        $acc_uren = get_field('acc_uren', $post->ID);
        $acc_beschrijving = get_field('acc_beschrijving', $post->ID); 
        ?>
    
              	<div class="grid-item"><p><?php echo $acc_aanvangsdatum ?></p></div>
                <div class="grid-item"><p><a href="<?php echo get_permalink($post->ID); ?>"><?php echo $title ?></a></p></div>
    			<div class="grid-items-status-uren">
                <div class="grid-item status"><p><?php echo $acc_status ?></p></div>
                <div class="grid-item uren"><p align="right"><?php echo $acc_uren ?></p></div>
    			</div>
        <?php
      }
      echo '</div>'; // Move the closing </grid-containe> tag here
      echo '</div>';
    }
    ?><br>
    
    <script>
      var years = document.getElementsByClassName("year");
      var i;
    
      for (i = 0; i < years.length; i++) {
        years[i].addEventListener("click", function() {
          var posts = this.nextElementSibling;
          if (posts.style.display === "block") {
            posts.style.display = "none";
          } else {
            posts.style.display = "block";
          }
        });
      }
    </script>
    
  • 
        usort($posts, function($a, $b) {
          $dateA = get_field('acc_aanvangsdatum', $a->ID);
          $dateB = get_field('acc_aanvangsdatum', $b->ID);
          return strtotime($dateB) - strtotime($dateA);
        });
    

    “d/m/Y” is not an valid date format for strtotime()

    https://www.php.net/manual/en/datetime.formats.php

    strtotime() should be interpreting “d/m/Y” as “m/d/Y” so the return should still be within the “Year”, so I’m not sure why it would be an issue, but it’s the only thing that I can see to cause it.

  • Thank you very much @hube2. I was able to solve it by getting rid of strtotime() all together.. For reference here my code:

    
    <?php
    // Retrieve the list of posts from your CPT 'accreditations' with ACF fields 'description' and 'date'
    $posts = get_posts(array(
        'post_type' => 'accreditaties',
        'posts_per_page' => -1,
    ));
    
    // Create an associative array to group posts by year
    $groupedPosts = array();
    
    // Iterate through the list of posts and assign each post to the corresponding year
    foreach ($posts as $post) {
        $date = get_field('acc_aanvangsdatum', $post->ID);
        $parsedDate = DateTime::createFromFormat('d/m/Y', $date);
        $year = $parsedDate->format('Y');
    
        if (!isset($groupedPosts[$year])) {
            $groupedPosts[$year] = array();
        }
    
        $groupedPosts[$year][] = $post;
    }
    
    // Sort the grouped posts by year in descending order
    krsort($groupedPosts);
    
    // Iterate through the grouped posts and generate the HTML markup for each year's section
    foreach ($groupedPosts as $year => $posts) {
        echo '<button class="accordion"><h4>' . $year . '</h4></button>';
        echo '<div class="panel accreditaties">'; 
        ?>
    
        <div class="grid-container">
            <div class="grid-item" id="grid-item-title"><p>Aanvangsdatum</p></div>
            <div class="grid-item" id="grid-item-title"><p>Titel</p></div>
            <div class="grid-item" id="grid-item-title"><p>Status</p></div>
            <div class="grid-item" id="grid-item-title"><p align="right">Uren</p></div>
    
            <?php
            // Sort the posts within each year section by date in descending order
            usort($posts, function($a, $b) {
                $dateA = DateTime::createFromFormat('d/m/Y', get_field('acc_aanvangsdatum', $a->ID));
                $dateB = DateTime::createFromFormat('d/m/Y', get_field('acc_aanvangsdatum', $b->ID));
                return $dateB <=> $dateA;
            });
    
            foreach ($posts as $post) {
                $title = get_the_title($post->ID);
                $acc_aanvangsdatum = get_field('acc_aanvangsdatum', $post->ID);
                $acc_status = get_field('acc_status', $post->ID);
                $acc_uren = get_field('acc_uren', $post->ID);
                $acc_beschrijving = get_field('acc_beschrijving', $post->ID);
                ?>
    
                <div class="grid-item"><p><?php echo $acc_aanvangsdatum ?></p></div>
                <div class="grid-item"><p><a href="<?php echo get_permalink($post->ID); ?>"><?php echo $title ?></a></p></div>
                <div class="grid-item status"><p><?php echo $acc_status ?></p></div>
                <div class="grid-item uren"><p align="right"><?php echo $acc_uren ?></p></div>
    
                <?php
            }
            echo '</div>'; // Close the grid-container
            echo '</div>'; // Close the panel for the current year
        }
        ?>
    
    <script>
      var years = document.getElementsByClassName("year");
      var i;
    
      for (i = 0; i < years.length; i++) {
        years[i].addEventListener("click", function() {
          var posts = this.nextElementSibling;
          if (posts.style.display === "block") {
            posts.style.display = "none";
          } else {
            posts.style.display = "block";
          }
        });
      }
    </script>
    <style>
    .grid-container {
      	display: grid;
      	grid-template-columns: 17% auto 16% 5%;
    	grid-column-gap: 0.5em;
    }
    .grid-item {
      border: 0px solid black;
      padding: 0em;
    }
    .grid-items-status-uren {
        display: contents;
    }
    </style>
    
  • I think I know what could be causing the original issue now
    I said

    should be interpreting “d/m/Y” as “m/d/Y”

    So if you had a day like 30/01/2023 (30 Jan 2023) then strtotime() tries to use “30” as the month it is returning false (error) and that was likely the source of not sorting them correctly. Any date with a day > the number of days in what it is using for month would return an error.

Viewing 4 posts - 1 through 4 (of 4 total)

You must be logged in to reply to this topic.