和暦を西暦に変換する – warekiToYear()

  • タグ:
  • タグはありません
<?php
// 和暦を西暦に変換する
echo warekiToYear('平成23年10月24日', 'UTF-8') . '<br />' . PHP_EOL;
echo warekiToYear('H23年10月24日', 'UTF-8') . '<br />' . PHP_EOL;
echo warekiToYear('H23-10-24.', 'UTF-8') . '<br />' . PHP_EOL;
echo warekiToYear('H23.10.24.', 'UTF-8') . '<br />' . PHP_EOL;

/**
 * 和暦年月日を西暦年月日に変換する
 *
 * @param string $strYmd 西暦の年月日
 * @param string $encoding 文字エンコーディング
 * @return string 西暦年月日(OK) / NULL(NG)
 * @exception Exception
 * @cation 年号、年、月、日の順になっている必要がある
 */
function warekiToYear($strYmd, $encoding = NULL)
{
	try {
		$judgeNengos = array(
			'明治' => array('nengo' => '明治', 'start' => '1868-09-08', 'end' => '1912-07-29', 'baseYear' => 1867),
			'大正' => array('nengo' => '大正', 'start' => '1912-07-30', 'end' => '1926-12-24', 'baseYear' => 1911),
			'昭和' => array('nengo' => '昭和', 'start' => '1926-12-25', 'end' => '1989-01-07', 'baseYear' => 1925),
			'平成' => array('nengo' => '平成', 'start' => '1989-01-08', 'end' => '9999-12-31', 'baseYear' => 1988)
		);
		$judgeNengos['m'] =& $judgeNengos['明治'];
		$judgeNengos['t'] =& $judgeNengos['大正'];
		$judgeNengos['s'] =& $judgeNengos['昭和'];
		$judgeNengos['h'] =& $judgeNengos['平成'];

		// エンコーディング指定なし
		if ($encoding === NULL) {
			// 内部エンコーディングを使用
			$encoding = mb_internal_encoding();
		}

		// 元年を1年に変換
		$strYmd = str_replace('元', '1', $strYmd);

		// 空白文字類を半角スペースに変換
		$strYmd = preg_replace('/\s/is', ' ', $strYmd);
		if ($strYmd === FALSE) {
			throw new Exception('空白文字類の置換に失敗しました。');
		}

		// a:「全角」英数字を「半角」に変換
		// s:「全角」スペースを「半角」に変換
		$strYmd = mb_convert_kana($strYmd, 'as', $encoding);

		// 大文字を小文字に変換
		$strYmd = strtolower($strYmd);

		// 年号部分が存在しない場合
		$matches = NULL;
		if (! preg_match('/明治|大正|昭和|平成|m|t|s|h/is', $strYmd, $matches)) {
			throw new Exception('未定義の年号です。');
		}
		// 年号
		$nengo = $matches[0];
		if (! array_key_exists($nengo, $judgeNengos)) {
			throw new Exception('不正な年号です。');
		}

		// 年号部分を削除
		$strYmd = str_replace($nengo, '', $strYmd);
		// 数字以外を半角スペースに変換
		$strYmd = preg_replace('/[^\d]+/', ' ', $strYmd);
		if ($strYmd === FALSE) {
			throw new Exception('数字以外の置換に失敗しました。');
		}

		list($wareki, $month, $day) = sscanf($strYmd, '%s %s %s');
		// 2桁0埋め
		$month = sprintf('%02d', $month);
		$day = sprintf('%02d', $day);

		if (! preg_match('/\d{1,2}/', $wareki)) {
			throw new Exception('不正な和歴です。');
		}

		if ($wareki <= 0) {
			throw new Exception('年は1以上を指定してください。');
		}

		$judgeNengo = $judgeNengos[$nengo];
		// 西暦変換
		$year = $wareki + $judgeNengo['baseYear'];

		$ymd = "$year-$month-$day";
		$bMatch = FALSE;
		foreach ($judgeNengos as $nengos) {
			if ($nengos['start'] <= $ymd && $ymd <= $nengos['end']) {
				$bMatch = TRUE;
				break;
			}
		}
		if (! $bMatch) {
			throw new Exception('範囲外の年月日です。');
		}
		// 日付の妥当性を検証
		if (! checkdate($month, $day, $year)) {
			throw new Exception('不正な年月日です。');
		}

		return $ymd;
	} catch (Exception $e) {
		// 例外メッセージを出力
		return $e->getMessage();
	}
}
?>