1 files changed, 73 insertions(+), 2 deletions(-)

M episode11/README.md
M episode11/README.md +73 -2
@@ 30,9 30,9 @@ one:
 [ep7]: http://henry.precheur.org/scratchpad/20180527_114309
 [ep8]: http://henry.precheur.org/scratchpad/20180604_083306
 [ep9]: http://henry.precheur.org/scratchpad/20190419_114828
-[ep10]: ...
+[ep10]: http://henry.precheur.org/scratchpad/20191103_102445
 [rfc7049]: https://tools.ietf.org/html/rfc7049
-[repo]: https://bitbucket.org/henry/cbor/src/default/episode9/
+[repo]: https://bitbucket.org/henry/cbor/src/default/episode11/
 
 ----
 

          
@@ 47,3 47,74 @@ 1. Implement RFC3339 first
 2. Introduce epoch base timestamp
 3. Optimize: rfc3339 for time.Time w/ timezone, epoch for time.Time w/o
 3. Fix old RFC3339 example
+
+We implemented all the Go native types, now we’ll implement a custom stype:
+time.Time, a timestamp type. According the the [CBOR spec][rfc7049]
+
+FIXME find link to section
+
+There are 3 types of timestamps supported by CBOR:
+
+1. RFC3339 string like "2019-02-01T17:45:23Z"
+2. floating point value ...
+3. integer value ...
+
+We'll start with the RFC3339 string, lookup the example in the spec and add our
+first test:
+
+    func TestTimestamp(t *testing.T) {
+        var rfc3339Timestamp, _ = time.Parse(time.RFC3339, "2013-03-21T20:04:00Z")
+
+        var cases = []struct {
+            Value    time.Time
+            Expected []byte
+        }{
+            {
+                Value: rfc3339Timestamp,
+                Expected: []byte{
+                    0xc0, 0x74, 0x32, 0x30, 0x31, 0x33, 0x2d, 0x30, 0x33, 0x2d,
+                    0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x34, 0x3a, 0x30,
+                    0x30, 0x3a,
+                },
+            },
+        }
+
+        for _, c := range cases {
+            t.Run(fmt.Sprintf("%v", c.Value), func(t *testing.T) {
+                testEncoder(t, c.Value, c.Expected)
+            })
+        }
+    }
+
+How can we detect if we have a time.Time object in the encoder? Looking at
+[time.Time’s definition](https://godoc.org/time#Time) we see that it’s a struct,
+a kind of object we already handle in the encoder. The reflect package lets us
+query the type of a value, so what we have to check is the struct’s type is
+time.Time when we have a struct.
+
+First we’ll set a variable to be time.Time’s type:
+
+    var typeTime = reflect.TypeOf(time.Time{})
+
+And in the main switch block we add a branch in the reflect.Struct case to
+handle time.Time if we have a value with that type:
+
+	case reflect.Struct:
+		if x.Type() == typeTime {
+            return ErrNotImplemented
+		}
+		return e.writeStruct(x)
+
+Let’s add a new function to write timestamps as CBOR values: writeTime. First
+we’ll implement RFC3339 string timestamps, and support other timestamp types
+after.
+
+The [CBOR spec][rfc7049]
+
+    func (e *Encoder) writeTime(v reflect.Value) error {
+        if err := e.writeHeader(majorTag, minorTimeString); err != nil {
+            return err
+        }
+        var t = v.Interface().(time.Time)
+        return e.writeUnicodeString(t.Format(time.RFC3339))
+    }