fix: make summaries display actual data range or requested interval if no data present

fix: use unix era start time in wakatime compat endpoints (resolve #843)
This commit is contained in:
Ferdinand Mütsch
2025-09-16 00:40:48 +02:00
parent 849d7a8996
commit 3154cd8519
6 changed files with 1225 additions and 1210 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -73,7 +73,7 @@ func ResolveIntervalTZ(interval *models.IntervalKey, tz *time.Location, startOfW
case models.IntervalPast12Months: case models.IntervalPast12Months:
from = now.AddDate(0, -12, 0) from = now.AddDate(0, -12, 0)
case models.IntervalAny: case models.IntervalAny:
from = time.Time{} from = utils.UnixEra()
default: default:
err = errors.New("invalid interval") err = errors.New("invalid interval")
} }

View File

@@ -10,6 +10,8 @@ import (
"github.com/muety/wakapi/models/types" "github.com/muety/wakapi/models/types"
routeutils "github.com/muety/wakapi/routes/utils" routeutils "github.com/muety/wakapi/routes/utils"
"github.com/muety/wakapi/services" "github.com/muety/wakapi/services"
"github.com/muety/wakapi/utils"
"net/http" "net/http"
"time" "time"
) )
@@ -63,7 +65,7 @@ func (h *AllTimeHandler) Get(w http.ResponseWriter, r *http.Request) {
func (h *AllTimeHandler) loadUserSummary(user *models.User, filters *models.Filters) (*models.Summary, error, int) { func (h *AllTimeHandler) loadUserSummary(user *models.User, filters *models.Filters) (*models.Summary, error, int) {
summaryParams := &models.SummaryParams{ summaryParams := &models.SummaryParams{
From: time.Time{}, From: utils.UnixEra(),
To: time.Now(), To: time.Now(),
User: user, User: user,
Recompute: false, Recompute: false,

View File

@@ -150,6 +150,11 @@ func (srv *SummaryService) Retrieve(from, to time.Time, user *models.User, filte
// prevent 0001-01-01T00:00:00 caused by empty "pre" missing interval, see https://github.com/muety/wakapi/issues/843 // prevent 0001-01-01T00:00:00 caused by empty "pre" missing interval, see https://github.com/muety/wakapi/issues/843
summary.FromTime = models.CustomTime(condition.Ternary(summary.FromTime.T().Before(from), from, summary.FromTime.T())) summary.FromTime = models.CustomTime(condition.Ternary(summary.FromTime.T().Before(from), from, summary.FromTime.T()))
if summary.TotalTime() == 0 {
summary.FromTime = models.CustomTime(from)
summary.ToTime = models.CustomTime(to)
}
if filters != nil && filters.CountDistinctTypes() == 1 && filters.SelectFilteredOnly { if filters != nil && filters.CountDistinctTypes() == 1 && filters.SelectFilteredOnly {
filter := filters.OneOrEmpty() filter := filters.OneOrEmpty()
summary.KeepOnly(map[uint8]bool{filter.Entity: true}).ApplyFilter(filter) summary.KeepOnly(map[uint8]bool{filter.Entity: true}).ApplyFilter(filter)
@@ -365,11 +370,12 @@ func (srv *SummaryService) mergeSummaries(summaries []*models.Summary) (*models.
return nil, errors.New("users don't match") return nil, errors.New("users don't match")
} }
if s.FromTime.T().Before(minTime) { totalTime := s.TotalTime()
if s.FromTime.T().Before(minTime) && totalTime > 0 { // only consider non-empty summaries
minTime = s.FromTime.T() minTime = s.FromTime.T()
} }
if s.ToTime.T().After(maxTime) && totalTime > 0 { // only consider non-empty summaries
if s.ToTime.T().After(maxTime) {
maxTime = s.ToTime.T() maxTime = s.ToTime.T()
} }
@@ -388,7 +394,7 @@ func (srv *SummaryService) mergeSummaries(summaries []*models.Summary) (*models.
} }
finalSummary.FromTime = models.CustomTime(minTime) finalSummary.FromTime = models.CustomTime(minTime)
finalSummary.ToTime = models.CustomTime(maxTime) finalSummary.ToTime = models.CustomTime(condition.Ternary(maxTime.Before(minTime), minTime, maxTime))
return finalSummary, nil return finalSummary, nil
} }

View File

@@ -462,8 +462,8 @@ func (suite *SummaryServiceTestSuite) TestSummaryService_Retrieve_DateRange() {
assert.Nil(suite.T(), err) assert.Nil(suite.T(), err)
assert.NotNil(suite.T(), result) assert.NotNil(suite.T(), result)
assert.Equal(suite.T(), from, result.FromTime.T()) // requested from date assert.Equal(suite.T(), summaries[0].FromTime.T(), result.FromTime.T()) // actual first data date
assert.Equal(suite.T(), to, result.ToTime.T()) // requested to date assert.Equal(suite.T(), summaries[0].ToTime.T(), result.ToTime.T()) // actual last data date
suite.DurationService.AssertNumberOfCalls(suite.T(), "Get", 2) suite.DurationService.AssertNumberOfCalls(suite.T(), "Get", 2)
} }

View File

@@ -7,6 +7,10 @@ import (
"github.com/duke-git/lancet/v2/datetime" "github.com/duke-git/lancet/v2/datetime"
) )
func UnixEra() time.Time {
return time.Unix(0, 0)
}
func MustParseTime(layout, value string) time.Time { func MustParseTime(layout, value string) time.Time {
t, _ := time.Parse(layout, value) t, _ := time.Parse(layout, value)
return t return t