#include <StringConstants.au3> ; to declare the Constants of StringRegExp
#include <Array.au3> ; UDF needed for _ArrayDisplay and _ArrayConcatenate
Local $sRegex = "(?m)(?=(?:^(?:\d\d\d\d-(?:0[1-9]|10|11|12)-(?:0[1-9]|1[0-9]|2[0-8])|\d\d\d\d-(?:0[13-9]|10|11|12)-(?:29|30)|\d\d\d\d-(?:0[13578]|10|12)-31|(?:\d\d[2468][048]|\d\d0[48]|\d\d[13579][26])-02-29|(?:[02468][048]00|[13579][26]00)-02-29)T(?:(?:0[0-9]|1[0-9]|2[0-3]):(?:[0-5][0-9]):(?:[0-5][0-9]))(?:\.\d\d\d)?(?:Z|[\+\-](?:0[0-9]|1[012]):00|\+0[34569]:30|\+10:30|-0[39]:30|\+1[34]:00|\+0[58]:45|\+12:45)$)|^(?:1972|198[1235]|199[2347]|2012|2015)-06-30T23:59:60Z$|^(?:197[2-9]|1987|1989|199[058]|2005|2008|2016)-12-31T23:59:60Z$)(?!.*-00:00$)^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(?:\.(\d\d\d))?((Z)|([\+\-])(\d\d):(\d\d))$"
Local $sString = "Strong Matcher for ISO 8601 / RFC 3339 Date Times; rejects bad TZ offsets, illegal times (Museum of Bad Data)" & @CRLF & _
"See below for expanded matcher" & @CRLF & _
"" & @CRLF & _
"```" & @CRLF & _
"// accept: Exemplars" & @CRLF & _
"2008-02-03T04:05:06.007Z" & @CRLF & _
"2008-02-03T04:05:06Z" & @CRLF & _
"0000-01-01T00:00:00.000Z" & @CRLF & _
"0000-02-29T04:05:06.007Z" & @CRLF & _
"9999-12-31T23:59:59.999Z" & @CRLF & _
"9999-12-31T23:59:59Z" & @CRLF & _
"2008-02-03T04:05:06.007+12:45" & @CRLF & _
"2008-02-03T04:05:06+03:30" & @CRLF & _
"0000-01-01T00:00:00.007-09:30" & @CRLF & _
"0000-02-29T04:05:06.007+14:00" & @CRLF & _
"9999-12-31T23:59:59.999+12:00" & @CRLF & _
"9999-12-31T23:59:59-12:00" & @CRLF & _
"// accept: Leap day, year is multiple of four" & @CRLF & _
"0004-02-29T04:05:06.007Z" & @CRLF & _
"0008-02-29T04:05:06.007Z" & @CRLF & _
"0012-02-29T04:05:06.007Z" & @CRLF & _
"0016-02-29T04:05:06.007Z" & @CRLF & _
"0020-02-29T04:05:06.007Z" & @CRLF & _
"0024-02-29T04:05:06.007Z" & @CRLF & _
"0028-02-29T04:05:06.007Z" & @CRLF & _
"0032-02-29T04:05:06.007Z" & @CRLF & _
"0036-02-29T04:05:06.007Z" & @CRLF & _
"0040-02-29T04:05:06.007Z" & @CRLF & _
"0044-02-29T04:05:06.007Z" & @CRLF & _
"0048-02-29T04:05:06.007Z" & @CRLF & _
"0052-02-29T04:05:06.007Z" & @CRLF & _
"0056-02-29T04:05:06.007Z" & @CRLF & _
"0060-02-29T04:05:06.007Z" & @CRLF & _
"0064-02-29T04:05:06.007Z" & @CRLF & _
"0068-02-29T04:05:06.007Z" & @CRLF & _
"0072-02-29T04:05:06.007Z" & @CRLF & _
"0076-02-29T04:05:06.007Z" & @CRLF & _
"0080-02-29T04:05:06.007Z" & @CRLF & _
"0084-02-29T04:05:06.007Z" & @CRLF & _
"0088-02-29T04:05:06.007Z" & @CRLF & _
"0092-02-29T04:05:06.007Z" & @CRLF & _
"0096-02-29T04:05:06.007Z" & @CRLF & _
"1560-02-29T04:05:06.007Z" & @CRLF & _
"2004-02-29T04:05:06.007Z" & @CRLF & _
"2008-02-29T04:05:06.007Z" & @CRLF & _
"2012-02-29T04:05:06.007Z" & @CRLF & _
"2016-02-29T04:05:06.007Z" & @CRLF & _
"2020-02-29T04:05:06.007Z" & @CRLF & _
"2024-02-29T04:05:06.007Z" & @CRLF & _
"2028-02-29T04:05:06.007Z" & @CRLF & _
"2032-02-29T04:05:06.007Z" & @CRLF & _
"2036-02-29T04:05:06.007Z" & @CRLF & _
"2040-02-29T04:05:06.007Z" & @CRLF & _
"2044-02-29T04:05:06.007Z" & @CRLF & _
"9996-02-29T04:05:06.007Z" & @CRLF & _
"// accept: Leap day, year is Multiple of 400" & @CRLF & _
"0000-02-29T04:05:06.007Z" & @CRLF & _
"0400-02-29T04:05:06.007Z" & @CRLF & _
"0800-02-29T04:05:06.007Z" & @CRLF & _
"1200-02-29T04:05:06.007Z" & @CRLF & _
"1600-02-29T04:05:06.007Z" & @CRLF & _
"2000-02-29T04:05:06.007Z" & @CRLF & _
"2400-02-29T04:05:06.007Z" & @CRLF & _
"2800-02-29T04:05:06.007Z" & @CRLF & _
"3200-02-29T04:05:06.007Z" & @CRLF & _
"3600-02-29T04:05:06.007Z" & @CRLF & _
"4000-02-29T04:05:06.007Z" & @CRLF & _
"4400-02-29T04:05:06.007Z" & @CRLF & _
"4800-02-29T04:05:06.007Z" & @CRLF & _
"5200-02-29T04:05:06.007Z" & @CRLF & _
"5600-02-29T04:05:06.007Z" & @CRLF & _
"6000-02-29T04:05:06.007Z" & @CRLF & _
"6400-02-29T04:05:06.007Z" & @CRLF & _
"6800-02-29T04:05:06.007Z" & @CRLF & _
"7200-02-29T04:05:06.007Z" & @CRLF & _
"7600-02-29T04:05:06.007Z" & @CRLF & _
"8000-02-29T04:05:06.007Z" & @CRLF & _
"8400-02-29T04:05:06.007Z" & @CRLF & _
"8800-02-29T04:05:06.007Z" & @CRLF & _
"9200-02-29T04:05:06.007Z" & @CRLF & _
"9600-02-29T04:05:06.007Z" & @CRLF & _
"// accept: Day in range for month" & @CRLF & _
"2008-01-30T04:05:06.007Z" & @CRLF & _
"2008-03-30T04:05:06.007Z" & @CRLF & _
"2008-04-30T04:05:06.007Z" & @CRLF & _
"2008-05-30T04:05:06.007Z" & @CRLF & _
"2008-06-30T04:05:06.007Z" & @CRLF & _
"2008-07-30T04:05:06.007Z" & @CRLF & _
"2008-08-30T04:05:06.007Z" & @CRLF & _
"2008-09-30T04:05:06.007Z" & @CRLF & _
"2008-10-30T04:05:06.007Z" & @CRLF & _
"2008-11-30T04:05:06.007Z" & @CRLF & _
"2008-12-30T04:05:06.007Z" & @CRLF & _
"2008-01-31T04:05:06.007Z" & @CRLF & _
"2008-03-31T04:05:06.007Z" & @CRLF & _
"2008-05-31T04:05:06.007Z" & @CRLF & _
"2008-07-31T04:05:06.007Z" & @CRLF & _
"2008-08-31T04:05:06.007Z" & @CRLF & _
"2008-10-31T04:05:06.007Z" & @CRLF & _
"2008-12-31T04:05:06.007Z" & @CRLF & _
"// accept: had leap second" & @CRLF & _
"1972-06-30T23:59:60Z" & @CRLF & _
"1981-06-30T23:59:60Z" & @CRLF & _
"1982-06-30T23:59:60Z" & @CRLF & _
"1983-06-30T23:59:60Z" & @CRLF & _
"1985-06-30T23:59:60Z" & @CRLF & _
"1992-06-30T23:59:60Z" & @CRLF & _
"1993-06-30T23:59:60Z" & @CRLF & _
"1994-06-30T23:59:60Z" & @CRLF & _
"1997-06-30T23:59:60Z" & @CRLF & _
"2012-06-30T23:59:60Z" & @CRLF & _
"2015-06-30T23:59:60Z" & @CRLF & _
"1972-12-31T23:59:60Z" & @CRLF & _
"1973-12-31T23:59:60Z" & @CRLF & _
"1974-12-31T23:59:60Z" & @CRLF & _
"1975-12-31T23:59:60Z" & @CRLF & _
"1976-12-31T23:59:60Z" & @CRLF & _
"1977-12-31T23:59:60Z" & @CRLF & _
"1978-12-31T23:59:60Z" & @CRLF & _
"1979-12-31T23:59:60Z" & @CRLF & _
"1987-12-31T23:59:60Z" & @CRLF & _
"1989-12-31T23:59:60Z" & @CRLF & _
"1990-12-31T23:59:60Z" & @CRLF & _
"1995-12-31T23:59:60Z" & @CRLF & _
"1998-12-31T23:59:60Z" & @CRLF & _
"2005-12-31T23:59:60Z" & @CRLF & _
"2008-12-31T23:59:60Z" & @CRLF & _
"2016-12-31T23:59:60Z" & @CRLF & _
"// REJECT: Year out of range" & @CRLF & _
"10000-02-29T04:05:06.007Z" & @CRLF & _
"// REJECT: Month out of range" & @CRLF & _
"2008-00-30T04:05:06.007Z" & @CRLF & _
"2008-13-30T04:05:06.007Z" & @CRLF & _
"2008-14-30T04:05:06.007Z" & @CRLF & _
"2008-20-30T04:05:06.007Z" & @CRLF & _
"// REJECT: Day out of range for month" & @CRLF & _
"2008-02-30T04:05:06.007Z" & @CRLF & _
"2008-04-31T04:05:06.007Z" & @CRLF & _
"2008-06-31T04:05:06.007Z" & @CRLF & _
"2008-09-31T04:05:06.007Z" & @CRLF & _
"2008-11-31T04:05:06.007Z" & @CRLF & _
"2008-02-31T04:05:06.007Z" & @CRLF & _
"// REJECT: Day out of range" & @CRLF & _
"2008-12-32T04:05:06.007Z" & @CRLF & _
"2008-12-99T04:05:06.007Z" & @CRLF & _
"2008-12-00T04:05:06.007Z" & @CRLF & _
"// REJECT: Hour out of range" & @CRLF & _
"2008-12-08T60:05:06.007Z" & @CRLF & _
"2008-12-08T99:05:06.007Z" & @CRLF & _
"// REJECT: Minute out of range" & @CRLF & _
"2008-12-08T04:60:06.007Z" & @CRLF & _
"2008-12-08T04:99:06.007Z" & @CRLF & _
"// REJECT: Seconds out of range" & @CRLF & _
"9999-12-31T59:59:61.999Z" & @CRLF & _
"2008-02-03T04:05:61.999Z" & @CRLF & _
"2008-02-03T04:05:61Z" & @CRLF & _
"// REJECT: Negative dates not accepted" & @CRLF & _
"-2000-02-29T04:05:06.007Z" & @CRLF & _
"-0400-02-29T04:05:06.007Z" & @CRLF & _
"-0100-02-29T04:05:06.007Z" & @CRLF & _
"-0004-02-29T04:05:06.007Z" & @CRLF & _
"// REJECT: stray characters" & @CRLF & _
" 2008-12-31T04:05:06.007Z" & @CRLF & _
"2008-12-31T04:05:06.007Z " & @CRLF & _
"2008-12-31T04:05:06.007 Z" & @CRLF & _
"// REJECT: Malformed" & @CRLF & _
"2008-02-0304:05:06.007Z" & @CRLF & _
"20080203T040506.007Z" & @CRLF & _
"2008-02-03T04:05:06007Z" & @CRLF & _
"2008-02-03T04:05:06.7Z" & @CRLF & _
"2008-02-03T04:05:06.07Z" & @CRLF & _
"2008-02-03T04:05:06.0007Z" & @CRLF & _
"2008-02-03T04:05:06" & @CRLF & _
"2008-02-03T04:05:06.Z" & @CRLF & _
"// REJECT: no leap second" & @CRLF & _
"1973-06-30T23:59:60Z" & @CRLF & _
"1974-06-30T23:59:60Z" & @CRLF & _
"1975-06-30T23:59:60Z" & @CRLF & _
"1976-06-30T23:59:60Z" & @CRLF & _
"1977-06-30T23:59:60Z" & @CRLF & _
"1978-06-30T23:59:60Z" & @CRLF & _
"1979-06-30T23:59:60Z" & @CRLF & _
"1980-06-30T23:59:60Z" & @CRLF & _
"1984-06-30T23:59:60Z" & @CRLF & _
"1986-06-30T23:59:60Z" & @CRLF & _
"1987-06-30T23:59:60Z" & @CRLF & _
"1988-06-30T23:59:60Z" & @CRLF & _
"1989-06-30T23:59:60Z" & @CRLF & _
"1990-06-30T23:59:60Z" & @CRLF & _
"1991-06-30T23:59:60Z" & @CRLF & _
"1995-06-30T23:59:60Z" & @CRLF & _
"1996-06-30T23:59:60Z" & @CRLF & _
"1998-06-30T23:59:60Z" & @CRLF & _
"1999-06-30T23:59:60Z" & @CRLF & _
"2000-06-30T23:59:60Z" & @CRLF & _
"2001-06-30T23:59:60Z" & @CRLF & _
"2002-06-30T23:59:60Z" & @CRLF & _
"2003-06-30T23:59:60Z" & @CRLF & _
"2004-06-30T23:59:60Z" & @CRLF & _
"2005-06-30T23:59:60Z" & @CRLF & _
"2006-06-30T23:59:60Z" & @CRLF & _
"2007-06-30T23:59:60Z" & @CRLF & _
"2008-06-30T23:59:60Z" & @CRLF & _
"2009-06-30T23:59:60Z" & @CRLF & _
"2010-06-30T23:59:60Z" & @CRLF & _
"2011-06-30T23:59:60Z" & @CRLF & _
"2013-06-30T23:59:60Z" & @CRLF & _
"2014-06-30T23:59:60Z" & @CRLF & _
"2016-06-30T23:59:60Z" & @CRLF & _
"2017-06-30T23:59:60Z" & @CRLF & _
"2018-06-30T23:59:60Z" & @CRLF & _
"2019-06-30T23:59:60Z" & @CRLF & _
"2020-06-30T23:59:60Z" & @CRLF & _
"2021-06-30T23:59:60Z" & @CRLF & _
"2022-06-30T23:59:60Z" & @CRLF & _
"2023-06-30T23:59:60Z" & @CRLF & _
"1980-12-31T23:59:60Z" & @CRLF & _
"1981-12-31T23:59:60Z" & @CRLF & _
"1982-12-31T23:59:60Z" & @CRLF & _
"1983-12-31T23:59:60Z" & @CRLF & _
"1984-12-31T23:59:60Z" & @CRLF & _
"1985-12-31T23:59:60Z" & @CRLF & _
"1986-12-31T23:59:60Z" & @CRLF & _
"1988-12-31T23:59:60Z" & @CRLF & _
"1991-12-31T23:59:60Z" & @CRLF & _
"1992-12-31T23:59:60Z" & @CRLF & _
"1993-12-31T23:59:60Z" & @CRLF & _
"1994-12-31T23:59:60Z" & @CRLF & _
"1996-12-31T23:59:60Z" & @CRLF & _
"1997-12-31T23:59:60Z" & @CRLF & _
"1999-12-31T23:59:60Z" & @CRLF & _
"2000-12-31T23:59:60Z" & @CRLF & _
"2001-12-31T23:59:60Z" & @CRLF & _
"2002-12-31T23:59:60Z" & @CRLF & _
"2003-12-31T23:59:60Z" & @CRLF & _
"2004-12-31T23:59:60Z" & @CRLF & _
"2006-12-31T23:59:60Z" & @CRLF & _
"2007-12-31T23:59:60Z" & @CRLF & _
"2009-12-31T23:59:60Z" & @CRLF & _
"2010-12-31T23:59:60Z" & @CRLF & _
"2011-12-31T23:59:60Z" & @CRLF & _
"2012-12-31T23:59:60Z" & @CRLF & _
"2013-12-31T23:59:60Z" & @CRLF & _
"2014-12-31T23:59:60Z" & @CRLF & _
"2015-12-31T23:59:60Z" & @CRLF & _
"2017-12-31T23:59:60Z" & @CRLF & _
"2018-12-31T23:59:60Z" & @CRLF & _
"2019-12-31T23:59:60Z" & @CRLF & _
"2020-12-31T23:59:60Z" & @CRLF & _
"2021-12-31T23:59:60Z" & @CRLF & _
"2022-12-31T23:59:60Z" & @CRLF & _
"2023-12-31T23:59:60Z" & @CRLF & _
"// REJECT: assumes no future leap seconds" & @CRLF & _
"2024-12-31T23:59:60Z" & @CRLF & _
"2099-12-31T23:59:60Z" & @CRLF & _
"9999-12-31T23:59:60Z" & @CRLF & _
"// REJECT: leap seconds only in UTC format" & @CRLF & _
"2005-12-31T23:59:60+00:00" & @CRLF & _
"2008-12-31T23:59:60+00:00" & @CRLF & _
"// REJECT: Not a leap day, year is not a multiple of four" & @CRLF & _
"0101-02-29T04:05:06.007Z" & @CRLF & _
"0102-02-29T04:05:06.007Z" & @CRLF & _
"0103-02-29T04:05:06.007Z" & @CRLF & _
"1537-02-29T04:05:06.007Z" & @CRLF & _
"1538-02-29T04:05:06.007Z" & @CRLF & _
"2001-02-29T04:05:06.007Z" & @CRLF & _
"2002-02-29T04:05:06.007Z" & @CRLF & _
"2003-02-29T04:05:06.007Z" & @CRLF & _
"2021-02-29T04:05:06.007Z" & @CRLF & _
"2022-02-29T04:05:06.007Z" & @CRLF & _
"2023-02-29T04:05:06.007Z" & @CRLF & _
"2025-02-29T04:05:06.007Z" & @CRLF & _
"2026-02-29T04:05:06.007Z" & @CRLF & _
"2027-02-29T04:05:06.007Z" & @CRLF & _
"2029-02-29T04:05:06.007Z" & @CRLF & _
"2030-02-29T04:05:06.007Z" & @CRLF & _
"2031-02-29T04:05:06.007Z" & @CRLF & _
"2033-02-29T04:05:06.007Z" & @CRLF & _
"2034-02-29T04:05:06.007Z" & @CRLF & _
"2035-02-29T04:05:06.007Z" & @CRLF & _
"2037-02-29T04:05:06.007Z" & @CRLF & _
"2038-02-29T04:05:06.007Z" & @CRLF & _
"2039-02-29T04:05:06.007Z" & @CRLF & _
"2041-02-29T04:05:06.007Z" & @CRLF & _
"2042-02-29T04:05:06.007Z" & @CRLF & _
"2043-02-29T04:05:06.007Z" & @CRLF & _
"9997-02-29T04:05:06.007Z" & @CRLF & _
"9998-02-29T04:05:06.007Z" & @CRLF & _
"9999-02-29T04:05:06.007Z" & @CRLF & _
"// REJECT: Not a leap day, year is a multiple of 100 but not 400" & @CRLF & _
"0100-02-29T04:05:06.007Z" & @CRLF & _
"0200-02-29T04:05:06.007Z" & @CRLF & _
"0300-02-29T04:05:06.007Z" & @CRLF & _
"0500-02-29T04:05:06.007Z" & @CRLF & _
"0600-02-29T04:05:06.007Z" & @CRLF & _
"0700-02-29T04:05:06.007Z" & @CRLF & _
"0900-02-29T04:05:06.007Z" & @CRLF & _
"1000-02-29T04:05:06.007Z" & @CRLF & _
"1100-02-29T04:05:06.007Z" & @CRLF & _
"1500-02-29T04:05:06.007Z" & @CRLF & _
"2100-02-29T04:05:06.007Z" & @CRLF & _
"2200-02-29T04:05:06.007Z" & @CRLF & _
"2300-02-29T04:05:06.007Z" & @CRLF & _
"2500-02-29T04:05:06.007Z" & @CRLF & _
"2600-02-29T04:05:06.007Z" & @CRLF & _
"2700-02-29T04:05:06.007Z" & @CRLF & _
"2900-02-29T04:05:06.007Z" & @CRLF & _
"3000-02-29T04:05:06.007Z" & @CRLF & _
"3100-02-29T04:05:06.007Z" & @CRLF & _
"3300-02-29T04:05:06.007Z" & @CRLF & _
"3400-02-29T04:05:06.007Z" & @CRLF & _
"3500-02-29T04:05:06.007Z" & @CRLF & _
"3700-02-29T04:05:06.007Z" & @CRLF & _
"```" & @CRLF & _
"" & @CRLF & _
"```" & @CRLF & _
"(?=" & @CRLF & _
" (?:^" & @CRLF & _
" (?: # All non-leap-second YYYY-MM-DD parts:" & @CRLF & _
" (?:\d\d\d\d-(?:0[1-9] |10|11|12)-(?:0[1-9]|1[0-9]|2[0-8])) # Days 01-28" & @CRLF & _
" | (?:\d\d\d\d-(?:0[13-9] |10|11|12)-(29|30)) # Days 29+30" & @CRLF & _
" | (?:\d\d\d\d-(?:0[13578]|10 |12)-31) # Day 31" & @CRLF & _
" | (?:\d\d[2468][048]|\d\d0[48]|\d\d[13579][26])-02-29 # leap years not divisible by 100" & @CRLF & _
" | (?:[02468][048]00|[13579][26]00)-02-29 # leap years divisible by 400" & @CRLF & _
" )" & @CRLF & _
" T" & @CRLF & _
" (?:(?:0[0-9]|1[0-9]|2[0-3]):(?:[0-5][0-9]):(?:[0-5][0-9])) # time part" & @CRLF & _
" (?:\.\d\d\d)? # ms part (optional)" & @CRLF & _
" (?:Z|[\+\-](?:0[0-9]|1[012]):00|\+0[34569]:30|\+10:30|-0[39]:30|\+1[34]:00|\+0[58]:45|\+12:45)" & @CRLF & _
" $)" & @CRLF & _
" |^(?:1972 |198[1235]|199[2347]|2012|2015 )-06-30T23:59:60Z$ # all june leapsecs" & @CRLF & _
" |^(?:197[2-9]|1987|1989|199[058] |2005|2008|2016)-12-31T23:59:60Z$ # all december leapsecs" & @CRLF & _
")" & @CRLF & _
"(?!.*-00:00$) # if given a -00:00 offset reject unconditionally, psychhhh" & @CRLF & _
"# OK! Since only valid times are now possible, we can use a loose pattern match to parse." & @CRLF & _
"^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(?:\.(\d\d\d))?((Z)|([\+\-])(\d\d):(\d\d))$" & @CRLF & _
"```"
Local $aArray = StringRegExp($sString, $sRegex, $STR_REGEXPARRAYGLOBALFULLMATCH)
Local $aFullArray[0]
For $i = 0 To UBound($aArray) -1
_ArrayConcatenate($aFullArray, $aArray[$i])
Next
$aArray = $aFullArray
; Present the entire match result
_ArrayDisplay($aArray, "Result")
Please keep in mind that these code samples are automatically generated and are not guaranteed to work. If you find any syntax errors, feel free to submit a bug report. For a full regex reference for AutoIt, please visit: https://www.autoitscript.com/autoit3/docs/functions/StringRegExp.htm