bump reva

fixes: #1747
This commit is contained in:
Ralf Haferkamp
2025-10-30 17:17:27 +01:00
committed by Ralf Haferkamp
parent e270cdbfd2
commit b5b15f29de
23 changed files with 366 additions and 162 deletions
+50
View File
@@ -6,6 +6,11 @@
[![codecov](https://codecov.io/gh/shamaton/msgpack/branch/master/graph/badge.svg?token=9PD2JUK5V3)](https://codecov.io/gh/shamaton/msgpack)
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fshamaton%2Fmsgpack.svg?type=shield)](https://app.fossa.com/projects/git%2Bgithub.com%2Fshamaton%2Fmsgpack?ref=badge_shield)
## 📣 Announcement: `time.Time` decoding defaults to **UTC** in v3
Starting with **v3.0.0**, when decoding MessagePack **Timestamp** into Gos `time.Time`,
the default `Location` will be **UTC** (previously `Local`). The instant is unchanged.
To keep the old behavior, use `SetDecodedTimeAsLocal()`.
## Features
* Supported types : primitive / array / slice / struct / map / interface{} and time.Time
* Renaming fields via `msgpack:"field_name"`
@@ -60,6 +65,51 @@ func handle(w http.ResponseWriter, r *http.Request) {
}
```
## 📣 Announcement: `time.Time` decoding defaults to **UTC** in v3
**TL;DR:** Starting with **v3.0.0**, when decoding MessagePack **Timestamp** into Gos `time.Time`, the default `Location` will be **UTC** (previously `Local`). The **instant** is unchanged—only the display/location changes. This avoids host-dependent differences and aligns with common distributed systems practice.
### What is changing?
* **Before (v2.x):** Decoded `time.Time` defaults to `Local`.
* **After (v3.0.0):** Decoded `time.Time` defaults to **UTC**.
MessagePacks Timestamp encodes an **instant** (epoch seconds + nanoseconds) and does **not** carry timezone info. Your datas point in time is the same; only `time.Time.Location()` differs.
### Why?
* Eliminate environment-dependent behavior (e.g., different hosts showing different local zones).
* Make “UTC by default” the safe, predictable baseline for logs, APIs, and distributed apps.
### Who is affected?
* Apps that **display local time** without explicitly converting from UTC.
* If your code already normalizes to UTC or explicitly sets a location, youre likely unaffected.
### Keep the old behavior (Local)
If you want the v2 behavior on v3:
```go
msgpack.SetDecodedTimeAsLocal()
```
Or convert after the fact:
```go
var t time.Time
_ = msgpack.Unmarshal(data, &t)
t = t.In(time.Local)
```
### Preview the new behavior on v2 (optional)
You can opt into UTC today on v2.x:
```go
msgpack.SetDecodedTimeAsUTC()
```
## Benchmark
This result made from [shamaton/msgpack_bench](https://github.com/shamaton/msgpack_bench)
+11
View File
@@ -10,6 +10,7 @@ import (
"github.com/shamaton/msgpack/v2/internal/encoding"
streamdecoding "github.com/shamaton/msgpack/v2/internal/stream/decoding"
streamencoding "github.com/shamaton/msgpack/v2/internal/stream/encoding"
"github.com/shamaton/msgpack/v2/time"
)
// StructAsArray is encoding option.
@@ -82,3 +83,13 @@ func RemoveExtStreamCoder(e ext.StreamEncoder, d ext.StreamDecoder) error {
func SetComplexTypeCode(code int8) {
def.SetComplexTypeCode(code)
}
// SetDecodedTimeAsUTC sets decoded time.Time values to UTC timezone.
func SetDecodedTimeAsUTC() {
time.SetDecodedAsLocal(false)
}
// SetDecodedTimeAsLocal sets decoded time.Time values to local timezone.
func SetDecodedTimeAsLocal() {
time.SetDecodedAsLocal(true)
}
+17 -5
View File
@@ -48,7 +48,11 @@ func (td *timeDecoder) AsValue(offset int, k reflect.Kind, d *[]byte) (interface
case def.Fixext4:
_, offset = td.ReadSize1(offset, d)
bs, offset := td.ReadSize4(offset, d)
return time.Unix(int64(binary.BigEndian.Uint32(bs)), 0), offset, nil
v := time.Unix(int64(binary.BigEndian.Uint32(bs)), 0)
if decodeAsLocal {
return v, offset, nil
}
return v.UTC(), offset, nil
case def.Fixext8:
_, offset = td.ReadSize1(offset, d)
@@ -56,9 +60,13 @@ func (td *timeDecoder) AsValue(offset int, k reflect.Kind, d *[]byte) (interface
data64 := binary.BigEndian.Uint64(bs)
nano := int64(data64 >> 34)
if nano > 999999999 {
return zero, 0, fmt.Errorf("In timestamp 64 formats, nanoseconds must not be larger than 999999999 : %d", nano)
return zero, 0, fmt.Errorf("in timestamp 64 formats, nanoseconds must not be larger than 999999999 : %d", nano)
}
return time.Unix(int64(data64&0x00000003ffffffff), nano), offset, nil
v := time.Unix(int64(data64&0x00000003ffffffff), nano)
if decodeAsLocal {
return v, offset, nil
}
return v.UTC(), offset, nil
case def.Ext8:
_, offset = td.ReadSize1(offset, d)
@@ -67,10 +75,14 @@ func (td *timeDecoder) AsValue(offset int, k reflect.Kind, d *[]byte) (interface
secbs, offset := td.ReadSize8(offset, d)
nano := binary.BigEndian.Uint32(nanobs)
if nano > 999999999 {
return zero, 0, fmt.Errorf("In timestamp 96 formats, nanoseconds must not be larger than 999999999 : %d", nano)
return zero, 0, fmt.Errorf("in timestamp 96 formats, nanoseconds must not be larger than 999999999 : %d", nano)
}
sec := binary.BigEndian.Uint64(secbs)
return time.Unix(int64(sec), int64(nano)), offset, nil
v := time.Unix(int64(sec), int64(nano))
if decodeAsLocal {
return v, offset, nil
}
return v.UTC(), offset, nil
}
return zero, 0, fmt.Errorf("should not reach this line!! code %x decoding %v", code, k)
+15 -3
View File
@@ -33,7 +33,11 @@ func (td *timeStreamDecoder) IsType(code byte, innerType int8, dataLength int) b
func (td *timeStreamDecoder) ToValue(code byte, data []byte, k reflect.Kind) (interface{}, error) {
switch code {
case def.Fixext4:
return time.Unix(int64(binary.BigEndian.Uint32(data)), 0), nil
v := time.Unix(int64(binary.BigEndian.Uint32(data)), 0)
if decodeAsLocal {
return v, nil
}
return v.UTC(), nil
case def.Fixext8:
data64 := binary.BigEndian.Uint64(data)
@@ -41,7 +45,11 @@ func (td *timeStreamDecoder) ToValue(code byte, data []byte, k reflect.Kind) (in
if nano > 999999999 {
return zero, fmt.Errorf("in timestamp 64 formats, nanoseconds must not be larger than 999999999 : %d", nano)
}
return time.Unix(int64(data64&0x00000003ffffffff), nano), nil
v := time.Unix(int64(data64&0x00000003ffffffff), nano)
if decodeAsLocal {
return v, nil
}
return v.UTC(), nil
case def.Ext8:
nano := binary.BigEndian.Uint32(data[:4])
@@ -49,7 +57,11 @@ func (td *timeStreamDecoder) ToValue(code byte, data []byte, k reflect.Kind) (in
return zero, fmt.Errorf("in timestamp 96 formats, nanoseconds must not be larger than 999999999 : %d", nano)
}
sec := binary.BigEndian.Uint64(data[4:12])
return time.Unix(int64(sec), int64(nano)), nil
v := time.Unix(int64(sec), int64(nano))
if decodeAsLocal {
return v, nil
}
return v.UTC(), nil
}
return zero, fmt.Errorf("should not reach this line!! code %x decoding %v", code, k)
+8
View File
@@ -0,0 +1,8 @@
package time
var decodeAsLocal = true
// SetDecodedAsLocal sets the decoded time to local time.
func SetDecodedAsLocal(b bool) {
decodeAsLocal = b
}