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" "os/signal"
"syscall" "syscall"
"weatherstation/internal/radar" "weatherstation/internal/radar"
"weatherstation/internal/rain"
"weatherstation/internal/server" "weatherstation/internal/server"
) )
@ -21,6 +22,11 @@ func main() {
log.Fatalf("service-radar start error: %v", err) 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 // Keep process alive until signal
<-ctx.Done() <-ctx.Done()
log.Println("service-radar shutting down") 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 { 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) 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 { 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 { if err != nil {
return err return err
} }
if exists { 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 return nil
} }
} }
@ -150,10 +159,30 @@ func downloadAndStoreTile(ctx context.Context, local time.Time, dateStr, hh, mm
if rerr != nil { if rerr != nil {
return fmt.Errorf("read saved tile: %w", rerr) 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) 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 return nil
} }

View File

@ -3,6 +3,8 @@ package rain
import ( import (
"context" "context"
"fmt" "fmt"
"log"
"os"
"path" "path"
"regexp" "regexp"
"strconv" "strconv"
@ -65,6 +67,15 @@ func StoreTileBytes(ctx context.Context, urlOrPath string, data []byte) error {
if err != nil { if err != nil {
return err 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() db := database.GetDB()
return database.UpsertRainTile(ctx, db, ref.Product, ref.DT, ref.Z, ref.Y, ref.X, 256, 256, data) return database.UpsertRainTile(ctx, db, ref.Product, ref.DT, ref.Z, ref.Y, ref.X, 256, 256, data)
} }