metar-taf-parser 4.1.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -39,9 +39,8 @@ const metar = parseMetar(rawMetarString);
39
39
 
40
40
  // -or-
41
41
 
42
- // Optionally pass a date (approximately when the report was issued, +/- a week)
43
- // to get the issued date on the report:
44
- const datedMetar = parseMetar(rawMetarString, { date: new Date() });
42
+ // Optionally pass the date issued to add it to the report
43
+ const datedMetar = parseMetar(rawMetarString, { issued });
45
44
  ```
46
45
 
47
46
  #### `parseTAF`
@@ -55,9 +54,9 @@ const taf = parseTAF(rawTAFString);
55
54
 
56
55
  // -or-
57
56
 
58
- // Optionally pass a date (approximately when the report was issued, +/- a week)
59
- // to get the report issued and trend validity dates (start/end) on the report:
60
- const datedTAF = parseTAF(rawTAFString, { date: new Date() });
57
+ // Optionally pass the date issued to get the report issued and
58
+ // trend validity dates (start/end) on the report:
59
+ const datedTAF = parseTAF(rawTAFString, { issued });
61
60
  ```
62
61
 
63
62
  ### Higher level parsing: The Forecast abstraction
@@ -72,7 +71,7 @@ Returns a more normalized TAF report. Most notably: while the `parseTAF` functio
72
71
  import { parseTAFAsForecast } from "metar-taf-parser";
73
72
 
74
73
  // You must provide an issued date to use the Forecast abstraction
75
- const report = parseTAFAsForecast(rawTAFString, { date: tafIssuedDate });
74
+ const report = parseTAFAsForecast(rawTAFString, { issued: tafIssuedDate });
76
75
 
77
76
  console.log(report.forecast);
78
77
  ```
@@ -98,7 +97,7 @@ import {
98
97
  getCompositeForecastForDate,
99
98
  } from "metar-taf-parser";
100
99
 
101
- const report = parseTAFAsForecast(rawTAFString, { date: tafIssuedDate });
100
+ const report = parseTAFAsForecast(rawTAFString, { issued: tafIssuedDate });
102
101
 
103
102
  const forecastPerHour = eachHourOfInterval({
104
103
  start: report.start,
@@ -1142,11 +1142,11 @@ interface IAbstractValidity {
1142
1142
  * Exclusive for the TS port (because python has `time()` and js does not)
1143
1143
  */
1144
1144
  interface ITime {
1145
- hour: number;
1146
- minute: number;
1145
+ hour?: number;
1146
+ minute?: number;
1147
1147
  }
1148
1148
  interface IAbstractWeatherCode extends IAbstractWeatherContainer, ITime {
1149
- day: number;
1149
+ day?: number;
1150
1150
  airport?: IAirport;
1151
1151
  message: string;
1152
1152
  station: string;
@@ -1171,9 +1171,14 @@ interface ITAF extends IAbstractWeatherCode {
1171
1171
  maxTemperature?: ITemperatureDated;
1172
1172
  minTemperature?: ITemperatureDated;
1173
1173
  trends: TAFTrend[];
1174
+ /**
1175
+ * Just the first part of the TAF message without trends (FM, BECMG, etc)
1176
+ */
1177
+ initialRaw: string;
1174
1178
  }
1175
1179
  interface IAbstractTrend extends IAbstractWeatherContainer {
1176
1180
  type: WeatherChangeType;
1181
+ raw: string;
1177
1182
  }
1178
1183
  interface IMetarTrendTime extends ITime {
1179
1184
  type: TimeIndicator;
@@ -1326,15 +1331,12 @@ interface IMetarTAFParserOptions {
1326
1331
  }
1327
1332
  interface IMetarTAFParserOptionsDated extends IMetarTAFParserOptions {
1328
1333
  /**
1329
- * This date should ideally be the date the report was issued. Otherwise, it
1330
- * can be be +/- one week of the actual report date and work properly.
1331
- *
1332
- * So if you know the report was recently issued, you can pass `new Date()`
1334
+ * This date should be the date the report was issued.
1333
1335
  *
1334
1336
  * This date is needed to create actual timestamps since the report only has
1335
- * day of month, hour, and minute.
1337
+ * day of month, hour, and minute (and sometimes not even that).
1336
1338
  */
1337
- date: Date;
1339
+ issued: Date;
1338
1340
  }
1339
1341
  declare function parseMetar(rawMetar: string, options?: IMetarTAFParserOptions): IMetar;
1340
1342
  declare function parseMetar(rawMetar: string, options?: IMetarTAFParserOptionsDated): IMetarDated;
@@ -2064,7 +2064,7 @@ function parseDeliveryTime(timeString) {
2064
2064
  const hour = +timeString.slice(2, 4);
2065
2065
  const minute = +timeString.slice(4, 6);
2066
2066
  if (isNaN(day) || isNaN(hour) || isNaN(minute))
2067
- throw new InvalidWeatherStatementError("Report time is invalid");
2067
+ return;
2068
2068
  return {
2069
2069
  day,
2070
2070
  hour,
@@ -2120,7 +2120,7 @@ function parseTemperature(input) {
2120
2120
  * @param input the string containing the validity
2121
2121
  * @returns Validity object
2122
2122
  */
2123
- function parseValidity(input, date) {
2123
+ function parseValidity(input) {
2124
2124
  const parts = pySplit(input, "/");
2125
2125
  return {
2126
2126
  startDay: +parts[0].slice(0, 2),
@@ -2304,6 +2304,7 @@ class MetarParser extends AbstractParser {
2304
2304
  clouds: [],
2305
2305
  times: [],
2306
2306
  remarks: [],
2307
+ raw: input,
2307
2308
  };
2308
2309
  index = this.parseTrend(index, trend, metarTab);
2309
2310
  metar.trends.push(trend);
@@ -2356,7 +2357,8 @@ class TAFParser extends AbstractParser {
2356
2357
  const station = lines[0][index];
2357
2358
  index += 1;
2358
2359
  const time = parseDeliveryTime(lines[0][index]);
2359
- index += 1;
2360
+ if (time)
2361
+ index += 1;
2360
2362
  const validity = parseValidity(lines[0][index]);
2361
2363
  const taf = {
2362
2364
  station,
@@ -2368,6 +2370,7 @@ class TAFParser extends AbstractParser {
2368
2370
  remarks: [],
2369
2371
  clouds: [],
2370
2372
  weatherConditions: [],
2373
+ initialRaw: lines[0].join(" "),
2371
2374
  };
2372
2375
  for (let i = index + 1; i < lines[0].length; i++) {
2373
2376
  const token = lines[0][i];
@@ -2434,6 +2437,7 @@ class TAFParser extends AbstractParser {
2434
2437
  ...this.makeEmptyTAFTrend(),
2435
2438
  type: WeatherChangeType.FM,
2436
2439
  validity: parseFromValidity(lineTokens[0]),
2440
+ raw: lineTokens.join(" "),
2437
2441
  };
2438
2442
  }
2439
2443
  else if (lineTokens[0].startsWith(this.PROB)) {
@@ -2444,12 +2448,14 @@ class TAFParser extends AbstractParser {
2444
2448
  ...this.makeEmptyTAFTrend(),
2445
2449
  type: WeatherChangeType.PROB,
2446
2450
  validity,
2451
+ raw: lineTokens.join(" "),
2447
2452
  };
2448
2453
  if (lineTokens.length > 1 && lineTokens[1] === this.TEMPO) {
2449
2454
  trend = {
2450
2455
  ...this.makeEmptyTAFTrend(),
2451
2456
  type: WeatherChangeType[lineTokens[1]],
2452
2457
  validity,
2458
+ raw: lineTokens.join(" "),
2453
2459
  };
2454
2460
  index = 2;
2455
2461
  }
@@ -2463,6 +2469,7 @@ class TAFParser extends AbstractParser {
2463
2469
  ...this.makeEmptyTAFTrend(),
2464
2470
  type: WeatherChangeType[lineTokens[0]],
2465
2471
  validity,
2472
+ raw: lineTokens.join(" "),
2466
2473
  };
2467
2474
  }
2468
2475
  this.parseTrend(index, lineTokens, trend);
@@ -2546,6 +2553,9 @@ _RemarkParser_supplier = new WeakMap();
2546
2553
  * @returns
2547
2554
  */
2548
2555
  function determineReportIssuedDate(date, day, hour, minute) {
2556
+ // Some TAF reports do not include a delivery time
2557
+ if (day == null || hour == null)
2558
+ return date;
2549
2559
  const months = [
2550
2560
  setDateComponents(addMonthsUTC(date, -1), day, hour, minute),
2551
2561
  setDateComponents(new Date(date), day, hour, minute),
@@ -2650,6 +2660,7 @@ function makeInitialForecast(taf) {
2650
2660
  remarks: taf.remarks,
2651
2661
  clouds: taf.clouds,
2652
2662
  weatherConditions: taf.weatherConditions,
2663
+ raw: taf.initialRaw,
2653
2664
  validity: {
2654
2665
  // End day/hour are for end of the entire TAF
2655
2666
  startDay: taf.validity.startDay,
@@ -2705,8 +2716,8 @@ function parse(rawReport, options, parser, datesHydrator) {
2705
2716
  const lang = options?.locale || en;
2706
2717
  try {
2707
2718
  const report = new parser(lang).parse(rawReport);
2708
- if (options && "date" in options) {
2709
- return datesHydrator(report, options.date);
2719
+ if (options && "issued" in options) {
2720
+ return datesHydrator(report, options.issued);
2710
2721
  }
2711
2722
  return report;
2712
2723
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metar-taf-parser",
3
- "version": "4.1.0",
3
+ "version": "5.1.0",
4
4
  "description": "Parse METAR and TAF reports",
5
5
  "homepage": "https://aeharding.github.io/metar-taf-parser",
6
6
  "keywords": [