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 }