mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-06 11:24:00 +00:00
fix(cyclones): accept advisories NHC publishes before their nominal time
NHC stamps an advisory with its nominal time and writes it about half an hour early, so the 5-minute future limit rejected the whole feed each advisory cycle and the layer showed no storms. Allow 90 minutes ahead.
This commit is contained in:
1 parent
e7707d9a0f
commit
9c15f093a1
3 files changed
+18
-1
No files matched your search
@@ -1,5 +1,10 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
- Cyclone advisories no longer go dark while NHC publishes an advisory ahead
|
||||||
|
of its nominal time: advisory and position times up to 90 minutes ahead of
|
||||||
|
the server clock are accepted (previously 5 minutes), so the whole feed is
|
||||||
|
not rejected for about half an hour each advisory cycle.
|
||||||
|
|
||||||
- Public Overpass instances are no longer used by default. Street Traffic
|
- Public Overpass instances are no longer used by default. Street Traffic
|
||||||
roads come from TomTom flow tiles, OpenFreeMap vector tiles, or both, chosen
|
roads come from TomTom flow tiles, OpenFreeMap vector tiles, or both, chosen
|
||||||
on the layer row (TomTom / OSM / Hybrid) or with `?trafficRoads=`. With a
|
on the layer row (TomTom / OSM / Hybrid) or with `?trafficRoads=`. With a
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ function number(value, min, max) {
|
|||||||
const n = Number(value);
|
const n = Number(value);
|
||||||
return Number.isFinite(n) && n >= min && n <= max ? n : null;
|
return Number.isFinite(n) && n >= min && n <= max ? n : null;
|
||||||
}
|
}
|
||||||
|
// NHC stamps an advisory with its nominal time (e.g. 03:00Z) and publishes it
|
||||||
|
// up to about half an hour before; allow that, but not a clock far ahead.
|
||||||
|
const EARLY_ADVISORY_MS = 90 * 60_000;
|
||||||
function iso(value, now) {
|
function iso(value, now) {
|
||||||
if (
|
if (
|
||||||
typeof value !== 'string' ||
|
typeof value !== 'string' ||
|
||||||
@@ -50,7 +53,7 @@ function iso(value, now) {
|
|||||||
const n = Date.parse(value);
|
const n = Date.parse(value);
|
||||||
if (
|
if (
|
||||||
!Number.isFinite(n) ||
|
!Number.isFinite(n) ||
|
||||||
n > now + 5 * 60_000 ||
|
n > now + EARLY_ADVISORY_MS ||
|
||||||
now - n > 12 * HOUR ||
|
now - n > 12 * HOUR ||
|
||||||
new Date(n).toISOString().replace('.000Z', 'Z') !==
|
new Date(n).toISOString().replace('.000Z', 'Z') !==
|
||||||
value.replace('.000Z', 'Z')
|
value.replace('.000Z', 'Z')
|
||||||
|
|||||||
@@ -162,6 +162,15 @@ test('malformed, duplicate, oversized, future and expired status is rejected rat
|
|||||||
assert.deepEqual(parseCycloneStatus({ activeStorms: [] }, NOW), []);
|
assert.deepEqual(parseCycloneStatus({ activeStorms: [] }, NOW), []);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('advisories published before their nominal time are accepted, far-future ones are not', () => {
|
||||||
|
// NHC wrote the 03:00Z advisory at 02:34Z.
|
||||||
|
const early = Date.UTC(2026, 8, 16, 2, 34);
|
||||||
|
assert.equal(parseCycloneStatus(status(), early)[0].issuedAt, TIME);
|
||||||
|
assert.throws(() =>
|
||||||
|
parseCycloneStatus(status(), Date.UTC(2026, 8, 16, 1, 25)),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('coherent geometry is retained with holes/dateline while older advisory geometry is omitted', () => {
|
test('coherent geometry is retained with holes/dateline while older advisory geometry is omitted', () => {
|
||||||
const storms = parseCycloneStatus(status(), NOW);
|
const storms = parseCycloneStatus(status(), NOW);
|
||||||
const parts = collections();
|
const parts = collections();
|
||||||
|
|||||||
Reference in new issue
Block a user