github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/lib/hrtime/time.go (about) 1 //go:build !windows 2 // +build !windows 3 4 package hrtime 5 6 // Central Standard Time (CST) 7 // https://www.timeanddate.com/time/zones/cst 8 // Coordinated Universal Time (UTC) 9 // Greenwich Mean Time (GMT) 10 11 import ( 12 "sync/atomic" 13 "time" 14 15 "github.com/samber/lo" 16 "golang.org/x/sys/unix" 17 ) 18 19 func NowIn(offset TimeZoneOffset) time.Time { 20 return time.Now().In(loadTZLocation(offset)) 21 } 22 23 func NowInDefaultTZ() time.Time { 24 return NowIn(TimeZoneOffset(atomic.LoadInt32(&defaultTimezoneOffset))) 25 } 26 27 func NowInUTC() time.Time { 28 return NowIn(TzUtc0Offset) 29 } 30 31 func MonotonicElapsed() time.Duration { 32 return time.Since(appStartTime) 33 } 34 35 func Since(beginTime time.Time) time.Duration { 36 return time.Since(beginTime) 37 } 38 39 var ( 40 SdkClock = &sdkClockTime{} 41 GoMonotonicClock Clock = &goNonSysClockTime{} 42 goMonotonicStartTs int64 43 UnixMonotonicClock Clock = &unixNonSysClockTime{} 44 unixMonotonicStartTs int64 45 ) 46 47 func ClockInit() { 48 appStartTime = time.Now().In(loadTZLocation(TimeZoneOffset(atomic.LoadInt32(&defaultTimezoneOffset)))) 49 50 goMonotonicStartTs = appStartTime.UnixNano() 51 52 ts := unix.Timespec{} 53 lo.Must0(unix.ClockGettime(unix.CLOCK_MONOTONIC, &ts)) 54 unixMonotonicStartTs = ts.Nano() 55 } 56 57 type goNonSysClockTime struct{} 58 59 func (g *goNonSysClockTime) now() time.Time { 60 nano := appStartTime.UnixNano() + g.MonotonicElapsed().Nanoseconds() 61 return time.UnixMilli(time.Duration(nano).Milliseconds()) 62 } 63 64 func (g *goNonSysClockTime) NowIn(offset TimeZoneOffset) time.Time { 65 return g.now().In(loadTZLocation(offset)) 66 } 67 68 func (g *goNonSysClockTime) NowInDefaultTZ() time.Time { 69 return g.NowIn(TimeZoneOffset(atomic.LoadInt32(&defaultTimezoneOffset))) 70 } 71 72 func (g *goNonSysClockTime) NowInUTC() time.Time { 73 return g.NowIn(TzUtc0Offset) 74 } 75 76 func (g *goNonSysClockTime) MonotonicElapsed() time.Duration { 77 return time.Duration(time.Now().UnixNano() - goMonotonicStartTs) 78 } 79 80 func (g *goNonSysClockTime) Since(beginTime time.Time) time.Duration { 81 return time.Duration(time.Now().UnixNano() - beginTime.UnixNano()) 82 } 83 84 type unixNonSysClockTime struct{} 85 86 func (u *unixNonSysClockTime) now() time.Time { 87 nano := appStartTime.UnixNano() + u.MonotonicElapsed().Nanoseconds() 88 return time.UnixMilli(time.Duration(nano).Milliseconds()) 89 } 90 91 func (u *unixNonSysClockTime) NowIn(offset TimeZoneOffset) time.Time { 92 return u.now().In(loadTZLocation(offset)) 93 } 94 95 func (u *unixNonSysClockTime) NowInDefaultTZ() time.Time { 96 return u.NowIn(TimeZoneOffset(atomic.LoadInt32(&defaultTimezoneOffset))) 97 } 98 99 func (u *unixNonSysClockTime) NowInUTC() time.Time { 100 return u.NowIn(TzUtc0Offset) 101 } 102 103 func (u *unixNonSysClockTime) MonotonicElapsed() time.Duration { 104 ts := unix.Timespec{} 105 lo.Must0(unix.ClockGettime(unix.CLOCK_MONOTONIC, &ts)) 106 currentTs := ts.Nano() 107 return time.Duration(currentTs - unixMonotonicStartTs) 108 } 109 110 func (u *unixNonSysClockTime) Since(beginTime time.Time) time.Duration { 111 n := NowInDefaultTZ() 112 return time.Duration(n.Nanosecond() - beginTime.In(loadTZLocation(TimeZoneOffset(DefaultTimezoneOffset()))).Nanosecond()) 113 } 114 115 type sdkClockTime struct{} 116 117 func (s *sdkClockTime) NowIn(offset TimeZoneOffset) time.Time { 118 return NowIn(offset) 119 } 120 121 func (s *sdkClockTime) NowInDefaultTZ() time.Time { 122 return s.NowIn(TimeZoneOffset(atomic.LoadInt32(&defaultTimezoneOffset))) 123 } 124 125 func (s *sdkClockTime) NowInUTC() time.Time { 126 return s.NowIn(TzUtc0Offset) 127 } 128 129 func (s *sdkClockTime) MonotonicElapsed() time.Duration { 130 return MonotonicElapsed() 131 } 132 133 func (s *sdkClockTime) Since(beginTime time.Time) time.Duration { 134 return Since(beginTime) 135 }