Files
Eric Rakestraw b8804d32d2 refactor(normalizers): deduplicate synthetic station ID generation
- 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.
2026-01-16 22:13:44 -06:00

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
}