Skip to content

Commit f60e275

Browse files
committed
feat: support FormatTime and TimeFormat.
1 parent c125189 commit f60e275

12 files changed

+107
-3
lines changed

dump.go

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"sort"
1212
"strconv"
1313
"strings"
14+
"time"
1415
)
1516

1617
var (
@@ -40,6 +41,13 @@ type Options struct {
4041
// when it's safe. This is useful for diffing two structures, where pointer variables would cause
4142
// false changes. However, circular graphs are still detected and elided to avoid infinite output.
4243
DisablePointerReplacement bool
44+
45+
// FormatTime, if true, will format [time.Time] values using the TimeFormat string.
46+
FormatTime bool
47+
48+
// TimeFormat is the format string used to format [time.Time] values. If blank,
49+
// time.Time.String() is used.
50+
TimeFormat string
4351
}
4452

4553
// Config is the default config used when calling Dump
@@ -59,6 +67,7 @@ type dumpState struct {
5967
parentPointers ptrmap
6068
currentPointer *ptrinfo
6169
homePackageRegexp *regexp.Regexp
70+
timeFormatter func(t time.Time) string
6271
}
6372

6473
func (s *dumpState) write(b []byte) {
@@ -129,6 +138,14 @@ func (s *dumpState) dumpSlice(v reflect.Value) {
129138
}
130139

131140
func (s *dumpState) dumpStruct(v reflect.Value) {
141+
val := v.Interface()
142+
if t, ok := val.(time.Time); ok && s.timeFormatter != nil {
143+
s.writeString("time.Time{ /* ")
144+
s.writeString(s.timeFormatter(t))
145+
s.writeString(" */ }")
146+
return
147+
}
148+
132149
dumpPreamble := func() {
133150
s.dumpType(v)
134151
s.write([]byte("{"))
@@ -246,7 +263,6 @@ func (s *dumpState) dumpChan(v reflect.Value) {
246263
}
247264

248265
func (s *dumpState) dumpCustom(v reflect.Value, buf *bytes.Buffer) {
249-
250266
// Dump the type
251267
s.dumpType(v)
252268

@@ -293,6 +309,8 @@ func (s *dumpState) dump(value interface{}) {
293309
s.dumpVal(v)
294310
}
295311

312+
var dumperType = reflect.TypeOf((*Dumper)(nil)).Elem()
313+
296314
func (s *dumpState) descendIntoPossiblePointer(value reflect.Value, f func()) {
297315
canonicalize := true
298316
if isPointerValue(value) {
@@ -345,7 +363,6 @@ func (s *dumpState) dumpVal(value reflect.Value) {
345363
}
346364

347365
// Handle custom dumpers
348-
dumperType := reflect.TypeOf((*Dumper)(nil)).Elem()
349366
if v.Type().Implements(dumperType) {
350367
s.descendIntoPossiblePointer(v, func() {
351368
// Run the custom dumper buffering the output
@@ -464,6 +481,18 @@ func newDumpState(value reflect.Value, options *Options, writer io.Writer) *dump
464481
w: writer,
465482
}
466483

484+
if options.FormatTime {
485+
if options.TimeFormat != "" {
486+
result.timeFormatter = func(t time.Time) string {
487+
return t.Format(options.TimeFormat)
488+
}
489+
} else {
490+
result.timeFormatter = func(t time.Time) string {
491+
return t.String()
492+
}
493+
}
494+
}
495+
467496
if options.HomePackage != "" {
468497
result.homePackageRegexp = regexp.MustCompile(fmt.Sprintf("\\b%s\\.", options.HomePackage))
469498
}

dump_test.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"os/exec"
99
"reflect"
1010
"testing"
11+
"time"
1112

1213
"github.com/stretchr/testify/assert"
1314
"github.com/stretchr/testify/require"
@@ -163,6 +164,7 @@ func TestSdump_config(t *testing.T) {
163164
(func(v IntAlias) *IntAlias { return &v })(20),
164165
litter.Dump,
165166
func(s string, i int) (bool, error) { return false, nil },
167+
time.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
166168
}
167169

168170
runTestWithCfg(t, "config_Compact", &litter.Options{
@@ -204,6 +206,13 @@ func TestSdump_config(t *testing.T) {
204206
return false
205207
},
206208
}, data)
209+
runTestWithCfg(t, "config_FormatTime", &litter.Options{
210+
FormatTime: true,
211+
}, data)
212+
runTestWithCfg(t, "config_FormatTimeWithTimeFormat", &litter.Options{
213+
FormatTime: true,
214+
TimeFormat: time.ANSIC,
215+
}, data)
207216

208217
basic := &BasicStruct{1, 2}
209218
runTestWithCfg(t, "config_DisablePointerReplacement_simpleReusedStruct", &litter.Options{

testdata/config_Compact.dump

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
[]interface{}{litter_test.options{Compact:false,StripPackageNames:false,HidePrivateFields:true,HomePackage:"",Separator:" ",StrictGo:false},&litter_test.BasicStruct{Public:1,private:2},litter_test.Function,&20,&20,litter.Dump,func(string,int)(bool,error)}
1+
[]interface{}{litter_test.options{Compact:false,StripPackageNames:false,HidePrivateFields:true,HomePackage:"",Separator:" ",StrictGo:false},&litter_test.BasicStruct{Public:1,private:2},litter_test.Function,&20,&20,litter.Dump,func(string,int)(bool,error),time.Time{wall:0,ext:63650361600,loc:nil}}

testdata/config_DumpFunc.dump

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,9 @@
1616
&20,
1717
litter.Dump,
1818
func(string, int) (bool, error),
19+
time.Time{
20+
wall: 0,
21+
ext: 63650361600,
22+
loc: nil,
23+
},
1924
}

testdata/config_FieldFilter.dump

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@
99
&20,
1010
litter.Dump,
1111
func(string, int) (bool, error),
12+
time.Time{},
1213
}

testdata/config_FormatTime.dump

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[]interface {}{
2+
litter_test.options{
3+
Compact: false,
4+
StripPackageNames: false,
5+
HidePrivateFields: true,
6+
HomePackage: "",
7+
Separator: " ",
8+
StrictGo: false,
9+
},
10+
&litter_test.BasicStruct{
11+
Public: 1,
12+
private: 2,
13+
},
14+
litter_test.Function,
15+
&20,
16+
&20,
17+
litter.Dump,
18+
func(string, int) (bool, error),
19+
time.Time{ /* 2018-01-01 00:00:00 +0000 UTC */ },
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[]interface {}{
2+
litter_test.options{
3+
Compact: false,
4+
StripPackageNames: false,
5+
HidePrivateFields: true,
6+
HomePackage: "",
7+
Separator: " ",
8+
StrictGo: false,
9+
},
10+
&litter_test.BasicStruct{
11+
Public: 1,
12+
private: 2,
13+
},
14+
litter_test.Function,
15+
&20,
16+
&20,
17+
litter.Dump,
18+
func(string, int) (bool, error),
19+
time.Time{ /* Mon Jan 1 00:00:00 2018 */ },
20+
}

testdata/config_HidePrivateFields.dump

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@
1515
&20,
1616
litter.Dump,
1717
func(string, int) (bool, error),
18+
time.Time{},
1819
}

testdata/config_HideZeroValues.dump

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,8 @@
1212
&20,
1313
litter.Dump,
1414
func(string, int) (bool, error),
15+
time.Time{
16+
wall: 0,
17+
ext: 63650361600,
18+
},
1519
}

testdata/config_HomePackage.dump

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,9 @@
1616
&20,
1717
litter.Dump,
1818
func(string, int) (bool, error),
19+
time.Time{
20+
wall: 0,
21+
ext: 63650361600,
22+
loc: nil,
23+
},
1924
}

0 commit comments

Comments
 (0)