- Introduce internal/providers/nws with shared timestamp parsing used by both NWS sources and normalizers - Migrate NWS observation source + normalizer to use the shared provider helper for consistent RFC3339/RFC3339Nano handling - Introduce internal/providers/openweather with a shared URL invariant helper enforcing units=metric - Remove duplicated OpenWeather URL validation logic from the observation source - Align provider layering: move provider “contract/quirk” logic out of normalizers and into internal/providers - Update normalizer and standards documentation to clearly distinguish: provider helpers (internal/providers) vs canonical mapping logic (internal/normalizers) This refactor reduces duplication between sources and normalizers, clarifies layering boundaries, and establishes a scalable pattern for future forecast and alert implementations.
27 lines
650 B
Go
27 lines
650 B
Go
package openweather
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"strings"
|
|
)
|
|
|
|
// RequireMetricUnits enforces weatherfeeder's OpenWeather invariant:
|
|
// the request URL must include units=metric (otherwise temperatures/winds/pressure differ).
|
|
func RequireMetricUnits(rawURL string) error {
|
|
u, err := url.Parse(strings.TrimSpace(rawURL))
|
|
if err != nil {
|
|
return fmt.Errorf("invalid url %q: %w", rawURL, err)
|
|
}
|
|
|
|
units := strings.ToLower(strings.TrimSpace(u.Query().Get("units")))
|
|
if units != "metric" {
|
|
if units == "" {
|
|
units = "(missing; defaults to standard)"
|
|
}
|
|
return fmt.Errorf("url must include units=metric (got units=%s)", units)
|
|
}
|
|
|
|
return nil
|
|
}
|