diff --git a/z/calendar.go b/z/calendar.go index bb515bc..db8938d 100644 --- a/z/calendar.go +++ b/z/calendar.go @@ -161,7 +161,7 @@ func (calendar *Calendar) GetOutputForWeekCalendar(date time.Time, month int, we bars = append(bars, bar) } - output = fmt.Sprintf("CW %02d %s H\n", GetISOCalendarWeek(date), totalHours.StringFixed(2)) + output = fmt.Sprintf("CW %02d %s H\n", GetISOCalendarWeek(date), fmtHours(totalHours)) for row := 0; row < len(bars[0]); row++ { output = fmt.Sprintf("%s%2d │", output, ((6 - row) * 4)) for col := 0; col < len(bars); col++ { @@ -184,7 +184,7 @@ func (calendar *Calendar) GetOutputForDistribution() (string) { for _, stat := range calendar.Distribution { divided := stat.Hours.Div(calendar.TotalHours) percentage := divided.Mul(decimal.NewFromInt(100)) - hoursStr := stat.Hours.StringFixed(2) + hoursStr := fmtHours(stat.Hours) percentageStr := percentage.StringFixed(2) dividedByBarLength := percentage.Div(decimal.NewFromInt(100)) diff --git a/z/entry.go b/z/entry.go index ce1c6ab..92a7eea 100644 --- a/z/entry.go +++ b/z/entry.go @@ -141,9 +141,9 @@ func (entry *Entry) GetOutputForFinish() (string) { var outputSuffix string = "" trackDiff := entry.Finish.Sub(entry.Begin) - trackDiffOut := time.Time{}.Add(trackDiff) + taskDuration := fmtDuration(trackDiff) - outputSuffix = fmt.Sprintf(" for %sh", color.FgLightWhite.Render(trackDiffOut.Format("15:04"))) + outputSuffix = fmt.Sprintf(" for %s h", color.FgLightWhite.Render(taskDuration)) if entry.Task != "" && entry.Project != "" { return fmt.Sprintf("%s finished tracking %s on %s%s\n", CharFinish, color.FgLightWhite.Render(entry.Task), color.FgLightWhite.Render(entry.Project), outputSuffix) @@ -169,24 +169,24 @@ func (entry *Entry) GetOutput(full bool) (string) { } trackDiff := entryFinish.Sub(entry.Begin) - trackDiffOut := time.Time{}.Add(trackDiff) - + taskDuration := fmtDuration(trackDiff) if full == false { - output = fmt.Sprintf("%s %s on %s from %s to %s (%sh) %s", + + output = fmt.Sprintf("%s %s on %s from %s to %s (%s h) %s", color.FgGray.Render(entry.ID), color.FgLightWhite.Render(entry.Task), color.FgLightWhite.Render(entry.Project), color.FgLightWhite.Render(entry.Begin.Format("2006-01-02 15:04 -0700")), color.FgLightWhite.Render(entryFinish.Format("2006-01-02 15:04 -0700")), - color.FgLightWhite.Render(trackDiffOut.Format("15:04")), + color.FgLightWhite.Render(taskDuration) , color.FgLightYellow.Render(isRunning), ) } else { - output = fmt.Sprintf("%s\n %s on %s\n %sh from %s to %s %s\n\n Notes:\n %s\n", + output = fmt.Sprintf("%s\n %s on %s\n %s h from %s to %s %s\n\n Notes:\n %s\n", color.FgGray.Render(entry.ID), color.FgLightWhite.Render(entry.Task), color.FgLightWhite.Render(entry.Project), - color.FgLightWhite.Render(trackDiffOut.Format("15:04")), + color.FgLightWhite.Render(taskDuration), color.FgLightWhite.Render(entry.Begin.Format("2006-01-02 15:04 -0700")), color.FgLightWhite.Render(entryFinish.Format("2006-01-02 15:04 -0700")), color.FgLightYellow.Render(isRunning), diff --git a/z/entryCmd.go b/z/entryCmd.go index 081bbc9..7864bec 100644 --- a/z/entryCmd.go +++ b/z/entryCmd.go @@ -71,6 +71,7 @@ func init() { entryCmd.Flags().StringVarP(&project, "project", "p", "", "Update activity project") entryCmd.Flags().StringVarP(¬es, "notes", "n", "", "Update activity notes") entryCmd.Flags().StringVarP(&task, "task", "t", "", "Update activity task") + entryCmd.Flags().BoolVar(&fractional, "decimal", false, "Show fractional hours in decimal format instead of minutes") var err error database, err = InitDatabase() diff --git a/z/listCmd.go b/z/listCmd.go index f7421fc..2549df9 100644 --- a/z/listCmd.go +++ b/z/listCmd.go @@ -13,6 +13,7 @@ var listTotalTime bool var listOnlyProjectsAndTasks bool var appendProjectIDToTask bool + var listCmd = &cobra.Command{ Use: "list", Short: "List activities", @@ -89,7 +90,7 @@ var listCmd = &cobra.Command{ } if listTotalTime == true { - fmt.Printf("\nTOTAL: %s H\n\n", totalHours.StringFixed(2)) + fmt.Printf("\nTOTAL: %s H\n\n", fmtHours(totalHours)); } return }, @@ -101,6 +102,7 @@ func init() { listCmd.Flags().StringVar(&until, "until", "", "Date/time to list until") listCmd.Flags().StringVarP(&project, "project", "p", "", "Project to be listed") listCmd.Flags().StringVarP(&task, "task", "t", "", "Task to be listed") + listCmd.Flags().BoolVar(&fractional, "decimal", false, "Show fractional hours in decimal format instead of minutes") listCmd.Flags().BoolVar(&listTotalTime, "total", false, "Show total time of hours for listed activities") listCmd.Flags().BoolVar(&listOnlyProjectsAndTasks, "only-projects-and-tasks", false, "Only list projects and their tasks, no entries") listCmd.Flags().BoolVar(&appendProjectIDToTask, "append-project-id-to-task", false, "Append project ID to tasks in the list") diff --git a/z/statsCmd.go b/z/statsCmd.go index 6f1d4c9..a91ecb3 100644 --- a/z/statsCmd.go +++ b/z/statsCmd.go @@ -51,7 +51,7 @@ var statsCmd = &cobra.Command{ func init() { rootCmd.AddCommand(statsCmd) - + statsCmd.Flags().BoolVar(&fractional, "decimal", false, "Show fractional hours in decimal format instead of minutes") var err error database, err = InitDatabase() if err != nil { diff --git a/z/util.go b/z/util.go new file mode 100644 index 0000000..4f15be2 --- /dev/null +++ b/z/util.go @@ -0,0 +1,28 @@ +package z + +import ( + "fmt" + "time" + + "github.com/shopspring/decimal" +) + +var fractional bool + +func fmtDuration(dur time.Duration) (string) { + return fmtHours(decimal.NewFromFloat(dur.Hours())) +} + +func fmtHours(hours decimal.Decimal) (string) { + if fractional { + return hours.StringFixed(2) + } else { + return fmt.Sprintf( + "%s:%02s", + hours.Floor(), // hours + hours.Sub(hours.Floor()). + Mul(decimal.NewFromFloat(.6)). + Mul(decimal.NewFromInt(100)). + Floor()) + } +}