Outlookの予定を自動処理するPythonスクリプトを書いていて、終日イベント(AllDayEvent)の扱いに関して面白い罠にハマりました。
同じような問題で困っている方のために、問題の原因と解決方法をご紹介します。
発生した問題
在宅勤務の予定を自動作成するスクリプトで、「特定の日に在宅勤務の予定が既に存在するかチェックする」機能を実装していました。
ところが、前日や翌日の在宅勤務予定が誤って検出されるという問題が発生しました。
具体的には:
- 1月20日を検索したのに、1月19日の在宅勤務予定が引っかかる
- 1月20日を検索したのに、1月21日の在宅勤務予定も引っかかる
原因:終日イベントの時間表現
調査の結果、Outlookの終日イベントは以下のように時刻が設定されることがわかりました。
1月20日の終日イベント
- 開始:
2026-01-20 00:00:00 - 終了:
2026-01-21 00:00:00(翌日の0時)
つまり、終日イベントは「その日の00:00から翌日の00:00まで」として扱われるのです。
なぜ誤検出が起きたか
当初のフィルター条件はこうでした:
# 1月20日の予定を検索
target_date = datetime(2026, 1, 20, 0, 0, 0)
filter_str = f"[End] >= '{target_date.strftime('%m/%d/%Y %H:%M %p')}'"
この条件だと:
- 1月19日の終日イベント(終了が01/20 00:00)→ 条件に合致してしまう
- 1月21日の終日イベント(開始が01/21 00:00だが、終了が01/22 00:00)→ 条件に合致してしまう
解決方法:開始日で厳密にチェック
終日イベントの存在確認は、開始日がターゲット日と一致するかで判定するように修正しました。
def is_allday_existing(self, appointments, keyword: str, target_date: datetime) -> bool:
"""
指定されたキーワードの終日イベントが、ターゲット日に存在するかチェック
Args:
appointments: 予定のリスト
keyword: 検索キーワード(例: "在宅勤務")
target_date: チェック対象の日付
Returns:
bool: 終日イベントが存在する場合True
"""
target_date_str = target_date.strftime('%Y-%m-%d')
for appt in appointments:
# キーワードが件名に含まれ、かつ終日イベントである
if keyword in appt.Subject and appt.AllDayEvent:
# 開始日がターゲット日と一致するかチェック
appt_start_str = appt.Start.strftime('%Y-%m-%d')
if appt_start_str == target_date_str:
return True
return False
ポイント
-
時刻を無視して日付のみで比較
–
strftime('%Y-%m-%d')で日付部分のみを文字列化 - 開始日ベースで判定 – 終了日ではなく開始日で判定することで、境界問題を回避
- 終日イベント専用の判定関数 – 通常の予定と終日イベントで判定ロジックを分離
注意点
通常の予定検索には使えない
この方法は終日イベント専用です。
時刻を持つ通常の予定(例:14:00-15:00の会議)を検索する場合は、従来通り開始・終了時刻の範囲でフィルタリングする必要があります。
タイムゾーンの考慮
環境によってはタイムゾーンの問題が発生する可能性があります。
PythonのdatetimeオブジェクトとOutlookの日時の間で、タイムゾーン情報が一致しているか確認してください。
まとめ
Outlook終日イベントの時間境界問題についてご紹介しました。
終日イベントは「00:00-翌日00:00」として扱われるため、単純な終了時刻比較では前後の日の予定が誤検出されます。
開始日の厳密チェックで解決できるので、同じ問題に遭遇した方の参考になれば幸いです。
日付(時間)を制するもの、仕事を制す、ということで、バリバリ使っていこうと思います。

コメント