@@ -80,6 +80,23 @@ def datetime? (i: Int) : Option Datetime :=
80
80
def dateContainsLeapSeconds (str: String) : Bool :=
81
81
str.length >= 20 && str.get? ⟨17 ⟩ == some '6' && str.get? ⟨18 ⟩ == some '0'
82
82
83
+ /--
84
+ Check that the minutes for the timezone offset are in bounds (<60). We
85
+ separately check that the whole offset is less than `MAX_OFFSET_SECONDS` which
86
+ ensures that the hour component is in bounds. The timezone offset does not
87
+ have a seconds component.
88
+ -/
89
+ def tzOffsetMinsLt60 (str : String) : Bool :=
90
+ -- Short string is `DateOnly`, so no offset
91
+ str.length <= 10 ||
92
+ -- Ends in `Z` is either `DateUTC` or `DateUTCWithMillis`, so no offset
93
+ str.endsWith "Z" ||
94
+ -- `DateWithOffset` or `DateWithOffsetAndMillis` offset is last 4 chars.
95
+ -- Minutes component is last two chars.
96
+ match (str.takeRight 2 ).toNat? with
97
+ | .some minsOffset => minsOffset < 60
98
+ | .none => false
99
+
83
100
/--
84
101
Workaround an issue in the datetime library by checking that the year, month,
85
102
day, hour, minute, and second components of the datetime string are not longer
@@ -107,6 +124,7 @@ def checkComponentLen (str : String) : Bool :=
107
124
def parse (str: String) : Option Datetime := do
108
125
if dateContainsLeapSeconds str then failure
109
126
if !checkComponentLen str then failure
127
+ if !tzOffsetMinsLt60 str then failure
110
128
let val :=
111
129
DateOnly.parse str <|>
112
130
DateUTC.parse str <|>
0 commit comments