@@ -1168,27 +1168,10 @@ defmodule Ecto.Type do
11681168
11691169 ## Naive datetime
11701170
1171- defp cast_naive_datetime ( "-" <> rest ) do
1172- with { :ok , naive_datetime } <- cast_naive_datetime ( rest ) do
1173- { :ok , % { naive_datetime | year: naive_datetime . year * - 1 } }
1174- end
1175- end
1176-
1177- defp cast_naive_datetime (
1178- << year :: 4 - bytes , ?- , month :: 2 - bytes , ?- , day :: 2 - bytes , sep , hour :: 2 - bytes , ?: ,
1179- minute :: 2 - bytes >>
1180- )
1181- when sep in [ ?\s , ?T ] do
1182- with { :ok , date } <- cast_date ( to_i ( year ) , to_i ( month ) , to_i ( day ) ) ,
1183- { :ok , time } <- cast_time ( to_i ( hour ) , to_i ( minute ) , 0 , nil ) do
1184- NaiveDateTime . new ( date , time )
1185- end
1186- end
1187-
11881171 defp cast_naive_datetime ( binary ) when is_binary ( binary ) do
11891172 case NaiveDateTime . from_iso8601 ( binary ) do
11901173 { :ok , _ } = ok -> ok
1191- { :error , _ } -> :error
1174+ { :error , _ } -> cast_naive_datetime_without_seconds ( binary )
11921175 end
11931176 end
11941177
@@ -1219,25 +1202,35 @@ defmodule Ecto.Type do
12191202 :error
12201203 end
12211204
1222- ## UTC datetime
1205+ # The ISO 8601 parsers already handle negative years, so the sign
1206+ # only needs special handling for datetimes without seconds.
1207+ defp cast_naive_datetime_without_seconds ( "-" <> rest ) do
1208+ case cast_naive_datetime_without_seconds ( rest ) do
1209+ { :ok , % { year: year } = naive_datetime } when year >= 0 ->
1210+ { :ok , % { naive_datetime | year: - year } }
12231211
1224- defp cast_utc_datetime ( "-" <> rest ) do
1225- with { :ok , utc_datetime } <- cast_utc_datetime ( rest ) do
1226- { :ok , % { utc_datetime | year: utc_datetime . year * - 1 } }
1212+ _ ->
1213+ :error
12271214 end
12281215 end
12291216
1230- defp cast_utc_datetime (
1217+ defp cast_naive_datetime_without_seconds (
12311218 << year :: 4 - bytes , ?- , month :: 2 - bytes , ?- , day :: 2 - bytes , sep , hour :: 2 - bytes , ?: ,
12321219 minute :: 2 - bytes >>
12331220 )
12341221 when sep in [ ?\s , ?T ] do
12351222 with { :ok , date } <- cast_date ( to_i ( year ) , to_i ( month ) , to_i ( day ) ) ,
12361223 { :ok , time } <- cast_time ( to_i ( hour ) , to_i ( minute ) , 0 , nil ) do
1237- DateTime . new ( date , time , "Etc/UTC" )
1224+ NaiveDateTime . new ( date , time )
12381225 end
12391226 end
12401227
1228+ defp cast_naive_datetime_without_seconds ( _ ) do
1229+ :error
1230+ end
1231+
1232+ ## UTC datetime
1233+
12411234 defp cast_utc_datetime ( binary ) when is_binary ( binary ) do
12421235 case DateTime . from_iso8601 ( binary ) do
12431236 { :ok , datetime , _offset } ->
@@ -1250,7 +1243,10 @@ defmodule Ecto.Type do
12501243 end
12511244
12521245 { :error , _ } ->
1253- :error
1246+ case cast_naive_datetime_without_seconds ( binary ) do
1247+ { :ok , naive_datetime } -> { :ok , DateTime . from_naive! ( naive_datetime , "Etc/UTC" ) }
1248+ :error -> :error
1249+ end
12541250 end
12551251 end
12561252
0 commit comments