package main import ( "errors" "fmt" "time" ) func GetRoundToDuration() time.Duration { var dur time.Duration var err error if dur, err = time.ParseDuration(cfg.Get("roundto")); err != nil { cfg.Set("roundto", DefRoundTo) dur, _ = time.ParseDuration(DefRoundTo) } return dur } func DurationToDecimal(dur time.Duration) float64 { mins := dur.Minutes() - (dur.Hours() * 60) return dur.Hours() + (mins / 60) } // pullRemoveTagsFromArgs takes a list of arguments, removes all 'remove tags' from them // then returns the tags and the remaining args func pullRemoveTagsFromArgs(args []string) ([]string, []string) { var tags, rem []string for _, opt := range args { if opt[0] == '-' { tags = append(tags, opt[1:]) } else { rem = append(rem, opt) } } return tags, rem } // pullTagsFromArgs takes a list of arguments, removes all tags from them // then returns the tags and the remaining args func pullTagsFromArgs(args []string) ([]string, []string) { var tags, rem []string for _, opt := range args { if opt[0] == '+' { tags = append(tags, opt[1:]) } else { rem = append(rem, opt) } } return tags, rem } func parseFuzzyTime(t string) (time.Time, error) { var ret time.Time var err error for i := range fuzzyFormats { ret, err = time.Parse(fuzzyFormats[i], t) if err == nil { // Make sure it's in the local timezone tz := time.Now().Format("Z07:00") t = ret.Format("2006-01-02T15:04:05") + tz if ret, err = time.Parse(time.RFC3339, t); err != nil { return ret, err } // Check for zero on year/mo/day if ret.Year() == 0 && ret.Month() == time.January && ret.Day() == 1 { ret = ret.AddDate(time.Now().Year(), int(time.Now().Month())-1, time.Now().Day()-1) } return ret, nil } } return time.Time{}, errors.New("Unable to parse time: " + t) } func friendlyFormatForTime(t time.Time) string { nowTime := time.Now() if t.Year() != nowTime.Year() || t.Month() != nowTime.Month() { return "2006-01-02 15:04" } else if t.Day() != nowTime.Day() { return "01/02 15:04" } return "15:04" } // timeToFriendlyString returns an easier to read version of the time // giving enough details that the user should be fine inferring the rest func timeToFriendlyString(t time.Time) string { return t.Format(friendlyFormatForTime(t)) } func sinceToString(tm time.Time) string { return diffToString(tm, time.Now()) } func diffToString(tm1, tm2 time.Time) string { ret := "" yr, mo, dy, hr, mn, sc := diff(tm1, tm2) higher := false if yr > 0 { ret += fmt.Sprintf("%4dy ", yr) higher = true } if mo > 0 || higher { ret += fmt.Sprintf("%2dm ", mo) higher = true } if dy > 0 || higher { ret += fmt.Sprintf("%2dd ", dy) higher = true } if hr > 0 || higher { ret += fmt.Sprintf("%2dh ", hr) higher = true } if mn > 0 || higher { ret += fmt.Sprintf("%2dm ", mn) higher = true } if sc > 0 || higher { ret += fmt.Sprintf("%2ds", sc) } return ret } func padRight(st string, l int) string { for len(st) < l { st = st + " " } return st } func padLeft(st string, l int) string { for len(st) < l { st = " " + st } return st } func diff(a, b time.Time) (year, month, day, hour, min, sec int) { if a.Location() != b.Location() { b = b.In(a.Location()) } if a.After(b) { a, b = b, a } y1, M1, d1 := a.Date() y2, M2, d2 := b.Date() h1, m1, s1 := a.Clock() h2, m2, s2 := b.Clock() year = int(y2 - y1) month = int(M2 - M1) day = int(d2 - d1) hour = int(h2 - h1) min = int(m2 - m1) sec = int(s2 - s1) // Normalize negative values if sec < 0 { sec += 60 min-- } if min < 0 { min += 60 hour-- } if hour < 0 { hour += 24 day-- } if day < 0 { // days in month: t := time.Date(y1, M1, 32, 0, 0, 0, 0, time.UTC) day += 32 - t.Day() month-- } if month < 0 { month += 12 year-- } return }