Local DateTime support (#317)
This commit is contained in:
+18
-2
@@ -69,6 +69,7 @@ const (
|
|||||||
var timeType = reflect.TypeOf(time.Time{})
|
var timeType = reflect.TypeOf(time.Time{})
|
||||||
var marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
|
var marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
|
||||||
var localDateType = reflect.TypeOf(LocalDate{})
|
var localDateType = reflect.TypeOf(LocalDate{})
|
||||||
|
var localDateTimeType = reflect.TypeOf(LocalDateTime{})
|
||||||
|
|
||||||
// Check if the given marshal type maps to a Tree primitive
|
// Check if the given marshal type maps to a Tree primitive
|
||||||
func isPrimitive(mtype reflect.Type) bool {
|
func isPrimitive(mtype reflect.Type) bool {
|
||||||
@@ -86,7 +87,7 @@ func isPrimitive(mtype reflect.Type) bool {
|
|||||||
case reflect.String:
|
case reflect.String:
|
||||||
return true
|
return true
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
return mtype == timeType || mtype == localDateType || isCustomMarshaler(mtype)
|
return mtype == timeType || mtype == localDateType || mtype == localDateTimeType || isCustomMarshaler(mtype)
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -706,12 +707,27 @@ func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}, mval1 *ref
|
|||||||
case reflect.Bool, reflect.Struct:
|
case reflect.Bool, reflect.Struct:
|
||||||
val := reflect.ValueOf(tval)
|
val := reflect.ValueOf(tval)
|
||||||
|
|
||||||
if val.Type() == localDateType {
|
switch val.Type() {
|
||||||
|
case localDateType:
|
||||||
localDate := val.Interface().(LocalDate)
|
localDate := val.Interface().(LocalDate)
|
||||||
switch mtype {
|
switch mtype {
|
||||||
case timeType:
|
case timeType:
|
||||||
return reflect.ValueOf(time.Date(localDate.Year, localDate.Month, localDate.Day, 0, 0, 0, 0, time.Local)), nil
|
return reflect.ValueOf(time.Date(localDate.Year, localDate.Month, localDate.Day, 0, 0, 0, 0, time.Local)), nil
|
||||||
}
|
}
|
||||||
|
case localDateTimeType:
|
||||||
|
localDateTime := val.Interface().(LocalDateTime)
|
||||||
|
switch mtype {
|
||||||
|
case timeType:
|
||||||
|
return reflect.ValueOf(time.Date(
|
||||||
|
localDateTime.Date.Year,
|
||||||
|
localDateTime.Date.Month,
|
||||||
|
localDateTime.Date.Day,
|
||||||
|
localDateTime.Time.Hour,
|
||||||
|
localDateTime.Time.Minute,
|
||||||
|
localDateTime.Time.Second,
|
||||||
|
localDateTime.Time.Nanosecond,
|
||||||
|
time.Local)), nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if this passes for when mtype is reflect.Struct, tval is a time.LocalTime
|
// if this passes for when mtype is reflect.Struct, tval is a time.LocalTime
|
||||||
|
|||||||
+165
@@ -1873,3 +1873,168 @@ func TestMarshalLocalDate(t *testing.T) {
|
|||||||
t.Errorf("expected '%s', got '%s'", expected, got)
|
t.Errorf("expected '%s', got '%s'", expected, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUnmarshalLocalDateTime(t *testing.T) {
|
||||||
|
examples := []struct {
|
||||||
|
name string
|
||||||
|
in string
|
||||||
|
out LocalDateTime
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "normal",
|
||||||
|
in: "1979-05-27T07:32:00",
|
||||||
|
out: LocalDateTime{
|
||||||
|
Date: LocalDate{
|
||||||
|
Year: 1979,
|
||||||
|
Month: 5,
|
||||||
|
Day: 27,
|
||||||
|
},
|
||||||
|
Time: LocalTime{
|
||||||
|
Hour: 7,
|
||||||
|
Minute: 32,
|
||||||
|
Second: 0,
|
||||||
|
Nanosecond: 0,
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
{
|
||||||
|
name: "with nanoseconds",
|
||||||
|
in: "1979-05-27T00:32:00.999999",
|
||||||
|
out: LocalDateTime{
|
||||||
|
Date: LocalDate{
|
||||||
|
Year: 1979,
|
||||||
|
Month: 5,
|
||||||
|
Day: 27,
|
||||||
|
},
|
||||||
|
Time: LocalTime{
|
||||||
|
Hour: 0,
|
||||||
|
Minute: 32,
|
||||||
|
Second: 0,
|
||||||
|
Nanosecond: 999999000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, example := range examples {
|
||||||
|
toml := fmt.Sprintf(`date = %s`, example.in)
|
||||||
|
|
||||||
|
t.Run(fmt.Sprintf("ToLocalDateTime_%d_%s", i, example.name), func(t *testing.T) {
|
||||||
|
type dateStruct struct {
|
||||||
|
Date LocalDateTime
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj dateStruct
|
||||||
|
|
||||||
|
err := Unmarshal([]byte(toml), &obj)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if obj.Date != example.out {
|
||||||
|
t.Errorf("expected '%s', got '%s'", example.out, obj.Date)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run(fmt.Sprintf("ToTime_%d_%s", i, example.name), func(t *testing.T) {
|
||||||
|
type dateStruct struct {
|
||||||
|
Date time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj dateStruct
|
||||||
|
|
||||||
|
err := Unmarshal([]byte(toml), &obj)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if obj.Date.Year() != example.out.Date.Year {
|
||||||
|
t.Errorf("expected year %d, got %d", example.out.Date.Year, obj.Date.Year())
|
||||||
|
}
|
||||||
|
if obj.Date.Month() != example.out.Date.Month {
|
||||||
|
t.Errorf("expected month %d, got %d", example.out.Date.Month, obj.Date.Month())
|
||||||
|
}
|
||||||
|
if obj.Date.Day() != example.out.Date.Day {
|
||||||
|
t.Errorf("expected day %d, got %d", example.out.Date.Day, obj.Date.Day())
|
||||||
|
}
|
||||||
|
if obj.Date.Hour() != example.out.Time.Hour {
|
||||||
|
t.Errorf("expected day %d, got %d", example.out.Time.Hour, obj.Date.Hour())
|
||||||
|
}
|
||||||
|
if obj.Date.Minute() != example.out.Time.Minute {
|
||||||
|
t.Errorf("expected day %d, got %d", example.out.Time.Minute, obj.Date.Minute())
|
||||||
|
}
|
||||||
|
if obj.Date.Second() != example.out.Time.Second {
|
||||||
|
t.Errorf("expected day %d, got %d", example.out.Time.Second, obj.Date.Second())
|
||||||
|
}
|
||||||
|
if obj.Date.Nanosecond() != example.out.Time.Nanosecond {
|
||||||
|
t.Errorf("expected day %d, got %d", example.out.Time.Nanosecond, obj.Date.Nanosecond())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMarshalLocalDateTime(t *testing.T) {
|
||||||
|
type dateStruct struct {
|
||||||
|
DateTime LocalDateTime
|
||||||
|
}
|
||||||
|
|
||||||
|
examples := []struct {
|
||||||
|
name string
|
||||||
|
in LocalDateTime
|
||||||
|
out string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "normal",
|
||||||
|
out: "DateTime = 1979-05-27T07:32:00\n",
|
||||||
|
in: LocalDateTime{
|
||||||
|
Date: LocalDate{
|
||||||
|
Year: 1979,
|
||||||
|
Month: 5,
|
||||||
|
Day: 27,
|
||||||
|
},
|
||||||
|
Time: LocalTime{
|
||||||
|
Hour: 7,
|
||||||
|
Minute: 32,
|
||||||
|
Second: 0,
|
||||||
|
Nanosecond: 0,
|
||||||
|
},
|
||||||
|
}},
|
||||||
|
{
|
||||||
|
name: "with nanoseconds",
|
||||||
|
out: "DateTime = 1979-05-27T00:32:00.999999000\n",
|
||||||
|
in: LocalDateTime{
|
||||||
|
Date: LocalDate{
|
||||||
|
Year: 1979,
|
||||||
|
Month: 5,
|
||||||
|
Day: 27,
|
||||||
|
},
|
||||||
|
Time: LocalTime{
|
||||||
|
Hour: 0,
|
||||||
|
Minute: 32,
|
||||||
|
Second: 0,
|
||||||
|
Nanosecond: 999999000,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, example := range examples {
|
||||||
|
t.Run(fmt.Sprintf("%d_%s", i, example.name), func(t *testing.T) {
|
||||||
|
obj := dateStruct{
|
||||||
|
DateTime: example.in,
|
||||||
|
}
|
||||||
|
b, err := Marshal(obj)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
got := string(b)
|
||||||
|
|
||||||
|
if got != example.out {
|
||||||
|
t.Errorf("expected '%s', got '%s'", example.out, got)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -138,6 +138,8 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen
|
|||||||
return value.Format(time.RFC3339), nil
|
return value.Format(time.RFC3339), nil
|
||||||
case LocalDate:
|
case LocalDate:
|
||||||
return value.String(), nil
|
return value.String(), nil
|
||||||
|
case LocalDateTime:
|
||||||
|
return value.String(), nil
|
||||||
case nil:
|
case nil:
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user