From e86f4d9dfd12775e57f8015d05600717611d0539 Mon Sep 17 00:00:00 2001 From: "Matt T. Proud" Date: Wed, 24 Apr 2013 12:05:52 +0200 Subject: [PATCH] Convert time readers to represent time in UTC. Go's time.Time represents time as UTC in its fundamental data type. That said, when using ``time.Unix(...)``, it sets the zone for the time representation to the local. Unfortunately with diagnosis and our tests, it is a PITA to jump between various zones, even though the serialized version remains the same. To keep things easy, all places where times are generated or read are converted into UTC. These conversions are cheap, for ``Time.In`` merely changes a pointer reference in the struct, nothing more. This enables me to diagnose test failures with fixture data very easily. --- coding/indexable/time.go | 12 +++++++----- model/metric.go | 2 +- model/samplekey.go | 2 +- model/watermark.go | 2 +- web/api/query.go | 4 ++-- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/coding/indexable/time.go b/coding/indexable/time.go index b5bdae126..852a551f8 100644 --- a/coding/indexable/time.go +++ b/coding/indexable/time.go @@ -18,14 +18,14 @@ import ( "time" ) -var ( - EarliestTime = EncodeTime(time.Time{}) -) - +// EncodeTimeInto writes the provided time into the specified buffer subject +// to the LevelDB big endian key sort order requirement. func EncodeTimeInto(dst []byte, t time.Time) { binary.BigEndian.PutUint64(dst, uint64(t.Unix())) } +// EncodeTime converts the provided time into a byte buffer subject to the +// LevelDB big endian key sort order requirement. func EncodeTime(t time.Time) []byte { buffer := make([]byte, 8) @@ -34,6 +34,8 @@ func EncodeTime(t time.Time) []byte { return buffer } +// DecodeTime deserializes a big endian byte array into a Unix time in UTC, +// omitting granularity precision less than a second. func DecodeTime(src []byte) time.Time { - return time.Unix(int64(binary.BigEndian.Uint64(src)), 0) + return time.Unix(int64(binary.BigEndian.Uint64(src)), 0).UTC() } diff --git a/model/metric.go b/model/metric.go index 6289f9057..223b2ab8e 100644 --- a/model/metric.go +++ b/model/metric.go @@ -139,7 +139,7 @@ func (v Values) InsideInterval(t time.Time) (s bool) { func NewValuesFromDTO(dto *dto.SampleValueSeries) (v Values) { for _, value := range dto.Value { v = append(v, SamplePair{ - Timestamp: time.Unix(*value.Timestamp, 0), + Timestamp: time.Unix(*value.Timestamp, 0).UTC(), Value: SampleValue(*value.Value), }) } diff --git a/model/samplekey.go b/model/samplekey.go index 75f5b365d..ed9be185c 100644 --- a/model/samplekey.go +++ b/model/samplekey.go @@ -73,7 +73,7 @@ func NewSampleKeyFromDTO(dto *dto.SampleKey) SampleKey { return SampleKey{ Fingerprint: NewFingerprintFromDTO(dto.Fingerprint), FirstTimestamp: indexable.DecodeTime(dto.Timestamp), - LastTimestamp: time.Unix(*dto.LastTimestamp, 0), + LastTimestamp: time.Unix(*dto.LastTimestamp, 0).UTC(), SampleCount: *dto.SampleCount, } } diff --git a/model/watermark.go b/model/watermark.go index e6126bd41..0268c35b4 100644 --- a/model/watermark.go +++ b/model/watermark.go @@ -37,7 +37,7 @@ func (w Watermark) ToMetricHighWatermarkDTO() *dto.MetricHighWatermark { // dto.MetricHighWatermark object. func NewWatermarkFromHighWatermarkDTO(d *dto.MetricHighWatermark) Watermark { return Watermark{ - time.Unix(*d.Timestamp, 0), + time.Unix(*d.Timestamp, 0).UTC(), } } diff --git a/web/api/query.go b/web/api/query.go index 9b3015a51..ac3641bf4 100644 --- a/web/api/query.go +++ b/web/api/query.go @@ -84,8 +84,8 @@ func (serv MetricsService) QueryRange(expr string, end int64, duration int64, st matrix, err := ast.EvalVectorRange( exprNode.(ast.VectorNode), - time.Unix(end-duration, 0), - time.Unix(end, 0), + time.Unix(end-duration, 0).UTC(), + time.Unix(end, 0).UTC(), time.Duration(step)*time.Second) if err != nil { return ast.ErrorToJSON(err)