package main import ( "fmt" "strconv" "strings" "time" gime "git.bullercodeworks.com/brian/gime-lib" ) func cmdPrintList(args []string) int { useDefaultFilter := true var showIds bool var beg, end time.Time tags, rem := pullTagsFromArgs(args) loadType := gime.TypeNoArchive for _, opt := range rem { var tmpBeg, tmpEnd time.Time // Check for command modifiers if strings.HasPrefix(opt, ":") { switch opt { case ":ids": showIds = true // Special durations 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 } // Was 'archive' requested? if strings.HasPrefix(opt, "arch") { loadType = gime.TypeArchive useDefaultFilter = false } } if end.IsZero() { end = time.Now() } timeEntries = gdb.LoadTimeEntryCollection(loadType) // By default, list all entries ending today or still running defaultFilter := func(t *gime.TimeEntry) bool { return t.EndsToday() || t.IsRunning() } timeSpanFilter := func(t *gime.TimeEntry) bool { return t.GetStart().After(beg) && t.GetEnd().Before(end) } tagFilter := func(t *gime.TimeEntry) bool { for i := range tags { if !t.HasTag(tags[i]) { return false } } return true } compoundFilter := func(t *gime.TimeEntry) bool { // If we didn't get any other filter specifications, just use the default if useDefaultFilter { return defaultFilter(t) } // Otherwise we want to filter timespan and tags return timeSpanFilter(t) && tagFilter(t) } dayStr := "" timers := filterTimerCollection(timeEntries, compoundFilter) var str string var currId int var err error if timers.Length() == 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 i := 0; i < timers.Length(); i++ { wrk := timers.Get(i) dur := wrk.GetEnd().Sub(wrk.GetStart()) if wrk.GetEnd().IsZero() { dur = time.Now().Sub(wrk.GetStart()) } dayTotals[wrk.GetStart().Format("2006/01/02")] += dur } for i := 0; i < timers.Length(); i++ { wrk := timers.Get(i) oldDayStr := dayStr dayStr = wrk.GetStart().Format("2006/01/02") if dayStr != oldDayStr { wrkDur := dayTotals[dayStr].Round(GetRoundToDuration()) fmtStr := dayStr + " ( %.2f )\n" str += fmt.Sprintf(fmtStr, DurationToDecimal(wrkDur)) } id := "" if showIds { if currId, err = findIdOfTimer(wrk); err == nil { id = fmt.Sprintf("%3s", fmt.Sprintf("@%d", currId)) } else { id = "@!" } } str += fmt.Sprintf(" %s %s\n", id, TimerToString(timers.Get(i))) } fmt.Println(str) return 0 } func cmdPrintDetail(args []string) int { fmt.Println("Not implemented yet.") return 1 } func cmdDoExport(args []string) int { return 0 }