tme

Toggl like Time Manager
git clone git://gtms.dev:tme
Log | Files | Refs

commit e715a580b779311dc42bf90a0d7802891f80c546
parent d9c509cc818a9ee0d92197746b13455c978a7992
Author: Tomas Nemec <nemi@skaut.cz>
Date:   Fri, 10 Feb 2023 19:59:10 +0100

feat: format duration

Diffstat:
Mcommand.go | 7++++---
Mtme/entry.go | 119-------------------------------------------------------------------------------
Atme/final_entry.go | 71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atme/running_entry.go | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtme/time.go | 9+++------
5 files changed, 143 insertions(+), 128 deletions(-)

diff --git a/command.go b/command.go @@ -202,11 +202,12 @@ func formatEntries(group tme.Group, entryTime *tme.Time) { switch e := entry.(type) { case tme.FinalEntry: - start := e.Start.Format(tme.TimeLayout) - stop := e.Stop.Format(tme.TimeLayout) + var start string + start = e.Start.Format(tme.DateTimeLayout) + stop := e.Stop.Format(tme.DateTimeLayout) fmt.Printf("%v\t%v\t%v\t%v\n", groupPath, start, stop, duration) case tme.RunningEntry: - start := e.Start.Format(tme.TimeLayout) + start := e.Start.Format(tme.DateTimeLayout) fmt.Printf("%v\t%v\t%s\t%v\n", groupPath, start, "running", duration) } } diff --git a/tme/entry.go b/tme/entry.go @@ -1,8 +1,6 @@ package tme import ( - "errors" - "fmt" "os" "path" "strings" @@ -45,120 +43,3 @@ func NewEntryFromPath(entryPath string, entryTime *Time) (Entry, error) { }, nil } } - -type FinalEntry struct { - Start time.Time - Stop time.Time -} - -func NewFinalEntry(start time.Time, stop time.Time) (FinalEntry, error) { - if start.After(stop) { - return FinalEntry{}, errors.New("duration must be positive") - } - - return FinalEntry{ - Start: start, - Stop: stop, - }, nil -} - -func NewFinalEntryFromPath(entryPath string, entryTime *Time) (FinalEntry, error) { - if _, err := os.Stat(entryPath); os.IsNotExist(err) { - return FinalEntry{}, err - } - - data, err := os.ReadFile(entryPath) - if err != nil { - return FinalEntry{}, err - } - - // TODO(tms) 11.11.22: format check - - lines := strings.Split(string(data), "\n") - start, _ := entryTime.ParseEntry(lines[0]) - stop, _ := entryTime.ParseEntry(lines[1]) - - return FinalEntry{ - Start: start, - Stop: stop, - }, nil -} - -func (e FinalEntry) Data() string { - return fmt.Sprintf("%s\n%s\n", e.Start.Format(DateTimeLayout), e.Stop.Format(DateTimeLayout)) -} - -func (e FinalEntry) FileName() string { - return strings.Join([]string{e.Start.Format(FileNameLayout), e.Stop.Format(FileNameLayout)}, "_") -} - -func (e FinalEntry) FullPath(group Group) string { - return path.Join(group.FullPath(), e.FileName()) -} - -func (e FinalEntry) Exists(group Group) bool { - if _, err := os.Stat(e.FullPath(group)); !os.IsNotExist(err) { - return true - } - return false -} - -func (e FinalEntry) Duration() time.Duration { - return e.Stop.Sub(e.Start) -} - -type RunningEntry struct { - Start time.Time -} - -func NewRunningEntry(start time.Time) RunningEntry { - return RunningEntry{ - Start: start, - } -} - -func NewRunningEntryFromPath(entryPath string, entryTime *Time) (RunningEntry, error) { - if _, err := os.Stat(entryPath); os.IsNotExist(err) { - return RunningEntry{}, err - } - - data, err := os.ReadFile(entryPath) - if err != nil { - return RunningEntry{}, err - } - - firstLine := strings.Split(string(data), "\n")[0] - start, _ := entryTime.ParseEntry(firstLine) - - return RunningEntry{ - Start: start, - }, nil - -} - -func (e RunningEntry) Data() string { - return fmt.Sprintf("%s\n", e.Start.Format(DateTimeLayout)) -} - -func (e RunningEntry) FileName() string { - return "active" -} - -func (e RunningEntry) FullPath(group Group) string { - return path.Join(group.FullPath(), e.FileName()) -} - -func (e RunningEntry) Exists(group Group) bool { - if _, err := os.Stat(e.FullPath(group)); !os.IsNotExist(err) { - return true - } - return false -} - -func (e RunningEntry) Stop(stop time.Time) (FinalEntry, error) { - return NewFinalEntry(e.Start, stop) -} - -func (e RunningEntry) Duration() time.Duration { - return time.Since(e.Start) -} diff --git a/tme/final_entry.go b/tme/final_entry.go @@ -0,0 +1,71 @@ +package tme + +import ( + "errors" + "fmt" + "os" + "path" + "strings" + "time" +) + +type FinalEntry struct { + Start time.Time + Stop time.Time +} + +func NewFinalEntry(start time.Time, stop time.Time) (FinalEntry, error) { + if start.After(stop) { + return FinalEntry{}, errors.New("duration must be positive") + } + + return FinalEntry{ + Start: start, + Stop: stop, + }, nil +} + +func NewFinalEntryFromPath(entryPath string, entryTime *Time) (FinalEntry, error) { + if _, err := os.Stat(entryPath); os.IsNotExist(err) { + return FinalEntry{}, err + } + + data, err := os.ReadFile(entryPath) + if err != nil { + return FinalEntry{}, err + } + + // TODO(tms) 11.11.22: format check + + lines := strings.Split(string(data), "\n") + start, _ := entryTime.ParseEntry(lines[0]) + stop, _ := entryTime.ParseEntry(lines[1]) + + return FinalEntry{ + Start: start, + Stop: stop, + }, nil +} + +func (e FinalEntry) Data() string { + return fmt.Sprintf("%s\n%s\n", e.Start.Format(DataTimeLayout), e.Stop.Format(DataTimeLayout)) +} + +func (e FinalEntry) FileName() string { + return strings.Join([]string{e.Start.Format(FileNameLayout), e.Stop.Format(FileNameLayout)}, "_") +} + +func (e FinalEntry) FullPath(group Group) string { + return path.Join(group.FullPath(), e.FileName()) +} + +func (e FinalEntry) Exists(group Group) bool { + if _, err := os.Stat(e.FullPath(group)); !os.IsNotExist(err) { + return true + } + return false +} + +func (e FinalEntry) Duration() time.Duration { + return e.Stop.Sub(e.Start) +} diff --git a/tme/running_entry.go b/tme/running_entry.go @@ -0,0 +1,65 @@ +package tme + +import ( + "fmt" + "os" + "path" + "strings" + "time" +) + +type RunningEntry struct { + Start time.Time +} + +func NewRunningEntry(start time.Time) RunningEntry { + return RunningEntry{ + Start: start, + } +} + +func NewRunningEntryFromPath(entryPath string, entryTime *Time) (RunningEntry, error) { + if _, err := os.Stat(entryPath); os.IsNotExist(err) { + return RunningEntry{}, err + } + + data, err := os.ReadFile(entryPath) + if err != nil { + return RunningEntry{}, err + } + + firstLine := strings.Split(string(data), "\n")[0] + start, _ := entryTime.ParseEntry(firstLine) + + return RunningEntry{ + Start: start, + }, nil + +} + +func (e RunningEntry) Data() string { + return fmt.Sprintf("%s\n", e.Start.Format(DataTimeLayout)) +} + +func (e RunningEntry) FileName() string { + return "active" +} + +func (e RunningEntry) FullPath(group Group) string { + return path.Join(group.FullPath(), e.FileName()) +} + +func (e RunningEntry) Exists(group Group) bool { + if _, err := os.Stat(e.FullPath(group)); !os.IsNotExist(err) { + return true + } + return false +} + +func (e RunningEntry) Stop(stop time.Time) (FinalEntry, error) { + return NewFinalEntry(e.Start, stop) +} + +func (e RunningEntry) Duration() time.Duration { + return time.Since(e.Start) +} diff --git a/tme/time.go b/tme/time.go @@ -4,8 +4,9 @@ import "time" const ( TimeLayout = "15:04" + DateTimeLayout = "15:04 02/01/2006" FileNameLayout = "0601021504" - DateTimeLayout = time.RFC3339 + DataTimeLayout = time.RFC3339 ) type Time struct { @@ -31,7 +32,7 @@ func (et *Time) ParseArg(raw string) (time.Time, error) { } func (et *Time) ParseEntry(raw string) (time.Time, error) { - t, err := time.Parse(DateTimeLayout, raw) + t, err := time.Parse(DataTimeLayout, raw) return time.Date( t.Year(), t.Month(), @@ -43,7 +44,3 @@ func (et *Time) ParseEntry(raw string) (time.Time, error) { et.context.Location(), ), err } - -func (et *Time) Duration(start time.Time, stop time.Time) time.Duration { - return start.Sub(stop) -}