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  }