Skip to content

Commit

Permalink
Move toml.LocalDatetime to internal package
Browse files Browse the repository at this point in the history
See the comment: writing a good API for this ties in to various other
issues, and I'd rather not add something now that I'll regret later and
that we're then stuck with due to compatibility.

This is the safer option, and allows me to release a new version which
gives people the bugfixes and TOML 1.0 support without having to wait
until such a time I can implement all of this (and I'd rather solve some
other issues first too).
  • Loading branch information
arp242 committed Aug 2, 2021
1 parent 5f40317 commit 642b87a
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 54 deletions.
7 changes: 1 addition & 6 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,7 @@ func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error {
// TOML table arrays correspond to either a slice of structs or a slice of maps.
//
// TOML datetimes correspond to Go time.Time values. Local datetimes are parsed
// in the local timezone and have the Location set to the decoders's Timezone
// value. This defaults to this computer's local timezone if not given.
// in the local timezone.
//
// All other TOML types (float, string, int, bool and array) correspond to the
// obvious Go types.
Expand Down Expand Up @@ -94,10 +93,6 @@ func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error {
// cyclic type is passed.
type Decoder struct {
r io.Reader

// Timezone to use for local times. Defaults to this computer's local
// timezone if nil.
//Timezone *time.Location
}

// NewDecoder creates a new Decoder.
Expand Down
14 changes: 8 additions & 6 deletions decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"strings"
"testing"
"time"

"github.com/BurntSushi/toml/internal"
)

func TestDecodeReader(t *testing.T) {
Expand Down Expand Up @@ -687,12 +689,12 @@ func TestDecodeDatetime(t *testing.T) {
{"1979-05-27T07:32:12-07:00 # c", time.Date(1979, 05, 27, 07, 32, 12, 0, tz7)},

// Local times.
{"1979-05-27T07:32:00", time.Date(1979, 05, 27, 07, 32, 0, 0, LocalDatetime)},
{"1979-05-27T07:32:00.999999", time.Date(1979, 05, 27, 07, 32, 0, 999999000, LocalDatetime)},
{"1979-05-27T07:32:00.25", time.Date(1979, 05, 27, 07, 32, 0, 250000000, LocalDatetime)},
{"1979-05-27", time.Date(1979, 05, 27, 0, 0, 0, 0, LocalDate)},
{"07:32:00", time.Date(0, 1, 1, 07, 32, 0, 0, LocalTime)},
{"07:32:00.999999", time.Date(0, 1, 1, 07, 32, 0, 999999000, LocalTime)},
{"1979-05-27T07:32:00", time.Date(1979, 05, 27, 07, 32, 0, 0, internal.LocalDatetime)},
{"1979-05-27T07:32:00.999999", time.Date(1979, 05, 27, 07, 32, 0, 999999000, internal.LocalDatetime)},
{"1979-05-27T07:32:00.25", time.Date(1979, 05, 27, 07, 32, 0, 250000000, internal.LocalDatetime)},
{"1979-05-27", time.Date(1979, 05, 27, 0, 0, 0, 0, internal.LocalDate)},
{"07:32:00", time.Date(0, 1, 1, 07, 32, 0, 0, internal.LocalTime)},
{"07:32:00.999999", time.Date(0, 1, 1, 07, 32, 0, 999999000, internal.LocalTime)},
} {
t.Run(tt.in, func(t *testing.T) {
var x struct{ D time.Time }
Expand Down
10 changes: 6 additions & 4 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
"strconv"
"strings"
"time"

"github.com/BurntSushi/toml/internal"
)

type tomlEncodeError struct{ error }
Expand Down Expand Up @@ -184,17 +186,17 @@ func (enc *Encoder) eElement(rv reflect.Value) {
case time.Time: // Using TextMarshaler adds extra quotes, which we don't want.
format := time.RFC3339Nano
switch v.Location() {
case LocalDatetime:
case internal.LocalDatetime:
format = "2006-01-02T15:04:05.999999999"
case LocalDate:
case internal.LocalDate:
format = "2006-01-02"
case LocalTime:
case internal.LocalTime:
format = "15:04:05.999999999"
}
switch v.Location() {
default:
enc.wf(v.Format(format))
case LocalDatetime, LocalDate, LocalTime:
case internal.LocalDatetime, internal.LocalDate, internal.LocalTime:
enc.wf(v.In(time.UTC).Format(format))
}
return
Expand Down
8 changes: 4 additions & 4 deletions internal/tag/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"math"
"time"

"github.com/BurntSushi/toml"
"github.com/BurntSushi/toml/internal"
)

// Add JSON tags to a data structure as expected by toml-test.
Expand Down Expand Up @@ -44,11 +44,11 @@ func Add(key string, tomlData interface{}) interface{} {
switch orig.Location() {
default:
return tag("datetime", orig.Format("2006-01-02T15:04:05.999999999Z07:00"))
case toml.LocalDatetime:
case internal.LocalDatetime:
return tag("datetime-local", orig.Format("2006-01-02T15:04:05.999999999"))
case toml.LocalDate:
case internal.LocalDate:
return tag("date-local", orig.Format("2006-01-02"))
case toml.LocalTime:
case internal.LocalTime:
return tag("time-local", orig.Format("15:04:05.999999999"))
}

Expand Down
8 changes: 4 additions & 4 deletions internal/tag/rm.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"strconv"
"time"

"github.com/BurntSushi/toml"
"github.com/BurntSushi/toml/internal"
)

// Rempve JSON tags to a data structure as returned by toml-test.
Expand Down Expand Up @@ -70,11 +70,11 @@ func untag(typed map[string]interface{}) interface{} {
case "datetime":
return parseTime(v, "2006-01-02T15:04:05.999999999Z07:00", nil)
case "datetime-local":
return parseTime(v, "2006-01-02T15:04:05.999999999", toml.LocalDatetime)
return parseTime(v, "2006-01-02T15:04:05.999999999", internal.LocalDatetime)
case "date-local":
return parseTime(v, "2006-01-02", toml.LocalDate)
return parseTime(v, "2006-01-02", internal.LocalDate)
case "time-local":
return parseTime(v, "15:04:05.999999999", toml.LocalTime)
return parseTime(v, "15:04:05.999999999", internal.LocalTime)
case "bool":
switch v {
case "true":
Expand Down
36 changes: 36 additions & 0 deletions internal/tz.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package internal

import "time"

// Timezones used for local datetime, date, and time TOML types.
//
// The exact way times and dates without a timezone should be interpreted is not
// well-defined in the TOML specification and left to the implementation. These
// defaults to current local timezone offset of the computer, but this can be
// changed by changing these variables before decoding.
//
// TODO:
// Ideally we'd like to offer people the ability to configure the used timezone
// by setting Decoder.Timezone and Encoder.Timezone; however, this is a bit
// tricky: the reason we use three different variables for this is to support
// round-tripping – without these specific TZ names we wouldn't know which
// format to use.
//
// There isn't a good way to encode this right now though, and passing this sort
// of information also ties in to various related issues such as string format
// encoding, encoding of comments, etc.
//
// So, for the time being, just put this in internal until we can write a good
// comprehensive API for doing all of this.
//
// The reason they're exported is because they're referred from in e.g.
// internal/tag.
//
// Note that this behaviour is valid according to the TOML spec as the exact
// behaviour is left up to implementations.
var (
localOffset = func() int { _, o := time.Now().Zone(); return o }()
LocalDatetime = time.FixedZone("datetime-local", localOffset)
LocalDate = time.FixedZone("date-local", localOffset)
LocalTime = time.FixedZone("time-local", localOffset)
)
35 changes: 5 additions & 30 deletions parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"strings"
"time"
"unicode/utf8"

"github.com/BurntSushi/toml/internal"
)

type parser struct {
Expand Down Expand Up @@ -298,41 +300,14 @@ func (p *parser) valueFloat(it item) (interface{}, tomlType) {
return num, p.typeOfPrimitive(it)
}

// Timezones used for local datetime, date, and time TOML types.
//
// The exact way times and dates without a timezone should be interpreted is not
// well-defined in the TOML specification and left to the implementation. These
// defaults to current local timezone offset of the computer, but this can be
// changed by changing these variables before decoding.
//
// The reason we use three different variables for this is to support
// round-tripping.
//
// TODO: these really shouldn't be package-level globals, and there also
// shouldn't be three variables. The problem is that the time is decoded in the
// parse stage, rather than the decode stage.
//
// Decoder and Encoder should both support a Timezone attribute instead.
// Round-tripping is more tricky though, as there isn't a way to pass this
// information yet.
//
// The reason they're exported is because they're referred from in e.g.
// internal/tag.
var (
localOffset = func() int { _, o := time.Now().Zone(); return o }()
LocalDatetime = time.FixedZone("datetime-local", localOffset)
LocalDate = time.FixedZone("date-local", localOffset)
LocalTime = time.FixedZone("time-local", localOffset)
)

var dtTypes = []struct {
fmt string
zone *time.Location
}{
{time.RFC3339Nano, time.Local},
{"2006-01-02T15:04:05.999999999", LocalDatetime},
{"2006-01-02", LocalDate},
{"15:04:05.999999999", LocalTime},
{"2006-01-02T15:04:05.999999999", internal.LocalDatetime},
{"2006-01-02", internal.LocalDate},
{"15:04:05.999999999", internal.LocalTime},
}

func (p *parser) valueDatetime(it item) (interface{}, tomlType) {
Expand Down

0 comments on commit 642b87a

Please sign in to comment.