Add support for RFC3164/RFC5424 formats

Many devices send dates that do not conform to the RFCs...

Also add support for the strange "TZ-0700" variant of the "UTC-0700"
offset.

Cover all the changes with new tests.
This commit is contained in:
Klondike Dragon 2025-04-12 15:48:03 -06:00
parent 2c0ba64777
commit b058bd310c
5 changed files with 101 additions and 3 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
dist
vendor
dateparse/dateparse
example/example

View File

@ -312,6 +312,30 @@ var examples = []string{
"1384216367189",
"1384216367111222",
"1384216367111222333",
// syslog RFC3164 (and non-conformant variants)
"Apr 9 12:37:24",
"Apr 9 12:37:24-10",
"Apr 9 12:37:24-1000",
"Apr 9 12:37:24 UTC-10",
"Apr 9 12:37:24 MST",
"Apr 9 12:37:24 MST-07:00",
"Apr 9 12:37:24 TZ-10",
"Apr 9 12:37:24 TZ+02:00",
"Apr 9 12:37:24+10",
"Apr 9 12:37:24+10:00",
"Apr 9 12:37:24 CEST",
"Apr 9 12:37:24 CEST+0200",
"Apr 9 12:37:24 2025",
"Apr 9 12:37:24 2025 +02:00",
"Apr 9 2025 12:37:24",
"Apr 9 2025 12:37:24 -0700",
// syslog RFC5424 (and non-conformant variants)
"2025-04-09T12:37:24Z",
"2025-04-09T12:37:24.123Z",
"2025-04-09T12:37:24.123456Z",
"2025-04-09T12:37:24-10:00",
"2025-04-09T12:37:24.123 +0200",
"2025-04-09T12:37:24.123456 -0700 MDT",
}
var (
@ -377,10 +401,10 @@ func main() {
| 1st February 2018 13:58:24 | 2018-02-01 13:58:24 +0000 UTC |
| Mon, 02 Jan 2006 15:04:05 MST | 2006-01-02 15:04:05 +0000 MST |
| Mon, 02 Jan 2006 15:04:05 -0700 | 2006-01-02 15:04:05 -0700 -0700 |
| Tue, 11 Jul 2017 16:28:13 +0200 (CEST) | 2017-07-11 16:28:13 +0200 +0200 |
| Tue, 11 Jul 2017 16:28:13 +0200 (CEST) | 2017-07-11 16:28:13 +0200 CEST |
| Mon 30 Sep 2018 09:09:09 PM UTC | 2018-09-30 21:09:09 +0000 UTC |
| Sun, 07 Jun 2020 00:00:00 +0100 | 2020-06-07 00:00:00 +0100 +0100 |
| Wed, 8 Feb 2023 19:00:46 +1100 (AEDT) | 2023-02-08 19:00:46 +1100 +1100 |
| Wed, 8 Feb 2023 19:00:46 +1100 (AEDT) | 2023-02-08 19:00:46 +1100 AEDT |
| Mon Jan 2 15:04:05 2006 | 2006-01-02 15:04:05 +0000 UTC |
| Mon Jan 2 15:04:05 MST 2006 | 2006-01-02 15:04:05 +0000 MST |
| Monday Jan 02 15:04:05 -0700 2006 | 2006-01-02 15:04:05 -0700 -0700 |
@ -526,6 +550,28 @@ func main() {
| 1384216367189 | 2013-11-12 00:32:47.189 +0000 UTC |
| 1384216367111222 | 2013-11-12 00:32:47.111222 +0000 UTC |
| 1384216367111222333 | 2013-11-12 00:32:47.111222333 +0000 UTC |
| Apr 9 12:37:24 | 0000-04-09 12:37:24 +0000 UTC |
| Apr 9 12:37:24-10 | 0000-04-09 12:37:24 -1000 -1000 |
| Apr 9 12:37:24-1000 | 0000-04-09 12:37:24 -1000 -1000 |
| Apr 9 12:37:24 UTC-10 | 0000-04-09 12:37:24 -1000 -1000 |
| Apr 9 12:37:24 MST | 0000-04-09 12:37:24 +0000 MST |
| Apr 9 12:37:24 MST-07:00 | 0000-04-09 12:37:24 -0700 MST |
| Apr 9 12:37:24 TZ-10 | 0000-04-09 12:37:24 -1000 -1000 |
| Apr 9 12:37:24 TZ+02:00 | 0000-04-09 12:37:24 +0200 +0200 |
| Apr 9 12:37:24+10 | 0000-04-09 12:37:24 +1000 +1000 |
| Apr 9 12:37:24+10:00 | 0000-04-09 12:37:24 +1000 +1000 |
| Apr 9 12:37:24 CEST | 0000-04-09 12:37:24 +0000 CEST |
| Apr 9 12:37:24 CEST+0200 | 0000-04-09 12:37:24 +0200 CEST |
| Apr 9 12:37:24 2025 | 2025-04-09 12:37:24 +0000 UTC |
| Apr 9 12:37:24 2025 +02:00 | 2025-04-09 12:37:24 +0200 +0200 |
| Apr 9 2025 12:37:24 | 2025-04-09 12:37:24 +0000 UTC |
| Apr 9 2025 12:37:24 -0700 | 2025-04-09 12:37:24 -0700 -0700 |
| 2025-04-09T12:37:24Z | 2025-04-09 12:37:24 +0000 UTC |
| 2025-04-09T12:37:24.123Z | 2025-04-09 12:37:24.123 +0000 UTC |
| 2025-04-09T12:37:24.123456Z | 2025-04-09 12:37:24.123456 +0000 UTC |
| 2025-04-09T12:37:24-10:00 | 2025-04-09 12:37:24 -1000 -1000 |
| 2025-04-09T12:37:24.123 +0200 | 2025-04-09 12:37:24.123 +0200 +0200 |
| 2025-04-09T12:37:24.123456 -0700 MDT | 2025-04-09 12:37:24.123456 -0700 MDT |
+------------------------------------------------------------+-----------------------------------------+
*/

View File

@ -220,6 +220,30 @@ var examples = []string{
"1384216367189",
"1384216367111222",
"1384216367111222333",
// syslog RFC3164 (and non-conformant variants)
"Apr 9 12:37:24",
"Apr 9 12:37:24-10",
"Apr 9 12:37:24-1000",
"Apr 9 12:37:24 UTC-10",
"Apr 9 12:37:24 MST",
"Apr 9 12:37:24 MST-07:00",
"Apr 9 12:37:24 TZ-10",
"Apr 9 12:37:24 TZ+02:00",
"Apr 9 12:37:24+10",
"Apr 9 12:37:24+10:00",
"Apr 9 12:37:24 CEST",
"Apr 9 12:37:24 CEST+0200",
"Apr 9 12:37:24 2025",
"Apr 9 12:37:24 2025 +02:00",
"Apr 9 2025 12:37:24",
"Apr 9 2025 12:37:24 -0700",
// syslog RFC5424 (and non-conformant variants)
"2025-04-09T12:37:24Z",
"2025-04-09T12:37:24.123Z",
"2025-04-09T12:37:24.123456Z",
"2025-04-09T12:37:24-10:00",
"2025-04-09T12:37:24.123 +0200",
"2025-04-09T12:37:24.123456 -0700 MDT",
}
var (

View File

@ -1934,7 +1934,7 @@ iterRunes:
switch r {
case '+', '-':
tzNameLower := strings.ToLower(p.datestr[p.tzi:i])
if tzNameLower == "gmt" || tzNameLower == "utc" {
if tzNameLower == "gmt" || tzNameLower == "utc" || tzNameLower == "tz" {
// This is a special form where the actual timezone isn't UTC, but is rather
// specifying that the correct offset is a specified numeric offset from UTC:
// 06:20:00 UTC-05

View File

@ -789,6 +789,31 @@ var testInputs = []dateTest{
{in: " 2018-01-02 17:08:09 -07:00", out: "2018-01-03 00:08:09 +0000 UTC"},
{in: " 2018-01-02 17:08:09 -07:00", out: "2018-01-03 00:08:09 +0000 UTC"},
{in: " 2018-01-02 17:08:09 -07:00", out: "2018-01-03 00:08:09 +0000 UTC"},
//syslog RFC3164 formats and non-conformant variants observed in the wild
{in: "Apr 9 12:37:24", out: "0000-04-09 12:37:24 +0000 UTC"},
{in: "Apr 9 12:37:24-10", out: "0000-04-09 22:37:24 +0000 UTC"},
{in: "Apr 9 12:37:24-1000", out: "0000-04-09 22:37:24 +0000 UTC"},
{in: "Apr 9 12:37:24 UTC-10", out: "0000-04-09 22:37:24 +0000 UTC"},
{in: "Apr 9 12:37:24 MST", out: "0000-04-09 12:37:24 +0000 UTC", zname: "MST"},
{in: "Apr 9 12:37:24 MST-07:00", out: "0000-04-09 19:37:24 +0000 UTC", zname: "MST"},
{in: "Apr 9 12:37:24 TZ-10", out: "0000-04-09 22:37:24 +0000 UTC"},
{in: "Apr 9 12:37:24 TZ+02:00", out: "0000-04-09 10:37:24 +0000 UTC"},
{in: "Apr 9 12:37:24+10", out: "0000-04-09 02:37:24 +0000 UTC"},
{in: "Apr 9 12:37:24+10:00", out: "0000-04-09 02:37:24 +0000 UTC"},
{in: "Apr 9 12:37:24 CEST", out: "0000-04-09 12:37:24 +0000 UTC", zname: "CEST"},
{in: "Apr 9 12:37:24 CEST+0200", out: "0000-04-09 10:37:24 +0000 UTC", zname: "CEST"},
{in: "Apr 9 12:37:24 2025", out: "2025-04-09 12:37:24 +0000 UTC"},
{in: "Apr 9 12:37:24 2025 +02:00", out: "2025-04-09 10:37:24 +0000 UTC"},
{in: "Apr 9 2025 12:37:24", out: "2025-04-09 12:37:24 +0000 UTC"},
{in: "Apr 9 2025 12:37:24 -0700", out: "2025-04-09 19:37:24 +0000 UTC"},
//syslog RFC5424 formats and non-conformant variants observed in the wild
{in: "2025-04-09T12:37:24Z", out: "2025-04-09 12:37:24 +0000 UTC"},
{in: "2025-04-09T12:37:24.123Z", out: "2025-04-09 12:37:24.123 +0000 UTC"},
{in: "2025-04-09T12:37:24.123456Z", out: "2025-04-09 12:37:24.123456 +0000 UTC"},
{in: "2025-04-09T12:37:24-10:00", out: "2025-04-09 22:37:24 +0000 UTC"},
{in: "2025-04-09T12:37:24.123 +0200", out: "2025-04-09 10:37:24.123 +0000 UTC"},
{in: "2025-04-09T12:37:24.123456 -0700 MDT", out: "2025-04-09 19:37:24.123456 +0000 UTC", zname: "MDT"},
}
func TestParse(t *testing.T) {
@ -1025,6 +1050,8 @@ var testParseErrors = []dateTest{
{in: "Fri Jul 3 2015 06:04:07 UTC (GMT", err: true},
{in: "Fri Jul 3 2015 06:04:07 PST (Pacific (Daylight) Time)", err: true},
{in: "Fri Jul 3 2015 06:04:07 CEST (Central European Summer Time) extra", err: true},
// Special TZ indicator must be followed by an offset
{in: "Apr 9 12:37:24 TZ", err: true},
}
func TestParseErrors(t *testing.T) {