Track visa-free stay limits from your Flighty flight data using rolling time windows.
Many visa-free regimes limit you to a number of days inside a rolling window rather than a fixed calendar period. South Korea allows 90 days within any 180-day span (with no single stay longer than 60 days). The Schengen Area uses the same 90-in-180 rule. Because the window slides forward every day, working out how many days you have left, or when you can next enter for a given length of trip, means recounting every past stay against a window that keeps moving.
Days of Stay reads the flight history you already keep in Flighty, pairs arrivals with departures to reconstruct each stay, and counts the days that fall inside the rolling window for a chosen country. It reports how many days remain today and the earliest dates you could return for a 30- or 60-day trip.
- Counts days spent in a country within a rolling window (for example, 90 days within 180 days).
- Reconstructs stays by pairing entry and exit flights, then clamps each stay to the window boundaries so partial overlaps count correctly.
- Enforces an optional consecutive-day cap per stay (South Korea limits a single stay to 60 days).
- Reports days used, days remaining, and how long you could stay if you flew in today.
- Calculates future availability: the earliest date you can return for a 30- or 60-day stay.
- Ships a ready-made South Korea analyzer and a generic analyzer that works for any country given its airport codes and rules.
- Includes a standalone browser version (
index.html) with drag-and-drop CSV upload and presets for South Korea, Schengen, Japan, Thailand, and the UK. - Runs on the Python standard library alone. No third-party packages to install.
The CLI needs Python 3.9 or newer and has no external dependencies.
Clone the repository:
git clone https://github.com/ivan-magda/days-of-stay.git
cd days-of-stayThe project is managed with uv. With uv installed, run the analyzers directly through the entry points declared in pyproject.toml:
uv run analyze-korea-stay
uv run visa-stay-analyzer --helpWithout uv, run the scripts with Python:
python analyze_korea_stay.py
python visa_stay_analyzer.py --helpanalyze_korea_stay.py comes preconfigured with South Korean airports and the 90-in-180 rule (60-day consecutive cap). It defaults to a CSV named FlightyExport-2025-10-18.csv in the project directory:
# Use the default CSV
python analyze_korea_stay.py
# Point at your own export
python analyze_korea_stay.py -f FlightyExport-2025-11-20.csvIt accepts a single flag:
-f, --file— path to the Flighty CSV export. Relative paths resolve against the script directory.
Sample output:
Analyzing visa-free stays: South Korea
======================================================================
Reference date: 2025-10-18
180-day window: 2025-04-22 to 2025-10-18
======================================================================
All South Korea stays:
======================================================================
Stay #1:
Entry: 2025-05-01 - KE 123 (LAX -> ICN)
Exit: 2025-05-15 - KE 124 (ICN -> LAX)
Total stay: 15 days
Days in window: 15 days
SUMMARY:
======================================================================
Total days in South Korea within rolling window: 62 days
Maximum allowed days: 90 days
Days remaining: 28 days
visa_stay_analyzer.py works for any country. Pass the airport codes and the visa rule:
python visa_stay_analyzer.py \
-f FlightyExport-2025-10-18.csv \
-a ICN,GMP,CJU,PUS \
-c "South Korea" \
-w 180 \
-m 90 \
-x 60Flags:
| Flag | Required | Description |
|---|---|---|
-f, --file |
yes | Path to the Flighty CSV export |
-a, --airports |
yes | Comma-separated IATA airport codes for the country |
-c, --country |
yes | Country or region name shown in the report |
-w, --window |
yes | Rolling window size in days (for example, 180) |
-m, --max-days |
yes | Maximum days allowed inside the window (for example, 90) |
-x, --max-consecutive |
no | Maximum consecutive days per single stay |
-d, --date |
no | Reference date YYYY-MM-DD for the analysis (defaults to today) |
Schengen Area (90 days in 180, no consecutive cap):
python visa_stay_analyzer.py \
-f flights.csv \
-a CDG,AMS,FCO,MAD,BCN,FRA,MUC,VIE,ZRH \
-c "Schengen" \
-w 180 \
-m 90Check your status as of a past date with -d:
python visa_stay_analyzer.py \
-f flights.csv \
-a ICN,GMP \
-c "South Korea" \
-w 180 -m 90 -x 60 \
-d 2025-06-01index.html is a self-contained page that runs the same analysis in your browser with no server or build step. Open it, pick a country from the dropdown (South Korea, Schengen, Japan, Thailand, or UK), and drop in your Flighty CSV. Everything is parsed and computed locally; the file never leaves your machine.
Both analyzers read a CSV exported from the Flighty iOS app. To produce one, open Flighty, go to Settings, choose Export Data, and save the FlightyExport-YYYY-MM-DD.csv file.
The analyzer reads these columns: Date, Airline, Flight, From, To, Canceled, Gate Arrival (Actual), Gate Departure (Actual), Landing (Actual), and Take off (Actual). Canceled flights are skipped. A flight counts as an arrival when To is one of the country's airports and From is not, and as a departure in the reverse case. Each arrival pairs with the next departure to form one stay.
days-of-stay/
├── visa_stay_analyzer.py # Core library and generic CLI
├── analyze_korea_stay.py # South Korea wrapper with preset rules
├── index.html # Standalone browser version
├── pyproject.toml # Project metadata and script entry points
├── ROADMAP.md # Planned features
└── README.md
visa_stay_analyzer.py holds the analysis logic. load_flights() parses the CSV and filters by airport, calculate_stays() pairs entries with exits, calculate_days_in_window() counts overlap with the rolling window, and analyze_visa_stays() ties it together. analyze_korea_stay.py imports analyze_visa_stays() and calls it with South Korea's airports and rules. To add another country, copy that pattern: define an airport set, set the window and limits, and call analyze_visa_stays().
Planned work is tracked in ROADMAP.md, including multi-country analysis, configuration files for visa rules, trip planning, and richer report exports.
Issues and pull requests are welcome. To add support for a new country, follow the analyze_korea_stay.py pattern and open a PR. Please keep the CLI dependency-free so it continues to run on a stock Python install.