package main import ( "fmt" "strconv" "strings" "time" "github.com/pborman/uuid" ) func cmdStartTimer(args []string) int { var err error var entry *Timer // By default we start the timer now tm := time.Now() tags, rem := pullTagsFromArgs(args) if len(rem) > 0 { // Check if the first argument looks like a date/time tm, err = parseFuzzyTime(rem[0]) } entry = NewTimer(tm, time.Time{}) entry.SetTags(tags) if err = SaveTimer(entry); err != nil { fmt.Println(err) return 1 } fmt.Println("Started:", entry.FriendlyString()) return 0 } func cmdAddTimer(args []string) int { var err error var entry *Timer // By default we're starting the time now tags, rem := pullTagsFromArgs(args) var beg, end time.Time for _, opt := range rem { var tmpBeg, tmpEnd time.Time if strings.Contains(opt, "-") { pts := strings.Split(opt, "-") if len(pts[0]) > 0 { // This should be the starting date tmpBeg, err = parseFuzzyTime(pts[0]) if err != nil { continue } } if len(pts[1]) > 0 { // This should be the ending date tmpEnd, err = parseFuzzyTime(pts[1]) if err != nil { continue } } } if !tmpBeg.IsZero() || !tmpEnd.IsZero() { beg, end = tmpBeg, tmpEnd } } if end.IsZero() { end = time.Now() } entry = NewTimer(beg, end) fmt.Println("Adding Timer:", entry.FriendlyString()) entry.Tags = tags if err = SaveTimer(entry); err != nil { fmt.Println(err) return 1 } fmt.Println("Added Time Entry:", entry.FriendlyString()) return 0 } func cmdContinueTimer(args []string) int { // Get the last running timer and start a new one with the same tags return 0 } func cmdStopTimer(args []string) int { var err error tm := time.Now() actTimers := LoadActiveTimers() var tmr *Timer stopId := "@0" // By default, stop the first timer for i := range args { if args[i][0] == '@' { stopId = args[i] continue } tmpTm, err := parseFuzzyTime(args[i]) if err == nil { // We found a time tm = tmpTm continue } } if stopId != "@all" { // Find the timer that we're stopping timerId, err := strconv.Atoi(stopId[1:]) if err != nil { fmt.Println("Error parsing timer id:", err.Error()) return 1 } tmr = &actTimers[timerId] if timerId >= len(actTimers) || timerId < 0 || tmr == nil { fmt.Println("Error finding timer with id:", timerId) return 1 } } stopTimer := func(tmr *Timer, at time.Time) int { tmr.SetEnd(at) if err = SaveTimer(tmr); err != nil { fmt.Println(err.Error()) return 1 } fmt.Println("Stopped:", tmr.InferDetailString()) return 0 } if stopId == "@all" { var ret int for _, v := range actTimers { ret += stopTimer(&v, tm) } if ret > 0 { return 1 } return 0 } return stopTimer(tmr, tm) } func cmdDeleteTimer(args []string) int { if len(args) < 1 { fmt.Println("Delete requires a timer UUID") return 1 } // Try to parse args[0] as a UUID if uuid.Parse(args[0]) == nil { // Not a UUID, bail for now fmt.Print("Invalid UUID given (", args[0], ")\n") return 1 } tmr := LoadTimer(args[0]) if tmr == nil { fmt.Println("Couldn't find timer with UUID (", args[0], ")\n") return 1 } if DeleteTimer(args[0]) != nil { fmt.Println("Error deleting timer") return 1 } return 0 } func cmdModifyTimer(args []string) int { return 0 } func cmdSwitchTimer(args []string) int { return 0 } func cmdPrintStatus(args []string) int { tmrs := LoadActiveTimers() curr := time.Now() fmt.Println("Current Time:", curr.Format(time.Stamp)) if len(tmrs) == 0 { fmt.Println("No timer running") } else { fmt.Print("Active Timers (", len(tmrs), ")\n") // Find the longest start time & longest duration short := true for _, v := range tmrs { if v.GetStart().Day() != curr.Day() { short = false break } } for i, v := range tmrs { if short { fmt.Printf(" @%d %s\n", i, v.DetailString()) } else { fmt.Printf(" @%d %s\n", i, v.LongDetailString()) } } } return 0 } func cmdPrintList(args []string) int { useDefaultFilter := true var showIds bool var beg, end time.Time tags, rem := pullTagsFromArgs(args) _ = tags for _, opt := range rem { var tmpBeg, tmpEnd time.Time // Check for command modifiers if strings.HasPrefix(opt, ":") { switch opt { case ":ids": showIds = true case ":day": beg, _ = parseFuzzyTime("00:00") end, _ = parseFuzzyTime("23:59") case ":week": currDoW := time.Now().Weekday() beg = time.Now().AddDate(0, 0, int(currDoW)*-1) beg = time.Date(beg.Year(), beg.Month(), beg.Day(), 0, 0, 0, 0, beg.Location()) case ":month": currDoM := time.Now().Day() beg = time.Now().AddDate(0, 0, int(currDoM)*-1) beg = time.Date(beg.Year(), beg.Month(), beg.Day(), 0, 0, 0, 0, beg.Location()) case ":year": yr := strconv.Itoa(time.Now().Year()) beg, _ = parseFuzzyTime(yr + "0101T00:00") end, _ = parseFuzzyTime(yr + "1231T23:59") } continue } // Do our best to figure out what timers the user wants to list var err error if strings.Contains(opt, "-") { useDefaultFilter = false pts := strings.Split(opt, "-") if len(pts[0]) > 0 { // This should be the starting date tmpBeg, err = parseFuzzyTime(pts[0]) if err != nil { continue } } if len(pts[1]) > 0 { // This should be the ending date tmpEnd, err = parseFuzzyTime(pts[1]) if err != nil { continue } } } if !tmpBeg.IsZero() || !tmpEnd.IsZero() { beg, end = tmpBeg, tmpEnd } } if end.IsZero() { end = time.Now() } // By default, list all entries ending today or still running dayStr := "" tmrs := LoadActiveTimers() tmrs = append(tmrs, LoadTimers(beg, end)...) var str string if len(tmrs) == 0 { if useDefaultFilter { fmt.Println("No timers found for today") } else { begFmt := friendlyFormatForTime(beg) endFmt := friendlyFormatForTime(end) useFmt := endFmt if len(begFmt) > len(endFmt) { useFmt = begFmt } fmt.Println("No timers found in period " + beg.Format(useFmt) + " - " + end.Format(useFmt)) } return 0 } // Get day totals dayTotals := make(map[string]time.Duration) for _, v := range tmrs { dur := v.GetEnd().Sub(v.GetStart()) if v.GetEnd().IsZero() { dur = time.Now().Sub(v.GetStart()) } dayTotals[v.GetStart().Format("2006/01/02")] += dur } for _, v := range tmrs { oldDayStr := dayStr dayStr = v.GetStart().Format("2006/01/02") if dayStr != oldDayStr { vDur := dayTotals[dayStr].Round(GetRoundToDuration()) fmtStr := dayStr + " ( %.2f )\n" str += fmt.Sprintf(fmtStr, DurationToDecimal(vDur)) } _ = showIds id := "" str += fmt.Sprintf(" %s %s\n", id, v.FriendlyString()) } fmt.Println(str) return 0 } func cmdPrintDetail(args []string) int { fmt.Println("Not implemented yet.") return 1 }