Pythonで日時や日付オブジェクトを扱う方法

環境

  • Windows 10
  • Python 3.10.1
  • VSCode

使用するソースコード

以下の公開リポジトリに置いています

GitHub - masayan1126/tao-py-py: 作業自動化用 Python ライブラリ
作業自動化用 Python ライブラリ. Contribute to masayan1126/tao-py-py development by creating an account on GitHub.

datetimeモジュール

標準ライブラリのdatetimeモジュールを使う

datetimeモジュールには以下のようなクラスが用意されている

クラス名内容
datetime.datetime日時(日付と時刻)

year, month, day, hour, minute, second, microsecond のプロパティをもつ

datetime.date日付
 

datetime.time

時刻

year、month、day のプロパティをもつ

datetime.timedelta時差等
本記事では、主にdatetimeとdateを中心に扱いますのでご留意ください

日時(日付)と文字列の相互変換

日時や日付を表す文字列から日時(日付)オブジェクトを作成したり、あるいはその逆の処理が高頻度で必要となることがしばしばあります

文字列から日時(日付)オブジェクト

文字列から日時オブジェクト

datetime.strptime()で日時文字列とフォーマット文字列を渡すと、日時オブジェクトを生成できます

import datetime

tdatetime = datetime.datetime.strptime(
    "2022-4-6 18:20:10", "%Y-%m-%d %H:%M:%S"
)  # datetimeオブジェクト(year: 2022, month: 4, day: 6, hour: 18, minute: 20, second: 10)

文字列から日付オブジェクト

datetime.date()で日付文字列とフォーマット文字列を渡すと、日付オブジェクトを生成できます
import datetime

dt = datetime.datetime.strptime("2022/4/6", "%Y/%m/%d")
date = datetime.date(
    dt.year, dt.month, dt.day
)  # dateオブジェクト(year: 2022, month: 4, day: 6)
datetimeオブジェクトはdate()メソッドでdateオブジェクトに変換可能です。

日時(日付)オブジェクトから文字列

こちらは、日時オブジェクトも日付オブジェクトも同じ方法(strftimeメソッド)で変換可能

日時オブジェクトから文字列

import datetime

# datetimeオブジェクト(year: 2022, month: 4, day: 6, hour: 0, minute: 0, second: 0)
dt = datetime.datetime.strptime("2022/4/6", "%Y/%m/%d")
date_str = dt.strftime("%Y年%m月%d日")  # 文字列 '2022年04月06日'

日付オブジェクトから文字列

import datetime

# dateオブジェクト(year: 2022, month: 4, day: 6)
dt = datetime.date(year=2022, month=4, day=6)
date_str = date.strftime("%Y年%m月%d日")  # 文字列 '2022年04月06日'

なお、相互変換の方法としては、上記の方法かISO8601の形式で処理する方法の2パターンが存在する

変換方法詳細
日付(日時)文字列と日時(日付)オブジェクト特に指定なし(以下のような形式も許容される)

  • “%Y/%m/%d”
  • “%Y/%m/%d %H:%M:%S”
ISO形式8601形式の日付(日時)文字列と日時(日付)オブジェクトY-m-dの形式を守る必要がある
方法がいろいろあって便利ですが混乱しやすいので、個人的には、ISO形式で必要に応じて相互変換を行い、ISO形式以外のフォーマットで日付文字列を生成したい場合に上記のstrftimeを使用するというのがわかりやすくてよいのではないかと考えています

ISO形式での日時(日付)と文字列の相互変換

文字列から日時オブジェクト

fromisoformat()

import datetime

dt = datetime.datetime.fromisoformat(
    "2022-12-29 20:10:05"
)  # datetimeオブジェクト(year: 2022, month: 12, day: 29, hour: 20, minute: 10, second: 5)

文字列から日付オブジェクト

fromisoformat()

import datetime

date = datetime.date.fromisoformat("2022-12-29")
masayan
masayan

ISO形式で日付文字列を渡しさえすればいいので、シンプルに書けますね。

日時オブジェクトから文字列

isoformat()

import datetime

date_str = (
    datetime.datetime.now().isoformat()
)  # プログラムを実行した日時 '2022-04-07T08:56:24.315226'

isoformat()

日付オブジェクトから文字列

import datetime

date_str = datetime.date.today().isoformat()  # プログラムを実行した日付 '2022-04-07'
masayan
masayan

こちらも、ISO形式で日付文字列を渡しさえすればいいので、シンプルに書けますね。

日時・日付を管理する自作クラス

とはいえ、メソッド名がわかりにくくて使いづらかったりして煩わしいので、これらを専用のクラスを管理する自作クラスを用意し、それらに必要なメソッドとして持たせる作成することで管理しやすくするのが吉です

日時

  • コンストラクタで日付文字列を受け取る
  • プロパティとしてdatetimeオブジェクトを保有しておく
  • 保有しているdatetimeオブジェクトをもとにyearやmonthなどの情報をgetterで呼び出せるように
  • 現在時刻を取得したいケースも結構あるので、メソッドとして用意しておく(時差の計算が必要となるため、ここで初めてdatetimeのtimedeltaを使用しています)

shared\Domain\Time\x_date_time.py

import datetime

class XDateTime:
    def __init__(self, date_time_str: str) -> None:
        try:
            # Y-m-d形式(例.2012-02-21)
            # 年月日時間分秒のどれかが省略されていたり、桁数が合っていなかったりするとValueError。
            self._datetime = datetime.datetime.fromisoformat(date_time_str)

        except ValueError:
            raise ValueError

    def datetime(self):
        return self._datetime

    def year(self) -> str:
        return self.format("%Y")

    def month(self) -> str:
        return self.format("%m")

    def day(self) -> str:
        return self.format("%d")

    def hour(self) -> str:
        return self.format("%H")

    def minutes(self) -> str:
        return self.format("%M")

    def seconds(self) -> str:
        return self.format("%S")

    @staticmethod
    def now():
        # timezoneを指定するとdatetimeの生成が早くなる
        t_delta = datetime.timedelta(hours=9)
        # 日本標準時
        jst = datetime.timezone(t_delta, "JST")
        now_str = datetime.datetime.now(jst).isoformat()

        return XDateTime(now_str)

    def format(self, format: str):
        # isoformat(Y-m-d)以外のフォーマットで取得したい場合に使用
        # format文字列は"%Y年%m月%d日%H時%M分%S秒"など
        # localにより、%Yなどの文字列は何を取得できるかが変わる
        # ここではエラーハンドリングしない。文字列が渡ってきさえすれば変換は可能。呼び出し側の記述が守れていればOKなため
        return self.datetime().strftime(format)
masayan
masayan

コンストラクタで初期化する際、ISO形式でない文字列がわたってきた場合はすぐに例外をthrowしてプログラムを落とします

formatメソッドは、ISO形式のフォーマット以外の日時文字列が欲しい場合に使用します

日付

基本的にはXDateTime.pyと同様の考え方です。

shared\Domain\Time\x_date.py

import datetime

class XDate:
    def __init__(self, date_str: str) -> None:

        try:
            # Y-m-d形式(例.2012-02-21)
            # 年月日が省略されていたり、桁数が合っていなかったりするとValueError。
            self._date = datetime.date.fromisoformat(date_str)
        except ValueError:
            raise ValueError

    def date(self):
        return self._date

    def year(self) -> str:
        return self.format("%Y")

    def month(self) -> str:
        return self.format("%m")

    def day(self) -> str:
        return self.format("%d")

    @staticmethod
    def today():
        date_str = datetime.date.today().isoformat()
        return XDate(date_str)

    def format(self, format: str):
        # isoformat(Y-m-d)以外のフォーマットで取得したい場合に使用
        # format文字列は"%Y年%m月%d日"など
        # localにより、%Yなどの文字列は何を取得できるかが変わる
        # ここではエラーハンドリングしない。文字列が渡ってきさえすれば変換は可能。呼び出し側の記述が守れていればOKなため
        return self.date().strftime(format)

主な日付のフォーマット

最後に、主なフォーマット文字列を載せておきます

この文字列はlocalにより異なりますので注意ください
書式説明
%Y年 西暦4桁(例、2021)
%y年 西暦2桁(例、21)
%m月2桁(例、12)
%d日2桁(例、31)
%H時 24時間表記(例、14)
%I時 12時間表記(例、02)
%pAM、PM
%M分2桁
%S秒2桁
%fマイクロ秒6桁

Python学習におすすめの書籍

独習Python/山田祥寛【3000円以上送料無料】
bookfan 1号店 楽天市場店
¥ 3,300(2022/08/04 17:32時点)
タイトルとURLをコピーしました