概要
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;
}
気をつけよう。
