毎月31日に更新するサブスクの「次の更新日」を計算したら、2月31日という存在しない日ができてしまい、更新日が少しずつずれていく。自作アプリ「サブスク番人」を作っているときに、このバグを踏みました。
この記事では、何が起きたのか、なぜずれるのか、今どう直しているのかをまとめます。日付の計算をするアプリを作る人の参考になればうれしいです。
同じ話は、30秒ほどのショート動画でも紹介しています。
何が起きたか
「サブスク番人」は、サブスクの更新日の前に知らせてくれるアプリです。更新日を知らせるには、今の更新日から「次の更新日」を計算する必要があります。
毎月払いなら、次の更新日は「1か月後」。ここで、毎月31日に更新するサブスクに1か月を足すと、2月31日のような存在しない日になってしまいました。その結果、更新日が少しずつずれていくバグになっていました。
なぜずれるのか
「1か月後」は、月によって日数がちがう(28日〜31日)ので、思ったよりあいまいです。ここからは、アプリの中の話ではなく、日付を計算するときに一般的に起きることです。

A そのまま1か月足すと、はみ出す
たとえば JavaScript の Date で、2026年1月31日の月に1を足すと、2月31日は無いので、はみ出した3日分が3月に回って3月3日になります。そこから先は毎月3日になり、31日には戻りません。
B 月末にそろえても、前回の日から足すと縮んでいく
「その月にない日は月末にそろえる」と、1月31日の次は2月28日になります。ただし、次の計算を前回の更新日(2月28日)からすると、3月28日、4月28日…と、28日のまま進んでしまいます。
C 「31日」を覚えておいて、毎回そこから決める
もとの「31日」を覚えておいて、毎回「その月の31日。なければ月末」と決めると、2月28日、3月31日、4月30日と、月末に合わせて進みます。うるう年の2028年なら、2月は29日になります。
今の直し方
まず、その月にその日がない場合は、月末にそろえるようにしました。1月31日の次は2月28日です。
ただ、最初の直し方では、その次を前回の更新日(2月28日)から計算していたので、3月28日になっていました。上の図でいうとBのやり方です。
そこで、サブスクごとにもとの更新日(31日など)を覚えておき、毎回そこから決めるように直しました(図のC)。1月31日の次は2月28日、その次は3月31日、4月30日と、月末に合わせて進みます。毎年2月29日に更新するものも、うるう年には2月29日に戻ります。この直しは、次のアプリの更新から使えます。
なお、前のバージョンですでに28日にずれてしまったサブスクは、もとが何日だったかの記録がないので、自動では戻りません。編集画面で更新日を選び直すと、その日が新しい基準になります。
日付の計算は、ふだんの日(たとえば15日)では問題が出ません。月末の29日・30日・31日と、うるう年の2月だけで起きるので、気づきにくいバグでした。
日付を計算するアプリを作る人へ
- 「1か月後」を計算するところでは、1月31日・3月31日・5月31日から始めて、何か月か先まで確かめる
- うるう年の2月29日と、30日までの月(4月・6月・9月・11月)も確かめる
- 前回の結果から足していくと、そろえた日がそのまま残る(上の図のB)。もとの日を覚えておくかどうかを決めておく
まとめ
- 毎月31日のサブスクに1か月足したら、2月31日という存在しない日ができた
- そのせいで、更新日が少しずつずれていくバグになっていた
- 月末にそろえるだけだと、そのあと28日のまま進んでいた
- 今は、もとの日を覚えておいて毎回そこから決める(1月31日 → 2月28日 → 3月31日)
「サブスク番人」は、App Store と Google Play で「サブスク番人」と検索すると見つかります。アプリを作って公開するまでの話は、「サブスク番人」を作って公開した話にまとめています。
ほかに作ったアプリは 作ったもの にまとめています。
ナノトイラボ 
