{
  "name": "NightLog Pro night-time test vectors",
  "version": 1,
  "url": "https://www.nightlogpro.com/night-vectors-v1.json",
  "definitions": {
    "night": "Time with the centre of the sun more than 6° below the horizon (civil twilight), geometric elevation, at the aircraft's position: EASA Part-FCL and FAA 14 CFR 1.1.",
    "sunsetToSunrise": "Time with the centre of the sun more than 0.833° below the horizon (standard refraction and semi-diameter): FAA 14 CFR 91.209.",
    "route": "Great circle at constant ground speed from wheels-off to wheels-on; the aircraft holds at the departure during taxi-out and at the arrival during taxi-in.",
    "times": "UTC throughout. Exact minutes to 0.001; whole minutes are the exact value rounded to the nearest minute. Crossing times are to the second, positions to 0.0001°."
  },
  "tolerance": {
    "exactMinutes": 0.05,
    "note": "A calculator using these definitions should agree with the exact minutes to within 0.05 min. Whole minutes can then still differ by one when the exact value is close to a half minute."
  },
  "cases": [
    {
      "id": "egll-kjfk-december-dusk",
      "description": "Westbound across the Atlantic into the night: one sunset and one end of civil twilight en route.",
      "tags": [
        "twilight"
      ],
      "from": {
        "icao": "EGLL",
        "lat": 51.4706001282,
        "lng": -0.4619410038
      },
      "to": {
        "icao": "KJFK",
        "lat": 40.63980103,
        "lng": -73.77890015
      },
      "offBlocks": "2026-12-21T15:00Z",
      "onBlocks": "2026-12-21T23:00Z",
      "taxiOutMinutes": 0,
      "taxiInMinutes": 0,
      "expected": {
        "nightMinutes": 176,
        "nightMinutesExact": 176.125,
        "sunsetToSunriseMinutes": 346,
        "sunsetToSunriseMinutesExact": 346.281,
        "crossings": [
          {
            "type": "sunset",
            "at": "2026-12-21T17:13:43Z",
            "lat": 53.6553,
            "lng": -23.11
          },
          {
            "type": "night-start",
            "at": "2026-12-21T20:03:52Z",
            "lat": 50.0923,
            "lng": -51.3312
          }
        ]
      }
    },
    {
      "id": "kjfk-egll-june-dawn",
      "description": "Eastbound overnight in June, across 00:00 UTC: night ends over the ocean.",
      "tags": [
        "twilight",
        "midnight-utc"
      ],
      "from": {
        "icao": "KJFK",
        "lat": 40.63980103,
        "lng": -73.77890015
      },
      "to": {
        "icao": "EGLL",
        "lat": 51.4706001282,
        "lng": -0.4619410038
      },
      "offBlocks": "2026-06-21T23:00Z",
      "onBlocks": "2026-06-22T05:45Z",
      "taxiOutMinutes": 0,
      "taxiInMinutes": 0,
      "expected": {
        "nightMinutes": 202,
        "nightMinutesExact": 201.578,
        "sunsetToSunriseMinutes": 262,
        "sunsetToSunriseMinutesExact": 261.806,
        "crossings": [
          {
            "type": "sunset",
            "at": "2026-06-22T00:09:43Z",
            "lat": 45.6171,
            "lng": -64.1952
          },
          {
            "type": "night-start",
            "at": "2026-06-22T00:39:47Z",
            "lat": 47.49,
            "lng": -59.5553
          },
          {
            "type": "night-end",
            "at": "2026-06-22T04:01:21Z",
            "lat": 53.6429,
            "lng": -21.2045
          },
          {
            "type": "sunrise",
            "at": "2026-06-22T04:31:31Z",
            "lat": 53.39,
            "lng": -14.9776
          }
        ]
      }
    },
    {
      "id": "lppt-egll-december-dusk",
      "description": "A short European sector flown through dusk.",
      "tags": [
        "twilight"
      ],
      "from": {
        "icao": "LPPT",
        "lat": 38.7812995911,
        "lng": -9.1359195709
      },
      "to": {
        "icao": "EGLL",
        "lat": 51.4706001282,
        "lng": -0.4619410038
      },
      "offBlocks": "2026-12-15T16:30Z",
      "onBlocks": "2026-12-15T19:00Z",
      "taxiOutMinutes": 0,
      "taxiInMinutes": 0,
      "expected": {
        "nightMinutes": 97,
        "nightMinutesExact": 96.727,
        "sunsetToSunriseMinutes": 119,
        "sunsetToSunriseMinutesExact": 118.585,
        "crossings": [
          {
            "type": "sunset",
            "at": "2026-12-15T17:01:25Z",
            "lat": 41.4883,
            "lng": -7.6163
          },
          {
            "type": "night-start",
            "at": "2026-12-15T17:23:16Z",
            "lat": 43.3592,
            "lng": -6.4825
          }
        ]
      }
    },
    {
      "id": "lppt-circuits-december-night",
      "description": "Night circuits at one airfield: departure and arrival are the same, every minute is night.",
      "tags": [
        "same-airport"
      ],
      "from": {
        "icao": "LPPT",
        "lat": 38.7812995911,
        "lng": -9.1359195709
      },
      "to": {
        "icao": "LPPT",
        "lat": 38.7812995911,
        "lng": -9.1359195709
      },
      "offBlocks": "2026-12-15T20:30Z",
      "onBlocks": "2026-12-15T22:00Z",
      "taxiOutMinutes": 0,
      "taxiInMinutes": 0,
      "expected": {
        "nightMinutes": 90,
        "nightMinutesExact": 90,
        "sunsetToSunriseMinutes": 90,
        "sunsetToSunriseMinutesExact": 90,
        "crossings": []
      }
    },
    {
      "id": "egtr-circuits-january-dusk",
      "description": "Circuits at a training airfield with no IATA code, started in daylight and finished in the dark.",
      "tags": [
        "same-airport",
        "twilight"
      ],
      "from": {
        "icao": "EGTR",
        "lat": 51.6557998657,
        "lng": -0.3258329928
      },
      "to": {
        "icao": "EGTR",
        "lat": 51.6557998657,
        "lng": -0.3258329928
      },
      "offBlocks": "2026-01-15T16:00Z",
      "onBlocks": "2026-01-15T17:30Z",
      "taxiOutMinutes": 0,
      "taxiInMinutes": 0,
      "expected": {
        "nightMinutes": 30,
        "nightMinutesExact": 30.372,
        "sunsetToSunriseMinutes": 69,
        "sunsetToSunriseMinutesExact": 69.044,
        "crossings": [
          {
            "type": "sunset",
            "at": "2026-01-15T16:20:57Z",
            "lat": 51.6558,
            "lng": -0.3258
          },
          {
            "type": "night-start",
            "at": "2026-01-15T16:59:38Z",
            "lat": 51.6558,
            "lng": -0.3258
          }
        ]
      }
    },
    {
      "id": "entc-ensb-midnight-sun",
      "description": "Midnight sun: the sun never sets, so there is no night and no sunset-to-sunrise time.",
      "tags": [
        "polar-day"
      ],
      "from": {
        "icao": "ENTC",
        "lat": 69.6832962036,
        "lng": 18.9188995361
      },
      "to": {
        "icao": "ENSB",
        "lat": 78.2461013794,
        "lng": 15.4656000137
      },
      "offBlocks": "2026-06-21T00:00Z",
      "onBlocks": "2026-06-21T01:00Z",
      "taxiOutMinutes": 0,
      "taxiInMinutes": 0,
      "expected": {
        "nightMinutes": 0,
        "nightMinutesExact": 0,
        "sunsetToSunriseMinutes": 0,
        "sunsetToSunriseMinutesExact": 0,
        "crossings": []
      }
    },
    {
      "id": "ensb-polar-night-noon",
      "description": "Polar night: the whole block is night, even at local noon.",
      "tags": [
        "polar-night",
        "same-airport"
      ],
      "from": {
        "icao": "ENSB",
        "lat": 78.2461013794,
        "lng": 15.4656000137
      },
      "to": {
        "icao": "ENSB",
        "lat": 78.2461013794,
        "lng": 15.4656000137
      },
      "offBlocks": "2026-12-21T10:00Z",
      "onBlocks": "2026-12-21T12:00Z",
      "taxiOutMinutes": 0,
      "taxiInMinutes": 0,
      "expected": {
        "nightMinutes": 120,
        "nightMinutesExact": 120,
        "sunsetToSunriseMinutes": 120,
        "sunsetToSunriseMinutesExact": 120,
        "crossings": []
      }
    },
    {
      "id": "enva-midsummer-twilight-only",
      "description": "Midsummer at 63°N: the sun sets but never reaches −6°, so there is sunset-to-sunrise time and no night.",
      "tags": [
        "twilight-only",
        "same-airport"
      ],
      "from": {
        "icao": "ENVA",
        "lat": 63.4578018188,
        "lng": 10.9239997864
      },
      "to": {
        "icao": "ENVA",
        "lat": 63.4578018188,
        "lng": 10.9239997864
      },
      "offBlocks": "2026-06-21T23:00Z",
      "onBlocks": "2026-06-22T00:30Z",
      "taxiOutMinutes": 0,
      "taxiInMinutes": 0,
      "expected": {
        "nightMinutes": 0,
        "nightMinutesExact": 0,
        "sunsetToSunriseMinutes": 90,
        "sunsetToSunriseMinutesExact": 90,
        "crossings": []
      }
    },
    {
      "id": "gulb-pagq-arctic-graze",
      "description": "A polar route that grazes −6° for hours over the Arctic: a small error in the sun is minutes of night here.",
      "tags": [
        "grazing",
        "midnight-utc"
      ],
      "from": {
        "icao": "GULB",
        "lat": 11.3261003494,
        "lng": -12.2868003845
      },
      "to": {
        "icao": "PAGQ",
        "lat": 61.5360984802,
        "lng": -149.8139953613
      },
      "offBlocks": "2026-08-18T18:19Z",
      "onBlocks": "2026-08-19T08:42Z",
      "taxiOutMinutes": 0,
      "taxiInMinutes": 0,
      "expected": {
        "nightMinutes": 659,
        "nightMinutesExact": 659.466,
        "sunsetToSunriseMinutes": 797,
        "sunsetToSunriseMinutesExact": 797.452,
        "crossings": [
          {
            "type": "sunset",
            "at": "2026-08-18T19:24:33Z",
            "lat": 18.4846,
            "lng": -14.894
          },
          {
            "type": "night-start",
            "at": "2026-08-18T19:56:52Z",
            "lat": 22.0003,
            "lng": -16.2557
          },
          {
            "type": "night-end",
            "at": "2026-08-19T04:55:08Z",
            "lat": 70.8258,
            "lng": -84.9217
          },
          {
            "type": "night-start",
            "at": "2026-08-19T06:40:49Z",
            "lat": 69.7922,
            "lng": -121.6696
          }
        ]
      }
    },
    {
      "id": "nzaa-ksfo-date-line",
      "description": "Across the Pacific and the 180° meridian.",
      "tags": [
        "date-line",
        "twilight"
      ],
      "from": {
        "icao": "NZAA",
        "lat": -37.0080986023,
        "lng": 174.7920074463
      },
      "to": {
        "icao": "KSFO",
        "lat": 37.6189994812,
        "lng": -122.375
      },
      "offBlocks": "2026-12-21T08:00Z",
      "onBlocks": "2026-12-21T22:00Z",
      "taxiOutMinutes": 0,
      "taxiInMinutes": 0,
      "expected": {
        "nightMinutes": 458,
        "nightMinutesExact": 457.731,
        "sunsetToSunriseMinutes": 485,
        "sunsetToSunriseMinutesExact": 484.8,
        "crossings": [
          {
            "type": "night-start",
            "at": "2026-12-21T08:06:27Z",
            "lat": -36.4933,
            "lng": 175.4299
          },
          {
            "type": "night-end",
            "at": "2026-12-21T15:44:11Z",
            "lat": 4.4587,
            "lng": -151.1217
          },
          {
            "type": "sunrise",
            "at": "2026-12-21T16:04:48Z",
            "lat": 6.3698,
            "lng": -149.8001
          }
        ]
      }
    },
    {
      "id": "yssy-kdfw-two-nights",
      "description": "An ultra-long sector across the date line that flies through two separate nights.",
      "tags": [
        "two-night-periods",
        "over-16h",
        "date-line",
        "southern-hemisphere"
      ],
      "from": {
        "icao": "YSSY",
        "lat": -33.9460983276,
        "lng": 151.1770019531
      },
      "to": {
        "icao": "KDFW",
        "lat": 32.8968009949,
        "lng": -97.0380020142
      },
      "offBlocks": "2026-01-01T07:00Z",
      "onBlocks": "2026-01-02T00:05Z",
      "taxiOutMinutes": 0,
      "taxiInMinutes": 0,
      "expected": {
        "nightMinutes": 431,
        "nightMinutesExact": 430.547,
        "sunsetToSunriseMinutes": 482,
        "sunsetToSunriseMinutesExact": 481.713,
        "crossings": [
          {
            "type": "sunset",
            "at": "2026-01-01T08:18:49Z",
            "lat": -30.3093,
            "lng": 161.6117
          },
          {
            "type": "night-start",
            "at": "2026-01-01T08:35:28Z",
            "lat": -29.4372,
            "lng": 163.7091
          },
          {
            "type": "night-end",
            "at": "2026-01-01T15:43:01Z",
            "lat": -0.1412,
            "lng": -151.423
          },
          {
            "type": "sunrise",
            "at": "2026-01-01T16:00:58Z",
            "lat": 1.215,
            "lng": -149.7219
          },
          {
            "type": "sunset",
            "at": "2026-01-01T23:45:26Z",
            "lat": 32.0055,
            "lng": -99.6408
          },
          {
            "type": "night-start",
            "at": "2026-01-02T00:02:00Z",
            "lat": 32.7635,
            "lng": -97.4409
          }
        ]
      }
    },
    {
      "id": "entc-engm-february-taxi",
      "description": "Taxi time: the aircraft holds 15 minutes at Tromsø, where it is already dark, and 8 at Oslo — about seven more minutes of night than with no taxi.",
      "tags": [
        "taxi",
        "twilight"
      ],
      "from": {
        "icao": "ENTC",
        "lat": 69.6832962036,
        "lng": 18.9188995361
      },
      "to": {
        "icao": "ENGM",
        "lat": 60.193901062,
        "lng": 11.100399971
      },
      "offBlocks": "2026-02-10T15:15Z",
      "onBlocks": "2026-02-10T17:00Z",
      "taxiOutMinutes": 15,
      "taxiInMinutes": 8,
      "expected": {
        "nightMinutes": 53,
        "nightMinutesExact": 53.093,
        "sunsetToSunriseMinutes": 105,
        "sunsetToSunriseMinutesExact": 105,
        "crossings": [
          {
            "type": "night-start",
            "at": "2026-02-10T16:06:54Z",
            "lat": 65.4623,
            "lng": 14.6991
          }
        ]
      }
    },
    {
      "id": "yssy-ymml-june-dusk",
      "description": "A southern-hemisphere winter evening.",
      "tags": [
        "southern-hemisphere",
        "twilight"
      ],
      "from": {
        "icao": "YSSY",
        "lat": -33.9460983276,
        "lng": 151.1770019531
      },
      "to": {
        "icao": "YMML",
        "lat": -37.6733016968,
        "lng": 144.8430023193
      },
      "offBlocks": "2026-06-21T06:30Z",
      "onBlocks": "2026-06-21T08:05Z",
      "taxiOutMinutes": 0,
      "taxiInMinutes": 0,
      "expected": {
        "nightMinutes": 33,
        "nightMinutesExact": 32.671,
        "sunsetToSunriseMinutes": 67,
        "sunsetToSunriseMinutesExact": 66.956,
        "crossings": [
          {
            "type": "sunset",
            "at": "2026-06-21T06:58:03Z",
            "lat": -35.0804,
            "lng": 149.3685
          },
          {
            "type": "night-start",
            "at": "2026-06-21T07:32:20Z",
            "lat": -36.4294,
            "lng": 147.089
          }
        ]
      }
    },
    {
      "id": "wsss-wiii-equinox-dusk",
      "description": "Near the equator at the equinox, where the sun sets steeply and twilight is short.",
      "tags": [
        "tropics",
        "twilight",
        "southern-hemisphere"
      ],
      "from": {
        "icao": "WSSS",
        "lat": 1.3501900434,
        "lng": 103.9940032959
      },
      "to": {
        "icao": "WIII",
        "lat": -6.1255698204,
        "lng": 106.65599823
      },
      "offBlocks": "2026-03-20T10:45Z",
      "onBlocks": "2026-03-20T12:30Z",
      "taxiOutMinutes": 0,
      "taxiInMinutes": 0,
      "expected": {
        "nightMinutes": 59,
        "nightMinutesExact": 59.153,
        "sunsetToSunriseMinutes": 78,
        "sunsetToSunriseMinutesExact": 77.935,
        "crossings": [
          {
            "type": "sunset",
            "at": "2026-03-20T11:12:04Z",
            "lat": -0.5771,
            "lng": 104.6781
          },
          {
            "type": "night-start",
            "at": "2026-03-20T11:30:51Z",
            "lat": -1.9146,
            "lng": 105.153
          }
        ]
      }
    }
  ]
}
