1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2026-05-22 10:15:43 +02:00
Files
lazygit/pkg/utils/date.go
T
stk 5761f92e16 Make UnixToDateSmart timezone-deterministic
The "custom time format" test case of TestGetCommitListDisplayStrings failed on
Windows. Root cause: UnixToDateSmart used time.Unix(timestamp, 0), which formats
in process-local time. In tests we pass an explicit 'now' (often UTC), but the
timestamp was rendered in Local, causing one-hour drift on non-UTC machines.

The test tried to work around this by doing os.Setenv("TZ", "UTC"); however,
this only worked on Mac and Linux. On Windows, it has no effect because Windows
uses registry-based timezone configuration, not TZ environment variables.

Change: convert the timestamp into now.Location() before both the same-day
comparison and formatting.

Why this is safe: callers already define the presentation timezone via the 'now'
argument (typically time.Now() in app code, controlled time in tests). This
aligns timestamp rendering with that caller intent and removes dependence on
global TZ state or OS-specific environment variable behavior.

Added regression tests for UTC and UTC+1 to ensure deterministic behavior across
all platforms.
2026-05-02 17:59:27 +02:00

68 lines
1.4 KiB
Go

package utils
import (
"fmt"
"time"
)
func UnixToTimeAgo(timestamp int64) string {
now := time.Now().Unix()
return formatSecondsAgo(now - timestamp)
}
const (
SECONDS_IN_SECOND = 1
SECONDS_IN_MINUTE = 60
SECONDS_IN_HOUR = 3600
SECONDS_IN_DAY = 86400
SECONDS_IN_WEEK = 604800
SECONDS_IN_YEAR = 31536000
SECONDS_IN_MONTH = SECONDS_IN_YEAR / 12
)
type period struct {
label string
secondsInPeriod int64
}
var periods = []period{
{"s", SECONDS_IN_SECOND},
{"m", SECONDS_IN_MINUTE},
{"h", SECONDS_IN_HOUR},
{"d", SECONDS_IN_DAY},
{"w", SECONDS_IN_WEEK},
{"M", SECONDS_IN_MONTH},
{"y", SECONDS_IN_YEAR},
}
func formatSecondsAgo(secondsAgo int64) string {
for i, period := range periods {
if i == 0 {
continue
}
if secondsAgo < period.secondsInPeriod {
return fmt.Sprintf("%d%s",
secondsAgo/periods[i-1].secondsInPeriod,
periods[i-1].label,
)
}
}
return fmt.Sprintf("%d%s",
secondsAgo/periods[len(periods)-1].secondsInPeriod,
periods[len(periods)-1].label,
)
}
// formats the date in a smart way, if the date is today, it will show the time, otherwise it will show the date
func UnixToDateSmart(now time.Time, timestamp int64, longTimeFormat string, shortTimeFormat string) string {
date := time.Unix(timestamp, 0).In(now.Location())
if date.Day() == now.Day() && date.Month() == now.Month() && date.Year() == now.Year() {
return date.Format(shortTimeFormat)
}
return date.Format(longTimeFormat)
}