github.com/go-graphite/carbonapi@v0.17.0/date/date.go (about) 1 package date 2 3 import ( 4 "errors" 5 "strconv" 6 "strings" 7 "time" 8 9 "github.com/go-graphite/carbonapi/pkg/parser" 10 ) 11 12 var errBadTime = errors.New("bad time") 13 var timeNow = time.Now 14 15 // parseTime parses a time and returns hours and minutes 16 func parseTime(s string) (hour, minute int, err error) { 17 18 switch s { 19 case "midnight": 20 return 0, 0, nil 21 case "noon": 22 return 12, 0, nil 23 case "teatime": 24 return 16, 0, nil 25 } 26 27 parts := strings.Split(s, ":") 28 29 if len(parts) != 2 { 30 return 0, 0, errBadTime 31 } 32 33 hour, err = strconv.Atoi(parts[0]) 34 if err != nil { 35 return 0, 0, errBadTime 36 } 37 38 minute, err = strconv.Atoi(parts[1]) 39 if err != nil { 40 return 0, 0, errBadTime 41 } 42 43 return hour, minute, nil 44 } 45 46 var TimeFormats = []string{"20060102", "01/02/06"} 47 48 // DateParamToEpoch turns a passed string parameter into a unix epoch 49 func DateParamToEpoch(s, qtz string, d int64, defaultTimeZone *time.Location) int64 { 50 51 if s == "" { 52 // return the default if nothing was passed 53 return d 54 } 55 56 // relative timestamp 57 if s[0] == '-' { 58 offset, err := parser.IntervalString(s, -1) 59 if err != nil { 60 return d 61 } 62 63 return timeNow().Add(time.Duration(offset) * time.Second).Unix() 64 } 65 66 switch s { 67 case "now": 68 return timeNow().Unix() 69 case "midnight", "noon", "teatime": 70 yy, mm, dd := timeNow().Date() 71 hh, min, _ := parseTime(s) // error ignored, we know it's valid 72 dt := time.Date(yy, mm, dd, hh, min, 0, 0, defaultTimeZone) 73 return dt.Unix() 74 } 75 76 sint, err := strconv.Atoi(s) 77 // need to check that len(s) != 8 to avoid turning 20060102 into seconds 78 if err == nil && len(s) != 8 { 79 return int64(sint) // We got a timestamp so returning it 80 } 81 82 s = strings.Replace(s, "_", " ", 1) // Go can't parse _ in date strings 83 84 var ts, ds string 85 split := strings.Fields(s) 86 87 switch { 88 case len(split) == 1: 89 ds = s 90 case len(split) == 2: 91 ts, ds = split[0], split[1] 92 case len(split) > 2: 93 return d 94 } 95 96 var tz = defaultTimeZone 97 if qtz != "" { 98 if z, err := time.LoadLocation(qtz); err != nil { 99 tz = z 100 } 101 } 102 103 var t time.Time 104 dateStringSwitch: 105 switch ds { 106 case "today": 107 t = timeNow() 108 // nothing 109 case "yesterday": 110 t = timeNow().AddDate(0, 0, -1) 111 case "tomorrow": 112 t = timeNow().AddDate(0, 0, 1) 113 default: 114 for _, format := range TimeFormats { 115 t, err = time.ParseInLocation(format, ds, tz) 116 if err == nil { 117 break dateStringSwitch 118 } 119 } 120 121 return d 122 } 123 124 var hour, minute int 125 if ts != "" { 126 hour, minute, _ = parseTime(ts) 127 // defaults to hour=0, minute=0 on error, which is midnight, which is fine for now 128 } 129 130 yy, mm, dd := t.Date() 131 t = time.Date(yy, mm, dd, hour, minute, 0, 0, defaultTimeZone) 132 133 return t.Unix() 134 }