Skip to main content

Exporting your session

A surreal painting: a brass pocket watch melts across an old wooden writing desk, its liquid metal running in streams over the edge, while a gull watches from the sill of an open harbour window

This post is about TiCaNo Stopwatch v1.7.0, and it is written against that build’s code, line by line. It is about what leaves your phone when you export: three formats, what each is for, and one change in this release that a returning user needs to know about before opening the file.

A stopwatch app's export sheet showing three format options as radio buttons, with CSV for spreadsheets selected above JSON for apps and import and TXT human readable.
TiCaNo Stopwatch v1.7.0, the Export sheet: the three doors out of the app, labelled by their jobs — CSV (comma-separated values) preselected because a session with laps is the normal case.

A session you have saved is a record — laps, names, pauses, timestamps, all on the device. Export is how it leaves. The Export sheet offers exactly three formats, each labelled by its job: CSV (comma-separated values)A plain-text table format with one record per line and values split by commas; opens in almost any spreadsheet app.Read more on Wikipedia ↗ (for spreadsheets), JSONJavaScript Object Notation (JSON): a plain-text format for structured data, written as named fields and lists; widely used to move data between programs.Read more on Wikipedia ↗ (for apps and import), TXT (human readable). CSV is selected by default — unless the session has no laps, in which case CSV is disabled, honestly labelled “no laps to export”, and TXT takes over as the default.

The CSV: one row per lap

The single-session CSV is six columns, in this order: segment_name, segment_number, segment_start, segment_end, segment_duration_seconds, pause_time_seconds. One row per lap. Batch exports — selecting several sessions on the Saved Sessions screen — prepend session_id and session_name, making eight, with one header row for the whole batch.

Every duration in the file is a single decimal-seconds value, rounded to your export-precision setting. Ten seconds at the default precision of 2 exports as 10.0.

A spreadsheet showing a stopwatch CSV export with the six column names segment_name through pause_time_seconds in a header row and three data rows of lap names, times and decimal-second values.
TiCaNo Stopwatch v1.7.0, a single-session CSV export: six columns, one row per lap, and every duration already in seconds — nothing to convert and nothing missing.

The 1.7.0 change, said plainly

Durations now export once, as seconds. The commit that did this is marked as a breaking change, and the marker is earned: if you built a spreadsheet on a CSV from an earlier version, its references to the duration columns must be repointed. In a single-session export, segment_duration_seconds is now column 5 of 6, and pause_time_seconds is column 6; in a batch export they are columns 7 and 8 of 8. Read the *_seconds columns and only those.

Two things did not change. TXT and Share keep their formatted clock strings — MM:SS.d-style — untouched by this commit. And the precision setting itself is older than this release: since v1.6.1 it rounds CSV and JSON too, where once those formats ignored it. On 1.7.0 the slider (0 to 4 decimals, default 2) governs every format the same way.

The JSON: the whole session, structured

A single-session JSON export is an array containing one session object. Always present: session_id, session_name, session_start, session_end, session_total_seconds, note, and a segments array whose objects mirror the CSV columns exactly — name, number, start, end, duration in seconds, pause in seconds.

A text viewer showing an indented JSON export of a stopwatch session with session keys at the top and a segments array below.
TiCaNo Stopwatch v1.7.0, a single-session JSON export: keys appear only when the data exists, and the event log’s six types — start through lastLapAndStop — are all there to parse.

Keys appear when the data exists. A session with an offset start carries actual_start_time; one with pauses carries total_paused_time_seconds; one recorded with the event log carries an events array — start, lap, pause, resume, stop and the combined final lap-and-stop, each with a timestamp. Lap events also name their number and title. Two metadata fields ride along, app_homepage and app_download_url, so a file that wanders can find its way back.

One honesty note, because the label invites the question: the sheet says “JSON (for apps and import)”, and the first half is the true half. JSON is for other apps and tools to read. TiCaNo does not re-import its own exports — there is no import path in the app at all.

The TXT: the report a human reads

A text file showing a formatted stopwatch session report with a session header, three lap blocks with names and times, trophy and turtle markers, and a statistics summary.
TiCaNo Stopwatch v1.7.0, a TXT session report: names, clock times and the fastest-lap markers — everything the CSV deliberately leaves out.

TXT is the comprehensive human-readable format. A session header with its note, start, end and total. One block per lap — number, name, lap time, split time, start and end clock times. Fastest and slowest laps are marked 🏆 and 🐢 when there is more than one lap, and a statistics block closes with total laps, fastest, slowest and average. Batch exports join sessions with a separator line and end with a single footer. Nothing in it is meant to be parsed; all of it is meant to be read.

The details that keep the file honest

Unnamed laps export named. A lap with no custom title exports under the app’s localised default name — the same name the screen shows — in all four formats. Before 1.7.0 the formats disagreed: the text formats printed a blank where the name goes, and the data formats substituted hard-coded English. Now one rule feeds every format, so a Hebrew user’s file says the same thing as their screen.

Deletion leaves no gaps. Lap names follow the lap’s number, and deleting a lap renumbers the survivors, folding the deleted time into the next lap when there is one — delete the last lap and its time stays in the session total instead. The exported file matches the screen — there is no missing #3 to preserve.

Pause time is computed, not stored. pause_time_seconds is derived at export time from the session’s event log, pause by pause, clamped to each segment. A session with no event data exports 0.0 — that is the computation’s result for no pauses, not a stored field surfacing.

Timestamps are ISO (International Organization for Standardization) 8601. Every timestamp in every exported file is an ISO 8601 string, in every locale. The Export Date Format and Export Time Format settings shape the Share tab’s text — they do not reach the files.

A small guard with a specific job

CSV fields are escaped centrally: standard quoting for fields containing commas, quotes or newlines, plus a spreadsheet formula-injection guard. A field starting with =, +, -, @, tab or carriage return gets a leading apostrophe — so a lap titled =1+1 is stored as text, not a formula, when the file is opened in a spreadsheet. That is the first-open risk the guard addresses, and it is the honest scope of the promise: what happens after the file is saved and re-opened by someone else’s spreadsheet is beyond any export writer’s control.

Where the file goes

Exporting writes the content to a temporary file and hands it to the operating system’s share sheet. The filename is the session’s name (cleaned of characters filesystems hate, truncated at 50) plus the date and the extension; batch files are stopwatch_sessions_ plus the date. From the share sheet, the file is yours — save it, send it, open it wherever you like. The app has no accounts, no destinations of its own, and no network code in the export path: no drive, no inbox, no upload. What leaves the phone leaves because you carried it.

That is the whole design: the record lives on your device, and the export is a complete, honest copy of it in whichever of three shapes suits what you do next. When you press start on TiCaNo Stopwatch, the timing is the free part; the file at the end is the part you keep. If the decimals in that file are what you care about, we have written about what they mean.

Sources

  • All behaviour claims were verified against the shipped TiCaNo Stopwatch v1.7.0 (1.7.0+29, release tag) by reading that build’s code, line by line — the export strategies, the export sheet, the sanitiser, the deletion logic and the export service. The file-and-line pins behind each claim are recorded in the post’s research notes, not repeated here.
  • Request for Comments (RFC) 4180 (CSV quoting rules) and the Open Worldwide Application Security Project (OWASP) Foundation’s CSV Injection page (formula-trigger characters, and the documented limits of any mitigation after a re-save) for the sanitizer’s external grounding. https://www.rfc-editor.org/rfc/rfc4180 · https://owasp.org/www-community/attacks/CSV_Injection