github.com/aldelo/common@v1.5.1/helper-time.go (about)

     1  package helper
     2  
     3  /*
     4   * Copyright 2020-2023 Aldelo, LP
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   *     http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  import (
    20  	"fmt"
    21  	"strings"
    22  	"time"
    23  )
    24  
    25  // ---------------------------------------------------------------------------------------------------------------------
    26  // custom time structs
    27  // ---------------------------------------------------------------------------------------------------------------------
    28  
    29  // JsonTime provides custom Json marshal and unmarshal interface implementations.
    30  // JsonTime marshals and unmarshal using RFC3339 time format
    31  type JsonTime time.Time
    32  
    33  // MarshalJSON marshals time value to format of RFC3339
    34  func (jt *JsonTime) MarshalJSON() ([]byte, error) {
    35  	if jt != nil {
    36  		t := time.Time(*jt)
    37  		buf := fmt.Sprintf(`"%s"`, t.Format(time.RFC3339))
    38  		return []byte(buf), nil
    39  	} else {
    40  		return []byte{}, fmt.Errorf("JsonTime Nil")
    41  	}
    42  }
    43  
    44  // UnmarshalJSON unmarshal time value in format of RFC3339 to JsonTime
    45  func (jt *JsonTime) UnmarshalJSON(b []byte) error {
    46  	if jt == nil {
    47  		return fmt.Errorf("JsonTime Nil")
    48  	}
    49  
    50  	buf := strings.Trim(string(b), `"`)
    51  	if t, e := time.Parse(time.RFC3339, buf); e != nil {
    52  		return e
    53  	} else {
    54  		*jt = JsonTime(t)
    55  		return nil
    56  	}
    57  }
    58  
    59  // ToTime converts JsonTime to time.Time
    60  func (jt *JsonTime) ToTime() time.Time {
    61  	if jt == nil {
    62  		return time.Time{}
    63  	} else {
    64  		return time.Time(*jt)
    65  	}
    66  }
    67  
    68  // ToJsonTime converts time.Time to JsonTime
    69  func ToJsonTime(t time.Time) JsonTime {
    70  	return JsonTime(t)
    71  }
    72  
    73  // ToJsonTimePtr converts time.Time to JsonTime pointer
    74  func ToJsonTimePtr(t time.Time) *JsonTime {
    75  	jt := JsonTime(t)
    76  	return &jt
    77  }
    78  
    79  // ---------------------------------------------------------------------------------------------------------------------
    80  // time helpers
    81  // ---------------------------------------------------------------------------------------------------------------------
    82  
    83  // FormatDate will format the input date value to yyyy-mm-dd
    84  func FormatDate(t time.Time, blankIfZero ...bool) string {
    85  	ifZero := false
    86  	if len(blankIfZero) > 0 {
    87  		ifZero = blankIfZero[0]
    88  	}
    89  
    90  	if ifZero {
    91  		if t.IsZero() {
    92  			return ""
    93  		}
    94  	}
    95  
    96  	return t.Format("2006-01-02")
    97  }
    98  
    99  // FormatTime will format the input date value to hh:mm:ss tt
   100  func FormatTime(t time.Time, blankIfZero ...bool) string {
   101  	ifZero := false
   102  	if len(blankIfZero) > 0 {
   103  		ifZero = blankIfZero[0]
   104  	}
   105  
   106  	if ifZero {
   107  		if t.IsZero() {
   108  			return ""
   109  		}
   110  	}
   111  
   112  	return t.Format("03:04:05 PM")
   113  }
   114  
   115  // FormatDateTime will format the input date value to yyyy-mm-dd hh:mm:ss tt
   116  func FormatDateTime(t time.Time, blankIfZero ...bool) string {
   117  	ifZero := false
   118  	if len(blankIfZero) > 0 {
   119  		ifZero = blankIfZero[0]
   120  	}
   121  
   122  	if ifZero {
   123  		if t.IsZero() {
   124  			return ""
   125  		}
   126  	}
   127  
   128  	return t.Format("2006-01-02 03:04:05 PM")
   129  }
   130  
   131  // FormatDateTimeToISO8601_RFC3339 accepts time struct and converts to iso8601 string output format
   132  func FormatDateTimeToISO8601_RFC3339(t time.Time, blankIfZero ...bool) string {
   133  	ifZero := false
   134  	if len(blankIfZero) > 0 {
   135  		ifZero = blankIfZero[0]
   136  	}
   137  
   138  	if ifZero {
   139  		if t.IsZero() {
   140  			return ""
   141  		}
   142  	}
   143  
   144  	return t.Format(time.RFC3339)
   145  }
   146  
   147  // DateFormatString returns the date format string constant (yyyy-mm-dd)
   148  func DateFormatString() string {
   149  	return "2006-01-02"
   150  }
   151  
   152  // TimeFormatString returns the time format string constant (hh:mm:ss tt)
   153  func TimeFormatString() string {
   154  	return "03:04:05 PM"
   155  }
   156  
   157  // DateTimeFormatString returns the date time format string constant (yyyy-mm-dd hh:mm:ss tt)
   158  func DateTimeFormatString() string {
   159  	return "2006-01-02 03:04:05 PM"
   160  }
   161  
   162  // ParseDate will parse a date value in yyyy-mm-dd format into time.Time object,
   163  // check time.IsZero() to verify if a zero time is returned indicating parser failure
   164  func ParseDate(s string) time.Time {
   165  	t, err := time.Parse("2006-01-02", strings.TrimSpace(s))
   166  
   167  	if err != nil {
   168  		return time.Time{}
   169  	}
   170  
   171  	return t
   172  }
   173  
   174  // ParseTime will parse a time vaule in hh:mm:ss tt format into time.Time object,
   175  // check time.IsZero() to verify if a zero time is returned indicating parser failure
   176  func ParseTime(s string) time.Time {
   177  	t, err := time.Parse("03:04:05 PM", strings.TrimSpace(s))
   178  
   179  	if err != nil {
   180  		return time.Time{}
   181  	}
   182  
   183  	return t
   184  }
   185  
   186  // ParseTimeFromhhmmss will parse a time value from hhmmss format into time.Time object,
   187  // if parse failed, time.Time{} is returned (use time.IsZero() to check if parse success)
   188  func ParseTimeFromhhmmss(s string) time.Time {
   189  	s = strings.TrimSpace(s)
   190  
   191  	if IsNumericIntOnly(s) == false {
   192  		return time.Time{}
   193  	}
   194  
   195  	if LenTrim(s) != 6 {
   196  		return time.Time{}
   197  	}
   198  
   199  	v := Left(s, 2) + ":" + Mid(s, 2, 2) + ":" + Right(s, 2)
   200  	t, err := time.Parse("15:04:05", v)
   201  
   202  	if err != nil {
   203  		return time.Time{}
   204  	}
   205  
   206  	return t
   207  }
   208  
   209  // ParseDateTime will parse a date time value in yyyy-mm-dd hh:mm:ss tt format into time.Time object,
   210  // check time.IsZero() to verify if a zero time is returned indicating parser failure
   211  func ParseDateTime(s string) time.Time {
   212  	t, err := time.Parse("2006-01-02 03:04:05 PM", strings.TrimSpace(s))
   213  
   214  	if err != nil {
   215  		return time.Time{}
   216  	}
   217  
   218  	return t
   219  }
   220  
   221  // ParseFromExcelDate will handle integer value of excel date to convert to time.Time
   222  func ParseFromExcelDate(s string, format string) time.Time {
   223  	i, _ := ParseInt32(s)
   224  
   225  	if i > 0 {
   226  		v := GetDate(1970, 1, 1)
   227  		return v.AddDate(0, 0, i-70*365-19)
   228  	} else {
   229  		return ParseDateTimeCustom(s, format)
   230  	}
   231  }
   232  
   233  // ParseDateTime24Hr will parse a date time value in yyyy-mm-dd HH:mm:ss format into time.Time object,
   234  // check time.IsZero() to verify if a zero time is returned indicating parser failure
   235  func ParseDateTime24Hr(s string) time.Time {
   236  	t, err := time.Parse("2006-01-02 15:04:05", strings.TrimSpace(s))
   237  
   238  	if err != nil {
   239  		return time.Time{}
   240  	}
   241  
   242  	return t
   243  }
   244  
   245  // ParseDateTimeCustom will parse a date time value in s string, based on the f format
   246  // f format is 2006 01 02 15:04:05 / 03:04:05 PM
   247  func ParseDateTimeCustom(s string, f string) time.Time {
   248  	t, err := time.Parse(f, strings.TrimSpace(s))
   249  
   250  	if err != nil {
   251  		return time.Time{}
   252  	}
   253  
   254  	return t
   255  }
   256  
   257  // ParseDateTimeFromYYYYMMDDhhmmss from string value
   258  func ParseDateTimeFromYYYYMMDDhhmmss(s string) time.Time {
   259  	s = strings.TrimSpace(s)
   260  
   261  	if IsNumericIntOnly(s) == false {
   262  		return time.Time{}
   263  	}
   264  
   265  	if LenTrim(s) != 14 {
   266  		return time.Time{}
   267  	}
   268  
   269  	d := Left(s, 4) + "-" + Mid(s, 4, 2) + "-" + Mid(s, 6, 2)
   270  	t := Mid(s, 8, 2) + ":" + Mid(s, 10, 2) + ":" + Mid(s, 12, 2)
   271  
   272  	dv := d + " " + t
   273  
   274  	return ParseDateTime24Hr(dv)
   275  }
   276  
   277  // ParseDateTimeFromMMDDYYYYhhmmss from string value
   278  func ParseDateTimeFromMMDDYYYYhhmmss(s string) time.Time {
   279  	s = strings.TrimSpace(s)
   280  
   281  	if IsNumericIntOnly(s) == false {
   282  		return time.Time{}
   283  	}
   284  
   285  	if LenTrim(s) != 14 {
   286  		return time.Time{}
   287  	}
   288  
   289  	d := Mid(s, 4, 4) + "-" + Left(s, 2) + "-" + Mid(s, 2, 2)
   290  	t := Mid(s, 8, 2) + ":" + Mid(s, 10, 2) + ":" + Mid(s, 12, 2)
   291  
   292  	dv := d + " " + t
   293  
   294  	return ParseDateTime24Hr(dv)
   295  }
   296  
   297  // ParseDateFromYYYYMMDD from string value
   298  func ParseDateFromYYYYMMDD(s string) time.Time {
   299  	s = strings.TrimSpace(s)
   300  
   301  	if IsNumericIntOnly(s) == false {
   302  		return time.Time{}
   303  	}
   304  
   305  	if LenTrim(s) != 8 {
   306  		return time.Time{}
   307  	}
   308  
   309  	d := Left(s, 4) + "-" + Mid(s, 4, 2) + "-" + Mid(s, 6, 2)
   310  
   311  	return ParseDate(d)
   312  }
   313  
   314  // ParseDateFromDDMMYYYY from string value
   315  func ParseDateFromDDMMYYYY(s string) time.Time {
   316  	s = strings.TrimSpace(s)
   317  
   318  	if IsNumericIntOnly(s) == false {
   319  		return time.Time{}
   320  	}
   321  
   322  	if LenTrim(s) != 8 {
   323  		return time.Time{}
   324  	}
   325  
   326  	d := Right(s, 4) + "-" + Mid(s, 2, 2) + "-" + Left(s, 2)
   327  
   328  	return ParseDate(d)
   329  }
   330  
   331  // ParseDateFromYYMMDD from string value
   332  func ParseDateFromYYMMDD(s string) time.Time {
   333  	s = strings.TrimSpace(s)
   334  
   335  	if IsNumericIntOnly(s) == false {
   336  		return time.Time{}
   337  	}
   338  
   339  	if LenTrim(s) != 6 {
   340  		return time.Time{}
   341  	}
   342  
   343  	d := Left(s, 2) + "-" + Mid(s, 2, 2) + "-" + Mid(s, 4, 2)
   344  
   345  	return ParseDateTimeCustom(d, "06-01-02")
   346  }
   347  
   348  // ParseDateFromYYMM from string value
   349  func ParseDateFromYYMM(s string) time.Time {
   350  	s = strings.TrimSpace(s)
   351  
   352  	if IsNumericIntOnly(s) == false {
   353  		return time.Time{}
   354  	}
   355  
   356  	if LenTrim(s) != 4 {
   357  		return time.Time{}
   358  	}
   359  
   360  	d := Left(s, 2) + "-" + Mid(s, 2, 2)
   361  
   362  	return ParseDateTimeCustom(d, "06-01")
   363  }
   364  
   365  // ParseDateFromMMYY from string value
   366  func ParseDateFromMMYY(s string) time.Time {
   367  	s = strings.TrimSpace(s)
   368  
   369  	if IsNumericIntOnly(s) == false {
   370  		return time.Time{}
   371  	}
   372  
   373  	if LenTrim(s) != 4 {
   374  		return time.Time{}
   375  	}
   376  
   377  	d := Left(s, 2) + "-" + Mid(s, 2, 2)
   378  
   379  	return ParseDateTimeCustom(d, "01-06")
   380  }
   381  
   382  // ParseDateToLastDayOfMonth takes in a time.Time struct and returns the last date of month
   383  func ParseDateToLastDayOfMonth(t time.Time) time.Time {
   384  	if t.IsZero() {
   385  		return t
   386  	}
   387  
   388  	newDate := t.AddDate(0, 1, 0)
   389  
   390  	y, m, _ := newDate.Date()
   391  
   392  	newDate = ParseDateFromYYYYMMDD(Padding(Itoa(y), 4, false, "0") + Padding(Itoa(int(m)), 2, false, "0") + "01")
   393  
   394  	newDate = newDate.AddDate(0, 0, -1)
   395  
   396  	return newDate
   397  }
   398  
   399  // ParseDateFromMMDD from string value
   400  func ParseDateFromMMDD(s string) time.Time {
   401  	s = strings.TrimSpace(s)
   402  
   403  	if IsNumericIntOnly(s) == false {
   404  		return time.Time{}
   405  	}
   406  
   407  	if LenTrim(s) != 4 {
   408  		return time.Time{}
   409  	}
   410  
   411  	d := Left(s, 2) + "-" + Mid(s, 2, 2)
   412  
   413  	return ParseDateTimeCustom(d, "01-02")
   414  }
   415  
   416  // ParseDateTimeFrom_ISO8601_RFC3339 from string value of RFC3339 date time format
   417  func ParseDateTimeFrom_ISO8601_RFC3339(s string) time.Time {
   418  	s = strings.TrimSpace(s)
   419  
   420  	if t, e := time.Parse(time.RFC3339, s); e != nil {
   421  		return time.Time{}
   422  	} else {
   423  		return t
   424  	}
   425  }
   426  
   427  // CurrentDate returns current date in yyyy-mm-dd format
   428  func CurrentDate() string {
   429  	return time.Now().Format("2006-01-02")
   430  }
   431  
   432  // CurrentDateStruct returns current date in yyyy-mm-dd format via time.Time struct
   433  func CurrentDateStruct() time.Time {
   434  	return ParseDate(CurrentDate())
   435  }
   436  
   437  // CurrentDateTime returns current date and time in yyyy-mm-dd hh:mm:ss tt format
   438  func CurrentDateTime() string {
   439  	return time.Now().Format("2006-01-02 03:04:05 PM")
   440  }
   441  
   442  // CurrentDateTimeStruct returns current date and time in yyyy-mm-dd hh:mm:ss tt format via time.Time struct
   443  func CurrentDateTimeStruct() time.Time {
   444  	return ParseDateTime(CurrentDateTime())
   445  }
   446  
   447  // CurrentTime returns current time in hh:mm:ss tt format
   448  func CurrentTime() string {
   449  	s := time.Now().Format("2006-01-02 03:04:05 PM")
   450  	s = s[11:]
   451  
   452  	return s
   453  }
   454  
   455  // DaysDiff gets the days difference between from and to date
   456  func DaysDiff(timeFrom time.Time, timeTo time.Time) int {
   457  	d := timeTo.Sub(timeFrom)
   458  	dv := d.Hours() / 24.0
   459  	days := int(dv)
   460  	return days
   461  }
   462  
   463  // HoursDiff gets the hours difference between from and to date
   464  func HoursDiff(timeFrom time.Time, timeTo time.Time) int {
   465  	d := timeTo.Sub(timeFrom)
   466  	dv := d.Hours()
   467  	hr := int(dv)
   468  	return hr
   469  }
   470  
   471  // MinutesDiff gets the minutes difference between from and to date
   472  func MinutesDiff(timeFrom time.Time, timeTo time.Time) int {
   473  	d := timeTo.Sub(timeFrom)
   474  	dv := d.Minutes()
   475  	mn := int(dv)
   476  	return mn
   477  }
   478  
   479  // SecondsDiff gets the seconds difference between from and to date
   480  func SecondsDiff(timeFrom time.Time, timeTo time.Time) int {
   481  	d := timeTo.Sub(timeFrom)
   482  	dv := d.Seconds()
   483  	s := int(dv)
   484  	return s
   485  }
   486  
   487  // DateBefore checks if testDate is before the beforeDate
   488  func DateBefore(testDate time.Time, beforeDate time.Time) bool {
   489  	if testDate.Before(beforeDate) {
   490  		return true
   491  	}
   492  
   493  	return false
   494  }
   495  
   496  // DateBeforeOrEqual checks if testDate is before or equal to the beforeEqualDate
   497  func DateBeforeOrEqual(testDate time.Time, beforeEqualDate time.Time) bool {
   498  	if testDate.Equal(beforeEqualDate) {
   499  		return true
   500  	}
   501  
   502  	if testDate.Before(beforeEqualDate) {
   503  		return true
   504  	}
   505  
   506  	return false
   507  }
   508  
   509  // DateAfter checks if testDate is after the afterDate
   510  func DateAfter(testDate time.Time, afterDate time.Time) bool {
   511  	if testDate.After(afterDate) {
   512  		return true
   513  	}
   514  
   515  	return false
   516  }
   517  
   518  // DateAfterOrEqual checks if testDate is after or equal to the afterEqualDate
   519  func DateAfterOrEqual(testDate time.Time, afterEqualDate time.Time) bool {
   520  	if testDate.Equal(afterEqualDate) {
   521  		return true
   522  	}
   523  
   524  	if testDate.After(afterEqualDate) {
   525  		return true
   526  	}
   527  
   528  	return false
   529  }
   530  
   531  // DateBetween checks if testDate is within the fromDate and toDate,
   532  // if doNotIncludeEqual = true, then testDate equals fromDate and toDate are skipped
   533  func DateBetween(testDate time.Time, fromDate time.Time, toDate time.Time, doNotIncludeEqual bool) bool {
   534  	if doNotIncludeEqual == false {
   535  		if testDate.Equal(fromDate) {
   536  			return true
   537  		}
   538  
   539  		if testDate.Equal(toDate) {
   540  			return true
   541  		}
   542  	}
   543  
   544  	if testDate.After(fromDate) {
   545  		return true
   546  	}
   547  
   548  	if testDate.Before(toDate) {
   549  		return true
   550  	}
   551  
   552  	return false
   553  }
   554  
   555  // DateOutside checks if the testDate is outside of the fromDate and toDate
   556  func DateOutside(testDate time.Time, fromDate time.Time, toDate time.Time) bool {
   557  	if testDate.Before(fromDate) {
   558  		return true
   559  	}
   560  
   561  	if testDate.After(toDate) {
   562  		return true
   563  	}
   564  
   565  	return false
   566  }
   567  
   568  // DateEqual checks if the testDate equals to the equalDate
   569  func DateEqual(testDate time.Time, equalDate time.Time) bool {
   570  	if testDate.Equal(equalDate) {
   571  		return true
   572  	}
   573  
   574  	return false
   575  }
   576  
   577  // DateToUTC converts given time to utc
   578  func DateToUTC(t time.Time) (time.Time, error) {
   579  	loc, err := time.LoadLocation("UTC")
   580  
   581  	if err != nil {
   582  		return time.Time{}, err
   583  	}
   584  
   585  	if loc == nil {
   586  		return time.Time{}, fmt.Errorf("DateToUTC Location Target is Not Retrieved")
   587  	}
   588  
   589  	return t.In(loc), nil
   590  }
   591  
   592  // DateToUTC2 returns utc value directly without error info
   593  func DateToUTC2(t time.Time) time.Time {
   594  	v, _ := DateToUTC(t)
   595  	return v
   596  }
   597  
   598  // DateToLocal converts given time to local time
   599  func DateToLocal(t time.Time) (time.Time, error) {
   600  	loc, err := time.LoadLocation("Local")
   601  
   602  	if err != nil {
   603  		return time.Time{}, err
   604  	}
   605  
   606  	if loc == nil {
   607  		return time.Time{}, fmt.Errorf("DateToLocal Location Targe is Not Retrieved")
   608  	}
   609  
   610  	return t.In(loc), nil
   611  }
   612  
   613  // DateToLocal2 returns local value directly without error info
   614  func DateToLocal2(t time.Time) time.Time {
   615  	v, _ := DateToLocal(t)
   616  	return v
   617  }
   618  
   619  // IsLeapYear checks if the year input is leap year or not
   620  func IsLeapYear(year int) bool {
   621  	if year%100 == 0 {
   622  		// is century year, divisible by 400 is leap year
   623  		if year%400 == 0 {
   624  			return true
   625  		} else {
   626  			return false
   627  		}
   628  	} else {
   629  		// not a century year, divisible by 4 is leap year
   630  		if year%4 == 0 {
   631  			return true
   632  		} else {
   633  			return false
   634  		}
   635  	}
   636  }
   637  
   638  // IsDayOfMonthValid checks if the month day number is valid
   639  func IsDayOfMonthValid(year int, month int, day int) bool {
   640  	switch month {
   641  	case 1:
   642  		fallthrough
   643  	case 3:
   644  		fallthrough
   645  	case 5:
   646  		fallthrough
   647  	case 7:
   648  		fallthrough
   649  	case 8:
   650  		fallthrough
   651  	case 10:
   652  		fallthrough
   653  	case 12:
   654  		if day < 1 || day > 31 {
   655  			return false
   656  		} else {
   657  			return true
   658  		}
   659  
   660  	case 4:
   661  		fallthrough
   662  	case 6:
   663  		fallthrough
   664  	case 9:
   665  		fallthrough
   666  	case 11:
   667  		if day < 1 || day > 30 {
   668  			return false
   669  		} else {
   670  			return true
   671  		}
   672  
   673  	case 2:
   674  		d := 28
   675  
   676  		if IsLeapYear(year) {
   677  			d = 29
   678  		}
   679  
   680  		if day < 1 || day > d {
   681  			return false
   682  		} else {
   683  			return true
   684  		}
   685  
   686  	default:
   687  		return false
   688  	}
   689  }
   690  
   691  // IsDateValidYYYYMMDD checks if input string value is a valid date represented in the format of YYYYMMDD
   692  // valid year detected is 1970 - 2099
   693  func IsDateValidYYYYMMDD(s string) bool {
   694  	s = Trim(s)
   695  
   696  	if len(s) != 8 {
   697  		return false
   698  	}
   699  
   700  	yyyy := 0
   701  	mm := 0
   702  	dd := 0
   703  
   704  	if yyyy = Atoi(Left(s, 4)); yyyy < 1970 || yyyy > 2099 {
   705  		return false
   706  	}
   707  
   708  	if mm = Atoi(Mid(s, 4, 2)); mm < 1 || mm > 12 {
   709  		return false
   710  	}
   711  
   712  	if dd = Atoi(Right(s, 2)); dd < 1 || dd > 31 {
   713  		return false
   714  	}
   715  
   716  	if !IsDayOfMonthValid(yyyy, mm, dd) {
   717  		return false
   718  	}
   719  
   720  	return true
   721  }
   722  
   723  // IsDateValidYYMMDD checks if input string value is a valid date represented in the format of YYMMDD
   724  // valid year detected is 00 - 99, with year 20xx assumed
   725  func IsDateValidYYMMDD(s string) bool {
   726  	s = Trim(s)
   727  
   728  	if len(s) != 6 {
   729  		return false
   730  	}
   731  
   732  	yy := 0
   733  	mm := 0
   734  	dd := 0
   735  
   736  	if yy = Atoi(Left(s, 2)); yy < 0 || yy > 99 {
   737  		return false
   738  	}
   739  
   740  	if mm = Atoi(Mid(s, 2, 2)); mm < 1 || mm > 12 {
   741  		return false
   742  	}
   743  
   744  	if dd = Atoi(Right(s, 2)); dd < 1 || dd > 31 {
   745  		return false
   746  	}
   747  
   748  	if !IsDayOfMonthValid(2000+yy, mm, dd) {
   749  		return false
   750  	}
   751  
   752  	return true
   753  }
   754  
   755  // IsDateValidYYYYMM checks if input string value is a valid date represented in the format of YYYYMM
   756  // valid year detected is 1970 - 2099
   757  func IsDateValidYYYYMM(s string) bool {
   758  	s = Trim(s)
   759  
   760  	if len(s) != 6 {
   761  		return false
   762  	}
   763  
   764  	if yyyy := Atoi(Left(s, 4)); yyyy < 1970 || yyyy > 2099 {
   765  		return false
   766  	}
   767  
   768  	if mm := Atoi(Right(s, 2)); mm < 1 || mm > 12 {
   769  		return false
   770  	}
   771  
   772  	return true
   773  }
   774  
   775  // IsDateValidYYMM checks if input string value is a valid date represented in the format of YYMM
   776  // valid year detected is 00 - 99, with year 20xx assumed
   777  func IsDateValidYYMM(s string) bool {
   778  	s = Trim(s)
   779  
   780  	if len(s) != 4 {
   781  		return false
   782  	}
   783  
   784  	if yy := Atoi(Left(s, 2)); yy < 0 || yy > 99 {
   785  		return false
   786  	}
   787  
   788  	if mm := Atoi(Right(s, 2)); mm < 1 || mm > 12 {
   789  		return false
   790  	}
   791  
   792  	return true
   793  }
   794  
   795  // IsDateValidMMDDYYYY checks if input string value is a valid date represented in the format of MMDDYYYY
   796  // valid year detected is 1970 - 2099
   797  func IsDateValidMMDDYYYY(s string) bool {
   798  	s = Trim(s)
   799  
   800  	if len(s) != 8 {
   801  		return false
   802  	}
   803  
   804  	mm := 0
   805  	dd := 0
   806  	yyyy := 0
   807  
   808  	if mm = Atoi(Left(s, 2)); mm < 1 || mm > 12 {
   809  		return false
   810  	}
   811  
   812  	if dd = Atoi(Mid(s, 2, 2)); dd < 1 || dd > 31 {
   813  		return false
   814  	}
   815  
   816  	if yyyy = Atoi(Right(s, 4)); yyyy < 1970 || yyyy > 2099 {
   817  		return false
   818  	}
   819  
   820  	if !IsDayOfMonthValid(yyyy, mm, dd) {
   821  		return false
   822  	}
   823  
   824  	return true
   825  }
   826  
   827  // IsDateValidMMDDYY checks if input string value is a valid date represented in the format of MMDDYY
   828  // valid year detected is 1970 - 2099
   829  func IsDateValidMMDDYY(s string) bool {
   830  	s = Trim(s)
   831  
   832  	if len(s) != 6 {
   833  		return false
   834  	}
   835  
   836  	mm := 0
   837  	dd := 0
   838  	yy := 0
   839  
   840  	if mm = Atoi(Left(s, 2)); mm < 1 || mm > 12 {
   841  		return false
   842  	}
   843  
   844  	if dd = Atoi(Mid(s, 2, 2)); dd < 1 || dd > 31 {
   845  		return false
   846  	}
   847  
   848  	if yy = Atoi(Right(s, 2)); yy < 0 || yy > 99 {
   849  		return false
   850  	}
   851  
   852  	if !IsDayOfMonthValid(2000+yy, mm, dd) {
   853  		return false
   854  	}
   855  
   856  	return true
   857  }
   858  
   859  // IsDateValidMMYYYY checks if input string value is a valid date represented in the format of MMYYYY
   860  // valid year detected is 1970 - 2099
   861  func IsDateValidMMYYYY(s string) bool {
   862  	s = Trim(s)
   863  
   864  	if len(s) != 6 {
   865  		return false
   866  	}
   867  
   868  	if mm := Atoi(Left(s, 2)); mm < 1 || mm > 12 {
   869  		return false
   870  	}
   871  
   872  	if yyyy := Atoi(Right(s, 4)); yyyy < 1970 || yyyy > 2099 {
   873  		return false
   874  	}
   875  
   876  	return true
   877  }
   878  
   879  // IsDateValidMMYY checks if input string value is a valid date represented in the format of MMYY
   880  // valid year detected is 00-99 with year 20xx assumed
   881  func IsDateValidMMYY(s string) bool {
   882  	s = Trim(s)
   883  
   884  	if len(s) != 4 {
   885  		return false
   886  	}
   887  
   888  	if mm := Atoi(Left(s, 2)); mm < 1 || mm > 12 {
   889  		return false
   890  	}
   891  
   892  	if yy := Atoi(Right(s, 2)); yy < 0 || yy > 99 {
   893  		return false
   894  	}
   895  
   896  	return true
   897  }
   898  
   899  // IsTimeValidhhmmss checks if input string value is a valid time represented in the format of hhmmss (24 hour format)
   900  func IsTimeValidhhmmss(s string) bool {
   901  	s = Trim(s)
   902  
   903  	if len(s) != 6 {
   904  		return false
   905  	}
   906  
   907  	if hh := Atoi(Left(s, 2)); hh < 0 || hh > 23 {
   908  		return false
   909  	}
   910  
   911  	if mm := Atoi(Mid(s, 2, 2)); mm < 0 || mm > 59 {
   912  		return false
   913  	}
   914  
   915  	if ss := Atoi(Right(s, 2)); ss < 0 || ss > 59 {
   916  		return false
   917  	}
   918  
   919  	return true
   920  }
   921  
   922  // IsTimeValidhhmm checks if input string value is a valid time represented in the format of hhmm (24 hour format)
   923  func IsTimeValidhhmm(s string) bool {
   924  	s = Trim(s)
   925  
   926  	if len(s) != 4 {
   927  		return false
   928  	}
   929  
   930  	if hh := Atoi(Left(s, 2)); hh < 0 || hh > 23 {
   931  		return false
   932  	}
   933  
   934  	if mm := Atoi(Right(s, 2)); mm < 0 || mm > 59 {
   935  		return false
   936  	}
   937  
   938  	return true
   939  }
   940  
   941  // IsDateTimeValidYYYYMMDDhhmmss checks if input string value is a valid date time represented in the format of YYYYMMDDhhmmss (24 hour format)
   942  func IsDateTimeValidYYYYMMDDhhmmss(s string) bool {
   943  	s = Trim(s)
   944  
   945  	if len(s) != 14 {
   946  		return false
   947  	}
   948  
   949  	if d := Left(s, 8); !IsDateValidYYYYMMDD(d) {
   950  		return false
   951  	}
   952  
   953  	if t := Right(s, 6); !IsTimeValidhhmmss(t) {
   954  		return false
   955  	}
   956  
   957  	return true
   958  }
   959  
   960  // IsDateTimeValidYYYYMMDDhhmm checks if input string value is a valid date time represented in the format of YYYYMMDDhhmm (24 hour format)
   961  func IsDateTimeValidYYYYMMDDhhmm(s string) bool {
   962  	s = Trim(s)
   963  
   964  	if len(s) != 12 {
   965  		return false
   966  	}
   967  
   968  	if d := Left(s, 8); !IsDateValidYYYYMMDD(d) {
   969  		return false
   970  	}
   971  
   972  	if t := Right(s, 4); !IsTimeValidhhmm(t) {
   973  		return false
   974  	}
   975  
   976  	return true
   977  }
   978  
   979  // IsDateTimeValidYYMMDDhhmmss checks if input string value is a valid date time represented in the format of YYMMDDhhmmss (24 hour format)
   980  func IsDateTimeValidYYMMDDhhmmss(s string) bool {
   981  	s = Trim(s)
   982  
   983  	if len(s) != 12 {
   984  		return false
   985  	}
   986  
   987  	if d := Left(s, 6); !IsDateValidYYMMDD(d) {
   988  		return false
   989  	}
   990  
   991  	if t := Right(s, 6); !IsTimeValidhhmmss(t) {
   992  		return false
   993  	}
   994  
   995  	return true
   996  }
   997  
   998  // IsDateTimeValidYYMMDDhhmm checks if input string value is a valid date time represented in the format of YYMMDDhhmm (24 hour format)
   999  func IsDateTimeValidYYMMDDhhmm(s string) bool {
  1000  	s = Trim(s)
  1001  
  1002  	if len(s) != 10 {
  1003  		return false
  1004  	}
  1005  
  1006  	if d := Left(s, 6); !IsDateValidYYMMDD(d) {
  1007  		return false
  1008  	}
  1009  
  1010  	if t := Right(s, 4); !IsTimeValidhhmm(t) {
  1011  		return false
  1012  	}
  1013  
  1014  	return true
  1015  }
  1016  
  1017  // IsDateTimeValid_ISO8601_RFC3339 checks if input string value is a valid date time represented in the format of ISO8601 RFC3339 date time
  1018  func IsDateTimeValid_ISO8601_RFC3339(s string) bool {
  1019  	s = Trim(s)
  1020  
  1021  	if t, e := time.Parse(time.RFC3339, s); e != nil {
  1022  		return false
  1023  	} else if t.IsZero() {
  1024  		return false
  1025  	} else {
  1026  		return true
  1027  	}
  1028  }
  1029  
  1030  // FormatDateTimeToYYYYMMDDhhmmss for the date time struct received
  1031  func FormatDateTimeToYYYYMMDDhhmmss(t time.Time) string {
  1032  	return t.Format("20060102150405")
  1033  }
  1034  
  1035  // FormatDateTimeToMMDDYYYYhhmmss for the date time struct received
  1036  func FormatDateTimeToMMDDYYYYhhmmss(t time.Time) string {
  1037  	return t.Format("01022006150405")
  1038  }
  1039  
  1040  // FormatTimeTohhmmss for the date time struct received
  1041  func FormatTimeTohhmmss(t time.Time) string {
  1042  	return t.Format("150405")
  1043  }
  1044  
  1045  // FormatDateToYYYYMMDD for the date time struct received
  1046  func FormatDateToYYYYMMDD(t time.Time) string {
  1047  	return t.Format("20060102")
  1048  }
  1049  
  1050  // FormatDateToDDMMYYYY for the date time struct received
  1051  func FormatDateToDDMMYYYY(t time.Time) string {
  1052  	return t.Format("02012006")
  1053  }
  1054  
  1055  // FormatDateToYYMMDD for the date time struct received
  1056  func FormatDateToYYMMDD(t time.Time) string {
  1057  	return t.Format("060102")
  1058  }
  1059  
  1060  // FormatDateToYYMM for the date time struct received
  1061  func FormatDateToYYMM(t time.Time) string {
  1062  	return t.Format("0601")
  1063  }
  1064  
  1065  // FormatDateToMMYY for the date time struct received
  1066  func FormatDateToMMYY(t time.Time) string {
  1067  	return t.Format("0106")
  1068  }
  1069  
  1070  // FormatDateToMMDD for the date time struct received
  1071  func FormatDateToMMDD(t time.Time) string {
  1072  	return t.Format("0102")
  1073  }
  1074  
  1075  // GetDate returns date based on given year month day,
  1076  // month max day is checked,
  1077  // leap year is checked
  1078  func GetDate(year int, month int, day int) time.Time {
  1079  	if year < 1970 || year > 2199 {
  1080  		return time.Time{}
  1081  	}
  1082  
  1083  	if month < 1 || month > 12 {
  1084  		return time.Time{}
  1085  	}
  1086  
  1087  	if day < 1 || day > 31 {
  1088  		return time.Time{}
  1089  	}
  1090  
  1091  	x := []int{4, 6, 9, 11}
  1092  
  1093  	if IntSliceContains(&x, month) {
  1094  		// 30
  1095  		if day == 31 {
  1096  			return time.Time{}
  1097  		}
  1098  	} else if month == 2 {
  1099  		// either 28 or 29
  1100  		ly := 28
  1101  
  1102  		if IsLeapYear(year) {
  1103  			ly = 29
  1104  		}
  1105  
  1106  		if day > ly {
  1107  			return time.Time{}
  1108  		}
  1109  	}
  1110  
  1111  	return time.Date(year, time.Month(month), day, 0, 0, 0, 0, time.UTC)
  1112  }
  1113  
  1114  // GetFirstDateOfMonth returns the given date's first date of month,
  1115  // for example, 8/21/2020 => 8/1/2020
  1116  func GetFirstDateOfMonth(t time.Time) time.Time {
  1117  	return GetDate(t.Year(), int(t.Month()), 1)
  1118  }
  1119  
  1120  // GetLastDateOfMonth returns the given date's last day of the month,
  1121  // for example, 8/21/2020 => 8/31/2020
  1122  func GetLastDateOfMonth(t time.Time) time.Time {
  1123  	x := GetFirstDateOfMonth(t).AddDate(0, 1, 0)
  1124  	return GetFirstDateOfMonth(x).AddDate(0, 0, -1)
  1125  }