Skip to content

Commit

Permalink
Force Timezone.get to return UTC when offset given is 0. Fix time shi…
Browse files Browse the repository at this point in the history
…fting with preformatted directives in Zulu time
  • Loading branch information
bitwalker committed Aug 12, 2014
1 parent 6da52c3 commit 564a620
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 19 deletions.
31 changes: 25 additions & 6 deletions lib/parsers/dateformat/parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,27 @@ defmodule Timex.Parsers.DateFormat.Parser do
end
end

defp do_parse(date_string, directives, parser), do: do_parse(date_string, directives, parser, DateTime.new)
defp do_parse(<<>>, [], _, %DateTime{} = date), do: {:ok, date}
defp do_parse(date_string, directives, parser), do: do_parse(date_string, directives, parser, %DateTime{})
defp do_parse(<<>>, [], _, %DateTime{timezone: nil} = date), do: {:ok, %{date | :timezone => Timezone.get(:utc)}}
defp do_parse(<<>>, [], _, %DateTime{} = date), do: {:ok, date}
defp do_parse(rest, [], _, _), do: {:error, "Unexpected end of string! Starts at: #{rest}"}
# Ignore :char directives when parsing
defp do_parse(date_string, [%Directive{type: :char}|rest], parser, date) do
do_parse(date_string, rest, parser, date)
end
# Inject component directives of pre-formatted directives.
defp do_parse(date_string, [%Directive{type: :format, format: format}|rest], parser, %DateTime{} = date) do
defp do_parse(date_string, [%Directive{token: token, type: :format, format: format}|rest], parser, %DateTime{} = date) do
case format do
[tokenizer: tokenizer, format: format_string] ->
# When parsing a date string with one of the zulu directives,
# shift the date to UTC/Zulu
date = case token do
token when token in [:iso_8601z, :rfc_822z, :rfc3339z, :rfc_1123z] ->
Date.set(date, timezone: Timezone.get(:utc))
_ ->
date
end
# Tokenize the nested directives and continue parsing
case tokenizer.tokenize(format_string) do
{:error, _} = error -> error
directives -> do_parse(date_string, directives ++ rest, parser, date)
Expand Down Expand Up @@ -303,10 +313,19 @@ defmodule Timex.Parsers.DateFormat.Parser do
%{date | :hour => Time.to_12hour_clock(date.hour)}
# Timezones
:zoffs ->
%{date | :timezone => Timezone.get(value)}
# If timezone is not nil, then we know it was set
# by a preformatted directive, so do not overrule that value
case date.timezone do
nil -> %{date | :timezone => Timezone.get(value)}
_ -> date
end
:zname ->
tz = Timezone.get(value)
Date.set(date, timezone: tz)
# If timezone is not nil, then we know it was set
# by a preformatted directive, so do not overrule that value
case date.timezone do
nil -> %{date | :timezone => Timezone.get(value)}
_ -> date
end
tz when tz in [:zoffs_colon, :zoffs_sec] ->
case value do
<<?-, h1::utf8, h2::utf8, _::binary>> ->
Expand Down
1 change: 1 addition & 0 deletions lib/timezone/timezone.ex
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,7 @@ defmodule Timex.Timezone do
# UTC is so common, we'll give it an extra shortcut, as well as handle common shortcuts
def get(tz) when tz in ["Z", "UT", "GMT"], do: get(:utc)
def get(:utc), do: get("UTC")
def get(0), do: get("UTC")
# These are shorthand for specific time zones
def get("A"), do: get(-1)
def get("M"), do: get(-12)
Expand Down
26 changes: 13 additions & 13 deletions test/parse_default_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -290,21 +290,21 @@ defmodule DateFormatTest.ParseDefault do
#assert { :ok, "2007-323" } = format(date, "{0YYYY}-{0Dord}")
#end

#test :format_compound_rfc1123 do
#date = Date.from({{2013,3,5},{23,25,19}})
#assert { :ok, "Tue, 05 Mar 2013 23:25:19 GMT" } = format(date, "{RFC1123}")
#assert { :ok, "Tue, 05 Mar 2013 23:25:19 +0000" } = format(date, "{RFC1123z}")
test :format_compound_rfc1123 do
gmt = Date.timezone("GMT")
date = Date.from({{2013,3,5},{23,25,19}}, gmt)
assert { :ok, ^date } = parse("Tue, 05 Mar 2013 23:25:19 GMT", "{RFC1123}")

#eet = Date.timezone(2, "EET")
#date = Date.from({{2013,3,5},{23,25,19}}, eet)
#assert { :ok, "Tue, 05 Mar 2013 23:25:19 EET" } = format(date, "{RFC1123}")
#assert { :ok, "Tue, 05 Mar 2013 23:25:19 +0200" } = format(date, "{RFC1123z}")
date = Date.from({{2013,3,5},{23,25,19}})
assert { :ok, ^date } = parse("Tue, 05 Mar 2013 23:25:19 +0000", "{RFC1123z}")

#pst = Date.timezone(-8, "PST")
#date = Date.from({{2013,3,5},{23,25,19}}, pst)
#assert { :ok, "Tue, 05 Mar 2013 23:25:19 PST" } = format(date, "{RFC1123}")
#assert { :ok, "Tue, 05 Mar 2013 23:25:19 -0800" } = format(date, "{RFC1123z}")
#end
eet = Date.timezone("EET")
date = Date.from({{2013,3,5},{23,25,19}}, eet)
assert { :ok, ^date } = parse("Tue, 05 Mar 2013 23:25:19 EET", "{RFC1123}")

date = Date.from({{2013,3,5},{23,25,19}})
assert { :ok, ^date } = parse("Tue, 05 Mar 2013 23:25:19 +0200", "{RFC1123z}")
end

#test :format_compound_rfc3339 do
#local = {{2013,3,5},{23,25,19}}
Expand Down

0 comments on commit 564a620

Please sign in to comment.