├── go.mod
├── renovate.json
├── assets
└── logo.png
├── now_windows.go
├── .whitesource
├── .gitignore
├── .reviewdog.yml
├── now.go
├── fastime_bench_test.go
├── example
└── main.go
├── LICENSE
├── Makefile
├── README.md
├── .circleci
└── config.yml
├── fastime.go
└── fastime_test.go
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/kpango/fastime
2 |
3 | go 1.12
4 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ice3man543/fastime/master/assets/logo.png
--------------------------------------------------------------------------------
/now_windows.go:
--------------------------------------------------------------------------------
1 | // +build windows
2 |
3 | package fastime
4 |
5 | import "time"
6 |
7 | func (f *Fastime) now() time.Time {
8 | return time.Now()
9 | }
10 |
--------------------------------------------------------------------------------
/.whitesource:
--------------------------------------------------------------------------------
1 | {
2 | "generalSettings": {
3 | "shouldScanRepo": true
4 | },
5 | "checkRunSettings": {
6 | "vulnerableCheckRunConclusionLevel": "failure"
7 | }
8 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Binaries for programs and plugins
2 | *.exe
3 | *.exe~
4 | *.dll
5 | *.so
6 | *.dylib
7 |
8 | # Test binary, build with `go test -c`
9 | *.test
10 |
11 | # Output of the go coverage tool, specifically when used with LiteIDE
12 | *.out
13 |
--------------------------------------------------------------------------------
/.reviewdog.yml:
--------------------------------------------------------------------------------
1 | runner:
2 | golint:
3 | cmd: golint $(go list ./...)
4 | megacheck:
5 | cmd: megacheck $(go list ./...)
6 | errorformat:
7 | - "%f:%l:%c:%m"
8 | errcheck:
9 | cmd: errcheck -asserts -ignoretests -blank $(go list ./...)
10 | errorformat:
11 | - "%f:%l:%c:%m"
12 |
--------------------------------------------------------------------------------
/now.go:
--------------------------------------------------------------------------------
1 | // +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris
2 |
3 | package fastime
4 |
5 | import (
6 | "syscall"
7 | "time"
8 | )
9 |
10 | func (f *Fastime) now() time.Time {
11 | var tv syscall.Timeval
12 | err := syscall.Gettimeofday(&tv)
13 | if err != nil {
14 | return time.Now()
15 | }
16 | return time.Unix(0, syscall.TimevalToNsec(tv))
17 | }
18 |
--------------------------------------------------------------------------------
/fastime_bench_test.go:
--------------------------------------------------------------------------------
1 | package fastime
2 |
3 | import (
4 | "testing"
5 | "time"
6 | )
7 |
8 | // BenchmarkFastime
9 | func BenchmarkFastime(b *testing.B) {
10 | b.ReportAllocs()
11 | b.ResetTimer()
12 | b.RunParallel(func(pb *testing.PB) {
13 | for pb.Next() {
14 | Now()
15 | }
16 | })
17 | }
18 |
19 | // BenchmarkTime
20 | func BenchmarkTime(b *testing.B) {
21 | b.ReportAllocs()
22 | b.ResetTimer()
23 | b.RunParallel(func(pb *testing.PB) {
24 | for pb.Next() {
25 | time.Now()
26 | }
27 | })
28 | }
29 |
--------------------------------------------------------------------------------
/example/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "time"
6 |
7 | "github.com/kpango/fastime"
8 | )
9 |
10 | func main() {
11 | s1 := fastime.Now()
12 | s2 := fastime.Now()
13 | s3 := fastime.Now()
14 | time.Sleep(time.Second * 2)
15 | s4 := fastime.Now()
16 |
17 | time.Sleep(time.Second * 5)
18 |
19 | fmt.Printf("s1=%v\ns2=%v\ns3=%v\ns4=%v\n", s1, s2, s3, s4)
20 |
21 | fmt.Printf("nanonow %v\nnow unixnano %v\nnow add unixnano%v\nnanonow + dur %v\nstring %v",
22 | fastime.UnixNanoNow(),
23 | fastime.Now().Unix(),
24 | fastime.Now().Add(time.Second),
25 | fastime.UnixNanoNow()+int64(time.Second),
26 | string(fastime.FormattedNow()))
27 |
28 | for i := 0; i < 30; i++ {
29 | time.Sleep(time.Millisecond * 400)
30 | fmt.Println(fastime.Now())
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Yusuke Kato
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | GO_VERSION:=$(shell go version)
2 |
3 | .PHONY: all clean bench bench-all profile lint test contributors update install
4 |
5 | all: clean install lint test bench
6 |
7 | clean:
8 | go clean ./...
9 | rm -rf ./*.log
10 | rm -rf ./*.svg
11 | rm -rf ./go.mod
12 | rm -rf ./go.sum
13 | rm -rf bench
14 | rm -rf pprof
15 | rm -rf vendor
16 |
17 |
18 | bench: clean
19 | go test -count=10 -run=NONE -bench . -benchmem
20 |
21 | profile: clean
22 | rm -rf bench
23 | mkdir bench
24 | mkdir pprof
25 | \
26 | go test -count=10 -run=NONE -bench=BenchmarkFastime -benchmem -o pprof/fastime-test.bin -cpuprofile pprof/cpu-fastime.out -memprofile pprof/mem-fastime.out
27 | go tool pprof --svg pprof/fastime-test.bin pprof/cpu-fastime.out > cpu-fastime.svg
28 | go tool pprof --svg pprof/fastime-test.bin pprof/mem-fastime.out > mem-fastime.svg
29 | go-torch -f bench/cpu-fastime-graph.svg pprof/fastime-test.bin pprof/cpu-fastime.out
30 | go-torch --alloc_objects -f bench/mem-fastime-graph.svg pprof/fastime-test.bin pprof/mem-fastime.out
31 | \
32 | go test -count=10 -run=NONE -bench=BenchmarkTime -benchmem -o pprof/default-test.bin -cpuprofile pprof/cpu-default.out -memprofile pprof/mem-default.out
33 | go tool pprof --svg pprof/default-test.bin pprof/mem-default.out > mem-default.svg
34 | go tool pprof --svg pprof/default-test.bin pprof/cpu-default.out > cpu-default.svg
35 | go-torch -f bench/cpu-default-graph.svg pprof/default-test.bin pprof/cpu-default.out
36 | go-torch --alloc_objects -f bench/mem-default-graph.svg pprof/default-test.bin pprof/mem-default.out
37 | \
38 | mv ./*.svg bench/
39 |
40 | cpu:
41 | go tool pprof pprof/fastime-test.bin pprof/cpu-fastime.out
42 |
43 | mem:
44 | go tool pprof --alloc_space pprof/fastime-test.bin pprof/mem-fastime.out
45 |
46 | lint:
47 | gometalinter --enable-all . | rg -v comment
48 |
49 | test: clean
50 | GO111MODULE=on go test --race -v $(go list ./... | rg -v vendor)
51 |
52 | contributors:
53 | git log --format='%aN <%aE>' | sort -fu > CONTRIBUTORS
54 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |

3 |
4 |
5 |
6 | [](https://opensource.org/licenses/MIT)
7 | [](https://github.com/kpango/fastime/releases/latest)
8 | [](https://circleci.com/gh/kpango/fastime)
9 | [](https://codecov.io/gh/kpango/fastime)
10 | [](https://www.codacy.com/app/i.can.feel.gravity/fastime?utm_source=github.com&utm_medium=referral&utm_content=kpango/fastime&utm_campaign=Badge_Grade)
11 | [](https://goreportcard.com/report/github.com/kpango/fastime)
12 | [](http://godoc.org/github.com/kpango/fastime)
13 | [](https://gitter.im/kpango/fastime?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
14 | fastime is a super fast time function library for Go with zero memory allocation. fastime returns the approximate time.
15 |
16 | ## Requirement
17 | Go 1.1
18 |
19 | ## Installation
20 | ```shell
21 | go get github.com/kpango/fastime
22 | ```
23 |
24 | ## Example
25 | ```go
26 | now := fastime.Now()
27 | defer fastime.Stop()
28 |
29 | // Create Instance
30 | ft := fastime.New()
31 | defer ft.Stop()
32 | ft.Now()
33 | ```
34 |
35 | ## Benchmark
36 |
37 | ```
38 | go test -count=10 -run=NONE -bench . -benchmem
39 | goos: linux
40 | goarch: amd64
41 | pkg: github.com/kpango/fastime
42 | BenchmarkFastime-8 2000000000 0.45 ns/op 0 B/op 0 allocs/op
43 | BenchmarkFastime-8 2000000000 0.45 ns/op 0 B/op 0 allocs/op
44 | BenchmarkFastime-8 2000000000 0.45 ns/op 0 B/op 0 allocs/op
45 | BenchmarkFastime-8 2000000000 0.45 ns/op 0 B/op 0 allocs/op
46 | BenchmarkFastime-8 2000000000 0.45 ns/op 0 B/op 0 allocs/op
47 | BenchmarkFastime-8 2000000000 0.45 ns/op 0 B/op 0 allocs/op
48 | BenchmarkFastime-8 2000000000 0.45 ns/op 0 B/op 0 allocs/op
49 | BenchmarkFastime-8 2000000000 0.45 ns/op 0 B/op 0 allocs/op
50 | BenchmarkFastime-8 2000000000 0.45 ns/op 0 B/op 0 allocs/op
51 | BenchmarkFastime-8 2000000000 0.46 ns/op 0 B/op 0 allocs/op
52 | BenchmarkTime-8 1000000 1683 ns/op 0 B/op 0 allocs/op
53 | BenchmarkTime-8 1000000 1720 ns/op 0 B/op 0 allocs/op
54 | BenchmarkTime-8 1000000 1688 ns/op 0 B/op 0 allocs/op
55 | BenchmarkTime-8 1000000 1716 ns/op 0 B/op 0 allocs/op
56 | BenchmarkTime-8 1000000 1691 ns/op 0 B/op 0 allocs/op
57 | BenchmarkTime-8 1000000 1693 ns/op 0 B/op 0 allocs/op
58 | BenchmarkTime-8 1000000 1703 ns/op 0 B/op 0 allocs/op
59 | BenchmarkTime-8 1000000 1668 ns/op 0 B/op 0 allocs/op
60 | BenchmarkTime-8 1000000 1685 ns/op 0 B/op 0 allocs/op
61 | BenchmarkTime-8 1000000 1716 ns/op 0 B/op 0 allocs/op
62 | PASS
63 | ok github.com/kpango/fastime 26.873s
64 | ```
65 | ## Contribution
66 | 1. Fork it ( https://github.com/kpango/fastime/fork )
67 | 2. Create your feature branch (git checkout -b my-new-feature)
68 | 3. Commit your changes (git commit -am 'Add some feature')
69 | 4. Push to the branch (git push origin my-new-feature)
70 | 5. Create new Pull Request
71 |
72 | ## Author
73 | [kpango](https://github.com/kpango)
74 |
75 | ## LICENSE
76 | fastime released under MIT license, refer [LICENSE](https://github.com/kpango/fastime/blob/master/LICENSE) file.
77 |
--------------------------------------------------------------------------------
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | alias:
2 | default: &default
3 | working_directory: /go/src/github.com/kpango/fastime
4 | docker:
5 | - image: circleci/golang:1.13.1
6 | environment:
7 | GOPATH: "/go"
8 | GO111MODULE: "on"
9 | REPO_NAME: "kpango"
10 | IMAGE_NAME: "fastime"
11 | GITHUB_API: "https://api.github.com/"
12 | DOCKER_USER: "kpango"
13 | setup_remote_docker: &setup_remote_docker
14 | version: 18.06.0-ce
15 | docker_layer_caching: true
16 |
17 | version: 2
18 | jobs:
19 | test:
20 | <<: *default
21 | steps:
22 | - checkout
23 | - restore_cache:
24 | key: gosum-{{ .Branch }}-{{ checksum "go.sum" }}
25 | - run:
26 | name: preparation
27 | command: |
28 | go mod vendor
29 | - run:
30 | name: run tests
31 | command: |
32 | go test -v -race -covermode=atomic -coverprofile=coverage.out ./...
33 | go tool cover -html=coverage.out -o coverage.html
34 | bash <(curl -s https://codecov.io/bash)
35 | - store_artifacts:
36 | path: ./coverage.html
37 | - save_cache:
38 | key: gosum-{{ .Branch }}-{{ checksum "go.sum" }}
39 | paths:
40 | - ./vendor
41 | versioning:
42 | <<: *default
43 | steps:
44 | - checkout
45 | - run:
46 | name: check
47 | command: |
48 | mkdir -p $HOME/.ssh/ && echo -e "Host github.com\n\tStrictHostKeyChecking no\n" > ~/.ssh/config
49 | LAST_COMMIT=`git log -1 --pretty=%B`
50 | VERSION=`git describe --abbrev=0 --tags`
51 | touch ./.tag
52 | if [ ! -z "`git diff $VERSION`" -o -z "$VERSION" ]; then
53 | VERSION=${VERSION:-'0.0.0'}
54 | MAJOR="${VERSION%%.*}"; VERSION="${VERSION#*.}"
55 | MINOR="${VERSION%%.*}"; VERSION="${VERSION#*.}"
56 | PATCH="${VERSION%%.*}"; VERSION="${VERSION#*.}"
57 | if echo $LAST_COMMIT | grep "\[\(major\|MAJOR\)\]" > /dev/null; then
58 | MAJOR=$((MAJOR+1))
59 | echo "$MAJOR.0.0" > ./.tag
60 | elif echo $LAST_COMMIT | grep "\[\(minor\|MINOR\)\]" > /dev/null; then
61 | MINOR=$((MINOR+1))
62 | echo "$MAJOR.$MINOR.0" > ./.tag
63 | elif echo $LAST_COMMIT | grep "\[\(patch\|PATCH\)\]" > /dev/null; then
64 | PATCH=$((PATCH+1))
65 | echo "$MAJOR.$MINOR.$PATCH" > ./.tag
66 | fi
67 | fi
68 | - persist_to_workspace:
69 | root: .
70 | paths:
71 | - .
72 | push:
73 | <<: *default
74 | steps:
75 | - attach_workspace:
76 | at: .
77 | - run:
78 | name: push tag and check PR body
79 | command: |
80 | mkdir -p $HOME/.ssh/ && echo -e "Host github.com\n\tStrictHostKeyChecking no\n" > ~/.ssh/config
81 | TAG=`cat ./.tag`
82 | if [ ! -z "$TAG" ]; then
83 | echo $TAG
84 | git tag $TAG
85 | git push https://${GITHUB_ACCESS_TOKEN}:x-oauth-basic@github.com/${REPO_NAME}/${IMAGE_NAME} --tags
86 | fi
87 | - persist_to_workspace:
88 | root: .
89 | paths:
90 | - .
91 | gh_release:
92 | <<: *default
93 | steps:
94 | - attach_workspace:
95 | at: .
96 | - run:
97 | name: release
98 | command: |
99 | mkdir -p $HOME/.ssh/ && echo -e "Host github.com\n\tStrictHostKeyChecking no\n" > ~/.ssh/config
100 | TAG=`cat ./.tag`
101 | if [ ! -z "$TAG" ]; then
102 | echo "Create release: ${TAG}"
103 | curl -H "Authorization: token ${GITHUB_ACCESS_TOKEN}" \
104 | -X POST \
105 | -d "{\"tag_name\": \"${TAG}\"}" \
106 | ${GITHUB_API}repos/${REPO_NAME}/${IMAGE_NAME}/releases
107 | fi
108 |
109 | workflows:
110 | version: 2
111 | build:
112 | jobs:
113 | - test
114 | - versioning:
115 | filters:
116 | branches:
117 | only:
118 | - master
119 | - push:
120 | requires:
121 | - versioning
122 | - gh_release:
123 | requires:
124 | - push
125 |
--------------------------------------------------------------------------------
/fastime.go:
--------------------------------------------------------------------------------
1 | package fastime
2 |
3 | import (
4 | "context"
5 | "sync"
6 | "sync/atomic"
7 | "time"
8 | "unsafe"
9 | )
10 |
11 | // Fastime is fastime's base struct, it's stores atomic time object
12 | type Fastime struct {
13 | running *atomic.Value
14 | t *atomic.Value
15 | ut int64
16 | unt int64
17 | uut uint32
18 | uunt uint32
19 | ft *atomic.Value
20 | format *atomic.Value
21 | cancel context.CancelFunc
22 | correctionDur time.Duration
23 | dur int64
24 | }
25 |
26 | var (
27 | once sync.Once
28 | instance *Fastime
29 | )
30 |
31 | func init() {
32 | once.Do(func() {
33 | instance = New().StartTimerD(context.Background(), time.Millisecond*5)
34 | })
35 | }
36 |
37 | // New returns Fastime
38 | func New() *Fastime {
39 | running := new(atomic.Value)
40 | running.Store(false)
41 | return (&Fastime{
42 | t: new(atomic.Value),
43 | running: running,
44 | format: func() *atomic.Value {
45 | av := new(atomic.Value)
46 | av.Store(time.RFC3339)
47 | return av
48 | }(),
49 | ft: func() *atomic.Value {
50 | av := new(atomic.Value)
51 | av.Store(make([]byte, 0, len(time.RFC3339))[:0])
52 | return av
53 | }(),
54 | correctionDur: time.Millisecond * 100,
55 | }).refresh()
56 | }
57 |
58 | func (f *Fastime) update() *Fastime {
59 | return f.store(f.Now().Add(time.Duration(atomic.LoadInt64(&f.dur))))
60 | }
61 |
62 | func (f *Fastime) refresh() *Fastime {
63 | return f.store(f.now())
64 | }
65 |
66 | func (f *Fastime) store(t time.Time) *Fastime {
67 | f.t.Store(t)
68 | ut := t.Unix()
69 | unt := t.UnixNano()
70 | atomic.StoreInt64(&f.ut, ut)
71 | atomic.StoreInt64(&f.unt, unt)
72 | atomic.StoreUint32(&f.uut, *(*uint32)(unsafe.Pointer(&ut)))
73 | atomic.StoreUint32(&f.uunt, *(*uint32)(unsafe.Pointer(&unt)))
74 | form := f.format.Load().(string)
75 | f.ft.Store(t.AppendFormat(make([]byte, 0, len(form)), form))
76 | return f
77 | }
78 |
79 | // SetFormat replaces time format
80 | func SetFormat(format string) *Fastime {
81 | return instance.SetFormat(format)
82 | }
83 |
84 | // SetFormat replaces time format
85 | func (f *Fastime) SetFormat(format string) *Fastime {
86 | f.format.Store(format)
87 | f.refresh()
88 | return f
89 | }
90 |
91 | // Now returns current time
92 | func Now() time.Time {
93 | return instance.Now()
94 | }
95 |
96 | // Stop stops stopping time refresh daemon
97 | func Stop() {
98 | instance.Stop()
99 | }
100 |
101 | // UnixNow returns current unix time
102 | func UnixNow() int64 {
103 | return instance.UnixNow()
104 | }
105 |
106 | // UnixNow returns current unix time
107 | func UnixUNow() uint32 {
108 | return instance.UnixUNow()
109 | }
110 |
111 | // UnixNanoNow returns current unix nano time
112 | func UnixNanoNow() int64 {
113 | return instance.UnixNanoNow()
114 | }
115 |
116 | // UnixNanoNow returns current unix nano time
117 | func UnixUNanoNow() uint32 {
118 | return instance.UnixUNanoNow()
119 | }
120 |
121 | // FormattedNow returns formatted byte time
122 | func FormattedNow() []byte {
123 | return instance.FormattedNow()
124 | }
125 |
126 | // StartTimerD provides time refresh daemon
127 | func StartTimerD(ctx context.Context, dur time.Duration) *Fastime {
128 | return instance.StartTimerD(ctx, dur)
129 | }
130 |
131 | // Now returns current time
132 | func (f *Fastime) Now() time.Time {
133 | return f.t.Load().(time.Time)
134 | }
135 |
136 | // Stop stops stopping time refresh daemon
137 | func (f *Fastime) Stop() {
138 | if f.running.Load().(bool) {
139 | f.cancel()
140 | atomic.StoreInt64(&f.dur, 0)
141 | return
142 | }
143 | }
144 |
145 | // UnixNow returns current unix time
146 | func (f *Fastime) UnixNow() int64 {
147 | return atomic.LoadInt64(&f.ut)
148 | }
149 |
150 | // UnixNow returns current unix time
151 | func (f *Fastime) UnixUNow() uint32 {
152 | return atomic.LoadUint32(&f.uut)
153 | }
154 |
155 | // UnixNanoNow returns current unix nano time
156 | func (f *Fastime) UnixNanoNow() int64 {
157 | return atomic.LoadInt64(&f.unt)
158 | }
159 |
160 | // UnixNanoNow returns current unix nano time
161 | func (f *Fastime) UnixUNanoNow() uint32 {
162 | return atomic.LoadUint32(&f.uunt)
163 | }
164 |
165 | // FormattedNow returns formatted byte time
166 | func (f *Fastime) FormattedNow() []byte {
167 | return f.ft.Load().([]byte)
168 | }
169 |
170 | // StartTimerD provides time refresh daemon
171 | func (f *Fastime) StartTimerD(ctx context.Context, dur time.Duration) *Fastime {
172 | if f.running.Load().(bool) {
173 | f.Stop()
174 | }
175 | f.refresh()
176 |
177 | var ct context.Context
178 | ct, f.cancel = context.WithCancel(ctx)
179 | go func() {
180 | f.running.Store(true)
181 | atomic.StoreInt64(&f.dur, dur.Nanoseconds())
182 | ticker := time.NewTicker(time.Duration(atomic.LoadInt64(&f.dur)))
183 | ctick := time.NewTicker(f.correctionDur)
184 | for {
185 | select {
186 | case <-ct.Done():
187 | f.running.Store(false)
188 | ticker.Stop()
189 | ctick.Stop()
190 | return
191 | case <-ticker.C:
192 | f.update()
193 | case <-ctick.C:
194 | <-ticker.C
195 | f.refresh()
196 | }
197 | }
198 | }()
199 |
200 | return f
201 | }
202 |
--------------------------------------------------------------------------------
/fastime_test.go:
--------------------------------------------------------------------------------
1 | package fastime
2 |
3 | import (
4 | "context"
5 | "reflect"
6 | "sync/atomic"
7 | "testing"
8 | "time"
9 | )
10 |
11 | func TestNew(t *testing.T) {
12 | tests := []struct {
13 | name string
14 | }{
15 | {
16 | name: "is daemon starts?",
17 | },
18 | }
19 | for _, tt := range tests {
20 | t.Run(tt.name, func(t *testing.T) {
21 | f := New().StartTimerD(context.Background(), 10000)
22 | time.Sleep(time.Second * 2)
23 | if (time.Now().Unix() - f.Now().Unix()) > 1000 {
24 | t.Error("time is not correct so daemon is not started")
25 | }
26 | })
27 | }
28 | }
29 |
30 | func TestNow(t *testing.T) {
31 | tests := []struct {
32 | name string
33 | }{
34 | {
35 | name: "time equality",
36 | },
37 | }
38 | for _, tt := range tests {
39 | t.Run(tt.name, func(t *testing.T) {
40 | if (time.Now().Unix() - Now().Unix()) > 1000 {
41 | t.Error("time is not correct")
42 | }
43 | })
44 | }
45 | }
46 |
47 | func TestStop(t *testing.T) {
48 | tests := []struct {
49 | name string
50 | }{
51 | {
52 | name: "check stop",
53 | },
54 | }
55 | for _, tt := range tests {
56 | t.Run(tt.name, func(t *testing.T) {
57 | now := Now().Unix()
58 | if (time.Now().Unix() - now) > 1000 {
59 | t.Error("time is not correct")
60 | }
61 | Stop()
62 | time.Sleep(time.Second * 3)
63 | now = Now().Unix()
64 | if now == time.Now().Unix() {
65 | t.Error("refresh daemon stopped but time is same")
66 | }
67 |
68 | })
69 | }
70 | }
71 |
72 | func TestFastime_Now(t *testing.T) {
73 | type fields struct {
74 | t atomic.Value
75 | cancel context.CancelFunc
76 | }
77 | tests := []struct {
78 | name string
79 | fields fields
80 | want time.Time
81 | }{
82 | {
83 | name: "time equality",
84 | },
85 | }
86 | for _, tt := range tests {
87 | t.Run(tt.name, func(t *testing.T) {
88 | f := New().StartTimerD(context.Background(), 10000)
89 | if f.Now().Unix() != time.Now().Unix() {
90 | t.Error("time is not correct")
91 | }
92 | })
93 | }
94 | }
95 |
96 | func TestFastime_Stop(t *testing.T) {
97 | type fields struct {
98 | t atomic.Value
99 | cancel context.CancelFunc
100 | }
101 | tests := []struct {
102 | name string
103 | fields fields
104 | }{
105 | {
106 | name: "check stop",
107 | },
108 | }
109 | for _, tt := range tests {
110 | t.Run(tt.name, func(t *testing.T) {
111 | f := New().StartTimerD(context.Background(), time.Nanosecond*5)
112 | time.Sleep(time.Second)
113 | now := f.Now().Unix()
114 | if (time.Now().Unix() - now) > 1000 {
115 | t.Error("time is not correct")
116 | }
117 | f.Stop()
118 | time.Sleep(time.Second * 3)
119 | now = f.Now().Unix()
120 | if now == time.Now().Unix() {
121 | t.Error("refresh daemon stopped but time is same")
122 | }
123 |
124 | })
125 | }
126 | }
127 |
128 | func TestUnixNow(t *testing.T) {
129 | tests := []struct {
130 | name string
131 | }{
132 | {
133 | name: "time equality",
134 | },
135 | }
136 | for _, tt := range tests {
137 | t.Run(tt.name, func(t *testing.T) {
138 | if UnixNow() != Now().Unix() {
139 | t.Error("time is not correct")
140 | }
141 | })
142 | }
143 | }
144 |
145 | func TestFastime_UnixNow(t *testing.T) {
146 | tests := []struct {
147 | name string
148 | }{
149 | {
150 | name: "time equality",
151 | },
152 | }
153 |
154 | f := New().StartTimerD(context.Background(), time.Millisecond)
155 | for _, tt := range tests {
156 | t.Run(tt.name, func(t *testing.T) {
157 | if f.UnixNow() != f.Now().Unix() {
158 | t.Error("time is not correct")
159 | }
160 | })
161 | }
162 | }
163 |
164 | func TestUnixUNow(t *testing.T) {
165 | tests := []struct {
166 | name string
167 | }{
168 | {
169 | name: "time equality",
170 | },
171 | }
172 | for _, tt := range tests {
173 | t.Run(tt.name, func(t *testing.T) {
174 | if UnixUNow() != uint32(Now().Unix()) {
175 | t.Error("time is not correct")
176 | }
177 | })
178 | }
179 | }
180 |
181 | func TestFastime_UnixUNow(t *testing.T) {
182 | tests := []struct {
183 | name string
184 | }{
185 | {
186 | name: "time equality",
187 | },
188 | }
189 |
190 | f := New().StartTimerD(context.Background(), time.Millisecond)
191 | for _, tt := range tests {
192 | t.Run(tt.name, func(t *testing.T) {
193 | if f.UnixUNow() != uint32(f.Now().Unix()) {
194 | t.Error("time is not correct")
195 | }
196 | })
197 | }
198 | }
199 |
200 | func TestFastime_UnixNanoNow(t *testing.T) {
201 | tests := []struct {
202 | name string
203 | }{
204 | {
205 | name: "time equality",
206 | },
207 | }
208 |
209 | f := New().StartTimerD(context.Background(), time.Nanosecond)
210 | for _, tt := range tests {
211 | t.Run(tt.name, func(t *testing.T) {
212 | if f.UnixNanoNow() != f.Now().UnixNano() {
213 | t.Error("time is not correct")
214 | }
215 | })
216 | }
217 | }
218 |
219 | func TestUnixUNanoNow(t *testing.T) {
220 | tests := []struct {
221 | name string
222 | }{
223 | {
224 | name: "time equality",
225 | },
226 | }
227 | for _, tt := range tests {
228 | t.Run(tt.name, func(t *testing.T) {
229 | if UnixUNanoNow() != uint32(Now().UnixNano()) {
230 | t.Error("time is not correct")
231 | }
232 | })
233 | }
234 | }
235 |
236 | func TestFastime_UnixUNanoNow(t *testing.T) {
237 | tests := []struct {
238 | name string
239 | }{
240 | {
241 | name: "time equality",
242 | },
243 | }
244 |
245 | f := New().StartTimerD(context.Background(), time.Nanosecond)
246 | for _, tt := range tests {
247 | t.Run(tt.name, func(t *testing.T) {
248 | if f.UnixUNanoNow() != uint32(f.Now().UnixNano()) {
249 | t.Error("time is not correct")
250 | }
251 | })
252 | }
253 | }
254 |
255 | func TestFastime_refresh(t *testing.T) {
256 | tests := []struct {
257 | name string
258 | f *Fastime
259 | }{
260 | {
261 | name: "refresh",
262 | f: New(),
263 | },
264 | }
265 | for _, tt := range tests {
266 | t.Run(tt.name, func(t *testing.T) {
267 | if got := tt.f.refresh(); time.Since(got.Now()) > time.Second {
268 | t.Errorf("time didn't refreshed Fastime.refresh() = %v", got.Now())
269 | }
270 | })
271 | }
272 | }
273 |
274 | func TestSetFormat(t *testing.T) {
275 | tests := []struct {
276 | name string
277 | format string
278 | }{
279 | {
280 | name: "set RFC3339",
281 | format: time.RFC3339,
282 | },
283 | }
284 | for _, tt := range tests {
285 | t.Run(tt.name, func(t *testing.T) {
286 | if got := SetFormat(tt.format); !reflect.DeepEqual(got.format.Load().(string), time.RFC3339) {
287 | t.Errorf("SetFormat() = %v, want %v", got.format.Load().(string), time.RFC3339)
288 | }
289 | })
290 | }
291 | }
292 | func TestFastime_SetFormat(t *testing.T) {
293 | tests := []struct {
294 | name string
295 | f *Fastime
296 | format string
297 | }{
298 | {
299 | name: "set RFC3339",
300 | f: New(),
301 | format: time.RFC3339,
302 | },
303 | }
304 | for _, tt := range tests {
305 | t.Run(tt.name, func(t *testing.T) {
306 | if got := tt.f.SetFormat(tt.format); !reflect.DeepEqual(got.format.Load().(string), time.RFC3339) {
307 | t.Errorf("Fastime.SetFormat() = %v, want %v", got.format.Load().(string), time.RFC3339)
308 | }
309 | })
310 | }
311 | }
312 |
313 | func TestFormattedNow(t *testing.T) {
314 | tests := []struct {
315 | name string
316 | }{
317 | {
318 | name: "fetch",
319 | },
320 | }
321 | for _, tt := range tests {
322 | t.Run(tt.name, func(t *testing.T) {
323 | t.Log(string(FormattedNow()))
324 | })
325 | }
326 | }
327 |
328 | func TestFastime_FormattedNow(t *testing.T) {
329 | tests := []struct {
330 | name string
331 | f *Fastime
332 | }{
333 | {
334 | name: "fetch",
335 | f: New(),
336 | },
337 | }
338 | for _, tt := range tests {
339 | t.Run(tt.name, func(t *testing.T) {
340 | t.Log(string(tt.f.FormattedNow()))
341 | })
342 | }
343 | }
344 |
345 | func TestFastime_now(t *testing.T) {
346 | tests := []struct {
347 | name string
348 | f *Fastime
349 | }{
350 | {
351 | name: "now",
352 | f: New(),
353 | },
354 | }
355 | for _, tt := range tests {
356 | t.Run(tt.name, func(t *testing.T) {
357 | if got := tt.f.now(); time.Since(got) > time.Second {
358 | t.Errorf("time didn't correct Fastime.now() = %v", got)
359 | }
360 | })
361 | }
362 | }
363 |
364 | func TestFastime_update(t *testing.T) {
365 | tests := []struct {
366 | name string
367 | f *Fastime
368 | }{
369 | {
370 | name: "update",
371 | f: New(),
372 | },
373 | }
374 | for _, tt := range tests {
375 | t.Run(tt.name, func(t *testing.T) {
376 | if got := tt.f.refresh(); time.Since(got.Now()) > time.Second {
377 | t.Errorf("time didn't refreshed Fastime.update() = %v", got.Now())
378 | }
379 | })
380 | }
381 | }
382 |
383 | func TestFastime_store(t *testing.T) {
384 | tests := []struct {
385 | name string
386 | f *Fastime
387 | }{
388 | {
389 | name: "store",
390 | f: New(),
391 | },
392 | }
393 | for _, tt := range tests {
394 | t.Run(tt.name, func(t *testing.T) {
395 | n := tt.f.now()
396 | if got := tt.f.store(n); tt.f.Now().UnixNano() != n.UnixNano() {
397 | t.Errorf("time didn't match Fastime.store() = %v", got.Now())
398 | }
399 | })
400 | }
401 |
402 | }
403 |
--------------------------------------------------------------------------------