package main import ( "time" "github.com/pborman/uuid" ) type Timer struct { Uuid string `json:"uuid"` Start time.Time `json:"start"` End time.Time `json:"end"` Tags []string `json:"tags"` Notes string `json:"notes"` Billed bool `json:"billed"` } // NewTimer returns a new timer with the given start and end func NewTimer(st, end time.Time) *Timer { ret := Timer{ Uuid: uuid.New(), Start: st, End: end, } return &ret } // GetUUID returns the uuid of the timer func (t *Timer) GetUUID() string { return t.Uuid } // GetStart returns the start time of the timer func (t *Timer) GetStart() time.Time { return t.Start } // SetStart sets the starting time of the timer func (t *Timer) SetStart(st time.Time) { t.Start = st } // GetEnd returns the end time of the timer func (t *Timer) GetEnd() time.Time { return t.End } // SetEnd sets the ending time of the timer func (t *Timer) SetEnd(end time.Time) { t.End = end } // IsActive returns if the timer is still active func (t *Timer) IsActive() bool { return time.Now().After(t.Start) && t.End.IsZero() } // SetTags sets the timer's tags func (t *Timer) SetTags(tags []string) { t.Tags = tags } // GetTags returns all of the tags for the timer func (t *Timer) GetTags() []string { return t.Tags } // AddTag adds the given tag to the timer func (t *Timer) AddTag(tg string) { for _, v := range t.Tags { if v == tg { return } } t.Tags = append(t.Tags, tg) } // HasTag returns if the timer has the given tag func (t *Timer) HasTag(s string) bool { for _, v := range t.Tags { if v == s { return true } } return false } // RemoveTag will remove the given tag from the timer func (t *Timer) RemoveTag(tg string) { var tgs []string for _, v := range t.Tags { if v != tg { tgs = append(tgs, v) } } t.Tags = tgs } // SetNotes sets the timer's notes to the given string func (t *Timer) SetNotes(nt string) { t.Notes = nt } // StartsToday returns if the timer's end time is today func (t *Timer) StartsToday() bool { currTime := time.Now() dur := int64(currTime.Hour())*int64(time.Hour) + int64(currTime.Minute())*int64(time.Minute) return int64(time.Since(t.GetStart())) < dur } // EndsToday returns if the timer's end time is today func (t *Timer) EndsToday() bool { currTime := time.Now() dur := int64(currTime.Hour())*int64(time.Hour) + int64(currTime.Minute())*int64(time.Minute) return int64(time.Since(t.GetEnd())) < dur } // IsRunning returns if the timer is still running func (t *Timer) IsRunning() bool { return t.GetEnd().IsZero() } // IsBillable checks if any of the tags on the timer are flagged as billable func (t *Timer) IsBillable() bool { m, err := LoadMetadata() if err != nil { return false } for _, v := range m.GetTags(t.Tags) { if v.Billable { return true } } return false } // String formats a string of the time entry func (t *Timer) String() string { var ret string ret = t.GetStart().Format(time.RFC3339) if !t.GetEnd().IsZero() { ret += " - " + t.GetEnd().Format(time.RFC3339) } if len(t.GetTags()) > 0 { ret += " [ " for _, v := range t.GetTags() { ret += v + " " } ret += "]" } if t.GetEnd().IsZero() { ret += " Running" } return ret } func (t *Timer) FriendlyString() string { var ret string var end string if t.StartsToday() { ret = t.GetStart().Format("15:04 - ") end = "**:**" } else { ret = t.GetStart().Format("2006/01/02 15:04:05 - ") end = "**:**:**" } if !t.GetEnd().IsZero() { if t.EndsToday() { end = t.GetEnd().Format("15:04") } else { end = t.GetEnd().Format("2006/01/02 15:04:05") } } ret += end if len(t.GetTags()) > 0 { ret += " [ " for _, v := range t.GetTags() { ret += v + " " } ret += "]" } return ret } func (t *Timer) InferDetailString() string { diffEnd := time.Now() if !t.GetEnd().IsZero() { diffEnd = t.GetEnd() } if int(diffEnd.Sub(t.GetStart())) >= (int(time.Hour) * diffEnd.Hour()) { return t.LongDetailString() } return t.DetailString() } func (t *Timer) DetailString() string { ret := t.GetStart().Format("15:04") + " - " if t.GetEnd().IsZero() { ret += "**:** (" + padLeft(sinceToString(t.GetStart()), len("00h 00m 00s")) + ") " } else { ret += t.GetEnd().Format("15:04") + " (" + padLeft(diffToString(t.GetStart(), t.GetEnd()), len("00h 00m 00s")) + ") " } if len(t.GetTags()) > 0 { ret += " [ " for _, v := range t.GetTags() { ret += v + " " } ret += "] " } return ret } func (t *Timer) LongDetailString() string { ret := t.GetStart().Format(time.Stamp) if t.GetEnd().IsZero() { ret += " (" + padLeft(sinceToString(t.GetStart()), len("0000y 00m 00d 00h 00m 00s")) + ") " } else { ret += " (" + padLeft(diffToString(t.GetStart(), t.GetEnd()), len("0000y 00m 00d 00h 00m 00s")) + ") " } if len(t.GetTags()) > 0 { ret += " [ " for _, v := range t.GetTags() { ret += v + " " } ret += "] " } return ret }