diff --git a/parse.go b/parse.go index e31dc839..33d8f025 100644 --- a/parse.go +++ b/parse.go @@ -372,6 +372,9 @@ func (p *parser) valueDatetime(it item) (any, tomlType) { } t, err = time.ParseInLocation(dt.fmt, it.val, dt.zone) if err == nil { + if missingLeadingZero(it.val, dt.fmt) { + p.panicErr(it, errParseDate{it.val}) + } ok = true break } @@ -382,6 +385,23 @@ func (p *parser) valueDatetime(it item) (any, tomlType) { return t, p.typeOfPrimitive(it) } +// Go's time.Parse() will accept numbers without a leading zero; there isn't any +// way to require it. https://github.com/golang/go/issues/29911 +// +// Depend on the fact that the separators (- and :) should always be at the same +// location. +func missingLeadingZero(d, l string) bool { + for i, c := range []byte(l) { + if c == '.' || c == 'Z' { + return false + } + if (c < '0' || c > '9') && d[i] != c { + return true + } + } + return false +} + func (p *parser) valueArray(it item) (any, tomlType) { p.setType(p.currentKey, tomlArray, it.pos) diff --git a/toml_test.go b/toml_test.go index 8f650e22..920f96dc 100644 --- a/toml_test.go +++ b/toml_test.go @@ -304,15 +304,6 @@ func runTomlTest(t *testing.T, includeNext bool, wantFail ...string) { Parser: parser{}, RunTests: runTests, SkipTests: []string{ - // "15" in time.Parse() accepts both "1" and "01". The TOML - // specification says that times *must* start with a leading - // zero, but this requires writing out own datetime parser. - // I think it's actually okay to just accept both really. - // https://github.com/BurntSushi/toml/issues/320 - "invalid/datetime/time-no-leads", - "invalid/local-time/time-no-leads", - "invalid/local-datetime/time-no-leads", - // These tests are fine, just doesn't deal well with empty output. "valid/comment/noeol", "valid/comment/nonascii",