From 778ab8854e53b316d744b1bdddeda793b91d48fc Mon Sep 17 00:00:00 2001 From: Dhruv Thakur Date: Thu, 16 Jan 2025 17:11:02 +0100 Subject: [PATCH] chore: store UTC timestamps in the database Timestamps will be saved in UTC format, and shown in the user's local timezone via the TUI. --- internal/persistence/queries.go | 30 ++++++++++++++++++++---------- internal/ui/cmds.go | 14 +++++++------- internal/ui/handle.go | 22 ++++++++++------------ internal/ui/msgs.go | 4 ++-- internal/ui/update.go | 3 +-- 5 files changed, 40 insertions(+), 33 deletions(-) diff --git a/internal/persistence/queries.go b/internal/persistence/queries.go index e291632..1e7718e 100644 --- a/internal/persistence/queries.go +++ b/internal/persistence/queries.go @@ -53,6 +53,10 @@ ORDER by end_ts DESC; if err != nil { return nil, err } + entry.BeginTS = entry.BeginTS.Local() + if entry.EndTS != nil { + *entry.EndTS = entry.EndTS.Local() + } logEntries = append(logEntries, entry) } @@ -63,7 +67,7 @@ ORDER by end_ts DESC; return logEntries, nil } -func InsertNewWLInDB(db *sql.DB, issueKey string, beginTs time.Time) error { +func InsertNewWLInDB(db *sql.DB, issueKey string, beginTS time.Time) error { stmt, err := db.Prepare(` INSERT INTO issue_log (issue_key, begin_ts, active, synced) VALUES (?, ?, ?, ?); @@ -73,7 +77,7 @@ func InsertNewWLInDB(db *sql.DB, issueKey string, beginTs time.Time) error { } defer stmt.Close() - _, err = stmt.Exec(issueKey, beginTs, true, 0) + _, err = stmt.Exec(issueKey, beginTS.UTC(), true, 0) if err != nil { return err } @@ -81,7 +85,7 @@ func InsertNewWLInDB(db *sql.DB, issueKey string, beginTs time.Time) error { return nil } -func UpdateActiveWLInDB(db *sql.DB, issueKey, comment string, beginTs, endTs time.Time) error { +func UpdateActiveWLInDB(db *sql.DB, issueKey, comment string, beginTS, endTS time.Time) error { stmt, err := db.Prepare(` UPDATE issue_log SET active = 0, @@ -96,7 +100,7 @@ AND active = 1; } defer stmt.Close() - _, err = stmt.Exec(beginTs, endTs, comment, issueKey) + _, err = stmt.Exec(beginTS.UTC(), endTS.UTC(), comment, issueKey) if err != nil { return err } @@ -104,7 +108,7 @@ AND active = 1; return nil } -func StopCurrentlyActiveWLInDB(db *sql.DB, issueKey string, endTs time.Time) error { +func StopCurrentlyActiveWLInDB(db *sql.DB, issueKey string, endTS time.Time) error { stmt, err := db.Prepare(` UPDATE issue_log SET active = 0, @@ -117,7 +121,7 @@ AND active = 1; } defer stmt.Close() - _, err = stmt.Exec(endTs, issueKey) + _, err = stmt.Exec(endTS.UTC(), issueKey) if err != nil { return err } @@ -152,6 +156,10 @@ ORDER by end_ts DESC; if err != nil { return nil, err } + entry.BeginTS = entry.BeginTS.Local() + if entry.EndTS != nil { + *entry.EndTS = entry.EndTS.Local() + } logEntries = append(logEntries, entry) } @@ -187,6 +195,8 @@ ORDER by end_ts DESC LIMIT 30; if err != nil { return nil, err } + entry.BeginTS = entry.BeginTS.Local() + entry.EndTS = entry.EndTS.Local() logEntries = append(logEntries, entry) } @@ -296,7 +306,7 @@ func QuickSwitchActiveWLInDB(db *sql.DB, currentIssue, selectedIssue string, cur return InsertNewWLInDB(db, selectedIssue, currentTime) } -func UpdateActiveWLBeginTSInDB(db *sql.DB, beginTs time.Time) error { +func UpdateActiveWLBeginTSInDB(db *sql.DB, beginTS time.Time) error { stmt, err := db.Prepare(` UPDATE issue_log SET begin_ts=? @@ -307,7 +317,7 @@ WHERE active is true; } defer stmt.Close() - _, err = stmt.Exec(beginTs, true) + _, err = stmt.Exec(beginTS.UTC(), true) if err != nil { return err } @@ -315,7 +325,7 @@ WHERE active is true; return nil } -func UpdateActiveWLBeginTSAndCommentInDB(db *sql.DB, beginTs time.Time, comment string) error { +func UpdateActiveWLBeginTSAndCommentInDB(db *sql.DB, beginTS time.Time, comment string) error { stmt, err := db.Prepare(` UPDATE issue_log SET begin_ts=?, @@ -327,7 +337,7 @@ WHERE active is true; } defer stmt.Close() - _, err = stmt.Exec(beginTs, comment, true) + _, err = stmt.Exec(beginTS.UTC(), comment, true) if err != nil { return err } diff --git a/internal/ui/cmds.go b/internal/ui/cmds.go index 50e9c61..67f414a 100644 --- a/internal/ui/cmds.go +++ b/internal/ui/cmds.go @@ -17,7 +17,7 @@ import ( var errWorklogsEndTSIsEmpty = errors.New("worklog's end timestamp is empty") -func toggleTracking(db *sql.DB, selectedIssue string, beginTs, endTs time.Time, comment string) tea.Cmd { +func toggleTracking(db *sql.DB, selectedIssue string, beginTS, endTS time.Time, comment string) tea.Cmd { return func() tea.Msg { row := db.QueryRow(` SELECT issue_key @@ -39,7 +39,7 @@ LIMIT 1 switch trackStatus { case trackingInactive: - err = pers.InsertNewWLInDB(db, selectedIssue, beginTs) + err = pers.InsertNewWLInDB(db, selectedIssue, beginTS) if err != nil { return trackingToggledInDB{err: err} } else { @@ -47,7 +47,7 @@ LIMIT 1 } default: - err := pers.UpdateActiveWLInDB(db, activeIssue, comment, beginTs, endTs) + err := pers.UpdateActiveWLInDB(db, activeIssue, comment, beginTS, endTS) if err != nil { return trackingToggledInDB{err: err} } else { @@ -127,7 +127,7 @@ WHERE ID = ?; } defer stmt.Close() - _, err = stmt.Exec(beginTS, endTS, comment, rowID) + _, err = stmt.Exec(beginTS.UTC(), endTS.UTC(), comment, rowID) if err != nil { return wLUpdatedInDB{rowID, issueKey, err} } @@ -146,9 +146,9 @@ ORDER BY begin_ts DESC LIMIT 1 `) var activeIssue string - var beginTs time.Time + var beginTS time.Time var comment *string - err := row.Scan(&activeIssue, &beginTs, &comment) + err := row.Scan(&activeIssue, &beginTS, &comment) if err == sql.ErrNoRows { return activeWLFetchedFromDB{activeIssue: activeIssue} } @@ -156,7 +156,7 @@ LIMIT 1 return activeWLFetchedFromDB{err: err} } - return activeWLFetchedFromDB{activeIssue: activeIssue, beginTs: beginTs, comment: comment} + return activeWLFetchedFromDB{activeIssue: activeIssue, beginTS: beginTS, comment: comment} }) } diff --git a/internal/ui/handle.go b/internal/ui/handle.go index 9584e53..ac58284 100644 --- a/internal/ui/handle.go +++ b/internal/ui/handle.go @@ -15,7 +15,7 @@ import ( ) func (m *Model) getCmdToUpdateActiveWL() tea.Cmd { - beginTS, err := time.ParseInLocation(string(timeFormat), m.trackingInputs[entryBeginTS].Value(), time.Local) + beginTS, err := time.ParseInLocation(timeFormat, m.trackingInputs[entryBeginTS].Value(), time.Local) if err != nil { m.message = err.Error() return nil @@ -32,14 +32,14 @@ func (m *Model) getCmdToUpdateActiveWL() tea.Cmd { } func (m *Model) getCmdToSaveActiveWL() tea.Cmd { - beginTS, err := time.ParseInLocation(string(timeFormat), m.trackingInputs[entryBeginTS].Value(), time.Local) + beginTS, err := time.ParseInLocation(timeFormat, m.trackingInputs[entryBeginTS].Value(), time.Local) if err != nil { m.message = err.Error() return nil } m.activeIssueBeginTS = beginTS.Local() - endTS, err := time.ParseInLocation(string(timeFormat), m.trackingInputs[entryEndTS].Value(), time.Local) + endTS, err := time.ParseInLocation(timeFormat, m.trackingInputs[entryEndTS].Value(), time.Local) if err != nil { m.message = err.Error() return nil @@ -66,20 +66,18 @@ func (m *Model) getCmdToSaveActiveWL() tea.Cmd { ) } -func (m *Model) getCmdToSaveManualWL() tea.Cmd { - beginTS, err := time.ParseInLocation(string(timeFormat), m.trackingInputs[entryBeginTS].Value(), time.Local) +func (m *Model) getCmdToSaveOrUpdateWL() tea.Cmd { + beginTS, err := time.ParseInLocation(timeFormat, m.trackingInputs[entryBeginTS].Value(), time.Local) if err != nil { m.message = err.Error() return nil } - beginTS = beginTS.Local() - endTS, err := time.ParseInLocation(string(timeFormat), m.trackingInputs[entryEndTS].Value(), time.Local) + endTS, err := time.ParseInLocation(timeFormat, m.trackingInputs[entryEndTS].Value(), time.Local) if err != nil { m.message = err.Error() return nil } - endTS = endTS.Local() if endTS.Sub(beginTS).Seconds() <= 0 { m.message = "time spent needs to be greater than zero" @@ -410,7 +408,7 @@ func (m *Model) getCmdToStartTracking() tea.Cmd { } m.changesLocked = true - m.activeIssueBeginTS = time.Now() + m.activeIssueBeginTS = time.Now().Truncate(time.Second) return toggleTracking(m.db, issue.IssueKey, m.activeIssueBeginTS, @@ -622,7 +620,7 @@ func (m *Model) handleActiveWLFetchedFromDBMsg(msg activeWLFetchedFromDB) { } else { m.lastChange = insertChange activeIssue, ok := m.issueMap[m.activeIssue] - m.activeIssueBeginTS = msg.beginTs + m.activeIssueBeginTS = msg.beginTS m.activeIssueComment = msg.comment if ok { activeIssue.TrackingActive = true @@ -762,14 +760,14 @@ func (m *Model) handleActiveWLSwitchedInDBMsg(msg activeWLSwitchedInDB) { currentActiveIssue.TrackingActive = true } m.activeIssue = msg.currentActiveIssue - m.activeIssueBeginTS = msg.beginTs + m.activeIssueBeginTS = msg.beginTS m.activeIssueComment = nil } func (m *Model) shiftTime(direction timeShiftDirection, duration timeShiftDuration) error { if m.activeView == editActiveWLView || m.activeView == saveActiveWLView || m.activeView == wlEntryView { if m.trackingFocussedField == entryBeginTS || m.trackingFocussedField == entryEndTS { - ts, err := time.ParseInLocation(string(timeFormat), m.trackingInputs[m.trackingFocussedField].Value(), time.Local) + ts, err := time.ParseInLocation(timeFormat, m.trackingInputs[m.trackingFocussedField].Value(), time.Local) if err != nil { return err } diff --git a/internal/ui/msgs.go b/internal/ui/msgs.go index 8e42f2d..ba3f068 100644 --- a/internal/ui/msgs.go +++ b/internal/ui/msgs.go @@ -17,7 +17,7 @@ type trackingToggledInDB struct { type activeWLSwitchedInDB struct { lastActiveIssue string currentActiveIssue string - beginTs time.Time + beginTS time.Time err error } @@ -44,7 +44,7 @@ type wLUpdatedInDB struct { type activeWLFetchedFromDB struct { activeIssue string - beginTs time.Time + beginTS time.Time comment *string err error } diff --git a/internal/ui/update.go b/internal/ui/update.go index 1eea4c2..299cc33 100644 --- a/internal/ui/update.go +++ b/internal/ui/update.go @@ -35,7 +35,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { saveCmd = m.getCmdToSaveActiveWL() ret = true case wlEntryView: - saveCmd = m.getCmdToSaveManualWL() + saveCmd = m.getCmdToSaveOrUpdateWL() ret = true } if saveCmd != nil { @@ -141,7 +141,6 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } case wLView: m.handleRequestToUpdateSavedWL() - } case "u":