You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

99 lines
2.5 KiB

package s3lifecycle
import (
"math"
"strconv"
"time"
)
// versionIdFormatThreshold distinguishes old vs new format version IDs.
// New format (inverted timestamps) produces values above this threshold;
// old format (raw timestamps) produces values below it.
const versionIdFormatThreshold = 0x4000000000000000
// GetVersionTimestamp extracts the actual timestamp from a SeaweedFS version ID,
// handling both old (raw nanosecond) and new (inverted nanosecond) formats.
// Returns zero time if the version ID is invalid or "null".
func GetVersionTimestamp(versionId string) time.Time {
ns := getVersionTimestampNanos(versionId)
if ns == 0 {
return time.Time{}
}
return time.Unix(0, ns)
}
// getVersionTimestampNanos extracts the raw nanosecond timestamp from a version ID.
func getVersionTimestampNanos(versionId string) int64 {
if len(versionId) < 16 || versionId == "null" {
return 0
}
timestampPart, err := strconv.ParseUint(versionId[:16], 16, 64)
if err != nil {
return 0
}
if timestampPart > math.MaxInt64 {
return 0
}
if timestampPart > versionIdFormatThreshold {
// New format: inverted timestamp, convert back.
return int64(math.MaxInt64 - timestampPart)
}
return int64(timestampPart)
}
// isNewFormatVersionId returns true if the version ID uses inverted timestamps.
func isNewFormatVersionId(versionId string) bool {
if len(versionId) < 16 || versionId == "null" {
return false
}
timestampPart, err := strconv.ParseUint(versionId[:16], 16, 64)
if err != nil {
return false
}
return timestampPart > versionIdFormatThreshold && timestampPart <= math.MaxInt64
}
// CompareVersionIds compares two version IDs for sorting (newest first).
// Returns negative if a is newer, positive if b is newer, 0 if equal.
// Handles both old and new format version IDs and uses full lexicographic
// comparison (not just timestamps) to break ties from the random suffix.
func CompareVersionIds(a, b string) int {
if a == b {
return 0
}
if a == "null" {
return 1
}
if b == "null" {
return -1
}
aIsNew := isNewFormatVersionId(a)
bIsNew := isNewFormatVersionId(b)
if aIsNew == bIsNew {
if aIsNew {
// New format: smaller hex = newer (inverted timestamps).
if a < b {
return -1
}
return 1
}
// Old format: smaller hex = older.
if a < b {
return 1
}
return -1
}
// Mixed formats: compare by actual timestamp.
aTime := getVersionTimestampNanos(a)
bTime := getVersionTimestampNanos(b)
if aTime > bTime {
return -1
}
if aTime < bTime {
return 1
}
return 0
}