From 91828e52c7c85737fe98c0516e93bef3839110a7 Mon Sep 17 00:00:00 2001 From: kpango Date: Tue, 8 Feb 2022 21:02:17 +0900 Subject: [PATCH] [minor] refactor and add Location setting interface Signed-off-by: kpango --- fastime.go | 150 ++++++++++++++++++++++-------------------------- fastime_test.go | 28 ++++----- global.go | 80 ++++++++++++++++++++++++++ now.go | 8 ++- now_windows.go | 5 +- renovate.json | 5 -- 6 files changed, 172 insertions(+), 104 deletions(-) create mode 100644 global.go delete mode 100644 renovate.json diff --git a/fastime.go b/fastime.go index 31da45a..67c8de4 100644 --- a/fastime.go +++ b/fastime.go @@ -10,8 +10,24 @@ import ( "unsafe" ) +type Fastime interface { + IsDaemonRunning() bool + GetFormat() string + SetFormat(format string) Fastime + GetLocation() *time.Location + SetLocation(location *time.Location) Fastime + Now() time.Time + Stop() + UnixNow() int64 + UnixUNow() uint32 + UnixNanoNow() int64 + UnixUNanoNow() uint32 + FormattedNow() []byte + StartTimerD(ctx context.Context, dur time.Duration) Fastime +} + // Fastime is fastime's base struct, it's stores atomic time object -type Fastime struct { +type fastime struct { uut uint32 uunt uint32 dur int64 @@ -22,42 +38,43 @@ type Fastime struct { t *atomic.Value ft *atomic.Value format *atomic.Value - pool sync.Pool + location *atomic.Value cancel context.CancelFunc + pool sync.Pool } -var ( - once sync.Once - instance *Fastime -) - -func init() { - once.Do(func() { - instance = New().StartTimerD(context.Background(), time.Millisecond*5) - }) +// New returns Fastime +func New() Fastime { + return newFastime() } -// New returns Fastime -func New() *Fastime { - running := new(atomic.Value) - running.Store(false) - f := &Fastime{ - t: new(atomic.Value), - running: running, - ut: math.MaxInt64, - unt: math.MaxInt64, - uut: math.MaxUint32, - uunt: math.MaxUint32, +func newFastime() *fastime { + f := &fastime{ + t: new(atomic.Value), + running: func() *atomic.Value { + av := new(atomic.Value) + av.Store(false) + return av + }(), + ut: math.MaxInt64, + unt: math.MaxInt64, + uut: math.MaxUint32, + uunt: math.MaxUint32, format: func() *atomic.Value { av := new(atomic.Value) av.Store(time.RFC3339) return av }(), + location: func() *atomic.Value { + av := new(atomic.Value) + av.Store(time.Local) + return av + }(), correctionDur: time.Millisecond * 100, } f.pool = sync.Pool{ New: func() interface{} { - return bytes.NewBuffer(make([]byte, 0, len(f.format.Load().(string)))) + return bytes.NewBuffer(make([]byte, 0, len(f.GetFormat()))) }, } f.ft = func() *atomic.Value { @@ -72,15 +89,15 @@ func New() *Fastime { return f.refresh() } -func (f *Fastime) update() *Fastime { +func (f *fastime) update() *fastime { return f.store(f.Now().Add(time.Duration(atomic.LoadInt64(&f.dur)))) } -func (f *Fastime) refresh() *Fastime { +func (f *fastime) refresh() *fastime { return f.store(f.now()) } -func (f *Fastime) store(t time.Time) *Fastime { +func (f *fastime) store(t time.Time) *fastime { f.t.Store(t) ut := t.Unix() unt := t.UnixNano() @@ -88,7 +105,7 @@ func (f *Fastime) store(t time.Time) *Fastime { atomic.StoreInt64(&f.unt, unt) atomic.StoreUint32(&f.uut, *(*uint32)(unsafe.Pointer(&ut))) atomic.StoreUint32(&f.uunt, *(*uint32)(unsafe.Pointer(&unt))) - form := f.format.Load().(string) + form := f.GetFormat() buf := f.pool.Get().(*bytes.Buffer) if buf == nil || len(form) > buf.Cap() { buf.Grow(len(form)) @@ -98,66 +115,40 @@ func (f *Fastime) store(t time.Time) *Fastime { return f } -// SetFormat replaces time format -func SetFormat(format string) *Fastime { - return instance.SetFormat(format) -} - -// SetFormat replaces time format -func (f *Fastime) SetFormat(format string) *Fastime { - f.format.Store(format) - f.refresh() - return f -} - -// Now returns current time -func Now() time.Time { - return instance.Now() -} - -// Stop stops stopping time refresh daemon -func Stop() { - instance.Stop() -} - -// UnixNow returns current unix time -func UnixNow() int64 { - return instance.UnixNow() -} - -// UnixNow returns current unix time -func UnixUNow() uint32 { - return instance.UnixUNow() +func (f *fastime) IsDaemonRunning() bool { + return f.running.Load().(bool) } -// UnixNanoNow returns current unix nano time -func UnixNanoNow() int64 { - return instance.UnixNanoNow() +func (f *fastime) GetLocation() *time.Location { + return f.location.Load().(*time.Location) } -// UnixNanoNow returns current unix nano time -func UnixUNanoNow() uint32 { - return instance.UnixUNanoNow() +func (f *fastime) GetFormat() string { + return f.format.Load().(string) } -// FormattedNow returns formatted byte time -func FormattedNow() []byte { - return instance.FormattedNow() +// SetLocation replaces time location +func (f *fastime) SetLocation(location *time.Location) Fastime { + f.location.Store(location) + f.refresh() + return f } -// StartTimerD provides time refresh daemon -func StartTimerD(ctx context.Context, dur time.Duration) *Fastime { - return instance.StartTimerD(ctx, dur) +// SetFormat replaces time format +func (f *fastime) SetFormat(format string) Fastime { + f.format.Store(format) + f.refresh() + return f } // Now returns current time -func (f *Fastime) Now() time.Time { +func (f *fastime) Now() time.Time { return f.t.Load().(time.Time) } // Stop stops stopping time refresh daemon -func (f *Fastime) Stop() { - if f.running.Load().(bool) { +func (f *fastime) Stop() { + if f.IsDaemonRunning() { f.cancel() atomic.StoreInt64(&f.dur, 0) return @@ -165,33 +156,33 @@ func (f *Fastime) Stop() { } // UnixNow returns current unix time -func (f *Fastime) UnixNow() int64 { +func (f *fastime) UnixNow() int64 { return atomic.LoadInt64(&f.ut) } // UnixNow returns current unix time -func (f *Fastime) UnixUNow() uint32 { +func (f *fastime) UnixUNow() uint32 { return atomic.LoadUint32(&f.uut) } // UnixNanoNow returns current unix nano time -func (f *Fastime) UnixNanoNow() int64 { +func (f *fastime) UnixNanoNow() int64 { return atomic.LoadInt64(&f.unt) } // UnixNanoNow returns current unix nano time -func (f *Fastime) UnixUNanoNow() uint32 { +func (f *fastime) UnixUNanoNow() uint32 { return atomic.LoadUint32(&f.uunt) } // FormattedNow returns formatted byte time -func (f *Fastime) FormattedNow() []byte { +func (f *fastime) FormattedNow() []byte { return f.ft.Load().([]byte) } // StartTimerD provides time refresh daemon -func (f *Fastime) StartTimerD(ctx context.Context, dur time.Duration) *Fastime { - if f.running.Load().(bool) { +func (f *fastime) StartTimerD(ctx context.Context, dur time.Duration) Fastime { + if f.IsDaemonRunning() { f.Stop() } f.refresh() @@ -226,6 +217,5 @@ func (f *Fastime) StartTimerD(ctx context.Context, dur time.Duration) *Fastime { } } }() - return f } diff --git a/fastime_test.go b/fastime_test.go index d661b1c..feb8827 100644 --- a/fastime_test.go +++ b/fastime_test.go @@ -255,11 +255,11 @@ func TestFastime_UnixUNanoNow(t *testing.T) { func TestFastime_refresh(t *testing.T) { tests := []struct { name string - f *Fastime + f *fastime }{ { name: "refresh", - f: New(), + f: newFastime(), }, } for _, tt := range tests { @@ -283,8 +283,8 @@ func TestSetFormat(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := SetFormat(tt.format); !reflect.DeepEqual(got.format.Load().(string), time.RFC3339) { - t.Errorf("SetFormat() = %v, want %v", got.format.Load().(string), time.RFC3339) + if got := SetFormat(tt.format); !reflect.DeepEqual(got.GetFormat(), time.RFC3339) { + t.Errorf("SetFormat() = %v, want %v", got.GetFormat(), time.RFC3339) } }) } @@ -292,7 +292,7 @@ func TestSetFormat(t *testing.T) { func TestFastime_SetFormat(t *testing.T) { tests := []struct { name string - f *Fastime + f Fastime format string }{ { @@ -303,8 +303,8 @@ func TestFastime_SetFormat(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := tt.f.SetFormat(tt.format); !reflect.DeepEqual(got.format.Load().(string), time.RFC3339) { - t.Errorf("Fastime.SetFormat() = %v, want %v", got.format.Load().(string), time.RFC3339) + if got := tt.f.SetFormat(tt.format); !reflect.DeepEqual(got.GetFormat(), time.RFC3339) { + t.Errorf("Fastime.SetFormat() = %v, want %v", got.GetFormat(), time.RFC3339) } }) } @@ -328,7 +328,7 @@ func TestFormattedNow(t *testing.T) { func TestFastime_FormattedNow(t *testing.T) { tests := []struct { name string - f *Fastime + f Fastime }{ { name: "fetch", @@ -345,11 +345,11 @@ func TestFastime_FormattedNow(t *testing.T) { func TestFastime_now(t *testing.T) { tests := []struct { name string - f *Fastime + f *fastime }{ { name: "now", - f: New(), + f: newFastime(), }, } for _, tt := range tests { @@ -364,11 +364,11 @@ func TestFastime_now(t *testing.T) { func TestFastime_update(t *testing.T) { tests := []struct { name string - f *Fastime + f *fastime }{ { name: "update", - f: New(), + f: newFastime(), }, } for _, tt := range tests { @@ -383,11 +383,11 @@ func TestFastime_update(t *testing.T) { func TestFastime_store(t *testing.T) { tests := []struct { name string - f *Fastime + f *fastime }{ { name: "store", - f: New(), + f: newFastime(), }, } for _, tt := range tests { diff --git a/global.go b/global.go new file mode 100644 index 0000000..20dcd77 --- /dev/null +++ b/global.go @@ -0,0 +1,80 @@ +package fastime + +import ( + "context" + "sync" + "time" +) + +var ( + once sync.Once + instance Fastime +) + +func init() { + once.Do(func() { + instance = New().StartTimerD(context.Background(), time.Millisecond*5) + }) +} + +func IsDaemonRunning() bool { + return instance.IsDaemonRunning() +} + +func GetLocation() *time.Location { + return instance.GetLocation() +} + +func GetFormat() string { + return instance.GetFormat() +} + +// SetLocation replaces time location +func SetLocation(location *time.Location) Fastime { + return instance.SetLocation(location) +} + +// SetFormat replaces time format +func SetFormat(format string) Fastime { + return instance.SetFormat(format) +} + +// Now returns current time +func Now() time.Time { + return instance.Now() +} + +// Stop stops stopping time refresh daemon +func Stop() { + instance.Stop() +} + +// UnixNow returns current unix time +func UnixNow() int64 { + return instance.UnixNow() +} + +// UnixUNow returns current unix time +func UnixUNow() uint32 { + return instance.UnixUNow() +} + +// UnixNanoNow returns current unix nano time +func UnixNanoNow() int64 { + return instance.UnixNanoNow() +} + +// UnixUNanoNow returns current unix nano time +func UnixUNanoNow() uint32 { + return instance.UnixUNanoNow() +} + +// FormattedNow returns formatted byte time +func FormattedNow() []byte { + return instance.FormattedNow() +} + +// StartTimerD provides time refresh daemon +func StartTimerD(ctx context.Context, dur time.Duration) Fastime { + return instance.StartTimerD(ctx, dur) +} diff --git a/now.go b/now.go index 4e6a773..3643822 100644 --- a/now.go +++ b/now.go @@ -1,3 +1,4 @@ +//go:build aix || darwin || dragonfly || freebsd || (js && wasm) || linux || nacl || netbsd || openbsd || solaris // +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris package fastime @@ -7,11 +8,12 @@ import ( "time" ) -func (f *Fastime) now() time.Time { +func (f *fastime) now() time.Time { var tv syscall.Timeval err := syscall.Gettimeofday(&tv) + loc := f.GetLocation() if err != nil { - return time.Now().In(time.Local) + return time.Now().In(loc) } - return time.Unix(0, syscall.TimevalToNsec(tv)).In(time.Local) + return time.Unix(0, syscall.TimevalToNsec(tv)).In(loc) } diff --git a/now_windows.go b/now_windows.go index 697e675..10f609b 100644 --- a/now_windows.go +++ b/now_windows.go @@ -1,9 +1,10 @@ +//go:build windows // +build windows package fastime import "time" -func (f *Fastime) now() time.Time { - return time.Now().In(time.Local) +func (f *fastime) now() time.Time { + return time.Now().In(f.GetLocation()) } diff --git a/renovate.json b/renovate.json deleted file mode 100644 index f45d8f1..0000000 --- a/renovate.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "extends": [ - "config:base" - ] -}