github.com/mithrandie/csvq@v1.18.1/lib/option/static.go (about) 1 package option 2 3 import ( 4 "fmt" 5 "math/rand" 6 "sync" 7 "time" 8 ) 9 10 var ( 11 TestTime time.Time // For Tests 12 Timezones = NewTimezoneMap() 13 14 random *rand.Rand 15 getRand sync.Once 16 ) 17 18 func GetRand() *rand.Rand { 19 getRand.Do(func() { 20 random = rand.New(rand.NewSource(time.Now().UnixNano())) 21 }) 22 return random 23 } 24 25 func GetLocation(timezone string) (*time.Location, error) { 26 return Timezones.Get(timezone) 27 } 28 29 func Now(location *time.Location) time.Time { 30 if !TestTime.IsZero() { 31 return TestTime 32 } 33 return time.Now().In(location) 34 } 35 36 type TimezoneMap struct { 37 m *sync.Map 38 mtx *sync.Mutex 39 } 40 41 func NewTimezoneMap() TimezoneMap { 42 return TimezoneMap{ 43 m: &sync.Map{}, 44 mtx: &sync.Mutex{}, 45 } 46 } 47 48 func (tzmap TimezoneMap) store(key string, value *time.Location) { 49 tzmap.m.Store(key, value) 50 } 51 52 func (tzmap TimezoneMap) load(key string) (*time.Location, bool) { 53 v, ok := tzmap.m.Load(key) 54 if ok { 55 return v.(*time.Location), ok 56 } 57 return nil, ok 58 } 59 60 func (tzmap TimezoneMap) Get(timezone string) (*time.Location, error) { 61 if v, ok := tzmap.load(timezone); ok { 62 return v, nil 63 } 64 65 tzmap.mtx.Lock() 66 defer tzmap.mtx.Unlock() 67 68 if v, ok := tzmap.load(timezone); ok { 69 return v, nil 70 } 71 72 l, err := time.LoadLocation(timezone) 73 if err != nil { 74 return nil, fmt.Errorf("timezone %q does not exist", timezone) 75 } 76 77 tzmap.store(timezone, l) 78 return l, nil 79 }