mirror of
https://github.com/tailscale/tailscale.git
synced 2026-09-15 07:20:36 -04:00
Add DurationNano, DurationUnits, DurationISO8601, TimeUnix, TimeUnixNano, and TimeRFC1123: wrappers around time.Duration and time.Time that marshal to the wire formats that json `format:` struct tag options (format:nano, format:units, and so on) used to produce with github.com/go-json-experiment/json. Go 1.27's encoding/json rejects format tag options outright, and the module moved its support behind a global experimental option that its documentation says will be removed (see golang/go#71631). Struct tags are also only honored by the marshaler that happens to encode the struct, so any stdlib encoding/json call reaching a tagged struct, including generated MarshalJSON methods, breaks under Go 1.27. These types instead carry their wire format with them: they implement both the v1 json.Marshaler/Unmarshaler and the module's MarshalerTo/UnmarshalerFrom interfaces and produce identical bytes under the standard library and the module, on Go 1.26 and Go 1.27. Tests verify byte-for-byte parity against the module's format tag encodings across randomized values. Unmarshal is additionally lenient where the legacy standard library produced a different encoding for the underlying type because it ignored the tags: the Time types also accept RFC 3339 strings and the string-formatted Duration types also accept nanosecond counts, so previously persisted data remains readable. The tailscale corp repo will migrate its format tag uses to these types; this repo has none. Updates #20220 Updates tailscale/corp#45953 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> Change-Id: Iabde575b0228eb782d00e7180044ddd2f01d505e