2 files changed, 51 insertions(+), 2 deletions(-)

M episode11/README.md
M episode11/cbor.go
M episode11/README.md +49 -0
@@ 160,4 160,53 @@ 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.
 
+We’ll minimize the size of our output by picking the most compact type we can
+use with our encoder. The timestamp can either be an integer, a floating point
+number, or a RFC3339 string. If there’s a timestamp’s timezone isn’t UTC we’ll
+have to use the largest type: the RFC3339 string, because we need to encode the
+timezone. If the timestamp’s timezone is UTC we can use a scalar timestamp
+because we don’t have to set the timezone because it’s assumed to be UTC. We’ll
+use an integer when the timestamp can be represented as whole seconds and use
+floating point number eitherwise.
 
+First we’ll add a condition to only use RFC3339 strings when the timestamp has a
+timezone that’s not UTC.
+
+    func (e *Encoder) writeTime(v reflect.Value) error {
+        var t = v.Interface().(time.Time)
+        if t.Location() != time.UTC && t.Location() != nil {
+            if err := e.writeHeader(majorTag, minorTimeString); err != nil {
+                return err
+            }
+            return e.writeUnicodeString(t.Format(time.RFC3339))
+        }
+        return ErrNotImplemented
+    }
+
+Because we’re changing the behavior of writeTime when the timezone is UTC, we
+need to fix the test to use timestamp with its timezone set. To do so we replace
+the Z at the end of rfc3339Timestamp with +07:00:
+
+    func TestTimestamp(t *testing.T) {
+        var rfc3339Timestamp, _ = time.Parse(time.RFC3339, "2013-03-21T20:04:00+07:00")
+
+        var cases = []struct {
+            Value    time.Time
+            Expected []byte
+        }{
+            {
+                Value: rfc3339Timestamp,
+                Expected: []byte{
+                    0xc0, 0x78, 0x19, 0x32, 0x30, 0x31, 0x33, 0x2d, 0x30, 0x33, 0x2d,
+                    0x32, 0x31, 0x54, 0x32, 0x30, 0x3a, 0x30, 0x34, 0x3a, 0x30, 0x30,
+                    '+', '0', '7', ':', '0', '0',
+                },
+            },
+        }
+
+        for _, c := range cases {
+            t.Run(fmt.Sprintf("%v", c.Value), func(t *testing.T) {
+                testEncoder(t, c.Value, c.Expected)
+            })
+        }
+    }

          
M episode11/cbor.go +2 -2
@@ 241,8 241,8 @@ func (e *Encoder) writeTime(v reflect.Va
 		}
 		return e.writeInteger(sign, uint64(unixTime))
 	} else {
-		var unixTime = float64(unixTimeNano) / float64(nanoSecondsInSecond)
-		return e.writeFloat(unixTime)
+		return e.writeFloat(
+			float64(unixTimeNano) / float64(nanoSecondsInSecond))
 	}
 }