Skip to content

Commit 5253737

Browse files
author
José Valim
committed
Improve ISO8601 offset parsing
1 parent 5b7d3ad commit 5253737

File tree

2 files changed

+37
-9
lines changed

2 files changed

+37
-9
lines changed

lib/elixir/lib/calendar.ex

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,7 @@ defmodule Date do
171171
As specified in the standard, the separator "T" may be omitted if
172172
desired as there is no ambiguity within this function.
173173
174-
Time representations with reduced accuracy and decimal fractions
175-
are not supported.
174+
Time representations with reduced accuracy are not supported.
176175
177176
## Examples
178177
@@ -418,8 +417,7 @@ defmodule Time do
418417
As specified in the standard, the separator "T" may be omitted if
419418
desired as there is no ambiguity within this function.
420419
421-
Time representations with reduced accuracy and decimal fractions
422-
are not supported.
420+
Time representations with reduced accuracy are not supported.
423421
424422
## Examples
425423
@@ -736,8 +734,7 @@ defmodule NaiveDateTime do
736734
As specified in the standard, the separator "T" may be omitted if
737735
desired as there is no ambiguity within this function.
738736
739-
Time representations with reduced accuracy and decimal fractions
740-
are not supported.
737+
Time representations with reduced accuracy are not supported.
741738
742739
## Examples
743740
@@ -766,6 +763,19 @@ defmodule NaiveDateTime do
766763
iex> NaiveDateTime.from_iso8601("2015-01-32 23:50:07")
767764
{:error, :invalid_date}
768765
766+
iex> NaiveDateTime.from_iso8601("2015-01-23T23:50:07.123+02:30")
767+
{:ok, ~N[2015-01-23 23:50:07.123]}
768+
iex> NaiveDateTime.from_iso8601("2015-01-23T23:50:07.123+00:00")
769+
{:ok, ~N[2015-01-23 23:50:07.123]}
770+
iex> NaiveDateTime.from_iso8601("2015-01-23T23:50:07.123-02:30")
771+
{:ok, ~N[2015-01-23 23:50:07.123]}
772+
iex> NaiveDateTime.from_iso8601("2015-01-23T23:50:07.123-00:00")
773+
{:error, :invalid_format}
774+
iex> NaiveDateTime.from_iso8601("2015-01-23T23:50:07.123-00:60")
775+
{:error, :invalid_format}
776+
iex> NaiveDateTime.from_iso8601("2015-01-23T23:50:07.123-24:00")
777+
{:error, :invalid_format}
778+
769779
"""
770780
@spec from_iso8601(String.t) :: {:ok, NaiveDateTime.t} | {:error, atom}
771781
def from_iso8601(<<year::4-bytes, ?-, month::2-bytes, ?-, day::2-bytes, sep,

lib/elixir/lib/calendar/iso.ex

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,25 @@ defmodule Calendar.ISO do
165165
do: {acc, precision, rest}
166166

167167
@doc false
168-
def parse_offset("Z"), do: {0, ""}
169-
def parse_offset(""), do: {nil, ""}
170-
def parse_offset(_), do: :error
168+
def parse_offset(""),
169+
do: {nil, ""}
170+
def parse_offset("Z"),
171+
do: {0, ""}
172+
def parse_offset("-00:00"),
173+
do: :error
174+
def parse_offset(<<?+, hour::2-bytes, ?:, min::2-bytes, rest::binary>>),
175+
do: parse_offset(1, hour, min, rest)
176+
def parse_offset(<<?-, hour::2-bytes, ?:, min::2-bytes, rest::binary>>),
177+
do: parse_offset(-1, hour, min, rest)
178+
def parse_offset(_),
179+
do: :error
180+
181+
defp parse_offset(sign, hour, min, rest) do
182+
with {hour, ""} when hour < 24 <- Integer.parse(hour),
183+
{min, ""} when min < 60 <- Integer.parse(min) do
184+
{((hour * 60) + min) * 60 * sign, rest}
185+
else
186+
_ -> :error
187+
end
188+
end
171189
end

0 commit comments

Comments
 (0)