bugfix wunderground reporting
This commit is contained in:
@@ -27,7 +27,9 @@ type Latest struct {
|
||||
|
||||
// rolling sums built from "rain increment" values (mm)
|
||||
rainIncs []rainIncPoint // last 1h
|
||||
dailyIncs []rainIncPoint // since midnight (or since start; we’ll trim daily by midnight)
|
||||
dailyIncs []rainIncPoint // since midnight in rainDayLoc (or since start; trimmed each update)
|
||||
|
||||
rainDayLoc *time.Location
|
||||
}
|
||||
|
||||
type rainIncPoint struct {
|
||||
@@ -35,6 +37,15 @@ type rainIncPoint struct {
|
||||
mm float64 // incremental rainfall at this timestamp (mm)
|
||||
}
|
||||
|
||||
func NewLatest(rainDayLoc *time.Location) *Latest {
|
||||
if rainDayLoc == nil {
|
||||
rainDayLoc = time.Local
|
||||
}
|
||||
return &Latest{
|
||||
rainDayLoc: rainDayLoc,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Latest) Update(ts time.Time, p *WS90Payload) {
|
||||
l.mu.Lock()
|
||||
defer l.mu.Unlock()
|
||||
@@ -49,9 +60,9 @@ func (l *Latest) Update(ts time.Time, p *WS90Payload) {
|
||||
cutoff := ts.Add(-1 * time.Hour)
|
||||
l.rainIncs = trimBefore(l.rainIncs, cutoff)
|
||||
|
||||
// Track daily increments: trim before local midnight
|
||||
// Track daily increments: trim before midnight in configured rain day timezone.
|
||||
l.dailyIncs = append(l.dailyIncs, rainIncPoint{ts: ts, mm: inc})
|
||||
midnight := localMidnight(ts)
|
||||
midnight := l.rainDayMidnight(ts)
|
||||
l.dailyIncs = trimBefore(l.dailyIncs, midnight)
|
||||
}
|
||||
|
||||
@@ -68,10 +79,13 @@ func trimBefore(a []rainIncPoint, cutoff time.Time) []rainIncPoint {
|
||||
return a
|
||||
}
|
||||
|
||||
// localMidnight returns midnight in the local timezone of the *process*.
|
||||
// If you want a specific timezone (e.g. Australia/Sydney) we can wire that in later.
|
||||
func localMidnight(t time.Time) time.Time {
|
||||
lt := t.Local()
|
||||
// rainDayMidnight returns midnight in the configured rain day timezone.
|
||||
func (l *Latest) rainDayMidnight(t time.Time) time.Time {
|
||||
loc := l.rainDayLoc
|
||||
if loc == nil {
|
||||
loc = time.Local
|
||||
}
|
||||
lt := t.In(loc)
|
||||
return time.Date(lt.Year(), lt.Month(), lt.Day(), 0, 0, 0, 0, lt.Location())
|
||||
}
|
||||
|
||||
|
||||
50
internal/mqttingest/latest_test.go
Normal file
50
internal/mqttingest/latest_test.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package mqttingest
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestLatestDailyRainUsesConfiguredTimezone(t *testing.T) {
|
||||
loc, err := time.LoadLocation("Australia/Sydney")
|
||||
if err != nil {
|
||||
t.Fatalf("load location: %v", err)
|
||||
}
|
||||
|
||||
l := NewLatest(loc)
|
||||
|
||||
// Crosses UTC midnight but remains the same local day in Sydney (UTC+11 during DST).
|
||||
l.Update(time.Date(2026, time.January, 14, 22, 0, 0, 0, time.UTC), &WS90Payload{RainMM: 0})
|
||||
l.Update(time.Date(2026, time.January, 14, 23, 30, 0, 0, time.UTC), &WS90Payload{RainMM: 2})
|
||||
l.Update(time.Date(2026, time.January, 15, 0, 5, 0, 0, time.UTC), &WS90Payload{RainMM: 2})
|
||||
|
||||
snap, ok := l.Snapshot()
|
||||
if !ok {
|
||||
t.Fatal("expected snapshot")
|
||||
}
|
||||
if snap.DailyRainMM != 2 {
|
||||
t.Fatalf("expected daily rain 2.0mm, got %.2fmm", snap.DailyRainMM)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLatestDailyRainResetsAtConfiguredLocalMidnight(t *testing.T) {
|
||||
loc, err := time.LoadLocation("Australia/Sydney")
|
||||
if err != nil {
|
||||
t.Fatalf("load location: %v", err)
|
||||
}
|
||||
|
||||
l := NewLatest(loc)
|
||||
|
||||
// Crosses local midnight in Sydney (00:00 local == 13:00 UTC during DST).
|
||||
l.Update(time.Date(2026, time.January, 15, 12, 30, 0, 0, time.UTC), &WS90Payload{RainMM: 0})
|
||||
l.Update(time.Date(2026, time.January, 15, 12, 50, 0, 0, time.UTC), &WS90Payload{RainMM: 1})
|
||||
l.Update(time.Date(2026, time.January, 15, 13, 10, 0, 0, time.UTC), &WS90Payload{RainMM: 1})
|
||||
|
||||
snap, ok := l.Snapshot()
|
||||
if !ok {
|
||||
t.Fatal("expected snapshot")
|
||||
}
|
||||
if snap.DailyRainMM != 0 {
|
||||
t.Fatalf("expected daily rain reset after local midnight; got %.2fmm", snap.DailyRainMM)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user