mirror of
https://github.com/moonD4rk/HackBrowserData.git
synced 2026-07-06 21:37:47 +02:00
fix(time): correct export data timestamp conversions (#586)
This commit is contained in:
@@ -348,17 +348,19 @@ func isSkippedDir(name string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// timeEpoch converts a WebKit/Chromium epoch timestamp (microseconds since
|
||||
// 1601-01-01) to a time.Time.
|
||||
// Offset from the Chromium epoch (1601-01-01 UTC) to the Unix epoch,
|
||||
// matching base::Time::kTimeTToMicrosecondsOffset in Chromium.
|
||||
const chromiumEpochOffsetMicros int64 = 11644473600000000
|
||||
|
||||
// timeEpoch converts a Chromium base::Time (μs since 1601 UTC) to UTC.
|
||||
// Returns zero for non-positive input or out-of-JSON-range values.
|
||||
func timeEpoch(epoch int64) time.Time {
|
||||
maxTime := int64(99633311740000000)
|
||||
if epoch > maxTime {
|
||||
return time.Date(2049, 1, 1, 1, 1, 1, 1, time.Local)
|
||||
if epoch <= 0 {
|
||||
return time.Time{}
|
||||
}
|
||||
t := time.Date(1601, 1, 1, 0, 0, 0, 0, time.Local)
|
||||
d := time.Duration(epoch)
|
||||
for i := 0; i < 1000; i++ {
|
||||
t = t.Add(d)
|
||||
t := time.UnixMicro(epoch - chromiumEpochOffsetMicros).UTC()
|
||||
if t.Year() < 1 || t.Year() > 9999 {
|
||||
return time.Time{}
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -720,3 +721,47 @@ func TestSetKeyRetrievers_SatisfiesInterface(t *testing.T) {
|
||||
SetKeyRetrievers(keyretriever.Retrievers)
|
||||
} = (*Browser)(nil)
|
||||
}
|
||||
|
||||
// Anchor: 2024-01-15T10:30:00Z as Chromium microseconds since 1601 UTC.
|
||||
const anchorUnixSeconds = int64(1705314600)
|
||||
|
||||
var anchorChromiumMicros = (anchorUnixSeconds + 11644473600) * 1_000_000
|
||||
|
||||
func TestTimeEpoch_AnchorDate(t *testing.T) {
|
||||
got := timeEpoch(anchorChromiumMicros)
|
||||
want := time.Date(2024, 1, 15, 10, 30, 0, 0, time.UTC)
|
||||
assert.Equal(t, want, got)
|
||||
assert.Equal(t, anchorUnixSeconds, got.Unix())
|
||||
}
|
||||
|
||||
func TestTimeEpoch_ZeroReturnsZeroTime(t *testing.T) {
|
||||
assert.True(t, timeEpoch(0).IsZero())
|
||||
}
|
||||
|
||||
func TestTimeEpoch_NegativeReturnsZeroTime(t *testing.T) {
|
||||
assert.True(t, timeEpoch(-1).IsZero())
|
||||
}
|
||||
|
||||
func TestTimeEpoch_AlwaysUTC(t *testing.T) {
|
||||
// assert.Same checks pointer equality: time.UTC and time.Local are
|
||||
// distinct *Location globals, so this catches any regression that
|
||||
// drops .UTC() even when the runner's TZ happens to be UTC.
|
||||
got := timeEpoch(anchorChromiumMicros)
|
||||
assert.Same(t, time.UTC, got.Location())
|
||||
}
|
||||
|
||||
func TestTimeEpoch_MicrosecondPrecisionPreserved(t *testing.T) {
|
||||
got := timeEpoch(anchorChromiumMicros + 123456)
|
||||
assert.Equal(t, 123456*int64(time.Microsecond), int64(got.Nanosecond()))
|
||||
}
|
||||
|
||||
func TestTimeEpoch_UnixEpochBoundary(t *testing.T) {
|
||||
got := timeEpoch(chromiumEpochOffsetMicros)
|
||||
assert.Equal(t, time.Unix(0, 0).UTC(), got)
|
||||
}
|
||||
|
||||
func TestTimeEpoch_OutOfJSONRangeReturnsZero(t *testing.T) {
|
||||
jsonBytes, err := timeEpoch(1 << 62).MarshalJSON()
|
||||
require.NoError(t, err)
|
||||
assert.JSONEq(t, `"0001-01-01T00:00:00Z"`, string(jsonBytes))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user