diff --git a/date_utils/date_utils.go b/date_utils/date_utils.go index 0b17c21426f76dfeb9abe161b58797b26cee5897..76f4dfc68333df5396a75b239793185da2e08faf 100644 --- a/date_utils/date_utils.go +++ b/date_utils/date_utils.go @@ -1,12 +1,14 @@ package date_utils import ( + "fmt" "reflect" "strconv" "strings" "time" "github.com/araddon/dateparse" + "gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/errors" ) const TimeZoneString = "Africa/Johannesburg" @@ -275,125 +277,76 @@ func formatTimestampsWithTimeZoneInSlice(fieldValue reflect.Value, location *tim } // TradingHours represents an array of (StartTime,EndTime) pairs, one for each day of the week. -// The array is 0 indexed, with 0 being Monday and 6 being Sunday. +// The array is 0 indexed, with 0 being Sunday and 6 being Saturday. type TradingHours []struct { StartTime string `json:"start_time"` EndTime string `json:"end_time"` } -func (t TradingHours) Validate() bool { - if t == nil { - return false +func (t TradingHours) Validate() error { + if len(t) != 7 { + return errors.Error("Trading hours must have 7 days") } for _, day := range t { if !TimeBefore(day.StartTime, day.EndTime) { - return false + return errors.Error("Start time must be before end time") } if len(day.StartTime) != 5 || len(day.EndTime) != 5 { - return false + return errors.Error("Time must be in the format HH:MM") } startHourMinSlice := strings.Split(day.StartTime, ":") if len(startHourMinSlice) != 2 { - return false + return errors.Error("Time must be in the format HH:MM") } startHour, startMin := startHourMinSlice[0], startHourMinSlice[1] startHourInt, err := strconv.Atoi(startHour) if err != nil || startHourInt < 0 || startHourInt > 23 { - return false + return errors.Error("Start hour must be between 0 and 23") } startMinInt, err := strconv.Atoi(startMin) if err != nil || !(startMinInt == 0 || startMinInt == 30) { - return false + return errors.Error("Start minute must be 0 or 30") } endHourMinSlice := strings.Split(day.EndTime, ":") if len(endHourMinSlice) != 2 { - return false + return errors.Error("Time must be in the format HH:MM") } endHour, endMin := endHourMinSlice[0], endHourMinSlice[1] endHourInt, err := strconv.Atoi(endHour) if err != nil || endHourInt < 0 || endHourInt > 23 { - return false + return errors.Error("End hour must be between 0 and 23") } endMinInt, err := strconv.Atoi(endMin) if err != nil || !(endMinInt == 0 || endMinInt == 30 || endMinInt == 59) { - return false + return errors.Error("End minute must be 0, 30 or 59") } } - return true + return nil } func (t TradingHours) String() string { - var dayMap = map[int]string{ - 0: "Mon", - 1: "Tue", - 2: "Wed", - 3: "Thu", - 4: "Fri", - 5: "Sat", - 6: "Sun", - } + var result strings.Builder + t = append(t, t[0]) // Add the first day (Sunday) to the end because we want Monday to be first in the string + const numberOfDaysInWeek = 7 - var timeMap = map[string]string{ - "00:00": "12am", - "00:30": "12:30am", - "01:00": "1am", - "01:30": "1:30am", - "02:00": "2am", - "02:30": "2:30am", - "03:00": "3am", - "03:30": "3:30am", - "04:00": "4am", - "04:30": "4:30am", - "05:00": "5am", - "05:30": "5:30am", - "06:00": "6am", - "06:30": "6:30am", - "07:00": "7am", - "07:30": "7:30am", - "08:00": "8am", - "08:30": "8:30am", - "09:00": "9am", - "09:30": "9:30am", - "10:00": "10am", - "10:30": "10:30am", - "11:00": "11am", - "11:30": "11:30am", - "12:00": "12pm", - "12:30": "12:30pm", - "13:00": "1pm", - "13:30": "1:30pm", - "14:00": "2pm", - "14:30": "2:30pm", - "15:00": "3pm", - "15:30": "3:30pm", - "16:00": "4pm", - "16:30": "4:30pm", - "17:00": "5pm", - "17:30": "5:30pm", - "18:00": "6pm", - "18:30": "6:30pm", - "19:00": "7pm", - "19:30": "7:30pm", - "20:00": "8pm", - "20:30": "8:30pm", - "21:00": "9pm", - "21:30": "9:30pm", - "22:00": "10pm", - "22:30": "10:30pm", - "23:00": "11pm", - "23:30": "11:30pm", - "23:59": "11:59pm", - } + rangeStartIndex := 1 + for i := 1; i < len(t); i++ { + startTime, err := time.Parse("15:04", t[i].StartTime) + if err != nil { + return "" + } - result := "" - rangeStartIndex := 0 - for i := 0; i < len(t); i++ { - times := timeMap[t[i].StartTime] + "-" + timeMap[t[i].EndTime] + endTime, err := time.Parse("15:04", t[i].EndTime) + if err != nil { + return "" + } + + times := startTime.Format("3:04pm") + "-" + endTime.Format("3:04pm") if t[i].StartTime == "00:00" && t[i].EndTime == "23:59" { times = "All day" } @@ -401,18 +354,27 @@ func (t TradingHours) String() string { // If we're at the last element or the next day doesn't have the same times, we end the current range if i == len(t)-1 || t[i].StartTime != t[i+1].StartTime || t[i].EndTime != t[i+1].EndTime { if rangeStartIndex == i { - result += dayMap[i] + ": " + times + day := time.Weekday(rangeStartIndex).String() + if rangeStartIndex == numberOfDaysInWeek { + day = time.Sunday.String() + } + result.WriteString(fmt.Sprintf("%s: %s", day, times)) } else { - result += dayMap[rangeStartIndex] + "-" + dayMap[i] + ": " + times + rangeStartDay := time.Weekday(rangeStartIndex).String() + rangeEndDay := time.Weekday(i).String() + if i == numberOfDaysInWeek { + rangeEndDay = time.Sunday.String() + } + result.WriteString(fmt.Sprintf("%s-%s: %s", rangeStartDay, rangeEndDay, times)) } if i < len(t)-1 { - result += ", " + result.WriteString(", ") } - rangeStartIndex++ + rangeStartIndex = i + 1 } } - return result + return result.String() }