feat: a typed QRZ start date fetches that period, not what QRZ edited in it

"Last download" and an operator-chosen date are different questions, and they
now ask QRZ different ones. The automatic run wants everything TOUCHED since it
last ran (MODSINCE) — that is what returns a 2015 QSO confirmed yesterday. A date
typed by the operator names a period of OPERATING, so it maps to BETWEEN date and
today, on the QSO date.

The client-side date filter is skipped only under MODSINCE, where it would throw
away the older-but-newly-confirmed records the query exists to fetch. Under
BETWEEN it agrees with the server and stays on as a backstop.
This commit is contained in:
2026-07-28 15:48:00 +02:00
parent 305da583e1
commit 1f2e86c04d
+24 -8
View File
@@ -9575,11 +9575,14 @@ func (a *App) runDownloadConfirmations(svc extsvc.Service, cfg extsvc.ExternalSe
// QSO date. sinceDate is "YYYY-MM-DD". // QSO date. sinceDate is "YYYY-MM-DD".
sinceDate := resolveSince(keyExtQRZLastDownload) sinceDate := resolveSince(keyExtQRZLastDownload)
emit(fmt.Sprintf("Window: since=%q → resolved date=%q (key %s%s)", since, sinceDate, a.profileScope(), keyExtQRZLastDownload)) emit(fmt.Sprintf("Window: since=%q → resolved date=%q (key %s%s)", since, sinceDate, a.profileScope(), keyExtQRZLastDownload))
if sinceDate != "" { // An automatic run ("last") and an operator-chosen date do not mean the
emit("Fetching QRZ.com logbook (records modified since " + sinceDate + ")…") // same thing, so they ask QRZ two different questions:
} else { // • "last" → MODSINCE: everything TOUCHED since the last run,
emit("Fetching QRZ.com logbook (full — no since date)…") // which is what catches a 2015 QSO confirmed yesterday.
} // • a typed date → BETWEEN: the QSOs MADE from that date to today. The
// operator asked for a period of operating, not for
// whatever QRZ happened to edit in that period.
autoWindow := strings.EqualFold(strings.TrimSpace(since), "last")
// Ask QRZ for the WINDOW rather than the whole logbook. "ALL" made the // Ask QRZ for the WINDOW rather than the whole logbook. "ALL" made the
// server serialise every QSO — 56 MB for a 117k-record log — which it // server serialise every QSO — 56 MB for a 117k-record log — which it
// truncates mid-record, so the parse died two thirds of the way through // truncates mid-record, so the parse died two thirds of the way through
@@ -9595,13 +9598,26 @@ func (a *App) runDownloadConfirmations(svc extsvc.Service, cfg extsvc.ExternalSe
// //
// It stays an optimisation, never a requirement: if QRZ refuses it, fall // It stays an optimisation, never a requirement: if QRZ refuses it, fall
// back to ALL rather than leaving the operator with no download at all. // back to ALL rather than leaving the operator with no download at all.
//
// serverWindowed is set only for MODSINCE, because it alone returns QSOs
// OLDER than the date — the client-side date filter would drop exactly
// those. Under BETWEEN the filter agrees with the server and stays on as a
// backstop.
fetchOpt, serverWindowed := "ALL", false fetchOpt, serverWindowed := "ALL", false
if sinceDate != "" { switch {
case sinceDate == "":
emit("Fetching QRZ.com logbook (full — no since date)…")
case autoWindow:
fetchOpt, serverWindowed = "MODSINCE:"+sinceDate, true fetchOpt, serverWindowed = "MODSINCE:"+sinceDate, true
emit("Fetching QRZ.com logbook (records modified since " + sinceDate + ")…")
default:
today := time.Now().UTC().Format("2006-01-02")
fetchOpt = "BETWEEN:" + sinceDate + "+" + today
emit("Fetching QRZ.com logbook (QSOs from " + sinceDate + " to " + today + ")…")
} }
fr, err := extsvc.FetchQRZ(ctx, nil, cfg.QRZ.APIKey, fetchOpt) fr, err := extsvc.FetchQRZ(ctx, nil, cfg.QRZ.APIKey, fetchOpt)
if err != nil && serverWindowed { if err != nil && fetchOpt != "ALL" {
emit("QRZ.com refused MODSINCE (" + err.Error() + ") — fetching the full logbook instead…") emit("QRZ.com refused " + fetchOpt + " (" + err.Error() + ") — fetching the full logbook instead…")
fetchOpt, serverWindowed = "ALL", false fetchOpt, serverWindowed = "ALL", false
fr, err = extsvc.FetchQRZ(ctx, nil, cfg.QRZ.APIKey, fetchOpt) fr, err = extsvc.FetchQRZ(ctx, nil, cfg.QRZ.APIKey, fetchOpt)
} }