概要
DateTimeImmutableに西暦1年を突っ込んだら勝手に2001年になる理由を探る。
なんだか、西暦は4桁0埋めじゃないと西暦1年扱いしてくれないようだった。
起きたこと
こういうコードだった。
無理やり2018年8月23日みたいな数字を2018-08-23にするやつ。
$target_date = '1年08月23日'; $search = array('年','月'); $date = str_replace($search,'-',$target_date); // string(10) "1-08-23日" $date = str_replace('日','',$date); // string(7) "1-08-23" $date = new \DateTimeImmutable($date); // object(DateTimeImmutable)#106 (3) { // ["date"]=> // string(26) "2001-08-23 00:00:00.000000" // ["timezone_type"]=> // int(3) // ["timezone"]=> // string(3) "UTC" // } $date = $jp_dt->format('Y-m-d'); // string(10) "2001-08-23"
なんだかDateTimeImmutableで2001年に変換されているみたいだ。
最初はunixtime(1970年1月1日9時0分0秒が0になるやつ)が原因かと思ったけどそれなら1971とかのはず…。
入力数値を変えることにする
0埋めが原因のような気がしたので桁を変える。
入力→出力
1年08月23日→2001-08-23
1年8月23日→2001-08-23
01年8月23日→2001-08-23
001年8月23日→2001-08-23
0001年08月23日→0001-08-23
0001年8月23日→0001-08-23
こんな感じになった。
どうやら西暦は4桁0埋めじゃないと西暦1年扱いしてくれないようだ…。
対策
こういう辛い関数を作って対応した。
//Y-m-d 00:00:00 形式の年月日を0埋めする Public static function convertToZeroPaddingDate($datetime){ $date = '0000-00-00'; $time = '00:00:00'; if(! is_string ( $datetime )){ return $date . ' ' . $time; } if(strpos($datetime,'-') === false){ return $date . ' ' . $time; } $dt = explode ( ' ' , $datetime ); if(empty($dt[0])){ return $date . ' ' . $time; } $date = $dt[0]; $fullDate = explode ( '-' , $date ); //年 if(empty($fullDate[0])){ return $date . ' ' . $time; } $year = $fullDate[0]; $year = str_pad($year, 4, 0, STR_PAD_LEFT); //月 if(empty($fullDate[1])){ return $date . ' ' . $time; } $month = $fullDate[1]; $month = str_pad($month, 2, 0, STR_PAD_LEFT); //日 if(empty($fullDate[2])){ return $date . ' ' . $time; } $day = $fullDate[2]; $day = str_pad($day, 2, 0, STR_PAD_LEFT); //時間 if(! empty($dt[1])){ $time = $dt[1]; }else{ return $year .'-' . $month . '-' . $day; } return $year .'-' . $month . '-' . $day .' '.$time; }
気をつけよう。