2012-05-31

相対的な経過時間を表示する WordPress 関数 human_time_diff()

Twitter や Facebook で見かける、「何分前」、「何時間前」、「何日前」のような相対的な時間表記。
これを WordPress で使いたい時は、human_time_diff() という関数があるので、こちらを使うのが手軽。
ver. 1.5.0 から実装されているようなので、2005年2月からある機能のようです( WordPress › Announcing WordPress 1.5 )。全く知らなかった。

human_time_diff( $from, $to );

Function Reference/human time diff « WordPress Codex

$from は必須、$to はオプションです。
Codex にサンプルとして挙げられているのは、以下の2パターン。

$from$to ともに UNIX タイムスタンプで指定する必要があります。
$to はデフォルトで time() から取得するので、指定しないと現在時刻との比較になります。

実際に使うときには以下のような感じで。
「前」の部分は好きなように変更してください。

<?php echo human_time_diff( $from, $to ) . '前'; ?>

$from に更新日時 ( get_post_modified_time() ) を入れれば、「最終更新から何日」のような表示が可能です。

「何ヶ月前」や「何年前」で表示できない

簡単に使える関数ですが、残念ながらこの関数で表現できるのは「何日前」までで、「何ヶ月前」や「何年前」という表現はできません。
human_time_diff() 関数のソースコード ( wp-includes/formatting.php 参照 ) を見ると、そんなに複雑なことをしているわけではなく、先に書いた $from$to で取得した UNIX タイムスタンプの差分を割り算していっているだけです。
なので、月ごとの日数の違いや、閏年を無視すれば、human_time_diff() を改造するだけで対応できそうな感じ。
というより、月ごとの違いなどの対応が難しいから日数の表示なんですかね。

オリジナルのソースコードは以下。

function human_time_diff( $from, $to = '' ) {
    if ( empty($to) )
        $to = time();
    $diff = (int) abs($to - $from);
    if ($diff <= 3600) {
        $mins = round($diff / 60);
        if ($mins <= 1) {
            $mins = 1;
    }
        /* translators: min=minute */
        $since = sprintf(_n('%s min', '%s mins', $mins), $mins);
    } else if (($diff <= 86400) && ($diff > 3600)) {
        $hours = round($diff / 3600);
        if ($hours <= 1) {
            $hours = 1;
        }
        $since = sprintf(_n('%s hour', '%s hours', $hours), $hours);
    } elseif ($diff >= 86400) {
        $days = round($diff / 86400);
        if ($days <= 1) {
            $days = 1;
        }
        $since = sprintf(_n('%s day', '%s days', $days), $days);
    }
    return $since;
}

これの条件分岐に、週、月、年を追加すればいいので、以下のようにする。
また、week、month、year が翻訳ファイルに入っていないようなので、ここの部分は日本語で直接書いておきます。

function human_time_diff_mod( $from, $to = '' ) {
    if ( empty($to) )
        $to = time();
    $diff = (int) abs($to - $from);
    // 条件: 3600秒 = 1時間以下なら (元のまま)
    if ($diff <= 3600) {
        $mins = round($diff / 60);
        if ($mins <= 1) {
            $mins = 1;
        }
        $since = sprintf(_n('%s min', '%s mins', $mins), $mins);
    }
    // 条件: 86400秒 = 24時間以下かつ、3600秒 = 1時間以上なら (元のまま)
    else if (($diff <= 86400) && ($diff > 3600)) {
        $hours = round($diff / 3600);
        if ($hours <= 1) {
            $hours = 1;
        }
        $since = sprintf(_n('%s hour', '%s hours', $hours), $hours);
    }
    // 条件: 604800秒 = 7日以下かつ、86400秒 = 24時間以上なら (条件追加)
    elseif (($diff <= 604800) && ($diff > 86400)) {
        $days = round($diff / 86400);
        if ($days <= 1) {
            $days = 1;
        }
        $since = sprintf(_n('%s day', '%s days', $days), $days);
    }
    // 条件: 2678400秒 = 31日以下かつ、2678400秒 = 7日以上なら (条件追加)
    elseif (($diff <= 2678400) && ($diff > 604800) ) {
        $weeks = round($diff / 604800);
        if ($weeks <= 1) {
            $weeks = 1;
        }
        $since = sprintf(_n('%s週間', '%s週間', $weeks), $weeks);
    }
    // 条件: 31536000秒 = 365日以下かつ、2678400秒 = 31日以上なら (条件追加)
    elseif (($diff <= 31536000) && ($diff > 2678400) ) {
        $months = round($diff / 2678400);
        if ($months <= 1) {
            $months = 1;
        }
        $since = sprintf(_n('約%sヶ月', '約%sヶ月', $months), $months);
    }
    // 条件: 31536000秒 = 365日以上なら (条件追加)
    elseif ($diff >= 31536000) {
        $years = round($diff / 31536000);
        if ($years <= 1) {
            $years = 1;
        }
        $since = sprintf(_n('約%s年', '約%s年', $years), $years);
    }
    return $since;
}

細かいところを無視した関数ですが、これを functions.php に書いておけばいつでも呼び出せるようになります。
あまり使いどころはないかもしれませんが。

元ネタは The Daily WordPress Reference のメルマガ。
毎日 WordPress の関数を簡単に紹介した内容のメルマガを送ってくれます。
かちびと.net さんで紹介されていたのをきっかけに購読し始めました。
現在1000人以上の方が購読しているようです。
関数の紹介なので、詳細については WordPress Codex を参照しましょう。

WordPressの関数の使い方を1日1回、メールで教えてくれる・The Daily WordPress Reference – かちびと.net