gtime_time.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package gtime
  7. import (
  8. "bytes"
  9. "strconv"
  10. "time"
  11. "github.com/gogf/gf/v2/errors/gcode"
  12. "github.com/gogf/gf/v2/errors/gerror"
  13. )
  14. // Time is a wrapper for time.Time for additional features.
  15. type Time struct {
  16. wrapper
  17. }
  18. // iUnixNano is an interface definition commonly for custom time.Time wrapper.
  19. type iUnixNano interface {
  20. UnixNano() int64
  21. }
  22. // New creates and returns a Time object with given parameter.
  23. // The optional parameter can be type of: time.Time/*time.Time, string or integer.
  24. func New(param ...interface{}) *Time {
  25. if len(param) > 0 {
  26. switch r := param[0].(type) {
  27. case time.Time:
  28. return NewFromTime(r)
  29. case *time.Time:
  30. return NewFromTime(*r)
  31. case Time:
  32. return &r
  33. case *Time:
  34. return r
  35. case string:
  36. if len(param) > 1 {
  37. switch t := param[1].(type) {
  38. case string:
  39. return NewFromStrFormat(r, t)
  40. case []byte:
  41. return NewFromStrFormat(r, string(t))
  42. }
  43. }
  44. return NewFromStr(r)
  45. case []byte:
  46. if len(param) > 1 {
  47. switch t := param[1].(type) {
  48. case string:
  49. return NewFromStrFormat(string(r), t)
  50. case []byte:
  51. return NewFromStrFormat(string(r), string(t))
  52. }
  53. }
  54. return NewFromStr(string(r))
  55. case int:
  56. return NewFromTimeStamp(int64(r))
  57. case int64:
  58. return NewFromTimeStamp(r)
  59. default:
  60. if v, ok := r.(iUnixNano); ok {
  61. return NewFromTimeStamp(v.UnixNano())
  62. }
  63. }
  64. }
  65. return &Time{
  66. wrapper{time.Time{}},
  67. }
  68. }
  69. // Now creates and returns a time object of now.
  70. func Now() *Time {
  71. return &Time{
  72. wrapper{time.Now()},
  73. }
  74. }
  75. // NewFromTime creates and returns a Time object with given time.Time object.
  76. func NewFromTime(t time.Time) *Time {
  77. return &Time{
  78. wrapper{t},
  79. }
  80. }
  81. // NewFromStr creates and returns a Time object with given string.
  82. // Note that it returns nil if there's error occurs.
  83. func NewFromStr(str string) *Time {
  84. if t, err := StrToTime(str); err == nil {
  85. return t
  86. }
  87. return nil
  88. }
  89. // NewFromStrFormat creates and returns a Time object with given string and
  90. // custom format like: Y-m-d H:i:s.
  91. // Note that it returns nil if there's error occurs.
  92. func NewFromStrFormat(str string, format string) *Time {
  93. if t, err := StrToTimeFormat(str, format); err == nil {
  94. return t
  95. }
  96. return nil
  97. }
  98. // NewFromStrLayout creates and returns a Time object with given string and
  99. // stdlib layout like: 2006-01-02 15:04:05.
  100. // Note that it returns nil if there's error occurs.
  101. func NewFromStrLayout(str string, layout string) *Time {
  102. if t, err := StrToTimeLayout(str, layout); err == nil {
  103. return t
  104. }
  105. return nil
  106. }
  107. // NewFromTimeStamp creates and returns a Time object with given timestamp,
  108. // which can be in seconds to nanoseconds.
  109. // Eg: 1600443866 and 1600443866199266000 are both considered as valid timestamp number.
  110. func NewFromTimeStamp(timestamp int64) *Time {
  111. if timestamp == 0 {
  112. return &Time{}
  113. }
  114. var sec, nano int64
  115. if timestamp > 1e9 {
  116. for timestamp < 1e18 {
  117. timestamp *= 10
  118. }
  119. sec = timestamp / 1e9
  120. nano = timestamp % 1e9
  121. } else {
  122. sec = timestamp
  123. }
  124. return &Time{
  125. wrapper{time.Unix(sec, nano)},
  126. }
  127. }
  128. // Timestamp returns the timestamp in seconds.
  129. func (t *Time) Timestamp() int64 {
  130. if t.IsZero() {
  131. return 0
  132. }
  133. return t.UnixNano() / 1e9
  134. }
  135. // TimestampMilli returns the timestamp in milliseconds.
  136. func (t *Time) TimestampMilli() int64 {
  137. if t.IsZero() {
  138. return 0
  139. }
  140. return t.UnixNano() / 1e6
  141. }
  142. // TimestampMicro returns the timestamp in microseconds.
  143. func (t *Time) TimestampMicro() int64 {
  144. if t.IsZero() {
  145. return 0
  146. }
  147. return t.UnixNano() / 1e3
  148. }
  149. // TimestampNano returns the timestamp in nanoseconds.
  150. func (t *Time) TimestampNano() int64 {
  151. if t.IsZero() {
  152. return 0
  153. }
  154. return t.UnixNano()
  155. }
  156. // TimestampStr is a convenience method which retrieves and returns
  157. // the timestamp in seconds as string.
  158. func (t *Time) TimestampStr() string {
  159. if t.IsZero() {
  160. return ""
  161. }
  162. return strconv.FormatInt(t.Timestamp(), 10)
  163. }
  164. // TimestampMilliStr is a convenience method which retrieves and returns
  165. // the timestamp in milliseconds as string.
  166. func (t *Time) TimestampMilliStr() string {
  167. if t.IsZero() {
  168. return ""
  169. }
  170. return strconv.FormatInt(t.TimestampMilli(), 10)
  171. }
  172. // TimestampMicroStr is a convenience method which retrieves and returns
  173. // the timestamp in microseconds as string.
  174. func (t *Time) TimestampMicroStr() string {
  175. if t.IsZero() {
  176. return ""
  177. }
  178. return strconv.FormatInt(t.TimestampMicro(), 10)
  179. }
  180. // TimestampNanoStr is a convenience method which retrieves and returns
  181. // the timestamp in nanoseconds as string.
  182. func (t *Time) TimestampNanoStr() string {
  183. if t.IsZero() {
  184. return ""
  185. }
  186. return strconv.FormatInt(t.TimestampNano(), 10)
  187. }
  188. // Month returns the month of the year specified by t.
  189. func (t *Time) Month() int {
  190. if t.IsZero() {
  191. return 0
  192. }
  193. return int(t.Time.Month())
  194. }
  195. // Second returns the second offset within the minute specified by t,
  196. // in the range [0, 59].
  197. func (t *Time) Second() int {
  198. if t.IsZero() {
  199. return 0
  200. }
  201. return t.Time.Second()
  202. }
  203. // Millisecond returns the millisecond offset within the second specified by t,
  204. // in the range [0, 999].
  205. func (t *Time) Millisecond() int {
  206. if t.IsZero() {
  207. return 0
  208. }
  209. return t.Time.Nanosecond() / 1e6
  210. }
  211. // Microsecond returns the microsecond offset within the second specified by t,
  212. // in the range [0, 999999].
  213. func (t *Time) Microsecond() int {
  214. if t.IsZero() {
  215. return 0
  216. }
  217. return t.Time.Nanosecond() / 1e3
  218. }
  219. // Nanosecond returns the nanosecond offset within the second specified by t,
  220. // in the range [0, 999999999].
  221. func (t *Time) Nanosecond() int {
  222. if t.IsZero() {
  223. return 0
  224. }
  225. return t.Time.Nanosecond()
  226. }
  227. // String returns current time object as string.
  228. func (t *Time) String() string {
  229. if t.IsZero() {
  230. return ""
  231. }
  232. return t.wrapper.String()
  233. }
  234. // IsZero reports whether t represents the zero time instant,
  235. // January 1, year 1, 00:00:00 UTC.
  236. func (t *Time) IsZero() bool {
  237. if t == nil {
  238. return true
  239. }
  240. return t.Time.IsZero()
  241. }
  242. // Clone returns a new Time object which is a clone of current time object.
  243. func (t *Time) Clone() *Time {
  244. return New(t.Time)
  245. }
  246. // Add adds the duration to current time.
  247. func (t *Time) Add(d time.Duration) *Time {
  248. newTime := t.Clone()
  249. newTime.Time = newTime.Time.Add(d)
  250. return newTime
  251. }
  252. // AddStr parses the given duration as string and adds it to current time.
  253. func (t *Time) AddStr(duration string) (*Time, error) {
  254. if d, err := time.ParseDuration(duration); err != nil {
  255. err = gerror.Wrapf(err, `time.ParseDuration failed for string "%s"`, duration)
  256. return nil, err
  257. } else {
  258. return t.Add(d), nil
  259. }
  260. }
  261. // UTC converts current time to UTC timezone.
  262. func (t *Time) UTC() *Time {
  263. newTime := t.Clone()
  264. newTime.Time = newTime.Time.UTC()
  265. return newTime
  266. }
  267. // ISO8601 formats the time as ISO8601 and returns it as string.
  268. func (t *Time) ISO8601() string {
  269. return t.Layout("2006-01-02T15:04:05-07:00")
  270. }
  271. // RFC822 formats the time as RFC822 and returns it as string.
  272. func (t *Time) RFC822() string {
  273. return t.Layout("Mon, 02 Jan 06 15:04 MST")
  274. }
  275. // AddDate adds year, month and day to the time.
  276. func (t *Time) AddDate(years int, months int, days int) *Time {
  277. newTime := t.Clone()
  278. newTime.Time = newTime.Time.AddDate(years, months, days)
  279. return newTime
  280. }
  281. // Round returns the result of rounding t to the nearest multiple of d (since the zero time).
  282. // The rounding behavior for halfway values is to round up.
  283. // If d <= 0, Round returns t stripped of any monotonic clock reading but otherwise unchanged.
  284. //
  285. // Round operates on the time as an absolute duration since the
  286. // zero time; it does not operate on the presentation form of the
  287. // time. Thus, Round(Hour) may return a time with a non-zero
  288. // minute, depending on the time's Location.
  289. func (t *Time) Round(d time.Duration) *Time {
  290. newTime := t.Clone()
  291. newTime.Time = newTime.Time.Round(d)
  292. return newTime
  293. }
  294. // Truncate returns the result of rounding t down to a multiple of d (since the zero time).
  295. // If d <= 0, Truncate returns t stripped of any monotonic clock reading but otherwise unchanged.
  296. //
  297. // Truncate operates on the time as an absolute duration since the
  298. // zero time; it does not operate on the presentation form of the
  299. // time. Thus, Truncate(Hour) may return a time with a non-zero
  300. // minute, depending on the time's Location.
  301. func (t *Time) Truncate(d time.Duration) *Time {
  302. newTime := t.Clone()
  303. newTime.Time = newTime.Time.Truncate(d)
  304. return newTime
  305. }
  306. // Equal reports whether t and u represent the same time instant.
  307. // Two times can be equal even if they are in different locations.
  308. // For example, 6:00 +0200 CEST and 4:00 UTC are Equal.
  309. // See the documentation on the Time type for the pitfalls of using == with
  310. // Time values; most code should use Equal instead.
  311. func (t *Time) Equal(u *Time) bool {
  312. switch {
  313. case t == nil && u != nil:
  314. return false
  315. case t == nil && u == nil:
  316. return true
  317. case t != nil && u == nil:
  318. return false
  319. default:
  320. return t.Time.Equal(u.Time)
  321. }
  322. }
  323. // Before reports whether the time instant t is before u.
  324. func (t *Time) Before(u *Time) bool {
  325. return t.Time.Before(u.Time)
  326. }
  327. // After reports whether the time instant t is after u.
  328. func (t *Time) After(u *Time) bool {
  329. switch {
  330. case t == nil:
  331. return false
  332. case t != nil && u == nil:
  333. return true
  334. default:
  335. return t.Time.After(u.Time)
  336. }
  337. }
  338. // Sub returns the duration t-u. If the result exceeds the maximum (or minimum)
  339. // value that can be stored in a Duration, the maximum (or minimum) duration
  340. // will be returned.
  341. // To compute t-d for a duration d, use t.Add(-d).
  342. func (t *Time) Sub(u *Time) time.Duration {
  343. if t == nil || u == nil {
  344. return 0
  345. }
  346. return t.Time.Sub(u.Time)
  347. }
  348. // StartOfMinute clones and returns a new time of which the seconds is set to 0.
  349. func (t *Time) StartOfMinute() *Time {
  350. newTime := t.Clone()
  351. newTime.Time = newTime.Time.Truncate(time.Minute)
  352. return newTime
  353. }
  354. // StartOfHour clones and returns a new time of which the hour, minutes and seconds are set to 0.
  355. func (t *Time) StartOfHour() *Time {
  356. y, m, d := t.Date()
  357. newTime := t.Clone()
  358. newTime.Time = time.Date(y, m, d, newTime.Time.Hour(), 0, 0, 0, newTime.Time.Location())
  359. return newTime
  360. }
  361. // StartOfDay clones and returns a new time which is the start of day, its time is set to 00:00:00.
  362. func (t *Time) StartOfDay() *Time {
  363. y, m, d := t.Date()
  364. newTime := t.Clone()
  365. newTime.Time = time.Date(y, m, d, 0, 0, 0, 0, newTime.Time.Location())
  366. return newTime
  367. }
  368. // StartOfWeek clones and returns a new time which is the first day of week and its time is set to
  369. // 00:00:00.
  370. func (t *Time) StartOfWeek() *Time {
  371. weekday := int(t.Weekday())
  372. return t.StartOfDay().AddDate(0, 0, -weekday)
  373. }
  374. // StartOfMonth clones and returns a new time which is the first day of the month and its is set to
  375. // 00:00:00
  376. func (t *Time) StartOfMonth() *Time {
  377. y, m, _ := t.Date()
  378. newTime := t.Clone()
  379. newTime.Time = time.Date(y, m, 1, 0, 0, 0, 0, newTime.Time.Location())
  380. return newTime
  381. }
  382. // StartOfQuarter clones and returns a new time which is the first day of the quarter and its time is set
  383. // to 00:00:00.
  384. func (t *Time) StartOfQuarter() *Time {
  385. month := t.StartOfMonth()
  386. offset := (int(month.Month()) - 1) % 3
  387. return month.AddDate(0, -offset, 0)
  388. }
  389. // StartOfHalf clones and returns a new time which is the first day of the half year and its time is set
  390. // to 00:00:00.
  391. func (t *Time) StartOfHalf() *Time {
  392. month := t.StartOfMonth()
  393. offset := (int(month.Month()) - 1) % 6
  394. return month.AddDate(0, -offset, 0)
  395. }
  396. // StartOfYear clones and returns a new time which is the first day of the year and its time is set to
  397. // 00:00:00.
  398. func (t *Time) StartOfYear() *Time {
  399. y, _, _ := t.Date()
  400. newTime := t.Clone()
  401. newTime.Time = time.Date(y, time.January, 1, 0, 0, 0, 0, newTime.Time.Location())
  402. return newTime
  403. }
  404. // getPrecisionDelta returns the precision parameter for time calculation depending on `withNanoPrecision` option.
  405. func getPrecisionDelta(withNanoPrecision ...bool) time.Duration {
  406. if len(withNanoPrecision) > 0 && withNanoPrecision[0] {
  407. return time.Nanosecond
  408. }
  409. return time.Second
  410. }
  411. // EndOfMinute clones and returns a new time of which the seconds is set to 59.
  412. func (t *Time) EndOfMinute(withNanoPrecision ...bool) *Time {
  413. return t.StartOfMinute().Add(time.Minute - getPrecisionDelta(withNanoPrecision...))
  414. }
  415. // EndOfHour clones and returns a new time of which the minutes and seconds are both set to 59.
  416. func (t *Time) EndOfHour(withNanoPrecision ...bool) *Time {
  417. return t.StartOfHour().Add(time.Hour - getPrecisionDelta(withNanoPrecision...))
  418. }
  419. // EndOfDay clones and returns a new time which is the end of day the and its time is set to 23:59:59.
  420. func (t *Time) EndOfDay(withNanoPrecision ...bool) *Time {
  421. y, m, d := t.Date()
  422. newTime := t.Clone()
  423. newTime.Time = time.Date(
  424. y, m, d, 23, 59, 59, int(time.Second-getPrecisionDelta(withNanoPrecision...)), newTime.Time.Location(),
  425. )
  426. return newTime
  427. }
  428. // EndOfWeek clones and returns a new time which is the end of week and its time is set to 23:59:59.
  429. func (t *Time) EndOfWeek(withNanoPrecision ...bool) *Time {
  430. return t.StartOfWeek().AddDate(0, 0, 7).Add(-getPrecisionDelta(withNanoPrecision...))
  431. }
  432. // EndOfMonth clones and returns a new time which is the end of the month and its time is set to 23:59:59.
  433. func (t *Time) EndOfMonth(withNanoPrecision ...bool) *Time {
  434. return t.StartOfMonth().AddDate(0, 1, 0).Add(-getPrecisionDelta(withNanoPrecision...))
  435. }
  436. // EndOfQuarter clones and returns a new time which is end of the quarter and its time is set to 23:59:59.
  437. func (t *Time) EndOfQuarter(withNanoPrecision ...bool) *Time {
  438. return t.StartOfQuarter().AddDate(0, 3, 0).Add(-getPrecisionDelta(withNanoPrecision...))
  439. }
  440. // EndOfHalf clones and returns a new time which is the end of the half year and its time is set to 23:59:59.
  441. func (t *Time) EndOfHalf(withNanoPrecision ...bool) *Time {
  442. return t.StartOfHalf().AddDate(0, 6, 0).Add(-getPrecisionDelta(withNanoPrecision...))
  443. }
  444. // EndOfYear clones and returns a new time which is the end of the year and its time is set to 23:59:59.
  445. func (t *Time) EndOfYear(withNanoPrecision ...bool) *Time {
  446. return t.StartOfYear().AddDate(1, 0, 0).Add(-getPrecisionDelta(withNanoPrecision...))
  447. }
  448. // MarshalJSON implements the interface MarshalJSON for json.Marshal.
  449. // Note that, DO NOT use `(t *Time) MarshalJSON() ([]byte, error)` as it looses interface
  450. // implement of `MarshalJSON` for struct of Time.
  451. func (t Time) MarshalJSON() ([]byte, error) {
  452. return []byte(`"` + t.String() + `"`), nil
  453. }
  454. // UnmarshalJSON implements the interface UnmarshalJSON for json.Unmarshal.
  455. func (t *Time) UnmarshalJSON(b []byte) error {
  456. if len(b) == 0 {
  457. t.Time = time.Time{}
  458. return nil
  459. }
  460. newTime, err := StrToTime(string(bytes.Trim(b, `"`)))
  461. if err != nil {
  462. return err
  463. }
  464. t.Time = newTime.Time
  465. return nil
  466. }
  467. // UnmarshalText implements the encoding.TextUnmarshaler interface.
  468. // Note that it overwrites the same implementer of `time.Time`.
  469. func (t *Time) UnmarshalText(data []byte) error {
  470. vTime := New(data)
  471. if vTime != nil {
  472. *t = *vTime
  473. return nil
  474. }
  475. return gerror.NewCodef(gcode.CodeInvalidParameter, `invalid time value: %s`, data)
  476. }
  477. // NoValidation marks this struct object will not be validated by package gvalid.
  478. func (t *Time) NoValidation() {}
  479. // DeepCopy implements interface for deep copy of current type.
  480. func (t *Time) DeepCopy() interface{} {
  481. if t == nil {
  482. return nil
  483. }
  484. return New(t.Time)
  485. }