Help us understand the problem. What is going on with this article?

PHPで和暦・日本語曜日を使う

More than 1 year has passed since last update.

和暦と日本語の曜日を表示する時に、毎回同じようなコードを書いている気がするので、使い勝手のいい感じにまとめてみた。
改良の余地は色々あるけど、まぁまぁ使えるかなぁと。
DateTimeクラス拡張版も作ってみました

説明

string DatetimeUtility::date(string $format[, int $timestamp = time()])

date関数を拡張した関数。

追加format文字

format文字 説明 戻り値の例
J 元号(明治より前はありません) 令和,平成,昭和,大正,明治,...
b 元号略称(明治より前はありません) R,H,S,T,M
K 元号に対応した年(1年を元年と表記) 元,2,3...
k 元号に対応した年 1,2,3...
x 日本語の曜日 日から土
E AM,PMの日本語 午前,午後
p 時。12時間単位。先頭にゼロを付けない。 0から11
q 時。数字。12 時間単位。 00から11

注意

明治5年以前は天保暦・寛政暦などが利用されており、現在のグレゴリオ暦と日付が一致していません。
そのため、和暦の年号(K,k)のオプションは明治5年以前では正しく出ない場合があります。
日付に関してもグレゴリオ暦のものが表示されるため、和暦としての表示と異なります。
「JK年n月j日」が正しく動作するのは明治6年以降となりますのでご注意ください。
例:西暦 1834年6月1日 => 実際の和暦 天保5年4月24日

@tadsanさん、情報・ご指摘ありがとうございます。

更新履歴

日時 更新内容
2015/04/13 午前午後を追加しました
2015/04/13 明治より前の元号に対応しました
2015/04/14 kとKのオプションが逆になっているバグ修正しました
2019/04/01 新元号「令和」を追加しました
2019/04/02 日本用の0〜11時のpとqを追加しました

ソース

<?php
/**
 * 日時用汎用クラス
 */
class DatetimeUtility {
    /** 元号用設定
     * 日付はウィキペディアを参照しました
     * http://ja.wikipedia.org/wiki/%E5%85%83%E5%8F%B7%E4%B8%80%E8%A6%A7_%28%E6%97%A5%E6%9C%AC%29
     */
    private static $gengoList = [
        ['name' => '令和', 'name_short' => 'R', 'timestamp' =>  1556636400],  // 2019-05-01,
        ['name' => '平成', 'name_short' => 'H', 'timestamp' =>  600188400],  // 1989-01-08,
        ['name' => '昭和', 'name_short' => 'S', 'timestamp' => -1357635600], // 1926-12-25'
        ['name' => '大正', 'name_short' => 'T', 'timestamp' => -1812186000], // 1912-07-30
        ['name' => '明治', 'name_short' => 'M', 'timestamp' => -3216790800], // 1868-01-25
    ];

    /** 日本語曜日設定 */
    private static $weekJp = [
        0 => '日',
        1 => '月',
        2 => '火',
        3 => '水',
        4 => '木',
        5 => '金',
        6 => '土',
    ];

    /** 午前午後 */
    private static $ampm = [
        'am' => '午前',
        'pm' => '午後',
    ];

    /**
     * 和暦などを追加したdate関数
     *
     * 追加した記号
     * J : 元号
     * b : 元号略称
     * K : 和暦年(1年を元年と表記)
     * k : 和暦年
     * x : 日本語曜日(0:日-6:土)
     * E : 午前午後
     */
    public static function date($format, $timestamp = null)
    {
        // 和暦関連のオプションがある場合は和暦取得
        $gengo = array();
        $timestamp = is_null($timestamp) ? time() : $timestamp;
        if (preg_match('/[J|b|K|k]/', $format)) {
            foreach (self::$gengoList as $g) {
                if ($g['timestamp'] <= $timestamp) {
                    $gengo = $g;
                    break;
                }
            }
            // 元号が取得できない場合はException
            if (empty($gengo)) {
                throw new Exception('Can not be converted to a timestamp : '.$timestamp);
            }
        }

        // J : 元号
        if (strpos($format, 'J') !== false) {
            $format = preg_replace('/J/', $gengo['name'], $format);
        }

        // b : 元号略称
        if (strpos($format, 'b') !== false) {
            $format = preg_replace('/b/', '¥¥' . $gengo['name_short'], $format);
        }

        // K : 和暦用年(元年表示)
        if (strpos($format, 'K') !== false) {
            $year = date('Y', $timestamp) - date('Y', $gengo['timestamp']) + 1;
            $year = $year == 1 ? '元' : $year;
            $format = preg_replace('/K/', $year, $format);
        }

        // k : 和暦用年
        if (strpos($format, 'k') !== false) {
            $year = date('Y', $timestamp) - date('Y', $gengo['timestamp']) + 1;
            $format = preg_replace('/k/', $year, $format);
        }

        // x : 日本語曜日
        if (strpos($format, 'x') !== false) {
            $w = date('w', $timestamp);
            $format = preg_replace('/x/', self::$weekJp[$w], $format);
        }

        // 午前午後
        if (strpos($format, 'E') !== false) {
            $a = date('a', $timestamp);
            $format = preg_replace('/E/', self::$ampm[$a], $format);
        }

        // 時。12時間単位。先頭にゼロを付けない。(0-11)
        if (strpos($format, 'p') !== false) {
            $hour = date('g', $timestamp);
            $hour = $hour == 12 ? 0 : $hour;
            $format = preg_replace('/p/', $hour, $format);
        }

        // 時。数字。12 時間単位。(00-11)
        if (strpos($format, 'q') !== false) {
            $hour = date('h', $timestamp);
            $hour = str_pad($hour == 12 ? 0 : $hour, 2, '0');
            $format = preg_replace('/q/', $hour, $format);
        }

        return date($format, $timestamp);
    }

}

おまけ

明治以前をおまけとして載せてみる。
実際は天保歴などを加味してタイムスタンプを変える必要があります。
記載しているものは単純に現在の暦から計算しただけのものです。

明治以前
    private static $gengoList = [
        // 江戸時代
        ['name' => '慶応', 'timestamp' => -3303104400], // 1865-05-01
        ['name' => '元治', 'timestamp' => -3337664400], // 1864-03-27
        ['name' => '文久', 'timestamp' => -3432186000], // 1861-03-29
        ['name' => '万延', 'timestamp' => -3462858000], // 1860-04-08
        ['name' => '安政', 'timestamp' => -3627882000], // 1855-01-15
        ['name' => '嘉永', 'timestamp' => -3842154000], // 1848-04-01
        ['name' => '弘化', 'timestamp' => -3943933200], // 1845-01-09
        ['name' => '天保', 'timestamp' => -4384573200], // 1831-01-23
        ['name' => '文政', 'timestamp' => -4784173200], // 1818-05-26
        ['name' => '文化', 'timestamp' => -5231552400], // 1804-03-22
        ['name' => '享和', 'timestamp' => -5326506000], // 1801-03-19
        ['name' => '寛政', 'timestamp' => -5707530000], // 1789-02-19
        ['name' => '天明', 'timestamp' => -5954374800], // 1781-04-25
        ['name' => '安永', 'timestamp' => -6218586000], // 1772-12-10
        ['name' => '明和', 'timestamp' => -6485130000], // 1764-06-30
        ['name' => '宝暦', 'timestamp' => -6881014800], // 1751-12-14
        ['name' => '寛延', 'timestamp' => -6986941200], // 1748-08-05
        ['name' => '延享', 'timestamp' => -7123885200], // 1744-04-03
        ['name' => '寛保', 'timestamp' => -7217802000], // 1741-04-12
        ['name' => '元文', 'timestamp' => -7370730000], // 1736-06-07
        ['name' => '享保', 'timestamp' => -7996438800], // 1716-08-09
        ['name' => '正徳', 'timestamp' => -8159389200], // 1711-06-11
        ['name' => '宝永', 'timestamp' => -8385066000], // 1704-04-16
        ['name' => '元禄', 'timestamp' => -8873485200], // 1688-10-23
        ['name' => '貞享', 'timestamp' => -9017082000], // 1684-04-05
        ['name' => '天和', 'timestamp' => -9092941200], // 1681-11-09
        ['name' => '延宝', 'timestamp' => -9346266000], // 1673-10-30
        ['name' => '寛文', 'timestamp' => -9738781200], // 1661-05-23
        ['name' => '万治', 'timestamp' => -9825699600], // 1658-08-21
        ['name' => '明暦', 'timestamp' => -9928602000], // 1655-05-18
        ['name' => '承応', 'timestamp' => -10009818000], // 1652-10-20
        ['name' => '正保', 'timestamp' => -10254934800], // 1645-01-13
        ['name' => '寛永', 'timestamp' => -10909501200], // 1624-04-17
        ['name' => '元和', 'timestamp' => -11181402000], // 1615-09-05
        // 安土桃山時代
        ['name' => '慶長', 'timestamp' => -11772118800], // 1596-12-16
        ['name' => '文禄', 'timestamp' => -11896189200], // 1593-01-10
        ['name' => '天正', 'timestamp' => -12507728400], // 1573-08-25
        // 戦国時代
        ['name' => '元亀', 'timestamp' => -12610198800], // 1570-05-27
        ['name' => '永禄', 'timestamp' => -12994938000], // 1558-03-18
        ['name' => '弘治', 'timestamp' => -13069414800], // 1555-11-07
        ['name' => '天文', 'timestamp' => -13801222800], // 1532-08-29
        ['name' => '享禄', 'timestamp' => -13927021200], // 1528-09-03
        ['name' => '大永', 'timestamp' => -14146218000], // 1521-09-23
        ['name' => '永正', 'timestamp' => -14699178000], // 1504-03-16
        ['name' => '文亀', 'timestamp' => -14793699600], // 1501-03-18
        ['name' => '明応', 'timestamp' => -15064909200], // 1492-08-12
        ['name' => '延徳', 'timestamp' => -15156579600], // 1489-09-16
        ['name' => '長享', 'timestamp' => -15223021200], // 1487-08-09
        ['name' => '文明', 'timestamp' => -15796371600], // 1469-06-08
        ['name' => '応仁', 'timestamp' => -15864714000], // 1467-04-09
    ]
chiyoyo
Web関連色々やってる個人事業主です
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした