diff --git a/command.go b/command.go index 992197ac..15a04c0e 100644 --- a/command.go +++ b/command.go @@ -355,6 +355,48 @@ func (cmd *DurationCmd) readReply(cn *pool.Conn) error { //------------------------------------------------------------------------------ +type TimeCmd struct { + baseCmd + + val time.Time +} + +func NewTimeCmd(args ...interface{}) *TimeCmd { + cmd := newBaseCmd(args) + return &TimeCmd{ + baseCmd: cmd, + } +} + +func (cmd *TimeCmd) reset() { + cmd.val = time.Time{} + cmd.err = nil +} + +func (cmd *TimeCmd) Val() time.Time { + return cmd.val +} + +func (cmd *TimeCmd) Result() (time.Time, error) { + return cmd.val, cmd.err +} + +func (cmd *TimeCmd) String() string { + return cmdString(cmd, cmd.val) +} + +func (cmd *TimeCmd) readReply(cn *pool.Conn) error { + v, err := cn.Rd.ReadArrayReply(timeParser) + if err != nil { + cmd.err = err + return err + } + cmd.val = v.(time.Time) + return nil +} + +//------------------------------------------------------------------------------ + type BoolCmd struct { baseCmd diff --git a/commands.go b/commands.go index 8a2b9c5d..5ac7de72 100644 --- a/commands.go +++ b/commands.go @@ -199,7 +199,7 @@ type Cmdable interface { ShutdownSave() *StatusCmd ShutdownNoSave() *StatusCmd SlaveOf(host, port string) *StatusCmd - Time() *StringSliceCmd + Time() *TimeCmd Eval(script string, keys []string, args ...interface{}) *Cmd EvalSha(sha1 string, keys []string, args ...interface{}) *Cmd ScriptExists(scripts ...string) *BoolSliceCmd @@ -1741,9 +1741,8 @@ func (c *cmdable) Sync() { panic("not implemented") } -// TODO: add TimeCmd and use it here -func (c *cmdable) Time() *StringSliceCmd { - cmd := NewStringSliceCmd("time") +func (c *cmdable) Time() *TimeCmd { + cmd := NewTimeCmd("time") c.process(cmd) return cmd } diff --git a/commands_test.go b/commands_test.go index e613d4ab..2db90e2a 100644 --- a/commands_test.go +++ b/commands_test.go @@ -159,9 +159,9 @@ var _ = Describe("Commands", func() { }) It("should Time", func() { - time := client.Time() - Expect(time.Err()).NotTo(HaveOccurred()) - Expect(time.Val()).To(HaveLen(2)) + tm, err := client.Time().Result() + Expect(err).NotTo(HaveOccurred()) + Expect(tm).To(BeTemporally("~", time.Now(), 3*time.Second)) }) }) diff --git a/parser.go b/parser.go index 50b2a956..578dbc93 100644 --- a/parser.go +++ b/parser.go @@ -4,6 +4,7 @@ import ( "fmt" "net" "strconv" + "time" "gopkg.in/redis.v5/internal/proto" ) @@ -364,6 +365,7 @@ func commandInfoParser(rd *proto.Reader, n int64) (interface{}, error) { return &cmd, nil } +// Implements proto.MultiBulkParse func commandInfoSliceParser(rd *proto.Reader, n int64) (interface{}, error) { m := make(map[string]*CommandInfo, n) for i := int64(0); i < n; i++ { @@ -377,3 +379,32 @@ func commandInfoSliceParser(rd *proto.Reader, n int64) (interface{}, error) { } return m, nil } + +// Implements proto.MultiBulkParse +func timeParser(rd *proto.Reader, n int64) (interface{}, error) { + if n != 2 { + fmt.Errorf("got %d elements, expected 2", n) + } + + secStr, err := rd.ReadStringReply() + if err != nil { + return nil, err + } + + microsecStr, err := rd.ReadStringReply() + if err != nil { + return nil, err + } + + sec, err := strconv.ParseInt(secStr, 10, 64) + if err != nil { + return nil, err + } + + microsec, err := strconv.ParseInt(microsecStr, 10, 64) + if err != nil { + return nil, err + } + + return time.Unix(sec, microsec*100), nil +}