Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

98 break #100

Merged
merged 6 commits into from
Jun 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions cli/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,18 @@ func statusCommand(t *core.Timetrace) *cobra.Command {
trackedTimeCurrent := defaultString

if report.TrackedTimeCurrent != nil {
trackedTimeCurrent = report.FormatCurrentTime()
trackedTimeCurrent = t.Formatter().FormatCurrentTime(report)
}

rows := [][]string{
{
project,
trackedTimeCurrent,
report.FormatTodayTime(),
t.Formatter().FormatTodayTime(report),
t.Formatter().FormatBreakTime(report),
},
}
out.Table([]string{"Current project", "Worked since start", "Worked today"}, rows, nil)
out.Table([]string{"Current project", "Worked since start", "Worked today", "Breaks"}, rows, nil)
},
}

Expand Down
36 changes: 36 additions & 0 deletions core/formatter.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package core

import (
"fmt"
"time"
)

Expand Down Expand Up @@ -67,3 +68,38 @@ func (f *Formatter) ParseRecordKey(key string) (time.Time, error) {
func (f *Formatter) RecordKey(record *Record) string {
return record.Start.Format(f.RecordKeyLayout())
}

// FormatTodayTime returns the formated string of the total
// time of today follwoing the format convention
func (f *Formatter) FormatTodayTime(report *Report) string {
return f.formatDuration(report.TrackedTimeToday)
}

// FormatCurrentTime returns the formated string of the current
// report time follwoing the format convention
func (f *Formatter) FormatCurrentTime(report *Report) string {
return f.formatDuration(*report.TrackedTimeCurrent)
}

// FormatBreakTime returns the formated string of the total time
// taking breaks today following the format convention
func (f *Formatter) FormatBreakTime(report *Report) string {
return f.formatDuration(report.BreakTimeToday)
}

// formatDuration formats the passed duration into a string.
// The format will be "8h 24min". If the duration is less then 60 secods
// the format will be "0h 0min 12sec".
func (f *Formatter) formatDuration(duration time.Duration) string {

hours := int64(duration.Hours()) % 60
minutes := int64(duration.Minutes()) % 60
secods := int64(duration.Seconds()) % 60

// as by convention if the duarion is < then 60 secods
// return "0h 0min Xsec"
if hours == 0 && minutes == 0 {
return fmt.Sprintf("0h 0min %dsec", secods)
}
return fmt.Sprintf("%dh %dmin", hours, minutes)
}
25 changes: 25 additions & 0 deletions core/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,31 @@ func (t *Timetrace) loadAllRecords(date time.Time) ([]*Record, error) {
return records, nil
}

func (t *Timetrace) loadAllRecordsSortedAscending(date time.Time) ([]*Record, error) {
rknizzle marked this conversation as resolved.
Show resolved Hide resolved
dir := t.fs.RecordDirFromDate(date)

recordFilepaths, err := t.fs.RecordFilepaths(dir, func(a, b string) bool {
timeA, _ := time.Parse(recordLayout, a)
timeB, _ := time.Parse(recordLayout, b)
return timeA.Before(timeB)
})
if err != nil {
return nil, err
}

var records []*Record

for _, recordFilepath := range recordFilepaths {
record, err := t.loadRecord(recordFilepath)
if err != nil {
return nil, err
}
records = append(records, record)
}

return records, nil
}

// LoadLatestRecord loads the youngest record. This may also be a record from
// another day. If there is no latest record, nil and no error will be returned.
func (t *Timetrace) LoadLatestRecord() (*Record, error) {
Expand Down
52 changes: 22 additions & 30 deletions core/timetrace.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package core

import (
"errors"
"fmt"
"io"
"os"
"time"
Expand All @@ -20,6 +19,7 @@ type Report struct {
Current *Record
TrackedTimeCurrent *time.Duration
TrackedTimeToday time.Duration
BreakTimeToday time.Duration
}

// Filesystem represents a filesystem used for storing and loading resources.
Expand Down Expand Up @@ -111,8 +111,14 @@ func (t *Timetrace) Status() (*Report, error) {
return nil, err
}

breakTimeToday, err := t.breakTime(now)
if err != nil {
return nil, err
}

report := &Report{
TrackedTimeToday: trackedTimeToday,
BreakTimeToday: breakTimeToday,
}

// If the latest record has been stopped, there is no active time tracking.
Expand All @@ -131,6 +137,21 @@ func (t *Timetrace) Status() (*Report, error) {
return report, nil
}

func (t *Timetrace) breakTime(date time.Time) (time.Duration, error) {
records, err := t.loadAllRecordsSortedAscending(date)
if err != nil {
return 0, err
}

// add up the time between records
var breakTime time.Duration
for i := 0; i < len(records)-1; i++ {
breakTime += records[i+1].Start.Sub(*records[i].End)
}

return breakTime, nil
}

// Stop stops the time tracking and marks the current record as ended.
func (t *Timetrace) Stop() error {
latestRecord, err := t.LoadLatestRecord()
Expand Down Expand Up @@ -182,35 +203,6 @@ func (t *Timetrace) trackedTime(date time.Time) (time.Duration, error) {
return trackedTime, nil
}

// FormatTodayTime returns the formated string of the total
// time of today follwoing the format convention
func (report *Report) FormatTodayTime() string {
return formatDuration(report.TrackedTimeToday)
}

// FormatCurrentTime returns the formated string of the current
// report time follwoing the format convention
func (report *Report) FormatCurrentTime() string {
return formatDuration(*report.TrackedTimeCurrent)
}

// formatDuration formats the passed duration into a string.
// The format will be "8h 24min". If the duration is less then 60 secods
// the format will be "0h 0min 12sec".
func formatDuration(duration time.Duration) string {

hours := int64(duration.Hours()) % 60
minutes := int64(duration.Minutes()) % 60
secods := int64(duration.Seconds()) % 60

// as by convention if the duarion is < then 60 secods
// return "0h 0min Xsec"
if hours == 0 && minutes == 0 {
return fmt.Sprintf("0h 0min %dsec", secods)
}
return fmt.Sprintf("%dh %dmin", hours, minutes)
}

func (t *Timetrace) isDirEmpty(dir string) (bool, error) {
openedDir, err := os.Open(dir)
if err != nil {
Expand Down