-
Notifications
You must be signed in to change notification settings - Fork 3.6k
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
feat(collections): add a time.Time key codec #19879
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package codec | ||
|
||
import ( | ||
"encoding/binary" | ||
"fmt" | ||
"time" | ||
) | ||
|
||
chixiaowen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
var timeSize = 8 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. idk if 8 bytes gives you the precision you're looking for, assuming the time is represented as Join(seconds,milliseconds) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Using a 64-bit integer to directly represent a Unix timestamp with millisecond precision usually provides sufficient precision and range, eliminating the need to separately represent seconds and milliseconds. |
||
|
||
type timeKey struct{} | ||
|
||
func NewTimeKey() KeyCodec[time.Time] { return timeKey{} } | ||
|
||
func (t timeKey) Encode(buffer []byte, key time.Time) (int, error) { | ||
if len(buffer) < timeSize { | ||
return 0, fmt.Errorf("buffer too small, required at least 8 bytes") | ||
} | ||
millis := key.UTC().UnixNano() / int64(time.Millisecond) | ||
binary.BigEndian.PutUint64(buffer, uint64(millis)) | ||
return timeSize, nil | ||
} | ||
|
||
func (t timeKey) Decode(buffer []byte) (int, time.Time, error) { | ||
if len(buffer) != timeSize { | ||
return 0, time.Time{}, fmt.Errorf("invalid time buffer buffer size") | ||
} | ||
millis := int64(binary.BigEndian.Uint64(buffer)) | ||
return timeSize, time.UnixMilli(millis).UTC(), nil | ||
} | ||
|
||
func (t timeKey) Size(_ time.Time) int { return timeSize } | ||
|
||
func (t timeKey) EncodeJSON(value time.Time) ([]byte, error) { return value.MarshalJSON() } | ||
|
||
func (t timeKey) DecodeJSON(b []byte) (time.Time, error) { | ||
time := time.Time{} | ||
err := time.UnmarshalJSON(b) | ||
return time, err | ||
} | ||
|
||
func (t timeKey) Stringify(key time.Time) string { return key.String() } | ||
func (t timeKey) KeyType() string { return "sdk/time.Time" } | ||
func (t timeKey) EncodeNonTerminal(buffer []byte, key time.Time) (int, error) { | ||
return t.Encode(buffer, key) | ||
} | ||
|
||
func (t timeKey) DecodeNonTerminal(buffer []byte) (int, time.Time, error) { | ||
if len(buffer) < timeSize { | ||
return 0, time.Time{}, fmt.Errorf("invalid time buffer size, wanted: %d at least, got: %d", timeSize, len(buffer)) | ||
} | ||
return t.Decode(buffer[:timeSize]) | ||
} | ||
func (t timeKey) SizeNonTerminal(key time.Time) int { return t.Size(key) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using
time.Now()
in tests can introduce non-determinism, which might lead to flaky tests. Consider using a fixedtime.Time
value to ensure the test's predictability and reliability. For example:Committable suggestion