Python で文字列を日時データに変換,時分秒の切り捨て,日時の比較,日時データの数え上げ

1. エグゼクティブサマリー

本記事では,Python を用いて文字列を日時データ(datetime.datetime 型)に変換する方法,時分秒の切り捨て,日時の比較,および日時データの数え上げについて解説する。

具体的には,以下の処理を扱う。

タイムゾーン情報(+09:00 等)を含む日時文字列の扱いを前提とし,datetime モジュールの strptime/strftime による変換,timestamp() による数値演算,timedelta による日時計算,および pandas DataFrame との連携を実例とともに示す。

2. 前準備(必要ソフトウェアの入手)

ここでは、最低限の事前準備について説明する。機械学習や深層学習を行う場合は、NVIDIA CUDA、Visual Studio、Cursorなどを追加でインストールすると便利である。これらについては別ページ https://www.kkaneko.jp/cc/dev/aiassist.htmlで詳しく解説しているので、必要に応じて参照してください。

Python 3.12 のインストール(Windows 上) [クリックして展開]

以下のいずれかの方法で Python 3.12 をインストールする。Python がインストール済みの場合、この手順は不要である。

方法1:winget によるインストール

管理者権限コマンドプロンプトで以下を実行する。管理者権限のコマンドプロンプトを起動するには、Windows キーまたはスタートメニューから「cmd」と入力し、表示された「コマンドプロンプト」を右クリックして「管理者として実行」を選択する。

winget install --scope machine --id Python.Python.3.12 -e --silent --disable-interactivity --force --accept-source-agreements --accept-package-agreements --override "/quiet InstallAllUsers=1 PrependPath=1 Include_pip=1 Include_test=0 Include_launcher=1 InstallLauncherAllUsers=1"

--scope machine を指定することで、システム全体(全ユーザー向け)にインストールされる。このオプションの実行には管理者権限が必要である。インストール完了後、コマンドプロンプトを再起動すると PATH が自動的に設定される。

方法2:インストーラーによるインストール

  1. Python 公式サイト(https://www.python.org/downloads/)にアクセスし、「Download Python 3.x.x」ボタンから Windows 用インストーラーをダウンロードする。
  2. ダウンロードしたインストーラーを実行する。
  3. 初期画面の下部に表示される「Add python.exe to PATH」に必ずチェックを入れてから「Customize installation」を選択する。このチェックを入れ忘れると、コマンドプロンプトから python コマンドを実行できない。
  4. 「Install Python 3.xx for all users」にチェックを入れ、「Install」をクリックする。

インストールの確認

コマンドプロンプトで以下を実行する。

python --version

バージョン番号(例:Python 3.12.x)が表示されればインストール成功である。「'python' は、内部コマンドまたは外部コマンドとして認識されていません。」と表示される場合は、インストールが正常に完了していない。

AIエディタ Windsurf のインストール(Windows 上) [クリックして展開]

Pythonプログラムの編集・実行には、AIエディタの利用を推奨する。ここでは、Windsurfのインストールを説明する。Windsurf がインストール済みの場合、この手順は不要である。

管理者権限コマンドプロンプトで以下を実行する。管理者権限のコマンドプロンプトを起動するには、Windows キーまたはスタートメニューから「cmd」と入力し、表示された「コマンドプロンプト」を右クリックして「管理者として実行」を選択する。

winget install --scope machine --id Codeium.Windsurf -e --silent --disable-interactivity --force --accept-source-agreements --accept-package-agreements --custom "/SP- /SUPPRESSMSGBOXES /NORESTART /CLOSEAPPLICATIONS /DIR=""C:\Program Files\Windsurf"" /MERGETASKS=!runcode,addtopath,associatewithfiles,!desktopicon"
powershell -Command "$env:Path=[System.Environment]::GetEnvironmentVariable('Path','Machine')+';'+[System.Environment]::GetEnvironmentVariable('Path','User'); windsurf --install-extension MS-CEINTL.vscode-language-pack-ja --force; windsurf --install-extension ms-python.python --force; windsurf --install-extension Codeium.windsurfPyright --force"

--scope machine を指定することで、システム全体(全ユーザー向け)にインストールされる。このオプションの実行には管理者権限が必要である。インストール完了後、コマンドプロンプトを再起動すると PATH が自動的に設定される。

関連する外部ページ

Windsurf の公式ページ: https://windsurf.com/

必要なライブラリのインストール [クリックして展開]

管理者権限コマンドプロンプトで以下を実行する。管理者権限のコマンドプロンプトを起動するには,Windows キーまたはスタートメニューから「cmd」と入力し,表示された「コマンドプロンプト」を右クリックして「管理者として実行」を選択する。

pip install -U pandas

本記事のプログラムでは,標準ライブラリの datetime に加え,外部ライブラリの pandas を使用する。datetime は Python に標準で含まれるため,別途インストールは不要である。

3. 実行のための準備とその確認手順(Windows 前提)

3.1 プログラムファイルの準備

第5章に掲載するソースコードをテキストエディタ(メモ帳,Windsurf 等)に貼り付け,main.py として保存する(文字コード:UTF-8)。本記事には複数の独立したコードブロックが含まれる。各コードブロックは単独で実行可能であるため,確認したいコードブロックの内容を main.py に貼り付けて保存し,順に実行する。

3.2 実行コマンド

コマンドプロンプトでファイルの保存先ディレクトリに移動し,以下を実行する。

cd ファイルの保存先ディレクトリ
python main.py

3.3 動作確認チェックリスト

確認項目期待される結果
文字列を datetime.datetime 型に変換するコードの実行変換後の日時 2020-06-30 13:00:00+09:00 とタイムゾーン情報 UTC+09:00 が表示される
その日の 0時 0分を取得するコードの実行2020-06-30 00:00:00+09:00 とタイムゾーン情報が表示される
0時 0分からの経過秒数を求めるコードの実行41904.0 が表示される
分の始めからの経過秒数を求めるコードの実行日時と経過秒数 24.0 が表示される
60秒前の日時を求めるコードの実行元の日時と60秒前の日時が表示される
2つの日時の差を日数で求めるコードの実行9 が表示される
日時の比較コードの実行basetime 以降の日時に対して True,以前の日時に対して False が表示される
300秒ごとの数え上げコードの実行300秒区間ごとの件数が value_counts の結果として表示される
日付による行選択コードの実行指定した日付と同じ日のデータのみが選択・表示される
datetime.datetime 型を文字列に変換するコードの実行2020/06/30 13:00:00 および 2020年06月30日 が表示される

4. 概要・使い方・実行上の注意

4.1 文字列を datetime.datetime 型に変換

次のような日時を表す文字列があるとする。

"2017-7-1 11:38:24"

文字列datetime.datetime 型に変換するには,datetime.strptime メソッドを使用する。書式文字列 %Y-%m-%d %H:%M:%S %z を指定することで,年・月・日・時・分・秒・タイムゾーンを含む文字列を解析できる。

4.2 秒,分,時の切り捨て

その日の 0時 0分の取得は,datetime.datetime 型の年・月・日のみを使って新たな datetime オブジェクトを生成することで実現する。結果は datetime.datetime 型で得る。

その日の 0時 0分から,何秒経過したかは,timestamp() メソッドで Unix タイムスタンプに変換し,その差を算出することで求める。

「分の始め」から何秒経過したかは,秒以下を切り捨てた datetime オブジェクトを生成し,元の日時との timestamp() の差を求めることで算出する。

4.3 日時の引き算

ある日時の 60 秒前を求めるには,timedelta(seconds=delta) を日時から減算する。

2つの日時の差を日数で求めるには,datetime オブジェクト同士の減算結果(timedelta 型)の days 属性を参照する。

実行結果として 9 が表示される。

4.4 日時の比較

グローバル変数 basetime で設定された日時以降なら True を返す。datetime オブジェクト同士は比較演算子(><== 等)で直接比較できる。

4.5 日時の数え上げ

次のようなデータがあるとする。日時を 300 秒ごとに区切って value_counts を使って数え上げを行う。経過秒数を 300 で整数除算し,再び 300 を乗じることで,300秒単位の区間に丸めている。

"2020-07-11 0:0:0" と同じ日のデータだけを選択するには,compare_by_date 関数を使用する。この関数は,指定した基準日と同じ日付(0時 0分の比較)かどうかを判定するラムダ関数を返す。

DataFrame に対して日付による選択を行う場合は,map メソッドで compare_by_date を各行に適用し,条件に合致する行を抽出する。

4.6 datetime.datetime 型を文字列に変換

datetime.datetime 型のデータを,指定した書式の文字列に変換するには strftime メソッドを使用する。書式文字列を変更することで,さまざまな形式の文字列を出力できる。

実行結果として 2020/06/30 13:00:00 および 2020年06月30日 が表示される。

5. ソースコード

5.1 文字列を datetime.datetime 型に変換

文字列datetime.datetime 型に変換

from datetime import datetime as dt

# 文字列を datetime.datetime 型に変換
def to_datetime(x):
    return dt.strptime(x, "%Y-%m-%d %H:%M:%S %z")

x = to_datetime("2020-06-30 13:00:00 +09:00")
print(x)
print(x.tzinfo)

5.2 秒,分,時の切り捨て

その日の 0時 0分の取得。結果は datetime.datetime 型で得る

from datetime import datetime as dt

# 文字列を datetime.datetime 型に変換
def to_datetime(x):
    return dt.strptime(x, "%Y-%m-%d %H:%M:%S %z")

# その日の 0時 0分。パラメータは datetime.datetime 型
def first_of_day(x):
    return dt(x.year, x.month, x.day, tzinfo=x.tzinfo)

x = to_datetime("2020-06-30 13:00:00 +09:00")
print(first_of_day(x))
print(first_of_day(x).tzinfo)

その日の 0時 0分から,何秒経過したかを表示

from datetime import datetime as dt

# 文字列を datetime.datetime 型に変換
def to_datetime(x):
    return dt.strptime(x, "%Y-%m-%d %H:%M:%S %z")

# その日の 0時 0分。パラメータは datetime.datetime 型
def first_of_day(x):
    return dt(x.year, x.month, x.day, tzinfo=x.tzinfo)

# その日の 0時 0分から,何秒経過したか
def elapsed(x):
    return x.timestamp() - first_of_day(x).timestamp()

x = to_datetime("2020-7-1 11:38:24 +09:00")
# 41904.0 が表示される
print(elapsed(x))

「分の始め」から何秒経過したかを表示

from datetime import datetime as dt

# 文字列を datetime.datetime 型に変換
def to_datetime(x):
    return dt.strptime(x, "%Y-%m-%d %H:%M:%S %z")

# 秒以下を切り捨て。パラメータは datetime.datetime 型
def first_of_minute(x):
    return dt(x.year, x.month, x.day, x.hour, x.minute, tzinfo=x.tzinfo)

x = to_datetime("2020-7-1 11:38:24 +09:00")
print(x)
print(x.timestamp() - first_of_minute(x).timestamp())

5.3 日時の引き算

ある日時の 60 秒前

from datetime import datetime as dt
from datetime import timedelta

# 文字列を datetime.datetime 型に変換
def to_datetime(x):
    return dt.strptime(x, "%Y-%m-%d %H:%M:%S %z")

# 指定した秒数だけ前の日時を返す
def past_time(x, delta):
    return x - timedelta(seconds=delta)

x = to_datetime("2020-7-1 11:38:24 +09:00")
print(x)
print(past_time(x, 60))

2つの日時の差を日数で求める

from datetime import datetime as dt

# 文字列を datetime.datetime 型に変換
def to_datetime(x):
    return dt.strptime(x, "%Y-%m-%d %H:%M:%S %z")

# 2つの日時の差を日数で返す
def days_between(a, b):
    return (a - b).days

x = to_datetime("2020-7-10 11:38:24 +09:00")
y = to_datetime("2020-7-1 11:38:24 +09:00")
print(days_between(x, y))

5.4 日時の比較

グローバル変数 basetime で設定された日時以降なら True

from datetime import datetime as dt

# 文字列を datetime.datetime 型に変換
def to_datetime(x):
    return dt.strptime(x, "%Y-%m-%d %H:%M:%S %z")

basetime = to_datetime("2020-06-30 09:00:00 +09:00")

def time_selection(x):
    return x > basetime

x = to_datetime("2020-7-1 11:38:24 +09:00")
print(x)
print(time_selection(x))

y = to_datetime("2020-6-29 11:38:24 +09:00")
print(y)
print(time_selection(y))

5.5 日時の数え上げ

日時を 300 秒ごとに区切って value_counts を使って数え上げを行う

import pandas as pd
from datetime import datetime as dt

# 文字列を datetime.datetime 型に変換
def to_datetime(x):
    return dt.strptime(x, "%Y-%m-%d %H:%M:%S %z")

m1 = pd.DataFrame([
    [1, "2020-7-1 11:38:00 +09:00"],
    [2, "2020-7-1 11:38:00 +09:00"],
    [4, "2020-7-1 11:39:00 +09:00"],
    [5, "2020-7-1 11:40:00 +09:00"],
    [6, "2020-7-1 11:40:00 +09:00"],
    [7, "2020-7-1 11:40:00 +09:00"]
],
columns=['id', 'datetime'])

# その日の 0時 0分。パラメータは datetime.datetime 型
def first_of_day(x):
    return dt(x.year, x.month, x.day, tzinfo=x.tzinfo)

# その日の 0時 0分から,何秒経過したか
def elapsed(x):
    return x.timestamp() - first_of_day(x).timestamp()

x = (m1.datetime.map(to_datetime).map(elapsed) // 300) * 300
print(x.value_counts(sort=True, ascending=True))

"2020-07-11 0:0:0" と同じ日のデータだけを選択する

from datetime import datetime as dt

# 文字列を datetime.datetime 型に変換
def to_datetime(x):
    return dt.strptime(x, "%Y-%m-%d %H:%M:%S %z")

# その日の 0時 0分。パラメータは datetime.datetime 型
def first_of_day(x):
    return dt(x.year, x.month, x.day, tzinfo=x.tzinfo)

def compare_by_date(base):
    return lambda x: first_of_day(to_datetime(x)) == first_of_day(to_datetime(base))

print(compare_by_date("2020-07-11 0:0:0 +09:00")("2020-07-11 10:0:0 +09:00"))
print(compare_by_date("2020-07-11 0:0:0 +09:00")("2020-07-12 10:0:0 +09:00"))

DataFrame に対して日付による選択を行う

import pandas as pd
from datetime import datetime as dt

# 文字列を datetime.datetime 型に変換
def to_datetime(x):
    return dt.strptime(x, "%Y-%m-%d %H:%M:%S %z")

# その日の 0時 0分。パラメータは datetime.datetime 型
def first_of_day(x):
    return dt(x.year, x.month, x.day, tzinfo=x.tzinfo)

def compare_by_date(base):
    return lambda x: first_of_day(to_datetime(x)) == first_of_day(to_datetime(base))

m2 = pd.DataFrame([
    [1, "2020-7-1 11:38:00 +09:00"],
    [2, "2020-7-1 11:38:00 +09:00"],
    [4, "2020-7-1 11:39:00 +09:00"],
    [5, "2020-7-1 11:40:00 +09:00"],
    [6, "2020-7-2 3:10:00 +09:00"],
    [7, "2020-7-2 3:10:00 +09:00"]
],
columns=['id', 'datetime'])

print('----')
print(m2[m2.datetime.map(compare_by_date("2020-07-1 0:0:0 +09:00"))])
print('----')
print(m2[m2.datetime.map(compare_by_date("2020-07-2 0:0:0 +09:00"))])

5.6 datetime.datetime 型を文字列に変換

datetime.datetime 型を任意の書式で文字列に変換する

from datetime import datetime as dt

# 文字列を datetime.datetime 型に変換
def to_datetime(x):
    return dt.strptime(x, "%Y-%m-%d %H:%M:%S %z")

# datetime.datetime 型を文字列に変換
def to_string(x, fmt="%Y/%m/%d %H:%M:%S"):
    return x.strftime(fmt)

x = to_datetime("2020-06-30 13:00:00 +09:00")
print(to_string(x))
print(to_string(x, "%Y年%m月%d日"))

6. まとめ

strptime による文字列から datetime.datetime 型への変換

datetime.strptime メソッドに書式文字列 %Y-%m-%d %H:%M:%S %z を指定することで,タイムゾーン情報を含む日時文字列を datetime.datetime 型に変換できる。

時分秒の切り捨てによる日時の丸め

datetime.datetime 型の年・月・日(および必要に応じて時・分)のみを使って新たな datetime オブジェクトを生成することで,その日の 0時 0分や分の始めの時刻を取得できる。timestamp() の差を求めることで経過秒数も算出できる。

timedelta を用いた日時の引き算

timedelta(seconds=delta) を日時から減算することで,指定した秒数だけ前の日時を求められる。また,datetime オブジェクト同士の減算結果(timedelta 型)の days 属性を参照することで,2つの日時の差を日数で求められる。

datetime オブジェクト同士の比較

datetime オブジェクト同士は比較演算子で直接比較できる。グローバル変数に基準日時を設定し,対象の日時が基準以降かどうかを True/False で判定する方法を示した。

pandas の value_counts を使った日時の数え上げ

経過秒数を一定の秒数(300秒)で整数除算し再び乗じることで,日時を一定区間に丸めて数え上げを行える。pandas DataFrame の map メソッドと value_counts を組み合わせることで,日時データの集計が可能である。