From 275e366c17446746c9cddae71147eaada7c08da5 Mon Sep 17 00:00:00 2001 From: Thomas Pelletier Date: Thu, 8 Apr 2021 08:00:31 -0400 Subject: [PATCH] decoder: handle casting local date into time.Time Refs #494 --- README.md | 1 + unmarshaler.go | 17 +++++++++++++++++ unmarshaler_test.go | 15 +++++++++++++++ 3 files changed, 33 insertions(+) diff --git a/README.md b/README.md index 934ae81..a3cccfc 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ Development branch. Use at your own risk. - [x] Original go-toml testgen tests pass. - [x] Track file position (line, column) for errors. - [ ] Strict mode. +- [ ] Document Unmarshal / Decode ### Marshal diff --git a/unmarshaler.go b/unmarshaler.go index 0f89703..1184e63 100644 --- a/unmarshaler.go +++ b/unmarshaler.go @@ -30,6 +30,9 @@ func NewDecoder(r io.Reader) *Decoder { } // Decode the whole content of r into v. +// +// When a TOML local date is decoded into a time.Time, its value is represented +// in time.Local timezone. func (d *Decoder) Decode(v interface{}) error { b, err := ioutil.ReadAll(d.r) if err != nil { @@ -224,6 +227,13 @@ func tryTextUnmarshaler(x target, node ast.Node) (bool, error) { if v.Kind() != reflect.Struct { return false, nil } + + // Special case for time, becase we allow to unmarshal to it from + // different kind of AST nodes. + if v.Type() == timeType { + return false, nil + } + if v.Type().Implements(textUnmarshalerType) { return true, v.Interface().(encoding.TextUnmarshaler).UnmarshalText(node.Data) } @@ -313,7 +323,14 @@ func setDateTime(x target, v time.Time) error { return x.set(reflect.ValueOf(v)) } +var timeType = reflect.TypeOf(time.Time{}) + func setDate(x target, v LocalDate) error { + if x.get().Type() == timeType { + cast := v.In(time.Local) + return setDateTime(x, cast) + } + return x.set(reflect.ValueOf(v)) } diff --git a/unmarshaler_test.go b/unmarshaler_test.go index ac874eb..2aa5daf 100644 --- a/unmarshaler_test.go +++ b/unmarshaler_test.go @@ -4,6 +4,7 @@ import ( "math" "strconv" "testing" + "time" "github.com/pelletier/go-toml/v2" "github.com/stretchr/testify/assert" @@ -780,6 +781,20 @@ val1 = "test1" require.Equal(t, "test2", cfg.Val2) } +func TestIssue494(t *testing.T) { + data := ` +foo = 2021-04-08 +bar = 2021-04-08 +` + type s struct { + Foo time.Time `toml:"foo"` + Bar time.Time `toml:"bar"` + } + ss := new(s) + err := toml.Unmarshal([]byte(data), ss) + require.NoError(t, err) +} + func TestUnmarshalDecodeErrors(t *testing.T) { examples := []struct { desc string