Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(datastore): Ensure the datastore time is returned as UTC #3521

Merged
merged 10 commits into from Jan 13, 2021
4 changes: 2 additions & 2 deletions datastore/load.go
Expand Up @@ -369,7 +369,7 @@ func setVal(v reflect.Value, p Property) (s string) {
if ok {
s := micros / 1e6
ns := micros % 1e6
v.Set(reflect.ValueOf(time.Unix(s, ns)))
v.Set(reflect.ValueOf(time.Unix(s, ns).In(time.UTC)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mind adding a test that ensures the times are returned in UTC?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1, might be easier said than done though :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test added.

break
}
x, ok := pValue.(time.Time)
Expand Down Expand Up @@ -536,7 +536,7 @@ func propToValue(v *pb.Value) (interface{}, error) {
case *pb.Value_DoubleValue:
return v.DoubleValue, nil
case *pb.Value_TimestampValue:
return time.Unix(v.TimestampValue.Seconds, int64(v.TimestampValue.Nanos)), nil
return time.Unix(v.TimestampValue.Seconds, int64(v.TimestampValue.Nanos)).In(time.UTC), nil
case *pb.Value_KeyValue:
return protoToKey(v.KeyValue)
case *pb.Value_StringValue:
Expand Down
30 changes: 30 additions & 0 deletions datastore/load_test.go
Expand Up @@ -569,6 +569,36 @@ func TestLoadToInterface(t *testing.T) {
}
}

func TestTimezone(t *testing.T) {
// Expect Local times to be represented in UTC
crwilcox marked this conversation as resolved.
Show resolved Hide resolved
src := &pb.Entity{
Key: keyToProto(testKey0),
Properties: map[string]*pb.Value{
"Time": {ValueType: &pb.Value_TimestampValue{TimestampValue: &timestamppb.Timestamp{Seconds: 1605504600}}},
},
}

dst := &struct{ Time time.Time }{
Time: time.Time{},
}
want := &struct{ Time time.Time }{
Time: time.Unix(1605504600, 0).In(time.UTC),
}

err := loadEntityProto(dst, src)

if err != nil {
t.Fatalf("loadEntityProto: %v", err)
}

gotZone, _ := dst.Time.Zone()
crwilcox marked this conversation as resolved.
Show resolved Hide resolved
wantZone, _ := want.Time.Zone()
if diff := testutil.Diff(gotZone, wantZone); diff != "" {
t.Fatalf("Mismatch: got - want +\n%s", diff)
}

}

func TestAlreadyPopulatedDst(t *testing.T) {
testCases := []struct {
desc string
Expand Down