Index: go/src/infra/gae/libs/wrapper/memory/binutils.go |
diff --git a/go/src/infra/gae/libs/wrapper/memory/binutils.go b/go/src/infra/gae/libs/wrapper/memory/binutils.go |
index 141a827d6e83eb750f632e54e59715176cb4ed77..5d262d20b76c83f0333695c96017a341f4053c61 100644 |
--- a/go/src/infra/gae/libs/wrapper/memory/binutils.go |
+++ b/go/src/infra/gae/libs/wrapper/memory/binutils.go |
@@ -9,6 +9,9 @@ import ( |
"encoding/binary" |
"fmt" |
"math" |
+ "time" |
+ |
+ "appengine" |
"github.com/luci/luci-go/common/funnybase" |
) |
@@ -66,3 +69,30 @@ func readFloat64(buf *bytes.Buffer) (float64, error) { |
bits := binary.BigEndian.Uint64(data) |
return math.Float64frombits(bits ^ (((bits >> 63) - 1) | (1 << 63))), nil |
} |
+ |
+// We truncate this to microseconds and drop the timezone, because that's the |
+// way that the appengine SDK does it. Awesome, right? Also: its not documented. |
+func writeTime(buf *bytes.Buffer, t time.Time) { |
+ funnybase.WriteUint(buf, uint64(t.Unix())*1e6+uint64(t.Nanosecond()/1e3)) |
+} |
+ |
+func readTime(buf *bytes.Buffer) (time.Time, error) { |
+ v, err := funnybase.ReadUint(buf) |
+ if err != nil { |
+ return time.Time{}, err |
+ } |
+ return time.Unix(int64(v/1e6), int64((v%1e6)*1e3)), nil |
+} |
+ |
+func writeGeoPoint(buf *bytes.Buffer, gp appengine.GeoPoint) { |
+ writeFloat64(buf, gp.Lat) |
+ writeFloat64(buf, gp.Lng) |
+} |
+ |
+func readGeoPoint(buf *bytes.Buffer) (pt appengine.GeoPoint, err error) { |
+ if pt.Lat, err = readFloat64(buf); err != nil { |
+ return |
+ } |
+ pt.Lng, err = readFloat64(buf) |
+ return |
+} |