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  }