LoginSignup
0
1

【PHP】西暦から干支・干支から西暦を算出する

Last updated at Posted at 2024-05-21

小ネタ。
PHPで西暦から十二支を出す必要があったので、ついでに十干十二支(干支=えと)を出す関数を作ってみた。

西暦→干支

getEto.php
function getEto(int $yyyy = NULL, bool $with_jikkan = TRUE) {
 // yyyyに西暦を入れるとその年の干支(十干十二支)を返す
 // yyyyが空のときは今年の干支
 // 第2引数を0にすると十二支のみ返す
 $yyyy = $yyyy ?: date("Y");
 if ($yyyy > 0) {
  $jikkan = [
   '庚',
   '辛',
   '壬',
   '癸',
   '甲',
   '乙',
   '丙',
   '丁',
   '戊',
   '己',
  ];
  $juunishi = [
   '申',
   '酉',
   '戌',
   '亥',
   '子',
   '丑',
   '寅',
   '卯',
   '辰',
   '巳',
   '午',
   '未',
  ];
  return ($with_jikkan ? $jikkan[$yyyy % 10] : '') . $juunishi[$yyyy % 12];
 }
 return NULL;
}

西暦が10で割り切れる年は「庚(かのえ)」、12で割り切れる年は「申(さる)」なので、そこから算出している。配列が「甲(きのえ)」や「子(ね)」から始まってないのはこのため。
第2引数を0(やfalsyな値)にすると十干ナシで十二支だけ返す。
まあこれは処理が簡単。

干支→西暦

getYearFromEto.php
function getYearFromEto(string $eto, int $yyyy = NULL) {
// yyyy年以降でeto(十干十二支)に当てはまる年を出す
// yyyyが空の場合は今年以降で算出
// 存在しない干支を入力した場合はNULLを返す
 $yyyy = $yyyy ?: date("Y");
 if ($yyyy > 0) {
  $jikkan_r = [
   '庚' => 0,
   '辛' => 1,
   '壬' => 2,
   '癸' => 3,
   '甲' => 4,
   '乙' => 5,
   '丙' => 6,
   '丁' => 7,
   '戊' => 8,
   '己' => 9,
  ];
  $juunishi_r = [
   '申' => 0,
   '酉' => 1,
   '戌' => 2,
   '亥' => 3,
   '子' => 4,
   '丑' => 5,
   '寅' => 6,
   '卯' => 7,
   '辰' => 8,
   '巳' => 9,
   '午' => 10,
   '未' => 11,
  ];
  $ji = $jikkan_r[mb_substr($eto, 0, 1)] ?? FALSE;
  $ju = $juunishi_r[mb_substr($eto, 1, 1)] ?? FALSE;
  if (($ji || $ji === 0) && ($ju || $ju === 0) && (($ji + $ju) % 2 === 0)) {
   for ($i = 0; 1; $i++) {
    $yi = $yyyy + $i;
    if (($yi % 10 === $ji) && ($yi % 12 === $ju)) {return $yi;}
   }
  }
 }
 return NULL;
}

第1引数は干支(十二支でなく十干十二支)、第2引数には西暦を入れると、その年以降で入れた干支に当てはまる西暦を返す。第2引数を省略すると今年以降から探す。
手順としては西暦→干支より複雑で、

  1. 干支を十干と十二支に分割
  2. 十干と十二支に当てはまる剰余を出す
  3. 西暦に1ずつ足していき、10の剰余と12の剰余の両方が一致する年を出力

というやや力技。もう少しスマートなやり方があるかもしれない。
ifの条件の1つめと2つめは干支にない文字を入れた場合に無視する(NULLを返す)ためだが「余りゼロ」もTRUEにしないといけないためちょっと手間がかかっている。3つめは例えば「甲丑」という干支は存在しない(十干の偶数番目は必ず十二支の偶数番目と結合する。奇数番目も同様)ので、それを回避するためのもの。2つの剰余の和が偶数なら偶数&偶数か奇数&奇数しかないので。XORを使うより簡単なんじゃあないかなと思った。

これがあると例えば「辛亥革命って何年だっけ?」というときに

echo getYearFromEto('辛亥', 1900); //1911

みたいなことができる。もっとも60年ごとに同じ干支が回ってくるので「だいたいこのあたりの年」がわかってないと使えないが…。

関連記事

西暦から和暦・和暦から西暦を算出する

0
1
0

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
0
1