1 files changed, 46 insertions(+), 5 deletions(-)

M episode11/README.md
M episode11/README.md +46 -5
@@ 59,8 59,19 @@ 1. RFC3339 string like "2019-02-01T17:45
 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:
+The [CBOR spec][rfc7049] has a special type of value called tags. This is used
+to represent data with additional semantics like timestamps. A tag is a major
+type with the value 6, it represents an integer number as indicated by the tag's
+integer value. That number corresponds to the tag’s type. For example URI’s are
+represented as a tagged unicode string in CBOR: first there’s the header with
+the major type 6 —indicating it’s a tag— with the value 32 —that corresponds to
+URIs—, this is followed by an UTF-8 CBOR string with the URI.
+Timestamps are like that, but they have two data item types: 0 for unicode
+strings encoded as a RFC3339 timestamp, or 1 for epoch-based timestamps.
+We'll start with RFC3339 string timestamps, 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")

@@ 92,7 103,7 @@ a kind of object we already handle in th
 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:
+First we’ll set a variable to be time.Time’s representation of its type:
     var typeTime = reflect.TypeOf(time.Time{})

@@ 109,9 120,23 @@ 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
-The [CBOR spec][rfc7049] indicates that 
+We add a few constants required to encode our new values:
+    const (
+        // major types
+        ...
+        majorTag             = 6
+        ...
+        // major type 6: tagged values
+        minorTimeString = 0
+        minorTimeEpoch  = 1
+        ...
+    )
+And then implement writeTime: it writes the tag’s header with minorTimeString
+to indicates an unicode string follows, and write the unicode string based on
+the timestamp’s value:
     func (e *Encoder) writeTime(v reflect.Value) error {
         if err := e.writeHeader(majorTag, minorTimeString); err != nil {

@@ 120,3 145,19 @@ EXPLAIN HOW TAGS WORK
         var t = v.Interface().(time.Time)
         return e.writeUnicodeString(t.Format(time.RFC3339))
+We hook it up to the rest of the code:
+	case reflect.Struct:
+		if x.Type() == typeTime {
+            return e.writeTime(x)
+		}
+		return e.writeStruct(x)
+We run `go test` to confirm everything works.
+Now we’ll handle epoch-based timestamps: those are scalar values where 0
+corresponds to the epoch (January 1, 1970), they can either be integer or
+floating point values.