fix: 修正雨量瓦片存储的时区

This commit is contained in:
yarnom 2025-10-14 15:23:33 +08:00
parent 0fd915a2ee
commit 08fa1e8a04
3 changed files with 51 additions and 5 deletions

View File

@ -7,6 +7,7 @@ import (
"os/signal"
"syscall"
"weatherstation/internal/radar"
"weatherstation/internal/rain"
"weatherstation/internal/server"
)
@ -21,6 +22,11 @@ func main() {
log.Fatalf("service-radar start error: %v", err)
}
// Also start CMPA hourly rain scheduler (StoreToDB=true; tiles/dir/url from env inside package)
if err := rain.Start(ctx, rain.Options{StoreToDB: true}); err != nil {
log.Fatalf("service-rain (embedded) start error: %v", err)
}
// Keep process alive until signal
<-ctx.Done()
log.Println("service-radar shutting down")

View File

@ -121,14 +121,23 @@ func runOnce(ctx context.Context, opts Options, loc *time.Location) error {
func downloadAndStoreTile(ctx context.Context, local time.Time, dateStr, hh, mm string, z, y, x int, opts Options) error {
url := fmt.Sprintf("https://image.data.cma.cn/tiles/China/CMPA_RT_China_0P01_HOR-PRE_GISJPG_Tiles/%s/%s/%s/%d/%d/%d.bin", dateStr, hh, mm, z, y, x)
// skip if exists in DB
// skip if exists in DB; dt source configurable (default: local slot time)
dtSource := strings.ToLower(getenvDefault("RAIN_DT_SOURCE", "local")) // local|url
var product string
var dtForKey time.Time
if ref, err := ParseCMPATileURL(url); err == nil {
exists, err := databaseHas(ctx, ref.Product, ref.DT, z, y, x)
product = ref.Product
if dtSource == "url" {
dtForKey = ref.DT
} else {
dtForKey = local
}
exists, err := databaseHas(ctx, product, dtForKey, z, y, x)
if err != nil {
return err
}
if exists {
log.Printf("[rain] skip: already in DB z=%d y=%d x=%d dt(local)=%s url=%s", z, y, x, ref.DT.Format("2006-01-02 15:04"), url)
log.Printf("[rain] skip: already in DB z=%d y=%d x=%d dt(%s)=%s url=%s", z, y, x, dtSource, dtForKey.Format("2006-01-02 15:04"), url)
return nil
}
}
@ -150,10 +159,30 @@ func downloadAndStoreTile(ctx context.Context, local time.Time, dateStr, hh, mm
if rerr != nil {
return fmt.Errorf("read saved tile: %w", rerr)
}
if err := StoreTileBytes(ctx, url, b); err != nil {
// Determine product and dt according to dtSource
if product == "" {
if ref, e := ParseCMPATileURL(url); e == nil {
product = ref.Product
if dtSource == "url" {
dtForKey = ref.DT
} else {
dtForKey = local
}
}
}
if product == "" {
return fmt.Errorf("cannot parse product from url for DB store")
}
if dtForKey.IsZero() {
if dtSource == "url" {
return fmt.Errorf("dt source=url but failed to parse dt")
}
dtForKey = local
}
if err := database.UpsertRainTile(ctx, database.GetDB(), product, dtForKey, z, y, x, 256, 256, b); err != nil {
return fmt.Errorf("store tile db: %w", err)
}
log.Printf("[rain] stored to DB: %s", fname)
log.Printf("[rain] stored to DB: %s (dt=%s, source=%s)", fname, dtForKey.Format("2006-01-02 15:04:05"), dtSource)
}
return nil
}

View File

@ -3,6 +3,8 @@ package rain
import (
"context"
"fmt"
"log"
"os"
"path"
"regexp"
"strconv"
@ -65,6 +67,15 @@ func StoreTileBytes(ctx context.Context, urlOrPath string, data []byte) error {
if err != nil {
return err
}
// 可选:强制 +8 小时(若上游传入的时间已为 UTC 且未转换,可用此开关修正)
if strings.EqualFold(strings.TrimSpace(strings.ToLower(os.Getenv("RAIN_FORCE_SHIFT8"))), "1") {
ref.DT = ref.DT.Add(8 * time.Hour)
}
// 可选调试打印解析出的时间CST与 URL
if strings.EqualFold(strings.TrimSpace(strings.ToLower(os.Getenv("RAIN_DEBUG"))), "1") {
log.Printf("[rain] store tile: url=%s -> product=%s dt(local)=%s z=%d y=%d x=%d",
urlOrPath, ref.Product, ref.DT.Format("2006-01-02 15:04:05 -0700"), ref.Z, ref.Y, ref.X)
}
db := database.GetDB()
return database.UpsertRainTile(ctx, db, ref.Product, ref.DT, ref.Z, ref.Y, ref.X, 256, 256, data)
}