github.com/qioalice/ekago/v3@v3.3.2-0.20221202205325-5c262d586ee4/ekatime/time.go (about) 1 // Copyright © 2020. All rights reserved. 2 // Author: Ilya Stroy. 3 // Contacts: iyuryevich@pm.me, https://github.com/qioalice 4 // License: https://opensource.org/licenses/MIT 5 6 package ekatime 7 8 type ( 9 // Hour is a special type that has enough space to store Hour's number. 10 // Valid values: [0..23]. 11 Hour int8 12 13 // Minute is a special type that has enough space to store Minute's number. 14 // Valid values: [0..59]. 15 Minute int8 16 17 // Second is a special type that has enough space to store Second's number. 18 // Valid values: [0..59]. 19 Second int8 20 21 // Time is a special object that has enough space to store a some Time (Clock) 22 // (including Hour, Minute, Second) but does it most RAM efficient way 23 // taking only 4 bytes. 24 Time uint32 25 ) 26 27 // IsValidTime reports whether 'h', 'm' and 's' in their valid ranges. 28 func IsValidTime(h Hour, m Minute, s Second) bool { 29 return h >= 0 && h <= 23 && m >= 0 && m <= 59 && s >= 0 && s <= 59 30 } 31 32 // IsValid is an alias for IsValidTime(). 33 func (t Time) IsValid() bool { 34 return IsValidTime(t.Split()) 35 } 36 37 // Hour returns the hour number the current Time includes which. 38 // 39 // It guarantees that Hour() returns the valid hour number Time is of, 40 // only if Time has not been created manually but using constructors 41 // like NewTime(), Timestamp.Time(), Timestamp.Split(), etc. 42 func (t Time) Hour() Hour { 43 return Hour(t>>_TIME_OFFSET_HOUR) & _TIME_MASK_HOUR 44 } 45 46 // Minute returns the minute number the current Time includes which. 47 // 48 // It guarantees that Minute() returns the valid minute number Time is of, 49 // only if Time has not been created manually but using constructors 50 // like NewTime(), Timestamp.Time(), Timestamp.Split(), etc. 51 func (t Time) Minute() Minute { 52 return Minute(t>>_TIME_OFFSET_MINUTE) & _TIME_MASK_MINUTE 53 } 54 55 // Second returns the second number the current Time includes which. 56 // 57 // It guarantees that Second() returns the valid hour number Time is of, 58 // only if Time has not been created manually but using constructors 59 // like NewTime(), Timestamp.Time(), Timestamp.Split(), etc. 60 func (t Time) Second() Second { 61 return Second(t>>_TIME_OFFSET_SECOND) & _TIME_MASK_SECOND 62 } 63 64 // Split returns the hour number, minutes number and seconds number the current Date 65 // includes which. 66 // It's just like a separate Hour(), Minute(), Second() calls. 67 func (t Time) Split() (h Hour, m Minute, s Second) { 68 return t.Hour(), t.Minute(), t.Second() 69 } 70 71 // NewTime creates a new Time object using provided hour number, minute number, 72 // second number, normalizing these values and shifting time if it's required. 73 // 74 // Totally, it just stores the provided data if values are in their valid ranges, 75 // like: [0..23] for hour, [0..59] for minutes and seconds. 76 // 77 // If they are not, the time may be (will be) shifted. E.g: 78 // 21:02:64 (h == 21, m == 2, s == 64) -> 21:03:04 (h == 21, m == 3, s == 4). 79 func NewTime(h Hour, m Minute, s Second) Time { 80 81 h, m, s = normalizeTime(h, m, s) 82 83 // Do not forgot 'bitwise AND' between h, m, s and their bitmasks 84 // if you will change the logic of getting valid h, m, s from invalid ones. 85 // Now it's unnecessary (redundant). 86 //h, m, s = h & _TIME_MASK_HOUR, m & _TIME_MASK_MINUTE, s & _TIME_MASK_SECOND 87 88 return (Time(h) << _TIME_OFFSET_HOUR) | 89 (Time(m) << _TIME_OFFSET_MINUTE) | 90 (Time(s) << _TIME_OFFSET_SECOND) 91 } 92 93 // Replace returns a new Time based on the current. 94 // It returns the current Time with changed Hour, Minute, Second to those passed values, 95 // which are in their allowed ranges. Does not doing time addition. Only replacing. 96 // For time addition, use Add() method. 97 // 98 // Examples: 99 // NewTime(12, 13, 14) // -> 12:13:14 100 // .Replace(13, 1, 2) // -> 13:01:02 101 // .Replace(20, -2, 4) // -> 20:01:04 102 // .Replace(1, 0, -50) // -> 01:00:04 103 // .Replace(24, 61, 30) // -> 01:00:30 104 func (t Time) Replace(h Hour, m Minute, s Second) Time { 105 h_, m_, s_ := t.Split() 106 if 0 <= h && h <= 23 { 107 h_ = h 108 } 109 if 0 <= m && m <= 59 { 110 m_ = m 111 } 112 if 0 <= s && s <= 59 { 113 s_ = s 114 } 115 return NewTime(h_, m_, s_) 116 } 117 118 // Add returns a new Time based on the current. 119 // It returns the current Time with changed Hour, Minute, Second, using passed values, 120 // as their addition's deltas. 121 // 122 // Examples: 123 // NewTime(12, 13, 14) // -> 12:13:14 124 // .Add(1, 2, 3) // -> 13:15:17 125 // .Add(-3, 0, 20) // -> 10:15:37 126 // .Add(-23, 0, 61) // -> 11:16:38 127 // .Add(0, -60, 0) // -> 10:16:38 128 // .Add(127, 0, 0) // -> 17:16:38 (works OK with potential integer overflow) 129 func (t Time) Add(h Hour, m Minute, s Second) Time { 130 h_, m_, s_ := t.Split() 131 132 h_ += h % 24 133 h_ += Hour(m / 60) 134 135 m_ += m % 60 136 m_ += Minute(s / 60) 137 138 s_ += s % 60 139 140 if h_ %= 24; h_ < 0 { 141 h_ += 24 142 } 143 if m_ %= 60; m_ < 0 { 144 m_ += 60 145 } 146 if s_ %= 60; s_ < 0 { 147 s_ += 60 148 } 149 150 return NewTime(h_, m_, s_) 151 } 152 153 // WithDate returns the current Time with the presented Date's year, month, day 154 // as a new Timestamp object. 155 func (t Time) WithDate(y Year, m Month, d Day) Timestamp { 156 hh, mm, ss := t.Split() 157 return NewTimestamp(y, m, d, hh, mm, ss) 158 }