Skip to content

Commit 800c87c

Browse files
committed
Update CHANGELOG and swift format
1 parent 3acd16b commit 800c87c

2 files changed

Lines changed: 94 additions & 70 deletions

File tree

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,29 @@
11
# Change Log
22

3+
## [3.0.0] - 2026-03-20
4+
5+
### Added
6+
7+
- XML parsing for METARs and TAFs from aviationweather.gov cache files.
8+
- `METAR.from(xml:)` and `TAF.from(xml:)` return `AsyncStream<Result<..., Error>>`
9+
for resilient batch parsing with per-entry error handling.
10+
- Winds aloft parsing.
11+
12+
### Changed
13+
14+
- CLI tools (`decode-metar`, `decode-taf`) now support `--format xml` and
15+
`--output json` options.
16+
- Log messages in CLI tools now go to stderr to keep JSON output clean.
17+
- Updated to Swift 6.2.
18+
- Added swift-format for code formatting.
19+
20+
### Fixed
21+
22+
- Fixed CSV parsing for updated aviationweather.gov format (quoted raw text,
23+
separate station_id column).
24+
- Fixed handling of TAF periods where the end date comes before the start date
25+
(e.g., crossing month boundaries).
26+
327
## [2.0.1] - 2025-08-20
428

529
### Fixed

Sources/SwiftMETAR/Error.swift

Lines changed: 70 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,18 @@ extension Error: LocalizedError {
5757
switch self {
5858
case .invalidWindsAloftHeader, .invalidWindsAloftGroup, .invalidWindsAloftColumns:
5959
#if canImport(Darwin)
60-
return String(
61-
localized: "Couldn’t parse Winds Aloft product.",
62-
comment: "error description"
63-
)
60+
return String(
61+
localized: "Couldn’t parse Winds Aloft product.",
62+
comment: "error description"
63+
)
6464
#else
65-
return "Couldn’t parse Winds Aloft product."
65+
return "Couldn’t parse Winds Aloft product."
6666
#endif
6767
default:
6868
#if canImport(Darwin)
69-
return String(localized: "Couldn’t parse METAR or TAF.", comment: "error description")
69+
return String(localized: "Couldn’t parse METAR or TAF.", comment: "error description")
7070
#else
71-
return "Couldn’t parse METAR or TAF."
71+
return "Couldn’t parse METAR or TAF."
7272
#endif
7373
}
7474
}
@@ -77,120 +77,120 @@ extension Error: LocalizedError {
7777
switch self {
7878
case .badFormat:
7979
#if canImport(Darwin)
80-
return String(localized: "METAR or TAF format is incorrect.", comment: "failure reason")
80+
return String(localized: "METAR or TAF format is incorrect.", comment: "failure reason")
8181
#else
82-
return "METAR or TAF format is incorrect."
82+
return "METAR or TAF format is incorrect."
8383
#endif
8484
case .invalidDate(let date):
8585
#if canImport(Darwin)
86-
return String(localized: "Invalid date ‘\(date)’.", comment: "failure reason")
86+
return String(localized: "Invalid date ‘\(date)’.", comment: "failure reason")
8787
#else
88-
return "Invalid date ‘\(date)’."
88+
return "Invalid date ‘\(date)’."
8989
#endif
9090
case .invalidWinds(let winds):
9191
#if canImport(Darwin)
92-
return String(localized: "Invalid winds ‘\(winds)’.", comment: "failure reason")
92+
return String(localized: "Invalid winds ‘\(winds)’.", comment: "failure reason")
9393
#else
94-
return "Invalid winds ‘\(winds)’."
94+
return "Invalid winds ‘\(winds)’."
9595
#endif
9696
case .invalidVisibility(let visibility):
9797
#if canImport(Darwin)
98-
return String(localized: "Invalid visibility ‘\(visibility)’.", comment: "failure reason")
98+
return String(localized: "Invalid visibility ‘\(visibility)’.", comment: "failure reason")
9999
#else
100-
return "Invalid visibility ‘\(visibility)’."
100+
return "Invalid visibility ‘\(visibility)’."
101101
#endif
102102
case .invalidWeather(let weather):
103103
#if canImport(Darwin)
104-
return String(localized: "Invalid weather ‘\(weather)’.", comment: "failure reason")
104+
return String(localized: "Invalid weather ‘\(weather)’.", comment: "failure reason")
105105
#else
106-
return "Invalid weather ‘\(weather)’."
106+
return "Invalid weather ‘\(weather)’."
107107
#endif
108108
case .invalidConditions(let conditions):
109109
#if canImport(Darwin)
110-
return String(localized: "Invalid conditions ‘\(conditions)’.", comment: "failure reason")
110+
return String(localized: "Invalid conditions ‘\(conditions)’.", comment: "failure reason")
111111
#else
112-
return "Invalid conditions ‘\(conditions)’."
112+
return "Invalid conditions ‘\(conditions)’."
113113
#endif
114114
case .invalidTempDewpoint(let temps):
115115
#if canImport(Darwin)
116-
return String(
117-
localized: "Invalid temperature and dewpoint ‘\(temps)’.",
118-
comment: "failure reason"
119-
)
116+
return String(
117+
localized: "Invalid temperature and dewpoint ‘\(temps)’.",
118+
comment: "failure reason"
119+
)
120120
#else
121-
return "Invalid temperature and dewpoint ‘\(temps)’."
121+
return "Invalid temperature and dewpoint ‘\(temps)’."
122122
#endif
123123
case .invalidAltimeter(let altimeter):
124124
#if canImport(Darwin)
125-
return String(
126-
localized: "Invalid altimeter setting ‘\(altimeter)’.",
127-
comment: "failure reason"
128-
)
125+
return String(
126+
localized: "Invalid altimeter setting ‘\(altimeter)’.",
127+
comment: "failure reason"
128+
)
129129
#else
130-
return "Invalid altimeter setting ‘\(altimeter)’."
130+
return "Invalid altimeter setting ‘\(altimeter)’."
131131
#endif
132132
case .invalidPeriod(let period):
133133
#if canImport(Darwin)
134-
return String(localized: "Invalid TAF period ‘\(period)’.", comment: "failure reason")
134+
return String(localized: "Invalid TAF period ‘\(period)’.", comment: "failure reason")
135135
#else
136-
return "Invalid TAF period ‘\(period)’."
136+
return "Invalid TAF period ‘\(period)’."
137137
#endif
138138
case .invalidWindshear(let windshear):
139139
#if canImport(Darwin)
140-
return String(
141-
localized: "Invalid low-level windshear ‘\(windshear)’.",
142-
comment: "failure reason"
143-
)
140+
return String(
141+
localized: "Invalid low-level windshear ‘\(windshear)’.",
142+
comment: "failure reason"
143+
)
144144
#else
145-
return "Invalid low-level windshear ‘\(windshear)’."
145+
return "Invalid low-level windshear ‘\(windshear)’."
146146
#endif
147147
case .invalidIcing(let icing):
148148
#if canImport(Darwin)
149-
return String(localized: "Invalid icing ‘\(icing)", comment: "failure reason")
149+
return String(localized: "Invalid icing ‘\(icing)", comment: "failure reason")
150150
#else
151-
return "Invalid icing ‘\(icing)"
151+
return "Invalid icing ‘\(icing)"
152152
#endif
153153
case .invalidTurbulence(let turbulence):
154154
#if canImport(Darwin)
155-
return String(localized: "Invalid turbulence ‘\(turbulence)", comment: "failure reason")
155+
return String(localized: "Invalid turbulence ‘\(turbulence)", comment: "failure reason")
156156
#else
157-
return "Invalid turbulence ‘\(turbulence)"
157+
return "Invalid turbulence ‘\(turbulence)"
158158
#endif
159159
case .invalidForecastTemperature(let temp):
160160
#if canImport(Darwin)
161-
return String(
162-
localized: "Invalid forecast temperature '\(temp)'",
163-
comment: "failure reason"
164-
)
161+
return String(
162+
localized: "Invalid forecast temperature '\(temp)'",
163+
comment: "failure reason"
164+
)
165165
#else
166-
return "Invalid forecast temperature '\(temp)'"
166+
return "Invalid forecast temperature '\(temp)'"
167167
#endif
168168
case .invalidWindsAloftHeader(let header):
169169
#if canImport(Darwin)
170-
return String(
171-
localized: "Invalid winds aloft header '\(header)'.",
172-
comment: "failure reason"
173-
)
170+
return String(
171+
localized: "Invalid winds aloft header '\(header)'.",
172+
comment: "failure reason"
173+
)
174174
#else
175-
return "Invalid winds aloft header '\(header)'."
175+
return "Invalid winds aloft header '\(header)'."
176176
#endif
177177
case .invalidWindsAloftGroup(let group):
178178
#if canImport(Darwin)
179-
return String(
180-
localized: "Invalid winds aloft data group '\(group)'.",
181-
comment: "failure reason"
182-
)
179+
return String(
180+
localized: "Invalid winds aloft data group '\(group)'.",
181+
comment: "failure reason"
182+
)
183183
#else
184-
return "Invalid winds aloft data group '\(group)'."
184+
return "Invalid winds aloft data group '\(group)'."
185185
#endif
186186
case .invalidWindsAloftColumns(let columns):
187187
#if canImport(Darwin)
188-
return String(
189-
localized: "Invalid winds aloft column layout '\(columns)'.",
190-
comment: "failure reason"
191-
)
188+
return String(
189+
localized: "Invalid winds aloft column layout '\(columns)'.",
190+
comment: "failure reason"
191+
)
192192
#else
193-
return "Invalid winds aloft column layout '\(columns)'."
193+
return "Invalid winds aloft column layout '\(columns)'."
194194
#endif
195195
}
196196
}
@@ -199,21 +199,21 @@ extension Error: LocalizedError {
199199
switch self {
200200
case .invalidWindsAloftHeader, .invalidWindsAloftGroup, .invalidWindsAloftColumns:
201201
#if canImport(Darwin)
202-
return String(
203-
localized: "Verify the format of the Winds Aloft product.",
204-
comment: "recovery suggestion"
205-
)
202+
return String(
203+
localized: "Verify the format of the Winds Aloft product.",
204+
comment: "recovery suggestion"
205+
)
206206
#else
207-
return "Verify the format of the Winds Aloft product."
207+
return "Verify the format of the Winds Aloft product."
208208
#endif
209209
default:
210210
#if canImport(Darwin)
211-
return String(
212-
localized: "Verify the format of the METAR or TAF string.",
213-
comment: "recovery suggestion"
214-
)
211+
return String(
212+
localized: "Verify the format of the METAR or TAF string.",
213+
comment: "recovery suggestion"
214+
)
215215
#else
216-
return "Verify the format of the METAR or TAF string."
216+
return "Verify the format of the METAR or TAF string."
217217
#endif
218218
}
219219
}

0 commit comments

Comments
 (0)