なんかうちの新人君が元号で記載された2通りの日付フォーマットを
西暦に変換するのに苦労していたので、ちょちょいと書いてみました
他のブログと記事が混ざるのが嫌なので2019年→2000年に時間を変更w


use Carbon\Carbon;

class CustomCarbon extends Carbon
{
    const eraCharacters = [
        '明治' => 'M',
        '大正' => 'T',
        '昭和' => 'S',
        '平成' => 'H',
        '令和' => 'R',
    ];

    const eraExchangeYears = [
        'M' => 1868,
        'T' => 1912,
        'S' => 1926,
        'H' => 1989,
        'R' => 2019,
    ];

    /**
     * 元号などの特殊な文字を含む年月日の情報をCarbonに変換する
     * @param $dateStr
     * @return CustomCarbon
     */
    public static function createFromJapaneseEra($dateStr):self
    {
        /**
         * パターンは2種類
         * [元号アルファベット]Y.m(.d)
         * [元号漢字]Y年m月(d日)
         *
         * 面倒なので全部を同じフォーマットに変えてしまう
         */
        foreach(self::eraCharacters as $chineseCharacter => $alphabet) {
            // カンマで区切らせておく
            $dateStr = str_replace($chineseCharacter, $alphabet, $dateStr);
            $dateStr = preg_replace("/({$alphabet})/", '$1,', $dateStr);
        }
        // 区切り文字を全部カンマに変更
        $dateStr = str_replace(['年','月','日','.','-','/'], ',', $dateStr);
        // 時間が入っていたら困るので時間が入っていそうな部分を削除
        $dateStr = preg_replace('/[0-9]*:[0-9:]+/', '', $dateStr);
        // 余分なスペースは削除
        $dateStr = str_replace(' ','', $dateStr);
        // 前後にカンマが入っていたら排除
        $dateStr = trim($dateStr,',');

        /**
         * この時点でだいたいの形式で送られてきたものは [元号],Y,m,dになっている
         */
        $dateArr = explode(',', $dateStr);
        if(isset(self::eraExchangeYears[$dateArr[0]])) {
            $y = $dateArr[1] ?? self::eraExchangeYears[$dateArr[0]];
            $m = $dateArr[2] ?? '1';
            $d = $dateArr[3] ?? '1';
            $y += self::eraExchangeYears[$dateArr[0]] - 1;
        } else {
            $y = $dateArr[0] ?? '2019';
            $m = $dateArr[1] ?? '1';
            $d = $dateArr[2] ?? '1';
        }
        return static::create($y, $m, $d);
    }
}