WordPress tweak: Proper navigation for date.php

Posted: - Modified: | blogging, geek, wordpress

I can’t be the only person who’s ever wanted proper navigation on WordPress date.php archive pages. By this, I mean that if you’re browsing, say, https://sachachua.com/blog/2009 and you’re on the first page, there should be a way for you to get to 2008.

So I spent a couple of hours hacking that in. This even skips non-existent years/months/days. Tweak and enjoy.

Minor notes: It jumps to the first page of the other year/month/day, so the results aren’t strictly chronological. Going to 2008 from 2009 will show you the blog posts from January 1 instead of the last posts of 2008. Since I display a huge list of posts and I only use one page, that’s fine with me.

<?php
  $y = mysql2date('Y', $wp_query->posts[0]->post_date);
  $m = mysql2date('m', $wp_query->posts[0]->post_date);
  $d = mysql2date('d', $wp_query->posts[0]->post_date);
  $display = mktime(0, 0, 0, $m, $d, $y);
  if (is_year()) {
    $format = 'Y';
    $prev_display = mktime(23, 59, 59, 12, 31, $y - 1);
    $next_display = mktime(0, 0, 0, 1, 1, $y + 1);
    $url_format = 'Y';
  } elseif (is_month()) {
    $prev_display = mktime(23, 59, 59, $m, 0, $y);
    $next_display = mktime(0, 0, 0, $m + 1, 1, $y);
    $format = 'F Y';
    $url_format = 'Y/n';
  } elseif (is_day()) {
    $prev_display = mktime(23, 59, 59, $m, $d - 1, $y);
    $next_display = mktime(0, 0, 0, $m, $d + 1, $y);
    $format = 'F j, Y';
    $url_format = 'Y/n/j';
  }
  $paged = get_query_var('paged');
  if ($paged < 2) { // No previous pages; navigate by date instead
    $past = $wpdb->get_row("SELECT UNIX_TIMESTAMP(MAX(post_date)) AS post_date
FROM $tableposts WHERE post_date <= FROM_UNIXTIME($prev_display) AND post_status='publish'");
    if ($past->post_date) {
      $prev_text = '&laquo; ' . date($format, $past->post_date);
      $prev_link = get_bloginfo('url') . '/'
        . date($url_format, $past->post_date);
    }
  }
  if ($paged >= $wp_query->max_num_pages) { // No next pages
    $future = $wpdb->get_row("SELECT UNIX_TIMESTAMP(MIN(post_date)) AS post_date
FROM $tableposts WHERE post_date >= FROM_UNIXTIME($next_display) AND post_status='publish'");
    if ($future->post_date) {
      $next_text = date($format, $future->post_date) . ' &raquo;';
      $next_link = get_bloginfo('url') . '/'
        . date($url_format, $future->post_date);
    }
  }
  $title = date($format, $display);
  ?>
  <div class="navigation">
    <div class="left">
      <?php if ($prev_text) { ?>
        <a href="<?php print $prev_link ?>"><?php print $prev_text ?></a>
      <?php } else { ?>
        <?php previous_posts_link('&laquo; Older posts'); ?>
      <?php } ?>
    </div>
    <div class="right">
      <?php if ($next_text) { ?>
        <a href="<?php print $next_link ?>"><?php print $next_text ?></a>
      <?php } else { ?>
        <?php next_posts_link('Newer posts &raquo;'); ?>
      <?php } ?>
    </div>
    <div style="clear: both"></div>
  </div>
  <h1><?php print $title ?></h1>
You can comment with Disqus or you can e-mail me at sacha@sachachua.com.