Commit c637e6cf authored by Ethan0x0000's avatar Ethan0x0000
Browse files

fix: use half-open date ranges for DST-safe usage queries

Replace t.Add(24*time.Hour - time.Nanosecond) with t.AddDate(0, 0, 1) and use SQL < instead of <= for end-of-day boundaries. This avoids edge-case misses around DST transitions.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode

)
Co-authored-by: default avatarSisyphus <clio-agent@sisyphuslabs.ai>
parent d3a9f5bb
...@@ -159,8 +159,8 @@ func (h *UsageHandler) List(c *gin.Context) { ...@@ -159,8 +159,8 @@ func (h *UsageHandler) List(c *gin.Context) {
response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD") response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD")
return return
} }
// Set end time to end of day // Use half-open range [start, end), move to next calendar day start (DST-safe).
t = t.Add(24*time.Hour - time.Nanosecond) t = t.AddDate(0, 0, 1)
endTime = &t endTime = &t
} }
...@@ -285,7 +285,8 @@ func (h *UsageHandler) Stats(c *gin.Context) { ...@@ -285,7 +285,8 @@ func (h *UsageHandler) Stats(c *gin.Context) {
response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD") response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD")
return return
} }
endTime = endTime.Add(24*time.Hour - time.Nanosecond) // 与 SQL 条件 created_at < end 对齐,使用次日 00:00 作为上边界(DST-safe)。
endTime = endTime.AddDate(0, 0, 1)
} else { } else {
period := c.DefaultQuery("period", "today") period := c.DefaultQuery("period", "today")
switch period { switch period {
......
...@@ -114,8 +114,8 @@ func (h *UsageHandler) List(c *gin.Context) { ...@@ -114,8 +114,8 @@ func (h *UsageHandler) List(c *gin.Context) {
response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD") response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD")
return return
} }
// Set end time to end of day // Use half-open range [start, end), move to next calendar day start (DST-safe).
t = t.Add(24*time.Hour - time.Nanosecond) t = t.AddDate(0, 0, 1)
endTime = &t endTime = &t
} }
...@@ -227,8 +227,8 @@ func (h *UsageHandler) Stats(c *gin.Context) { ...@@ -227,8 +227,8 @@ func (h *UsageHandler) Stats(c *gin.Context) {
response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD") response.BadRequest(c, "Invalid end_date format, use YYYY-MM-DD")
return return
} }
// 设置结束时间为当天结束 // 与 SQL 条件 created_at < end 对齐,使用次日 00:00 作为上边界(DST-safe)。
endTime = endTime.Add(24*time.Hour - time.Nanosecond) endTime = endTime.AddDate(0, 0, 1)
} else { } else {
// 使用 period 参数 // 使用 period 参数
period := c.DefaultQuery("period", "today") period := c.DefaultQuery("period", "today")
......
...@@ -3004,7 +3004,7 @@ func (r *usageLogRepository) GetGlobalStats(ctx context.Context, startTime, endT ...@@ -3004,7 +3004,7 @@ func (r *usageLogRepository) GetGlobalStats(ctx context.Context, startTime, endT
COALESCE(SUM(actual_cost), 0) as total_actual_cost, COALESCE(SUM(actual_cost), 0) as total_actual_cost,
COALESCE(AVG(duration_ms), 0) as avg_duration_ms COALESCE(AVG(duration_ms), 0) as avg_duration_ms
FROM usage_logs FROM usage_logs
WHERE created_at >= $1 AND created_at <= $2 WHERE created_at >= $1 AND created_at < $2
` `
stats := &UsageStats{} stats := &UsageStats{}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment