Skip to content

Commit cf84b7b

Browse files
tfiedlerdejanzejosevalim
authored andcommitted
Support plus sign prefix in Calendar.ISO.parse_duration/1 (#13613)
1 parent b84dd54 commit cf84b7b

File tree

3 files changed

+17
-4
lines changed

3 files changed

+17
-4
lines changed

lib/elixir/lib/calendar/duration.ex

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,16 @@ defmodule Duration do
287287
@doc """
288288
Parses an [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601#Durations) formatted duration string to a `Duration` struct.
289289
290-
- 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`.
291-
- A duration string may be prefixed with a minus sign to negate it: `-P10DT4H`.
292-
- Individual units may be prefixed with a minus sign: `P-10DT4H`.
293-
- Only seconds may be specified with a decimal fraction, using either a comma or a full stop: `P1DT4,5S`.
290+
Duration strings, as well as individual units, may be prefixed with plus/minus signs so that:
291+
292+
- `-PT6H3M` parses as `%Duration{hour: -6, minute: -3}`
293+
- `-PT6H-3M` parses as `%Duration{hour: -6, minute: 3}`
294+
- `+PT6H3M` parses as `%Duration{hour: 6, minute: 3}`
295+
- `+PT6H-3M` parses as `%Duration{hour: 6, minute: -3}`
296+
297+
Duration designators must be provided in order of magnitude: `P[n]Y[n]M[n]W[n]DT[n]H[n]M[n]S`.
298+
299+
Only seconds may be specified with a decimal fraction, using either a comma or a full stop: `P1DT4,5S`.
294300
295301
## Examples
296302

lib/elixir/lib/calendar/iso.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,10 @@ defmodule Calendar.ISO do
675675
parse_duration_date(string, [], year: ?Y, month: ?M, week: ?W, day: ?D)
676676
end
677677

678+
def parse_duration("+P" <> string) when byte_size(string) > 0 do
679+
parse_duration_date(string, [], year: ?Y, month: ?M, week: ?W, day: ?D)
680+
end
681+
678682
def parse_duration("-P" <> string) when byte_size(string) > 0 do
679683
with {:ok, fields} <- parse_duration_date(string, [], year: ?Y, month: ?M, week: ?W, day: ?D) do
680684
{:ok,

lib/elixir/test/elixir/calendar/duration_test.exs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,9 @@ defmodule DurationTest do
265265
assert Duration.from_iso8601!("-P10DT4H") == %Duration{day: -10, hour: -4}
266266
assert Duration.from_iso8601!("-P10DT-4H") == %Duration{day: -10, hour: 4}
267267
assert Duration.from_iso8601!("P-10D") == %Duration{day: -10}
268+
assert Duration.from_iso8601!("+P10DT-4H") == %Duration{day: 10, hour: -4}
269+
assert Duration.from_iso8601!("P+10D") == %Duration{day: 10}
270+
assert Duration.from_iso8601!("-P+10D") == %Duration{day: -10}
268271

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

0 commit comments

Comments
 (0)