Repository: go-redis/redis
Pull request #1102 (2019-07-25 09:21:55)

Marshal time as RFC3339. Add StringCmd.Time helper.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3728c9d..cd9af8f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,11 +3,12 @@
 ## v7 WIP
 
 - WrapProcess is replaced with more convenient AddHook that has access to context.Context.
-- WithContext no longer creates shallow copy.
+- WithContext now can not be used to create a shallow copy of the client.
 - New methods ProcessContext, DoContext, and ExecContext.
 - Client respects Context.Deadline when setting net.Conn deadline.
-- Client listens on Context.Done while waiting for a connection from the pool.
+- Client listens on Context.Done while waiting for a connection from the pool and returns an error when context context is cancelled.
 - Add PubSub.ChannelWithSubscriptions that sends `*Subscription` in addition to `*Message` to allow detecting reconnections.
+- `time.Time` is now marshalled in RFC3339 format. `rdb.Get("foo").Time()` helper is added to parse time.
 
 ## v6.15
 
diff --git a/command.go b/command.go
index c302597..7b7c353 100644
--- a/command.go
+++ b/command.go
@@ -659,6 +659,13 @@ func (cmd *StringCmd) Float64() (float64, error) {
 	return strconv.ParseFloat(cmd.Val(), 64)
 }
 
+func (cmd *StringCmd) Time() (time.Time, error) {
+	if cmd.err != nil {
+		return time.Time{}, cmd.err
+	}
+	return time.Parse(time.RFC3339, cmd.Val())
+}
+
 func (cmd *StringCmd) Scan(val interface{}) error {
 	if cmd.err != nil {
 		return cmd.err
diff --git a/internal/proto/writer.go b/internal/proto/writer.go
index d106ce0..cded347 100644
--- a/internal/proto/writer.go
+++ b/internal/proto/writer.go
@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"io"
 	"strconv"
+	"time"
 
 	"github.com/go-redis/redis/internal/util"
 )
@@ -92,6 +93,8 @@ func (w *Writer) writeArg(v interface{}) error {
 		} else {
 			return w.int(0)
 		}
+	case time.Time:
+		return w.string(v.Format(time.RFC3339))
 	case encoding.BinaryMarshaler:
 		b, err := v.MarshalBinary()
 		if err != nil {


Test patch:
diff --git a/command_test.go b/command_test.go
index 020f8aa..54e9945 100644
--- a/command_test.go
+++ b/command_test.go
@@ -1,6 +1,8 @@
 package redis_test
 
 import (
+	"time"
+
 	"github.com/go-redis/redis"
 
 	. "github.com/onsi/ginkgo"
@@ -67,4 +69,19 @@ var _ = Describe("Cmd", func() {
 		Expect(err).NotTo(HaveOccurred())
 		Expect(val).To(Equal(f))
 	})
+
+	It("supports time.Time", func() {
+		tm := time.Date(2019, 01, 01, 0, 0, 0, 0, time.UTC)
+
+		err := client.Set("time_key", tm, 0).Err()
+		Expect(err).NotTo(HaveOccurred())
+
+		s, err := client.Get("time_key").Result()
+		Expect(err).NotTo(HaveOccurred())
+		Expect(s).To(Equal("2019-01-01T00:00:00Z"))
+
+		tm2, err := client.Get("time_key").Time()
+		Expect(err).NotTo(HaveOccurred())
+		Expect(tm2).To(BeTemporally("==", tm))
+	})
 })
diff --git a/internal/proto/write_buffer_test.go b/internal/proto/write_buffer_test.go
index 29aa469..2de532e 100644
--- a/internal/proto/write_buffer_test.go
+++ b/internal/proto/write_buffer_test.go
@@ -2,6 +2,7 @@ package proto_test
 
 import (
 	"bytes"
+	"encoding"
 	"io/ioutil"
 	"testing"
 	"time"
@@ -12,6 +13,14 @@ import (
 	. "github.com/onsi/gomega"
 )
 
+type MyType struct{}
+
+var _ encoding.BinaryMarshaler = (*MyType)(nil)
+
+func (t *MyType) MarshalBinary() ([]byte, error) {
+	return []byte("hello"), nil
+}
+
 var _ = Describe("WriteBuffer", func() {
 	var buf *bytes.Buffer
 	var wr *proto.Writer
@@ -45,16 +54,25 @@ var _ = Describe("WriteBuffer", func() {
 			"\r\n")))
 	})
 
-	It("should append marshalable args", func() {
-		err := wr.WriteArgs([]interface{}{time.Unix(1414141414, 0)})
+	It("should append time", func() {
+		err := wr.WriteArgs([]interface{}{time.Unix(1414141414, 0).UTC()})
 		Expect(err).NotTo(HaveOccurred())
 
 		err = wr.Flush()
 		Expect(err).NotTo(HaveOccurred())
 
-		Expect(buf.Len()).To(Equal(26))
+		Expect(buf.Len()).To(Equal(31))
 	})
 
+	It("should append marshalable args", func() {
+		err := wr.WriteArgs([]interface{}{&MyType{}})
+		Expect(err).NotTo(HaveOccurred())
+
+		err = wr.Flush()
+		Expect(err).NotTo(HaveOccurred())
+
+		Expect(buf.Len()).To(Equal(15))
+	})
 })
 
 func BenchmarkWriteBuffer_Append(b *testing.B) {