ZweiteGPS の JSON ログを GPX 形式に変換する zweg を作った

ZweiteGPS という iPhone 用の GPS ロガーアプリを愛用している。 10 年以上使っているがほぼ落ちたことがなく、長時間安定して記録できる。

最近、世界の霧 というアプリを使い始めた。 このアプリは、初めて起動すると地図上に霧がかかっていて、自分が通った場所の霧を晴らしていくゲームだ。霧を晴らすために今まで通ったことのない道を通ってみようという気になったりして、日常の楽しみになっている。

世界の霧は、アプリを起動して記録する以外に、GPX (GPS eXchange Format) 形式のファイルをインポートして過去に通った場所の霧を晴らすことができる。 そこで、ZweiteGPS で記録したログファイルをインポートすることにした。

課題になったのは、ZweiteGPS のログファイルは独自の JSON データになっていることで、これを GPX 形式に変換する必要がある。 ZweiteGPS 内で GPX 形式に変換することはできるのだが、ログファイルを 1 つずつ操作する必要がある。ログファイルを一括でエクスポートすることはできるが、まとめて GPX 形式に変換することができない。

変換ツールを探したが存在しなかったので、JSON ファイルを GPX 形式に変換する zweg というツールを作った。

使い方

基本的な使い方は以下。

zweg --timezone-offset +09:00 data.json

コマンドを実行すると、20251201-123456.gpx といったファイル名でエクスポートされる。 ZweiteGPS の「フォーマット変換 > GPX」でエクスポートしたときと同じ挙動になる。

README に複数のログファイルをまとめて変換する方法など、色々な使い方を書いている。

GPX のタイムゾーンの仕様

--timezone-offset を指定すると、ファイル名にタイムゾーン (例は JST) が反映されるが、ファイル内の time タグの日時は UTC で保存される。

「フォーマット変換 > GPX (ローカル時間)」でエクスポートすると、time タグの日時にもタイムゾーンが反映されるが、GPX のスキーマtime タグの説明には「Date and time in are in Univeral Coordinated Time (UTC), not local time!」 (原文ママ) と記載がある。 したがって、「フォーマット変換 > GPX (ローカル時間)」相当の機能は実装していない。

zweg も GPX の仕様に合わせて、GPX ファイルの日時は UTC で保存して、それをどのタイムゾーンで扱うかは利用するアプリケーションに任せることにした。

例えば、写真編集ツールの Lightroom Classic には、読み込んだ GPX ファイルの日時をオフセットする機能があるし、ログ閲覧ツールの GPX Binder にはタイムゾーンを指定する機能がある。 世界の霧のようにタイムゾーンの影響を受けないアプリケーションもある。

とはいえ、ファイル名の日時にタイムゾーンを反映しないと、ファイルのリストを見たときに混乱するので、ファイル名にだけ適用することにした。

開発

Claude Code に ZweiteGPS のログファイルを解析してもらい、それを元に 9 割のコードを書いてもらった。 実装はもちろん、CI でバイナリを生成する設定もすぐに作ってくれた。

伝えた仕様を間違って実装することは結構ある印象なので、コードを確認したり、挙動がおかしくないかを検証する必要があった。

CLI ツールを作るという用途なので、言語には Golang を選択した。 型が違っていたり、間違った書き方をしているとビルドが失敗するのは安心感があった。