github.com/diadata-org/diadata@v1.4.593/pkg/utils/dates.go (about) 1 package utils 2 3 import ( 4 "errors" 5 "strconv" 6 "time" 7 ) 8 9 // StrToUnixtime converts a string corresponding to an int to Unix time 10 func StrToUnixtime(s string) (t time.Time, err error) { 11 i, err := strconv.ParseInt(s, 10, 64) 12 if err != nil { 13 return 14 } 15 t = time.Unix(i, 0) 16 return 17 } 18 19 // CheckWeekDay returns true if @date is not weekend and false otherwise. 20 func CheckWeekDay(date time.Time) bool { 21 if date.Weekday() == time.Saturday || date.Weekday() == time.Sunday { 22 return false 23 } 24 return true 25 } 26 27 // ContainsDay returns true if day @date is contained in slice @s, independent of the daytime. 28 // As a consequence, be cautious when comparing days in different timezones. 29 func ContainsDay(s []time.Time, date time.Time) bool { 30 for _, a := range s { 31 if SameDays(a, date) { 32 return true 33 } 34 } 35 return false 36 } 37 38 // SameDays returns true if @date1 is the same date as @date2, independent of the daytime. 39 func SameDays(date1, date2 time.Time) bool { 40 if date1.Year() == date2.Year() && date1.Month() == date2.Month() && date1.Day() == date2.Day() { 41 return true 42 } 43 return false 44 } 45 46 // AfterDay returns true if date1 is a date after date2, irrespective of the daytime. 47 // The go method "After" respects daytime. 48 func AfterDay(date1, date2 time.Time) bool { 49 date1Str := date1.Format("2006-01-02") 50 date2Str := date2.Format("2006-01-02") 51 return date1Str > date2Str 52 } 53 54 // CountDays returns the number of days between 55 // @dateInit and @dateFinal, both given as converted from a string in the format yyyy-mm-dd, excluding the last day. 56 // @bool If true only business days are counted. 57 func CountDays(dateInit, dateFinal time.Time, business bool) (days int, err error) { 58 59 if SameDays(dateInit, dateFinal) { 60 return 0, nil 61 } 62 days = 0 63 if dateInit.After(dateFinal) { 64 log.Error("The final date cannot be smaller than the initial date.") 65 err = errors.New("date error") 66 return 67 } 68 69 for { 70 if SameDays(dateInit, dateFinal) { 71 return days, nil 72 } 73 if business { 74 if CheckWeekDay(dateInit) { 75 days++ 76 } 77 dateInit = dateInit.Add(time.Hour * 24) 78 } else { 79 days++ 80 dateInit = dateInit.Add(time.Hour * 24) 81 } 82 } 83 } 84 85 // GetHolidays returns "holidays" as non-weekend complement of given days @workdays 86 func GetHolidays(workdays []time.Time, dateInit, dateFinal time.Time) []time.Time { 87 88 if AfterDay(dateInit, dateFinal) { 89 log.Error("The initial date must not be after the final date.") 90 return []time.Time{} 91 } 92 auxDate := dateInit 93 holidays := []time.Time{} 94 for !SameDays(auxDate, dateFinal.AddDate(0, 0, 1)) { 95 if CheckWeekDay(auxDate) && !ContainsDay(workdays, auxDate) { 96 holidays = append(holidays, auxDate) 97 auxDate = auxDate.AddDate(0, 0, 1) 98 } else { 99 auxDate = auxDate.AddDate(0, 0, 1) 100 } 101 } 102 return holidays 103 } 104 105 // GetYesterday returns the day before @date in the world of strings, formatted as @layout 106 func GetYesterday(date, layout string) string { 107 dateTime, err := time.Parse(layout, date) 108 if err != nil { 109 log.Printf("Error: %v on date format %s\n", err, date) 110 } 111 yesterday := dateTime.AddDate(0, 0, -1) 112 return yesterday.Format(layout) 113 } 114 115 // GetTomorrow returns the day before @date in the world of strings, formatted as @layout 116 func GetTomorrow(date, layout string) string { 117 dateTime, err := time.Parse(layout, date) 118 if err != nil { 119 log.Printf("Error: %v on date format %s\n", err, date) 120 } 121 tomorrow := dateTime.AddDate(0, 0, 1) 122 return tomorrow.Format(layout) 123 } 124 125 // MakeTimeRanges returns @numRanges start- and endtimes partitioning [@timeInit, @timeFinal] in intervals of identical size. 126 func MakeTimeRanges(timeInit, timeFinal time.Time, numRanges int) (starttimes, endtimes []time.Time) { 127 a := timeInit 128 b := timeFinal 129 totalSize := b.Sub(a) 130 sizeRange := totalSize / time.Duration(numRanges) 131 starttime := timeInit 132 for k := 0; k < numRanges; k++ { 133 starttimes = append(starttimes, starttime) 134 endtimes = append(endtimes, starttime.Add(sizeRange)) 135 starttime = starttime.Add(sizeRange) 136 } 137 return 138 } 139 140 // MakeTimerange parses Unix timestamps given as strings. 141 // In case one of the two is empty, it returns a time-range based on @timeRange. 142 // Default is a 24h window ending now. 143 func MakeTimerange(starttimeString string, endtimeString string, timeRange time.Duration) (starttime time.Time, endtime time.Time, err error) { 144 145 var ( 146 starttimeInt int64 147 endtimeInt int64 148 ) 149 150 if starttimeString == "" && endtimeString == "" { 151 endtime = time.Now() 152 starttime = endtime.Add(-timeRange) 153 } else if starttimeString == "" && endtimeString != "" { 154 // zero time if not given 155 endtimeInt, err = strconv.ParseInt(endtimeString, 10, 64) 156 if err != nil { 157 return 158 } 159 endtime = time.Unix(endtimeInt, 0) 160 starttime = endtime.Add(-timeRange) 161 } else if starttimeString != "" && endtimeString == "" { 162 starttimeInt, err = strconv.ParseInt(starttimeString, 10, 64) 163 if err != nil { 164 return 165 } 166 starttime = time.Unix(starttimeInt, 0) 167 endtime = starttime.Add(timeRange) 168 } else { 169 starttimeInt, err = strconv.ParseInt(starttimeString, 10, 64) 170 if err != nil { 171 return 172 } 173 starttime = time.Unix(starttimeInt, 0) 174 endtimeInt, err = strconv.ParseInt(endtimeString, 10, 64) 175 if err != nil { 176 return 177 } 178 endtime = time.Unix(endtimeInt, 0) 179 } 180 return starttime, endtime, nil 181 } 182 183 // ValidTimeRange returns true if the interval [@starttime, @endtime] is at most @maxDuration. 184 func ValidTimeRange(starttime time.Time, endtime time.Time, maxDuration time.Duration) (ok bool) { 185 if endtime.Sub(starttime) <= maxDuration { 186 ok = true 187 } 188 return 189 }