Skip to content

Commit

Permalink
Support plus sign prefix in Calendar.ISO.parse_duration/1 (#13613)
Browse files Browse the repository at this point in the history
  • Loading branch information
tfiedlerdejanze authored May 28, 2024
1 parent a64f28c commit 29fb214
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 4 deletions.
14 changes: 10 additions & 4 deletions lib/elixir/lib/calendar/duration.ex
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,16 @@ defmodule Duration do
@doc """
Parses an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) formatted duration string to a `Duration` struct.
- A duration string must be designated in order of magnitude: `P[n]Y[n]M[n]W[n]DT[n]H[n]M[n]S`.
- A duration string may be prefixed with a minus sign to negate it: `-P10DT4H`.
- Individual units may be prefixed with a minus sign: `P-10DT4H`.
- Only seconds may be specified with a decimal fraction, using either a comma or a full stop: `P1DT4,5S`.
Duration strings, as well as individual units, may be prefixed with plus/minus signs so that:
- `-PT6H3M` parses as `%Duration{hour: -6, minute: -3}`
- `-PT6H-3M` parses as `%Duration{hour: -6, minute: 3}`
- `+PT6H3M` parses as `%Duration{hour: 6, minute: 3}`
- `+PT6H-3M` parses as `%Duration{hour: 6, minute: -3}`
Duration designators must be provided in order of magnitude: `P[n]Y[n]M[n]W[n]DT[n]H[n]M[n]S`.
Only seconds may be specified with a decimal fraction, using either a comma or a full stop: `P1DT4,5S`.
## Examples
Expand Down
4 changes: 4 additions & 0 deletions lib/elixir/lib/calendar/iso.ex
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,10 @@ defmodule Calendar.ISO do
parse_duration_date(string, [], year: ?Y, month: ?M, week: ?W, day: ?D)
end

def parse_duration("+P" <> string) when byte_size(string) > 0 do
parse_duration_date(string, [], year: ?Y, month: ?M, week: ?W, day: ?D)
end

def parse_duration("-P" <> string) when byte_size(string) > 0 do
with {:ok, fields} <- parse_duration_date(string, [], year: ?Y, month: ?M, week: ?W, day: ?D) do
{:ok,
Expand Down
3 changes: 3 additions & 0 deletions lib/elixir/test/elixir/calendar/duration_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,9 @@ defmodule DurationTest do
assert Duration.from_iso8601!("-P10DT4H") == %Duration{day: -10, hour: -4}
assert Duration.from_iso8601!("-P10DT-4H") == %Duration{day: -10, hour: 4}
assert Duration.from_iso8601!("P-10D") == %Duration{day: -10}
assert Duration.from_iso8601!("+P10DT-4H") == %Duration{day: 10, hour: -4}
assert Duration.from_iso8601!("P+10D") == %Duration{day: 10}
assert Duration.from_iso8601!("-P+10D") == %Duration{day: -10}

assert Duration.from_iso8601!("PT-1.234567S") == %Duration{
second: -1,
Expand Down

0 comments on commit 29fb214

Please sign in to comment.