{
  "schemaVersion": 1,
  "slug": "flight-time-calculator",
  "category": "travel",
  "kind": "implementation",
  "independentValidation": false,
  "implementationHash": "c77055970dfdbd95c3b62574a4d47f481077f90b3b6150d35dbfe1268ee17678",
  "provenance": "Generated from the calculation contract used by the published page. Publication is not external validation.",
  "sourceFiles": [
    "data/calculators/flight-time-calculator.json",
    "src/engine.js"
  ],
  "runtimeSource": "/sources/engine.txt",
  "runtimeHash": "5c888d8898afbdee36267bb9977829e1e2ac568f6677c8ee87469c139864645c",
  "scope": "The compute function records implemented equations, constants, lookup tables and custom rules. Inputs record defaults and allowed values; outputs record precision and units. Defaults are examples, not recommendations. General background references are not evidence for this specific algorithm.",
  "publishedFormula": {
    "formula": "a = sin²(Δφ ÷ 2) + cos φ1 × cos φ2 × sin²(Δλ ÷ 2); d = 2R × atan2(√a, √(1−a)); T = d ÷ v + 0.5",
    "vars": [
      [
        "φ1",
        "origin latitude"
      ],
      [
        "φ2",
        "destination latitude"
      ],
      [
        "Δφ",
        "latitude difference (rad)"
      ],
      [
        "Δλ",
        "longitude difference (rad)"
      ],
      [
        "R",
        "Earth radius, 6371 km"
      ],
      [
        "v",
        "cruise speed (km/h)"
      ],
      [
        "a",
        "haversine intermediate"
      ],
      [
        "d",
        "great-circle distance (km)"
      ],
      [
        "T",
        "total flight time (h)"
      ]
    ],
    "note": "Coordinates are converted from degrees to radians; the haversine value is clamped for floating-point safety. Estimated time adds a fixed 0.5 h after distance ÷ airborne speed. Arrival uses a manually entered time-zone shift, displays clock time only, and does not model calendar dates or daylight-saving rules. CO₂ is a simple distance proxy."
  },
  "externalEvidence": null,
  "contract": {
    "compute": "const toRad = (d) => d*Math.PI/180; const dLat = toRad(lat2-lat1); const dLon = toRad(lon2-lon1); const a = Math.sin(dLat/2)*Math.sin(dLat/2)+Math.cos(toRad(lat1))*Math.cos(toRad(lat2))*Math.sin(dLon/2)*Math.sin(dLon/2); const distanceKm = 6371*2*Math.atan2(Math.sqrt(Math.min(1,Math.max(0,a))), Math.sqrt(1-Math.min(1,Math.max(0,a)))); const hours = cruiseSpeed > 0 ? distanceKm/cruiseSpeed : 0; const total = hours+0.5; const arrival = departureTime+total+timezoneShift; return { distanceKm, distanceMiles: distanceKm*0.621371, flightTimeHours: total, arrivalLocal: ((arrival%24)+24)%24, co2PerPassenger: distanceKm*0.09 };",
    "inputs": [
      {
        "name": "lat1",
        "type": "number",
        "default": 40.7128,
        "min": -90,
        "max": 90,
        "step": 0.01
      },
      {
        "name": "lon1",
        "type": "number",
        "default": -74.006,
        "min": -180,
        "max": 180,
        "step": 0.01
      },
      {
        "name": "lat2",
        "type": "number",
        "default": 51.5074,
        "min": -90,
        "max": 90,
        "step": 0.01
      },
      {
        "name": "lon2",
        "type": "number",
        "default": -0.1278,
        "min": -180,
        "max": 180,
        "step": 0.01
      },
      {
        "name": "cruiseSpeed",
        "type": "number",
        "default": 850,
        "min": 200,
        "max": 1200,
        "step": 10,
        "slider": true
      },
      {
        "name": "timezoneShift",
        "type": "number",
        "default": 5,
        "min": -14,
        "max": 14,
        "step": 0.5,
        "slider": true
      },
      {
        "name": "departureTime",
        "type": "number",
        "default": 9,
        "min": 0,
        "max": 23.99,
        "step": 0.25,
        "slider": true
      }
    ],
    "outputs": [
      {
        "name": "distanceKm",
        "precision": 0,
        "unit": "km"
      },
      {
        "name": "distanceMiles",
        "precision": 0,
        "unit": "mi"
      },
      {
        "name": "flightTimeHours",
        "precision": 2,
        "unit": "h"
      },
      {
        "name": "arrivalLocal",
        "precision": 2,
        "unit": "h"
      },
      {
        "name": "co2PerPassenger",
        "precision": 0,
        "unit": "kg"
      }
    ],
    "interpret": null
  }
}
