github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/util/attime/attime.go (about) 1 package attime 2 3 import ( 4 "regexp" 5 "strconv" 6 "strings" 7 "time" 8 ) 9 10 // this code is a rough copy of this code https://github.com/graphite-project/graphite-web/blob/master/webapp/graphite/render/attime.py 11 12 var digitsOnly = regexp.MustCompile("^\\d+$") 13 14 func Parse(s string) time.Time { 15 s = strings.TrimSpace(s) 16 // s = strings.ToLower(s) 17 s = strings.Replace(s, "_", "", -1) 18 s = strings.Replace(s, ",", "", -1) 19 s = strings.Replace(s, " ", "", -1) 20 21 if digitsOnly.MatchString(s) { 22 t, _ := time.Parse("20060102", s) 23 if len(s) == 8 && t.Year() > 1900 && t.Month() < 13 && t.Day() < 32 { 24 return t 25 } 26 27 // Unix time. 28 v, _ := strconv.Atoi(s) 29 switch len(s) { 30 default: 31 // Seconds. 32 return time.Unix(int64(v), 0) 33 case 13: 34 return time.UnixMilli(int64(v)) 35 case 16: 36 return time.UnixMicro(int64(v)) 37 case 19: 38 return time.Unix(0, int64(v)) 39 } 40 } 41 42 ref := s 43 offset := "" 44 45 if i := strings.Index(s, "+"); i != -1 { 46 ref = s[:i] 47 offset = s[i:] 48 } else if i := strings.Index(s, "-"); i != -1 { 49 ref = s[:i] 50 offset = s[i:] 51 } 52 53 return parseTimeReference(ref).Add(parseTimeOffset(offset)) 54 } 55 56 func parseTimeReference(_ string) time.Time { 57 now := time.Now() 58 // TODO: implement 59 return now 60 } 61 62 func parseTimeOffset(offset string) (d time.Duration) { 63 if offset == "" { 64 return 0 65 } 66 67 sign := 1 68 69 if offset[0] == '-' { 70 sign = -1 71 offset = offset[1:] 72 } else if offset[0] == '+' { 73 offset = offset[1:] 74 } 75 76 for offset != "" { 77 // TODO: this is kind of ugly IMO, I bet it could be refactored to look better 78 i := 1 79 for i <= len(offset) && digitsOnly.MatchString(offset[:i]) { 80 i++ 81 } 82 num, _ := strconv.Atoi(offset[:i-1]) 83 offset = offset[i-1:] 84 85 i = 1 86 for i <= len(offset) && !digitsOnly.MatchString(offset[:i]) { 87 i++ 88 } 89 unit := offset[:i-1] 90 offset = offset[i-1:] 91 92 d += time.Second * time.Duration(num*sign*getUnitMultiplier(unit)) 93 } 94 95 return d 96 } 97 98 func getUnitMultiplier(s string) int { 99 if strings.HasPrefix(s, "s") { 100 return 1 101 } 102 if strings.HasPrefix(s, "mon") || strings.HasPrefix(s, "M") { 103 return 3600 * 24 * 30 104 } 105 if strings.HasPrefix(s, "min") || strings.HasPrefix(s, "m") { 106 return 60 107 } 108 if strings.HasPrefix(s, "h") { 109 return 3600 110 } 111 if strings.HasPrefix(s, "d") { 112 return 3600 * 24 113 } 114 if strings.HasPrefix(s, "w") { 115 return 3600 * 24 * 7 116 } 117 if strings.HasPrefix(s, "y") { 118 return 3600 * 24 * 365 119 } 120 return 0 121 }