PHPで和暦・日本語曜日を使うのDateTimeクラス拡張版を作ってみました。
お好きな方をお使いください。
フォーマットに使えるものも変わりありません。
注意
明治5年以前は天保暦・寛政暦などが利用されており、現在のグレゴリオ暦と日付が一致していません。
そのため、和暦の年号(K,k)のオプションは明治5年以前では正しく出ない場合があります。
日付に関してもグレゴリオ暦のものが表示されるため、和暦としての表示と異なります。
「JK年n月j日」が正しく動作するのは明治6年以降となりますのでご注意ください。
例:西暦 1834年6月1日 => 実際の和暦 天保5年4月24日
※@tadsanさん、情報・ご指摘ありがとうございます。
ソース
<?php
namespace MyLibrary;
/**
* 日本語対応DateTime拡張クラス
*
* 元号、曜日などの日本語表記に対応したDateTime拡張クラス
*
* @version 1.0.1
* @author chiyoyo
* @caution PHP5.2以上
*/
class DateTimeJp extends \DateTime
{
// フォーマット定義追加
const JP_DATE = 'JK年n月j日'; // 例:平成元年5月7日(明治5年以前は当時と異なる日付が出るので注意)
const JP_TIME = 'Eg時i分s秒'; // 例:午後3時05分07秒
const DEFAULT_TO_STRING_FORMAT = 'Y-m-d H:i:s'; // toString()で利用する表示フォーマット
/**
* 元号用設定
* 日付はウィキペディアを参照しました
*
* @see 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' => '午後',
];
/**
* 文字列に変換された際に返却するもの
*
* @return string
*/
public function __toString()
{
return $this->format(self::DEFAULT_TO_STRING_FORMAT);
}
/**
* 和暦などを追加したformatメソッド
*
* 追加した記号
* J : 元号
* b : 元号略称
* K : 和暦年(1年を元年と表記)
* k : 和暦年
* x : 日本語曜日(0:日-6:土)
* E : 午前午後
*
* @param string $format DateTime::formatに準ずるformat文字列
* @return string
*/
public function format($format)
{
// 和暦関連のオプションがある場合は和暦取得
$gengo = array();
if (preg_match('/(?<!\\\)[J|b|K|k]/', $format)) {
foreach (self::$gengoList as $g) {
if ($g['timestamp'] <= $this->getTimestamp()) {
$gengo = $g;
break;
}
}
// 元号が取得できない場合はException
if (empty($gengo)) {
throw new Exception('Can not be converted to a timestamp : '.$this->getTimestamp());
}
}
// J : 元号
if ($this->isCharactor('J', $format)) {
$format = $this->replaceCharactor('J', $gengo['name'], $format);
}
// b : 元号略称
if ($this->isCharactor('b', $format)) {
$format = preg_replace('/b/', '¥¥' . $gengo['name_short'], $format);
}
// K : 和暦用年(元年表示)
if ($this->isCharactor('K', $format)) {
$year = date('Y', $this->getTimestamp()) - date('Y', $gengo['timestamp']) + 1;
$year = $year == 1 ? '元' : $year;
$format = $this->replaceCharactor('K', $year, $format);
}
// k : 和暦用年
if ($this->isCharactor('k', $format)) {
$year = date('Y', $this->getTimestamp()) - date('Y', $gengo['timestamp']) + 1;
$format = $this->replaceCharactor('k', $year, $format);
}
// x : 日本語曜日
if ($this->isCharactor('x', $format)) {
$w = date('w', $this->getTimestamp());
$format = $this->replaceCharactor('x', self::$weekJp[$w], $format);
}
// 午前午後
if ($this->isCharactor('E', $format)) {
$a = date('a', $this->getTimestamp());
$value = isset(self::$ampm[$a]) ? self::$ampm[$a] : '';
$format = $this->replaceCharactor('E', $value, $format);
}
return parent::format($format);
}
/**
* 指定した文字があるかどうか調べる(エスケープされているものは除外)
* @param string $char 検索する文字
* @param string $string 検索される文字列
* @return boolean
*/
private function isCharactor($char, $string)
{
return preg_match('/(?<!\\\)'.$char.'/', $string);
}
/**
* 指定した文字を置換する(エスケープされていないもののみ)
* @param string $char 置換される文字
* @param string $replace 置換する文字列
* @param string $string 元の文字列
* @return string 置換した文字列
*/
private function replaceCharactor($char, $replace, $string)
{
// エスケープされていないもののみ置換
$string = preg_replace('/(?<!\\\)'.$char.'/', '${1}'.$replace, $string);
// エスケープ文字を削除
$string = preg_replace('/\\\\'.$char.'/', $char, $string);
return $string;
}
}
参考
おまけ
利用できない元号をおまけとして載せてみます。
実際は天保歴などを計算しなければならないため、タイムスタンプが異なります。
以下は現在の暦から計算しただけのタイムスタンプです。
明治以前の元号
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
];
更新履歴
日付 | 更新内容 |
---|---|
2015/04/14 | エスケープすることで置換しないように修正 |
2016/01/15 | 日本語曜日出力のバグ修正 |