| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package serialize | 5 package serialize |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | 8 "bytes" |
| 9 "errors" | 9 "errors" |
| 10 "fmt" | 10 "fmt" |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 | 182 |
| 183 gp.Lng, _, e = cmpbin.ReadFloat64(buf) | 183 gp.Lng, _, e = cmpbin.ReadFloat64(buf) |
| 184 panicIf(e) | 184 panicIf(e) |
| 185 | 185 |
| 186 if !gp.Valid() { | 186 if !gp.Valid() { |
| 187 err = fmt.Errorf("helper: decoded invalid GeoPoint: %v", gp) | 187 err = fmt.Errorf("helper: decoded invalid GeoPoint: %v", gp) |
| 188 } | 188 } |
| 189 return | 189 return |
| 190 } | 190 } |
| 191 | 191 |
| 192 // TimeToInt converts a time value to a datastore-appropraite integer value. |
| 193 // |
| 194 // This method truncates the time to microseconds and drops the timezone, |
| 195 // because that's the (undocumented) way that the appengine SDK does it. |
| 196 func TimeToInt(t time.Time) int64 { |
| 197 t = t.Round(time.Microsecond) |
| 198 return t.Unix()*1e6 + int64(t.Nanosecond()/1e3) |
| 199 } |
| 200 |
| 201 // IntToTime converts a time integer produced by TimeToInt to a time.Time |
| 202 // instance. |
| 203 func IntToTime(v int64) time.Time { |
| 204 t := time.Unix(v/1e6, (v%1e6)*1e3) |
| 205 if t.IsZero() { |
| 206 return time.Time{} |
| 207 } |
| 208 return t.UTC() |
| 209 } |
| 210 |
| 192 // WriteTime writes a time.Time in a byte-sortable way. | 211 // WriteTime writes a time.Time in a byte-sortable way. |
| 193 // | 212 // |
| 194 // This method truncates the time to microseconds and drops the timezone, | 213 // This method uses TimeToInt to convert the time to an integer value. This |
| 195 // because that's the (undocumented) way that the appengine SDK does it. | 214 // truncates the time to microseconds and drops the timezone. |
| 196 func WriteTime(buf Buffer, t time.Time) error { | 215 func WriteTime(buf Buffer, t time.Time) error { |
| 197 name, off := t.Zone() | 216 name, off := t.Zone() |
| 198 if name != "UTC" || off != 0 { | 217 if name != "UTC" || off != 0 { |
| 199 panic(fmt.Errorf("helper: UTC OR DEATH: %s", t)) | 218 panic(fmt.Errorf("helper: UTC OR DEATH: %s", t)) |
| 200 } | 219 } |
| 201 » _, err := cmpbin.WriteInt(buf, t.Unix()*1e6+int64(t.Nanosecond()/1e3)) | 220 » _, err := cmpbin.WriteInt(buf, TimeToInt(t)) |
| 202 return err | 221 return err |
| 203 } | 222 } |
| 204 | 223 |
| 205 // ReadTime reads a time.Time from the buffer. | 224 // ReadTime reads a time.Time from the buffer. |
| 206 func ReadTime(buf Buffer) (time.Time, error) { | 225 func ReadTime(buf Buffer) (time.Time, error) { |
| 207 v, _, err := cmpbin.ReadInt(buf) | 226 v, _, err := cmpbin.ReadInt(buf) |
| 208 if err != nil { | 227 if err != nil { |
| 209 return time.Time{}, err | 228 return time.Time{}, err |
| 210 } | 229 } |
| 211 » t := time.Unix(v/1e6, (v%1e6)*1e3) | 230 » return IntToTime(v), nil |
| 212 » if t.IsZero() { | |
| 213 » » return time.Time{}, nil | |
| 214 » } | |
| 215 » return t.UTC(), nil | |
| 216 } | 231 } |
| 217 | 232 |
| 218 // WriteProperty writes a Property to the buffer. `context` behaves the same | 233 // WriteProperty writes a Property to the buffer. `context` behaves the same |
| 219 // way that it does for WriteKey, but only has an effect if `p` contains a | 234 // way that it does for WriteKey, but only has an effect if `p` contains a |
| 220 // Key as its Value. | 235 // Key as its Value. |
| 221 func WriteProperty(buf Buffer, context KeyContext, p ds.Property) (err error) { | 236 func WriteProperty(buf Buffer, context KeyContext, p ds.Property) (err error) { |
| 222 defer recoverTo(&err) | 237 defer recoverTo(&err) |
| 223 typb := byte(p.Type()) | 238 typb := byte(p.Type()) |
| 224 if p.IndexSetting() != ds.NoIndex { | 239 if p.IndexSetting() != ds.NoIndex { |
| 225 typb |= 0x80 | 240 typb |= 0x80 |
| (...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 593 } | 608 } |
| 594 } | 609 } |
| 595 | 610 |
| 596 func recoverTo(err *error) { | 611 func recoverTo(err *error) { |
| 597 if r := recover(); r != nil { | 612 if r := recover(); r != nil { |
| 598 if rerr := r.(parseError); rerr != nil { | 613 if rerr := r.(parseError); rerr != nil { |
| 599 *err = error(rerr) | 614 *err = error(rerr) |
| 600 } | 615 } |
| 601 } | 616 } |
| 602 } | 617 } |
| OLD | NEW |