0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

日付を文字列で比較すると全件ヒット/0件になる4つのパターンと直し方(Python / JavaScript)

0
Posted at

はじめに

日時の列を >= で絞り込んだら全件、< にしたら0件。境目の日付をどう動かしても中間の件数が出てこない、という状態にハマりました。

原因は 日付を文字列のまま比較していた ことです。エラーは出ず、比較としては仕様どおりに動くので、結果の件数を見るまで気づけません。

作業は Claude Code と一緒に進めていて、原因の切り分けも AI 側がやってくれました。そのとき出てきたパターンを4つに分けて整理します。

環境

  • Python 3.13
  • JavaScript(日本時間の環境で実行)

文字列比較は「辞書順」

文字列の < > は日付として比べているわけではなく、先頭から1文字ずつ文字コードを比べて、最初に違った位置で決着します。

>>> "2026/09/23 01:26" >= "2026-09-24"
True
>>> "2026/09/23 01:26" <= "2026-09-24"
False

5文字目で /(47)と -(45)がぶつかった時点で / 側が勝ちます。月・日は一度も比較されません。

rows = ["2026/09/22 23:10", "2026/09/23 01:26", "2026/09/24 21:00"]

[r for r in rows if r >= "2026-09-24"]
# ['2026/09/22 23:10', '2026/09/23 01:26', '2026/09/24 21:00']

[r for r in rows if r < "2026-09-24"]
# []

ハマるパターン4つ

パターン1:区切り記号の不一致(/ と -)

  • 2026-09-24:ISO 8601。DB や API に多い
  • 2026/09/24:画面表示、表計算ソフトからの書き出しに多い

症状は 全件 or 0件。どちらになるかは不等号の向き次第です。

パターン2:ゼロ埋めなし

>>> "2026/9/5" > "2026/10/01"
True

6文字目の 9 と 1 で決着するため、9月5日が10月1日より後になります。月・日の桁が変わる境目だけ順序が崩れるので、月またぎ・年またぎの集計で一部だけ件数がおかしいときに疑います。

パターン3:日付のみの値と日時を比べて、当日分が抜ける

>>> "2026-09-23 10:00" <= "2026-09-23"
False

先頭が同じなら長いほうが大きい、というルールで、23日の記録は0時0分も含めて全部「23日まで」から外れます。日時型の列でも、日付だけの値は0時0分として扱われがちで同じことが起きます。

終わりの日を含めたいなら半開区間で書きます。

start <= t < 翌日 00:00

パターン4:T と空白の混在、タイムゾーン表記

>>> "2026-09-23T10:00" > "2026-09-23 23:00"
True

T(84)が空白(32)に必ず勝つので、10時が23時より後になります。

>>> "2026-09-23T00:00:00Z" < "2026-09-23T08:00:00+09:00"
True     # 文字列の比較

>>> from datetime import datetime
>>> datetime.fromisoformat("2026-09-23T08:00:00+09:00") > datetime.fromisoformat("2026-09-23T00:00:00+00:00")
False    # 時刻としての比較

JST 8:00 は UTC で前日 23:00。時刻としては前なのに、文字列では後になります。複数システムのログを混ぜるときに起きやすいです。

対処:比較する前に日時型へ変換する

Python

from datetime import datetime

FMT = "%Y/%m/%d %H:%M"
start = datetime(2026, 9, 24)

picked = [r for r in rows if datetime.strptime(r, FMT) >= start]
# ['2026/09/24 21:00']

strptime で書式を明示すると、形式違いの値が混ざったときに例外で止まります。

ValueError: time data '2026-09-24 21:00' does not match format '%Y/%m/%d %H:%M'

「件数がなんか変」と後から気づくより圧倒的に早いです。なお 2026/9/5 7:03 のようなゼロ埋めなしも同じ書式で読めます。

JavaScript

スラッシュ区切りをそのまま new Date() に渡すのは避けます。ISO 8601 以外の形式の解釈は仕様上、実装依存です。

function parseSlashDate(s) {
  const [d, t] = s.split(" ");
  const [y, mo, day] = d.split("/").map(Number);
  const [h, mi] = t.split(":").map(Number);
  return new Date(y, mo - 1, day, h, mi); // 月は0始まり
}

const start = new Date(2026, 8, 24); // 9月24日 0:00
rows.filter(r => parseSlashDate(r) >= start);
// [ '2026/09/24 21:00' ]

ISO 8601 の形でも、日付のみか時刻付きかで解釈が変わる点に注意です(JST 環境で確認)。

new Date("2026-09-24").toISOString()       // 2026-09-24T00:00:00.000Z(UTC扱い)
new Date("2026-09-24T00:00").toISOString() // 2026-09-23T15:00:00.000Z(ローカル扱い)

比較する両辺は同じ方法で生成しましょう。

文字列比較で問題ない条件

以下をすべて満たすなら、辞書順=時間順になります。

  • 書式と桁数が統一されている(年4桁、月日時分は2桁ゼロ埋め)
  • 区切り記号と、日付・時刻のつなぎ(T / 空白)が統一されている
  • タイムゾーンが統一されている(例:すべて UTC + Z)
  • 日付のみの値と日時の値が混ざっていない

ISO 8601 で保存された DB の列などは満たしやすく、表示用の値・手入力値・複数ソースから集めた値は崩れやすいです。

まとめ

症状 原因 対処
全件 or 0件 区切り記号の不一致 日時型に変換して比較
桁が変わる境目だけ順序が崩れる ゼロ埋めなし 書式指定で変換
終わりの日が丸ごと抜ける 日付のみの値と比較 < 翌日0時 で書く
一部の時刻だけ前後逆転 T/空白の混在・TZ表記差 型変換+TZ統一
JS で9時間ずれる 日付のみの形は UTC 解釈 両辺を同じ方法で生成

おかしな件数が出たら、比較式をいじる前に 比べている2つの値を1件ずつ print する。これが一番の近道でした。

参考

元になった作業の記録(AI 側の視点):
https://kujiragames.com/2026/09/compare-date-strings/

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?