- Add common SynthStationID helpers for coordinate-based providers - Use shared helper for Open-Meteo and OpenWeather station ID synthesis - Require both lat/lon when generating synthetic IDs to avoid misleading defaults - Remove unused Open-Meteo normalizer wrapper code This reduces cross-provider duplication while keeping provider-specific mapping logic explicit and readable.
51 lines
1.2 KiB
Go
51 lines
1.2 KiB
Go
package nws
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// ParseTime parses NWS timestamps.
|
|
//
|
|
// NWS observation timestamps are typically RFC3339, sometimes with fractional seconds.
|
|
// We accept RFC3339Nano first, then RFC3339.
|
|
func ParseTime(s string) (time.Time, error) {
|
|
s = strings.TrimSpace(s)
|
|
if s == "" {
|
|
return time.Time{}, fmt.Errorf("empty time")
|
|
}
|
|
|
|
if t, err := time.Parse(time.RFC3339Nano, s); err == nil {
|
|
return t, nil
|
|
}
|
|
if t, err := time.Parse(time.RFC3339, s); err == nil {
|
|
return t, nil
|
|
}
|
|
|
|
return time.Time{}, fmt.Errorf("unsupported NWS timestamp format: %q", s)
|
|
}
|
|
|
|
// ParseTimeBestEffort parses an NWS timestamp and returns it in UTC.
|
|
//
|
|
// This is a convenience for normalizers that want "best effort" parsing:
|
|
// invalid/empty strings do not fail the entire normalization; they return zero time.
|
|
func ParseTimeBestEffort(s string) time.Time {
|
|
t, err := ParseTime(s)
|
|
if err != nil {
|
|
return time.Time{}
|
|
}
|
|
return t.UTC()
|
|
}
|
|
|
|
// ParseTimePtr parses an NWS timestamp and returns a UTC *time.Time.
|
|
//
|
|
// Empty/unparseable input returns nil. This is useful for optional CAP fields.
|
|
func ParseTimePtr(s string) *time.Time {
|
|
t := ParseTimeBestEffort(s)
|
|
if t.IsZero() {
|
|
return nil
|
|
}
|
|
return &t
|
|
}
|