From e03423ce2cce00c1942e22073a16d4493d539e14 Mon Sep 17 00:00:00 2001 From: Vlad Vitan <23100181+vlasebian@users.noreply.github.com> Date: Wed, 15 Jan 2025 18:28:07 +0200 Subject: [PATCH] util: Add support for time.Time in goproto struct --- go.mod | 1 + pkg/goproto/struct.go | 7 +++++++ pkg/goproto/struct_test.go | 10 ++++++++++ 3 files changed, 18 insertions(+) diff --git a/go.mod b/go.mod index 00f0b10d32..a12c8a4afa 100644 --- a/go.mod +++ b/go.mod @@ -179,6 +179,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/couchbase/vellum v1.0.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dlclark/regexp2 v1.11.4 // indirect github.com/docker/go-units v0.5.0 // indirect diff --git a/pkg/goproto/struct.go b/pkg/goproto/struct.go index 8decdfdce3..81cee4cfbc 100644 --- a/pkg/goproto/struct.go +++ b/pkg/goproto/struct.go @@ -17,6 +17,7 @@ package goproto import ( "fmt" "reflect" + "time" "go.thethings.network/lorawan-stack/v3/pkg/errors" "google.golang.org/protobuf/types/known/structpb" @@ -203,6 +204,12 @@ func valueFromReflect(rv reflect.Value, opts ...Option) (*structpb.Value, error) return &structpb.Value{Kind: &structpb.Value_StructValue{StructValue: pv}}, nil case reflect.Struct: + if rv.Type() == reflect.TypeOf(time.Time{}) { + return &structpb.Value{Kind: &structpb.Value_StringValue{ + StringValue: rv.Interface().(time.Time).Format(time.RFC3339Nano), + }}, nil + } + state, err := createSerializationState(opts...) if err != nil { return nil, err diff --git a/pkg/goproto/struct_test.go b/pkg/goproto/struct_test.go index 15e077514e..e0bb618d52 100644 --- a/pkg/goproto/struct_test.go +++ b/pkg/goproto/struct_test.go @@ -18,6 +18,7 @@ import ( "bytes" "reflect" "testing" + "time" "github.com/smarty/assertions" "github.com/spf13/cast" @@ -55,6 +56,7 @@ func TestStructProto(t *testing.T) { "map": map[string]string{"foo": "bar"}, "eui": types.EUI64{1, 2, 3, 4, 5, 6, 7, 8}, "jsonMarshaler": &jsonMarshaler{Text: "testtext"}, + "time": time.Time{}, } s, err := goproto.Struct(m) a.So(err, should.BeNil) @@ -106,6 +108,14 @@ func TestStructProto(t *testing.T) { } case reflect.Struct, reflect.Map: + if rv.Type() == reflect.TypeOf(time.Time{}) { + var vt string + a.So(s.Fields[k].Kind, should.HaveSameTypeAs, &structpb.Value_StringValue{}) + a.So(sm[k], should.HaveSameTypeAs, vt) + a.So(sm[k], should.Equal, rv.Interface().(time.Time).Format(time.RFC3339Nano)) + continue + } + var vt map[string]any a.So(s.Fields[k].Kind, should.HaveSameTypeAs, &structpb.Value_StructValue{}) a.So(sm[k], should.HaveSameTypeAs, vt)