LoginSignup
57
52

More than 5 years have passed since last update.

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

Last updated at Posted at 2014-12-17

和暦と日本語の曜日を表示する時に、毎回同じようなコードを書いている気がするので、使い勝手のいい感じにまとめてみた。
改良の余地は色々あるけど、まぁまぁ使えるかなぁと。
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
    ]
57
52
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
57
52