diff --git a/datastore/load.go b/datastore/load.go index 5b1102961b8..821331151a8 100644 --- a/datastore/load.go +++ b/datastore/load.go @@ -384,13 +384,13 @@ func setVal(v reflect.Value, p Property) (s string) { } v.Set(reflect.ValueOf(x)) case typeOfCivilDate: - date := civil.DateOf(pValue.(time.Time)) + date := civil.DateOf(pValue.(time.Time).In(time.UTC)) v.Set(reflect.ValueOf(date)) case typeOfCivilDateTime: - dateTime := civil.DateTimeOf(pValue.(time.Time)) + dateTime := civil.DateTimeOf(pValue.(time.Time).In(time.UTC)) v.Set(reflect.ValueOf(dateTime)) case typeOfCivilTime: - timeVal := civil.TimeOf(pValue.(time.Time)) + timeVal := civil.TimeOf(pValue.(time.Time).In(time.UTC)) v.Set(reflect.ValueOf(timeVal)) default: ent, ok := pValue.(*Entity) diff --git a/datastore/load_test.go b/datastore/load_test.go index 518fa61c10b..8b154419578 100644 --- a/datastore/load_test.go +++ b/datastore/load_test.go @@ -439,6 +439,42 @@ type withUntypedInterface struct { Field interface{} } +func TestLoadCivilTimeInNonUTCZone(t *testing.T) { + src := &pb.Entity{ + Key: keyToProto(testKey0), + Properties: map[string]*pb.Value{ + "Time": {ValueType: &pb.Value_TimestampValue{TimestampValue: ×tamppb.Timestamp{Seconds: 1605504600}}}, + }, + } + dst := &struct{ Time civil.Time }{ + Time: civil.Time{}, + } + want := &struct{ Time civil.Time }{ + Time: civil.Time{ + Hour: 5, + Minute: 30, + }, + } + loc, err := time.LoadLocation("Africa/Cairo") + if err != nil { + t.Fatalf("LoadLocation: %v", err) + } + time.Local = loc + + err = loadEntityProto(dst, src) + if err != nil { + t.Fatalf("loadEntityProto: %v", err) + } + if diff := testutil.Diff(dst, want); diff != "" { + t.Fatalf("Mismatch: got - want +\n%s", diff) + } + loc, err = time.LoadLocation("UTC") + if err != nil { + t.Fatalf("LoadLocation: %v", err) + } + time.Local = loc +} + func TestLoadToInterface(t *testing.T) { testCases := []struct { name string