Fix Timestamp Unmarshaling for pre-epoch times The `%` operator is the remainder, so was resulting in negative nano components. The UnixNano call can also overflow, notably for the zero time. Switch to using `Unix()` directly for seconds, and `Nanosecond()` for the nanosecond component.
diff --git a/jsonpb/jsonpb.go b/jsonpb/jsonpb.go index 38f86c5..1fc8ae8 100644 --- a/jsonpb/jsonpb.go +++ b/jsonpb/jsonpb.go
@@ -608,11 +608,8 @@ if err != nil { return fmt.Errorf("bad Timestamp: %v", err) } - ns := t.UnixNano() - s := ns / 1e9 - ns %= 1e9 - target.Field(0).SetInt(s) - target.Field(1).SetInt(ns) + target.Field(0).SetInt(int64(t.Unix())) + target.Field(1).SetInt(int64(t.Nanosecond())) return nil } }
diff --git a/jsonpb/jsonpb_test.go b/jsonpb/jsonpb_test.go index d2f6604..bd1449c 100644 --- a/jsonpb/jsonpb_test.go +++ b/jsonpb/jsonpb_test.go
@@ -468,6 +468,8 @@ {"Duration", Unmarshaler{}, `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}}, {"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}}, + {"PreEpochTimestamp", Unmarshaler{}, `{"ts":"1969-12-31T23:59:58.999999995Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: -2, Nanos: 999999995}}}, + {"ZeroTimeTimestamp", Unmarshaler{}, `{"ts":"0001-01-01T00:00:00Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: -62135596800, Nanos: 0}}}, {"DoubleValue", Unmarshaler{}, `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}}, {"FloatValue", Unmarshaler{}, `{"flt":1.2}`, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}},