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