From 8fb8f7b7d5e006e9bfea2468cd9cd1f545dc6915 Mon Sep 17 00:00:00 2001 From: Juliusz Chroboczek Date: Sat, 2 May 2020 18:41:18 +0200 Subject: [PATCH] Implement NTP time. --- mono/mono.go | 22 ++++++++++++++++++++++ mono/mono_test.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/mono/mono.go b/mono/mono.go index e17eafb..82ba5c7 100644 --- a/mono/mono.go +++ b/mono/mono.go @@ -10,6 +10,10 @@ func fromDuration(d time.Duration, hz uint32) uint64 { return uint64(d) * uint64(hz) / uint64(time.Second) } +func toDuration(tm uint64, hz uint32) time.Duration { + return time.Duration(tm * uint64(time.Second) / uint64(hz)) +} + func Now(hz uint32) uint64 { return fromDuration(time.Since(epoch), hz) } @@ -17,3 +21,21 @@ func Now(hz uint32) uint64 { func Microseconds() uint64 { return Now(1000000) } + +var ntpEpoch = time.Date(1900, 1, 1, 0, 0, 0, 0, time.UTC) + +func NTPToTime(ntp uint64) time.Time { + sec := uint32(ntp >> 32) + frac := uint32(ntp & 0xFFFFFFFF) + return ntpEpoch.Add( + time.Duration(sec) * time.Second + + ((time.Duration(frac) * time.Second) >> 32), + ) +} + +func TimeToNTP(tm time.Time) uint64 { + d := tm.Sub(ntpEpoch) + sec := uint32(d / time.Second) + frac := uint32(d % time.Second) + return (uint64(sec) << 32) + (uint64(frac) << 32) / uint64(time.Second) +} diff --git a/mono/mono_test.go b/mono/mono_test.go index f592c83..26c2e13 100644 --- a/mono/mono_test.go +++ b/mono/mono_test.go @@ -5,6 +5,18 @@ import ( "time" ) +func TestDuration(t *testing.T) { + a := fromDuration(time.Second, 48000) + if a != 48000 { + t.Errorf("Expected 48000, got %v", a) + } + + b := toDuration(48000, 48000) + if b != time.Second { + t.Errorf("Expected %v, got %v", time.Second, b) + } +} + func differs(a, b, delta uint64) bool { if a < b { a, b = b, a @@ -27,3 +39,29 @@ func TestMono(t *testing.T) { t.Errorf("Expected %v, got %v", 4000, d) } } + +func TestNTP(t *testing.T) { + now := time.Now() + ntp := TimeToNTP(now) + now2 := NTPToTime(ntp) + ntp2 := TimeToNTP(now2) + + diff1 := now2.Sub(now) + if diff1 < 0 { + diff1 = -diff1 + } + if diff1 > time.Nanosecond { + t.Errorf("Expected %v, got %v (diff=%v)", + now, now2, diff1) + } + + diff2 := int64(ntp2 - ntp) + if diff2 < 0 { + diff2 = -diff2 + } + if diff2 > (1 << 8) { + t.Errorf("Expected %v, got %v (diff=%v)", + ntp, ntp2, float64(diff2) / float64(1<<32)) + } + +}