Skip to content

Commit ebad701

Browse files
author
Simon Coffey
committed
Add full ISO8601 duration decimal support
In previous commits I added millisecond support for the validUntil duration field. It turns out that the ISO8601 spec[1] also supports milliseconds for some other duration components (S4.4.3.2): > If necessary for a particular application, the lowest order > components may have a decimal fraction. Which components this affects is slightly ambiguous; I've interpreted it to mean the hours, minutes and seconds components. In part that's because our current implementation uses DateTime#next_year, #next_month and #next_day to apply all other fields to the computed duration, and these methods only respect integer step inputs. They accept floats, but fractional parts are ignored. This commit therefore adds fractional support to the H/M/S components, and updates the computation to support a comma decimal separator. [1] https://www.loc.gov/standards/datetime/iso-tc154-wg5_n0038_iso_wd_8601-1_2016-02-16.pdf
1 parent cb98e39 commit ebad701

1 file changed

Lines changed: 10 additions & 15 deletions

File tree

lib/onelogin/ruby-saml/utils.rb

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,18 @@ class Utils
1616
DSIG = "http://www.w3.org/2000/09/xmldsig#"
1717
XENC = "http://www.w3.org/2001/04/xmlenc#"
1818
DURATION_FORMAT = %r(^
19-
(-?)P # 1: Duration sign
19+
(-?)P # 1: Duration sign
2020
(?:
21-
(?:(\d+)Y)? # 2: Years
22-
(?:(\d+)M)? # 3: Months
23-
(?:(\d+)D)? # 4: Days
21+
(?:(\d+)Y)? # 2: Years
22+
(?:(\d+)M)? # 3: Months
23+
(?:(\d+)D)? # 4: Days
2424
(?:T
25-
(?:(\d+)H)? # 5: Hours
26-
(?:(\d+)M)? # 6: Minutes
27-
(?:(\d+(?:\.\d{3})?)S)? # 7: Seconds and optional milliseconds
25+
(?:(\d+(?:[.,]\d+)?)H)? # 5: Hours
26+
(?:(\d+(?:[.,]\d+)?)M)? # 6: Minutes
27+
(?:(\d+(?:[.,]\d+)?)S)? # 7: Seconds
2828
)?
2929
|
30-
(\d+)W # 8: Weeks
30+
(\d+)W # 8: Weeks
3131
)
3232
$)x
3333

@@ -59,13 +59,8 @@ def self.parse_duration(duration, timestamp=Time.now.utc)
5959
raise Exception.new("Invalid ISO 8601 duration")
6060
end
6161

62-
durYears = matches[2].to_i
63-
durMonths = matches[3].to_i
64-
durDays = matches[4].to_i
65-
durHours = matches[5].to_i
66-
durMinutes = matches[6].to_i
67-
durSeconds = matches[7].to_f
68-
durWeeks = matches[8].to_i
62+
durYears, durMonths, durDays, durHours, durMinutes, durSeconds, durWeeks =
63+
matches[2..8].map { |match| match ? match.tr(',', '.').to_f : 0.0 }
6964

7065
if matches[1] == "-"
7166
durYears = -durYears

0 commit comments

Comments
 (0)