diff --git a/internal/forecast/caiyun.go b/internal/forecast/caiyun.go index fca76bc..96fc889 100644 --- a/internal/forecast/caiyun.go +++ b/internal/forecast/caiyun.go @@ -65,7 +65,10 @@ func RunCaiyunFetch(ctx context.Context, token string) error { issuedAt := time.Now().In(loc) startHour := issuedAt.Truncate(time.Hour) - targets := []time.Time{startHour.Add(1 * time.Hour), startHour.Add(2 * time.Hour), startHour.Add(3 * time.Hour)} + // 彩云小时接口返回的是“左端点”时刻(例如 13:00 表示 13:00-14:00 区间)。 + // 我们将左端点列表保留为 startHour, startHour+1h, startHour+2h,并在写库时统一 +1h + // 使得 forecast_time 表示区间右端,与实测聚合对齐。 + leftEdges := []time.Time{startHour, startHour.Add(1 * time.Hour), startHour.Add(2 * time.Hour)} for _, s := range stations { if !s.lat.Valid || !s.lon.Valid { @@ -161,27 +164,30 @@ func RunCaiyunFetch(ctx context.Context, token string) error { } } - log.Printf("处理时间点: %v", targets) - for _, ft := range targets { - if v, ok := table[ft]; ok { - log.Printf("写入预报点: station=%s time=%s rain=%.3f temp=%.2f rh=%.1f ws=%.3f wdir=%.1f prob=%.1f pres=%.2f", - s.id, ft.Format(time.RFC3339), v.rain, v.temp, v.rh, v.ws, v.wdir, v.prob, v.pres) - if err := upsertForecastCaiyun(ctx, db, s.id, issuedAt, ft, - int64(v.rain*1000.0), // mm → x1000 - int64(v.temp*100.0), // °C → x100 - int64(v.rh), // % - int64(v.ws*1000.0), // m/s → x1000 - int64(0), // gust: 彩云小时接口无阵风,置0 - int64(v.wdir), // 度 - int64(v.prob), // % - int64(v.pres*100.0), // hPa → x100 - ); err != nil { - log.Printf("写入forecast失败(caiyun) station=%s time=%s err=%v", s.id, ft.Format(time.RFC3339), err) - } else { - log.Printf("写入forecast成功(caiyun) station=%s time=%s", s.id, ft.Format(time.RFC3339)) - } + log.Printf("处理时间点(彩云左端): %v", leftEdges) + for _, left := range leftEdges { + v, ok := table[left] + if !ok { + log.Printf("时间点无数据: %s", left.Format(time.RFC3339)) + continue + } + ft := left.Add(1 * time.Hour) + log.Printf("写入预报点: station=%s forecast_time=%s (source=%s) rain=%.3f temp=%.2f rh=%.1f ws=%.3f wdir=%.1f prob=%.1f pres=%.2f", + s.id, ft.Format(time.RFC3339), left.Format(time.RFC3339), v.rain, v.temp, v.rh, v.ws, v.wdir, v.prob, v.pres) + err := upsertForecastCaiyun(ctx, db, s.id, issuedAt, ft, + int64(v.rain*1000.0), // mm → x1000 + int64(v.temp*100.0), // °C → x100 + int64(v.rh), // % + int64(v.ws*1000.0), // m/s → x1000 + int64(0), // gust: 彩云小时接口无阵风,置0 + int64(v.wdir), // 度 + int64(v.prob), // % + int64(v.pres*100.0), // hPa → x100 + ) + if err != nil { + log.Printf("写入forecast失败(caiyun) station=%s time=%s err=%v", s.id, ft.Format(time.RFC3339), err) } else { - log.Printf("时间点无数据: %s", ft.Format(time.RFC3339)) + log.Printf("写入forecast成功(caiyun) station=%s time=%s", s.id, ft.Format(time.RFC3339)) } } }