- Python
Python datetimeの使い方|タイムゾーン・月末計算を実行結果で
Pythonのdatetimeとは、日付・時刻・時間の差を扱うための標準ライブラリです。 import するだけで、現在日時の取得、文字列との相互変換、日数の足し引き、タイムゾーン変換ができます。
この記事では、よく使う操作を「やりたいこと」ごとにまとめ、すべてのコードを Python 3.14.7 で実際に実行した出力 つきで載せています。utcnow() が3.12から出す警告、naive と aware を混ぜたときの実際の TypeError、fromisoformat() が3.10と3.11で受け付ける文字列の違い、月末・1か月後・営業日の計算まで、実務で必要になる部分を一通り確認できます。
Python datetimeの早見表
| やりたいこと | 書き方 | 結果の例 |
|---|---|---|
| 現在日時(ローカル) | datetime.now() |
2026-09-29 14:50:20.575689 |
| 現在日時(UTC) | datetime.now(UTC) |
2026-09-29 05:50:20+00:00 |
| 現在日時(日本時間) | datetime.now(ZoneInfo("Asia/Tokyo")) |
...+09:00 |
| 今日の日付 | date.today() |
2026-09-29 |
| 日時を作る | datetime(2026, 9, 28, 14, 5) |
2026-09-28 14:05:00 |
| 日時 → 文字列 | d.strftime("%Y/%m/%d") |
2026/09/28 |
| 文字列 → 日時 | datetime.strptime(s, "%Y/%m/%d") |
datetime(2026, 9, 28, 0, 0) |
| ISO形式の文字列 → 日時 | datetime.fromisoformat(s) |
Z 付きも3.11以降で可 |
| 7日後 | d + timedelta(days=7) |
|
| 日付の差(日数) | (d2 - d1).days |
88 |
| 差を秒・時間で | delta.total_seconds() |
55800.0 |
| 月末日 | calendar.monthrange(y, m)[1] |
28 |
| 1か月後 | d + relativedelta(months=1) |
1/31 → 2/28 |
| 曜日 | d.weekday() |
月曜=0 |
| JST → UTC | d.astimezone(UTC) |
|
| UNIX時間 → 日時 | datetime.fromtimestamp(ts, UTC) |
|
| 日時 → UNIX時間 | d.timestamp() |
1790553600.0 |
| 処理時間の計測 | time.perf_counter() |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Python datetimeの使い方|タイムゾーン・月末計算を実行結果で」
以降のコードは、先頭に次の import がある前提です(各コードにも必要なものを書いています)。UTC は Python 3.11 で追加された timezone.utc の別名です。3.10以前では from datetime import timezone として timezone.utc と書きます。
from datetime import datetime, date, time, timedelta, UTC
from zoneinfo import ZoneInfo
date・time・datetime・timedeltaの使い分け
datetimeモジュールには4つの主要なクラスがあり、「何を表したいか」で選びます。
| クラス | 表すもの | 作り方の例 | 向いている用途 |
|---|---|---|---|
date |
日付だけ | date(2026, 9, 28) |
締め日、誕生日、日単位の集計 |
time |
時刻だけ | time(9, 30) |
始業時刻、毎日の実行時刻 |
datetime |
日付+時刻 | datetime(2026, 9, 28, 9, 30) |
登録日時、ログ、予約日時 |
timedelta |
時間の長さ(差) | timedelta(days=7) |
〇日後、経過時間、期限までの残り |
timezone / ZoneInfo |
タイムゾーン | ZoneInfo("Asia/Tokyo") |
日時に付けて aware にする |
変換もよく使うので、あわせて確認しておきます。
from datetime import datetime, date, time
now = datetime(2026, 9, 28, 14, 0)
print(now.date(), now.time()) # datetime → date / time
print(datetime.combine(date(2026, 9, 28), time(9, 0))) # date + time → datetime
2026-09-28 14:00:00
2026-09-28 09:00:00
※1行目は print がスペース区切りで 2026-09-28 と 14:00:00 を出しています。
datetime と date は比較できません。 片方に揃えてから比べます。
try:
print(now < date(2026, 9, 29))
except TypeError as e:
print("TypeError:", e)
TypeError: '<' not supported between instances of 'datetime.datetime' and 'datetime.date'
→ now.date() < date(2026, 9, 29) のように date に揃えると比較できます。
現在日時を取得する
from datetime import datetime, date, UTC
from zoneinfo import ZoneInfo
print(datetime.now()) # ローカル時刻(naive)
print(datetime.now(UTC)) # UTCの現在時刻(aware)
print(datetime.now(ZoneInfo("Asia/Tokyo"))) # 日本時間(aware)
print(date.today()) # 今日の日付
実行結果(Python 3.14.7、環境変数 TZ=Asia/Tokyo):
2026-09-29 14:50:20.575689
2026-09-29 05:50:20.575724+00:00
2026-09-29 14:50:20.575879+09:00
2026-09-29
datetime.now() の結果はサーバーのタイムゾーン設定で変わります。 日本のPCでは日本時間ですが、クラウドのサーバーやコンテナはUTCになっていることが多いです。どの環境でも同じ意味にしたいときは、now(UTC) か now(ZoneInfo("Asia/Tokyo")) のようにタイムゾーンを明示するのが確実です。
utcnow()は3.12から非推奨:now(UTC)に置き換える
datetime.utcnow() は Python 3.12 で非推奨になり、実行すると DeprecationWarning が出ます。 公式ドキュメントでも datetime.now(UTC) を使うよう案内されています。
import warnings
warnings.simplefilter("default") # 警告を表示する設定
from datetime import datetime
print(datetime.utcnow())
実行結果(Python 3.14.7):
02_utcnow.py:4: DeprecationWarning: datetime.datetime.utcnow() is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC: datetime.datetime.now(datetime.UTC).
print(datetime.utcnow())
2026-09-29 05:50:20.744014
同じコードを Python 3.10.20 で実行すると、警告は出ずに時刻だけが表示されました。
utcnow() は「UTCの時刻なのにタイムゾーン情報を持たない(naive)」値を返すため、あとで astimezone() や timestamp() を使うとローカル時刻と誤解されることがあります。utcfromtimestamp() も同様に3.12から非推奨です。
| 置き換え前 | 置き換え後 |
|---|---|
datetime.utcnow() |
datetime.now(UTC) |
datetime.utcfromtimestamp(ts) |
datetime.fromtimestamp(ts, UTC) |
naiveとawareの違い
naive(ナイーブ)はタイムゾーン情報を持たない日時、aware(アウェア)はタイムゾーン情報を持つ日時です。 tzinfo 属性が None なら naive です。
| naive | aware | |
|---|---|---|
tzinfo |
None |
UTC、ZoneInfo("Asia/Tokyo") など |
| 作り方 | datetime.now()、datetime(2026, 9, 28)、strptime(%zなし) |
datetime.now(UTC)、tzinfo= を指定 |
| 表示 | 2026-09-28 12:00:00 |
2026-09-28 12:00:00+00:00 |
| 向いている場面 | 1つのタイムゾーンだけで完結する処理 | サーバー・API・DBとのやり取り、複数地域 |
naiveとawareを混ぜたときのエラー
from datetime import datetime, UTC
naive = datetime(2026, 9, 28, 12, 0)
aware = datetime(2026, 9, 28, 12, 0, tzinfo=UTC)
print(naive.tzinfo, aware.tzinfo)
try:
print(aware - naive)
except TypeError as e:
print("TypeError:", e)
try:
print(aware < naive)
except TypeError as e:
print("TypeError:", e)
print(aware == naive) # == はエラーにならず False
実行結果(Python 3.14.7):
None UTC
TypeError: can't subtract offset-naive and offset-aware datetimes
TypeError: can't compare offset-naive and offset-aware datetimes
False
引き算と大小比較は TypeError、== はエラーにならず常に False になります。== は気づきにくいので、プログラム内では aware に統一するのがおすすめです。外部から naive が来たら、次の章の replace(tzinfo=...) で aware にしてから使います。
zoneinfoで日本時間(JST)とUTCを変換する
Python 3.9以降は標準ライブラリの zoneinfo でタイムゾーンを扱えます。 以前よく使われた pytz は不要です。
from datetime import datetime, UTC
from zoneinfo import ZoneInfo
JST = ZoneInfo("Asia/Tokyo")
jst = datetime(2026, 9, 28, 9, 30, tzinfo=JST) # 日本時間の日時を作る
print(jst)
utc = jst.astimezone(UTC) # JST → UTC
print(utc)
print(utc.astimezone(JST)) # UTC → JST
naive = datetime(2026, 9, 28, 9, 30)
print(naive.replace(tzinfo=JST)) # naiveを「日本時間だった」として aware に
print(jst.astimezone(ZoneInfo("America/New_York"))) # 別の地域の時刻へ
実行結果(Python 3.14.7):
2026-09-28 09:30:00+09:00
2026-09-28 00:30:00+00:00
2026-09-28 09:30:00+09:00
2026-09-28 09:30:00+09:00
2026-09-27 20:30:00-04:00
replace(tzinfo=) と astimezone() は意味が違います。
| メソッド | すること | 時刻の数字 |
|---|---|---|
replace(tzinfo=JST) |
タイムゾーン情報を「付け替える」 | 変わらない(9:30のまま) |
astimezone(UTC) |
同じ瞬間を別のタイムゾーンで表す | 変わる(9:30 JST → 0:30 UTC) |
naive に astimezone() を使うと「実行環境のローカル時刻」とみなされるため、naive を aware にするときは replace(tzinfo=) を使います。
夏時間のある地域も自動で計算される
ZoneInfo は夏時間(DST)の切り替えも反映します。
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
ny = ZoneInfo("America/New_York")
d = datetime(2026, 3, 7, 12, 0, tzinfo=ny)
print(d, d + timedelta(days=1)) # 夏時間の切り替えをまたぐ
2026-03-07 12:00:00-05:00 2026-03-08 12:00:00-04:00
Windowsでは pip install tzdata が必要な場合があります。 zoneinfo はOSのタイムゾーンデータを使い、見つからないときは tzdata パッケージを参照します。ZoneInfoNotFoundError が出たら tzdata を入れてください。日本時間だけなら、固定オフセットの timezone(timedelta(hours=9)) でも表せます。
日時を文字列に変換する(strftime)
from datetime import datetime
d = datetime(2026, 9, 28, 14, 5, 9, 123456)
print(d.strftime("%Y-%m-%d %H:%M:%S"))
print(f"{d:%Y-%m-%d}") # f-stringでも書ける
print(d.isoformat())
print(d.isoformat(timespec="seconds"))
2026-09-28 14:05:09
2026-09-28
2026-09-28T14:05:09.123456
2026-09-28T14:05:09
strftime・strptimeの書式コード一覧
datetime(2026, 9, 28, 14, 5, 9, 123456) を各書式で出力した実行結果です(Python 3.14.7、ロケールはC)。
| 書式 | 意味 | 実行結果 |
|---|---|---|
%Y / %y |
西暦4桁 / 2桁 | 2026 / 26 |
%m |
月(ゼロ埋め2桁) | 09 |
%d |
日(ゼロ埋め2桁) | 28 |
%H / %I |
時(24時間 / 12時間) | 14 / 02 |
%M |
分 | 05 |
%S |
秒 | 09 |
%f |
マイクロ秒(6桁) | 123456 |
%p |
AM/PM | PM |
%a / %A |
曜日(短縮 / 正式) | Mon / Monday |
%b / %B |
月名(短縮 / 正式) | Sep / September |
%j |
年の通算日 | 271 |
%U / %W |
年の週番号(日曜始まり / 月曜始まり) | 39 / 39 |
%G-W%V-%u |
ISO週(年-週-曜日) | 2026-W40-1 |
%z |
UTCからのオフセット | +0900(awareのとき) |
%Z |
タイムゾーン名 | JST(awareのとき) |
%x / %X |
ロケールの日付 / 時刻 | 09/28/26 / 14:05:09 |
%% |
% そのもの |
% |
日本語を混ぜることもできます。d.strftime("%Y年%m月%d日") は 2026年09月28日 になりました。%a や %A はロケールで結果が変わるため、日本語の曜日が欲しいときは次の「曜日」の章の方法が確実です。
文字列を日時に変換する(strptime・fromisoformat)
strptimeで書式を指定して変換する
from datetime import datetime
print(datetime.strptime("2026/09/28 14:05", "%Y/%m/%d %H:%M"))
print(datetime.strptime("2026年9月28日", "%Y年%m月%d日"))
print(datetime.strptime("2026-09-28T14:05:09+0900", "%Y-%m-%dT%H:%M:%S%z"))
try:
datetime.strptime("2026-09-28", "%Y/%m/%d")
except ValueError as e:
print("ValueError:", e)
2026-09-28 14:05:00
2026-09-28 00:00:00
2026-09-28 14:05:09+09:00
ValueError: time data '2026-09-28' does not match format '%Y/%m/%d'
%m や %d は「9」のようなゼロ埋めなしの数字も読めます。 書式と文字列が1文字でも合わないと ValueError になるので、区切り文字(/ と -)を確認します。%z を含めると aware になります。
Python 3.14 から date.strptime() と time.strptime() が追加されました。 日付だけ・時刻だけを直接作れます。
from datetime import date, time
print(date.strptime("2026/09/28", "%Y/%m/%d"))
print(time.strptime("14:05", "%H:%M"))
2026-09-28
14:05:00
3.13以前では datetime.strptime(...).date() のように書きます。
年を含まない文字列は3.13から警告が出る
"02/28" のように年がない文字列を %m/%d で読むと、既定の年は1900年になります。1900年はうるう年ではないため "02/29" が読めません。Python 3.13 からはこの書き方で DeprecationWarning が出ます。
DeprecationWarning: Parsing dates involving a day of month without a year specified is ambiguous
and fails to parse leap day. The default behavior will change in Python 3.15
to either always raise an exception or to use a different default year (TBD).
To avoid trouble, add a specific year to the input & format.
1900-02-28 00:00:00
(Python 3.14.7 で datetime.strptime("02/28", "%m/%d") を実行した結果)
→ 年を補ってから読むと確実です。例:datetime.strptime(f"2026/{s}", "%Y/%m/%d")
fromisoformatはPython 3.11で受け付ける形式が広がった
ISO 8601形式(2026-09-28T14:05:09+09:00 のような形)なら fromisoformat() が書式指定なしで速く読めます。 Python 3.11 で対応範囲が広がり、APIでよく見る末尾の Z も読めるようになりました。同じコードを3.10と3.14で実行した結果です。
from datetime import datetime
for s in ["2026-09-28", "2026-09-28T14:05:09", "2026-09-28 14:05:09+09:00",
"2026-09-28T14:05:09Z", "20260928T140509", "2026-W40-1", "2026-09-28T14:05:09.5+09:00"]:
try:
print(f"{s!r:30} → {datetime.fromisoformat(s)!r}")
except ValueError as e:
print(f"{s!r:30} → ValueError: {e}")
| 入力文字列 | Python 3.10.20 | Python 3.11.15 / 3.14.7 |
|---|---|---|
2026-09-28 |
読める | 読める |
2026-09-28T14:05:09 |
読める | 読める |
2026-09-28 14:05:09+09:00 |
読める | 読める |
2026-09-28T14:05:09Z |
ValueError: Invalid isoformat string |
tzinfo=datetime.timezone.utc で読める |
20260928T140509(区切りなし) |
ValueError |
読める |
2026-W40-1(ISO週) |
ValueError |
datetime(2026, 9, 28, 0, 0) |
2026-09-28T14:05:09.5+09:00(小数秒1桁) |
ValueError |
500000 マイクロ秒で読める |
3.10以前の環境で Z 付きを読むときは s.replace("Z", "+00:00") してから渡すと動きます。
日時の足し算・引き算(timedelta)
from datetime import datetime, date, timedelta
d = datetime(2026, 9, 28, 14, 0)
print(d + timedelta(days=7))
print(d - timedelta(hours=36))
print(d + timedelta(weeks=1, minutes=90))
2026-10-05 14:00:00
2026-09-27 02:00:00
2026-10-05 15:30:00
timedelta に指定できるのは weeks、days、hours、minutes、seconds、milliseconds、microseconds です。months や years はありません(月の長さが一定でないため)。月単位は後の章で扱います。
日付の差を求める
diff = date(2026, 12, 25) - date(2026, 9, 28)
print(diff, type(diff).__name__)
print(diff.days)
delta = datetime(2026, 9, 29, 9, 30) - datetime(2026, 9, 28, 18, 0)
print(delta)
print(delta.total_seconds() / 3600, "時間")
print(delta.seconds, delta.days)
print(date(2026, 9, 1) - date(2026, 9, 28)) # 負の差
88 days, 0:00:00 timedelta
88
15:30:00
15.5 時間
55800 0
-27 days, 0:00:00
差の合計を秒で欲しいときは total_seconds() を使います。 delta.seconds は「日を除いた残りの秒数」なので、1日以上の差では合計になりません。
| 属性・メソッド | 意味 | 使いどころ |
|---|---|---|
.days |
日数部分 | 「残り何日」 |
.seconds |
日を除いた秒(0〜86399) | 時刻部分だけ欲しいとき |
.total_seconds() |
合計秒数(小数) | 時間・分に換算するとき |
月末・月初・1か月後を求める
calendar.monthrangeで月末日を出す
import calendar
from datetime import date, timedelta
y, m = 2026, 2
first_weekday, last_day = calendar.monthrange(y, m)
print(first_weekday, last_day) # 1日の曜日(月=0), 月の日数
print(date(y, m, 1), date(y, m, last_day)) # 月初, 月末
print(calendar.monthrange(2028, 2)) # うるう年
today = date(2026, 9, 28)
print(today.replace(day=calendar.monthrange(today.year, today.month)[1])) # 今月末
nxt = (today.replace(day=1) + timedelta(days=32)).replace(day=1) # 翌月1日
print(nxt - timedelta(days=1)) # その前日=月末
6 28
2026-02-01 2026-02-28
(calendar.TUESDAY, 29)
2026-09-30
2026-09-30
月初は replace(day=1)、月末は calendar.monthrange(y, m)[1] で求められます。うるう年も自動で判定されます。なお monthrange の1つ目の値は、3.14では calendar.TUESDAY のような名前付きの値で表示されました(中身は整数と同じように使えます)。
1か月後:replace(month=)ではエラーになることがある
1月31日の月だけを2に変えると、2月31日は存在しないため ValueError になります。
from datetime import date
try:
date(2026, 1, 31).replace(month=2)
except ValueError as e:
print("ValueError:", e)
ValueError: day 31 must be in range 1..28 for month 2 in year 2026
方法1:dateutilのrelativedelta(おすすめ)
pip install python-dateutil で使える relativedelta は、月末を自動で丸めてnか月後を計算します。
from datetime import date
from dateutil.relativedelta import relativedelta
print(date(2026, 1, 31) + relativedelta(months=1))
print(date(2028, 1, 31) + relativedelta(months=1))
print(date(2026, 9, 28) + relativedelta(years=1, months=2, days=3))
print(date(2026, 9, 28) + relativedelta(day=31)) # 月末(dayは絶対指定)
r = relativedelta(date(2026, 9, 28), date(2019, 4, 1)) # 年月の差
print(r)
print(f"{r.years}年{r.months}か月")
実行結果(Python 3.14.7、python-dateutil 2.9.0.post0):
2026-02-28
2028-02-29
2027-12-01
2026-09-30
relativedelta(years=+7, months=+5, days=+27)
7年5か月
months=1(複数形)は相対指定、day=31(単数形)は絶対指定です。day=31 は「その月の31日、なければ月末」になるので、月末を出す書き方としても使えます。勤続年数のような「何年何か月」も1行で出せます。
方法2:標準ライブラリだけで書く
外部パッケージを入れられない環境では、次の関数で同じ結果になります。
import calendar
from datetime import date
def add_months(d: date, months: int) -> date:
"""標準ライブラリだけで nか月後を求める(月末は丸める)"""
total = d.year * 12 + (d.month - 1) + months
y, m = divmod(total, 12)
m += 1
last = calendar.monthrange(y, m)[1]
return d.replace(year=y, month=m, day=min(d.day, last))
print(add_months(date(2026, 1, 31), 1))
print(add_months(date(2028, 1, 31), 1))
print(add_months(date(2026, 11, 30), 3))
print(add_months(date(2026, 3, 31), -1))
2026-02-28
2028-02-29
2027-02-28
2026-02-28
年をまたぐ場合や、マイナス(nか月前)にも対応しています。
曜日を取得する
from datetime import date
d = date(2026, 9, 28)
print(d.weekday(), d.isoweekday()) # 月=0 / 月=1
print("月火水木金土日"[d.weekday()])
print(d.strftime("%a"), d.isocalendar())
0 1
月
Mon datetime.IsoCalendarDate(year=2026, week=40, weekday=1)
| メソッド | 月曜 | 日曜 |
|---|---|---|
weekday() |
0 | 6 |
isoweekday() |
1 | 7 |
日本語の曜日は "月火水木金土日"[d.weekday()] がロケールに左右されず確実です。
営業日を計算する
土日と休日リストを除いて数えます。休日は自社カレンダーなどから用意したものを set で持つと、判定が速くなります。
from datetime import date, timedelta
HOLIDAYS = {date(2026, 9, 21), date(2026, 9, 22), date(2026, 9, 23)} # 例:休日一覧
def is_business_day(d: date) -> bool:
return d.weekday() < 5 and d not in HOLIDAYS
def add_business_days(d: date, n: int) -> date:
while n > 0:
d += timedelta(days=1)
if is_business_day(d):
n -= 1
return d
def count_business_days(start: date, end: date) -> int:
"""start以上end未満の営業日数"""
return sum(is_business_day(start + timedelta(days=i)) for i in range((end - start).days))
print(add_business_days(date(2026, 9, 18), 3))
print(count_business_days(date(2026, 9, 1), date(2026, 10, 1)))
2026-09-28
19
9月18日(金)の3営業日後は、土日と3連休を飛ばして9月28日(月)になりました。NumPyがある環境なら numpy.busday_count / busday_offset でも同じ結果になります(NumPy 2.5.3で確認:19 と 2026-09-28)。日本の祝日を自動で扱いたい場合は、祝日判定のライブラリを使うか、公的な祝日データを休日リストに読み込みます。
UNIX時間と相互変換する
UNIX時間(エポック秒)とは、1970年1月1日0時(UTC)からの経過秒数です。 APIやログでよく使われます。
from datetime import datetime, UTC
from zoneinfo import ZoneInfo
ts = 1790000000
print(datetime.fromtimestamp(ts, UTC))
print(datetime.fromtimestamp(ts, ZoneInfo("Asia/Tokyo")))
d = datetime(2026, 9, 28, 9, 0, tzinfo=ZoneInfo("Asia/Tokyo"))
print(d.timestamp())
print(int(d.timestamp() * 1000)) # ミリ秒(JavaScriptのDate.now()と同じ単位)
2026-09-21 14:13:20+00:00
2026-09-21 23:13:20+09:00
1790553600.0
1790553600000
fromtimestamp() には第2引数でタイムゾーンを渡すと、実行環境に左右されない aware な日時になります。13桁の数字はミリ秒なので、/ 1000 してから渡します。
処理時間を計測する(perf_counter)
処理時間の計測には time.perf_counter() を使います。 datetime.now() の差でも測れますが、perf_counter() は時計合わせ(NTP補正など)の影響を受けない、計測専用の時計です。
import time
start = time.perf_counter()
sum(range(10_000_000))
elapsed = time.perf_counter() - start
print(f"{elapsed:.3f} 秒")
0.529 秒
(実行環境によって値は変わります)
よくある失敗と直し方
| 症状・エラー | 原因 | 直し方 |
|---|---|---|
can't subtract offset-naive and offset-aware datetimes |
naiveとawareを混ぜた | どちらかに統一(replace(tzinfo=)) |
== で同じ時刻なのに False |
naiveとawareを比べた | 同上 |
| サーバーで9時間ずれる | now() がサーバーのTZ(UTC)で動いた |
now(ZoneInfo("Asia/Tokyo")) と明示 |
DeprecationWarning: ...utcnow() is deprecated |
3.12以降で utcnow() を使用 |
datetime.now(UTC) |
time data '...' does not match format |
文字列と書式が不一致 | 区切り文字・桁を確認 |
Invalid isoformat string: '...Z' |
3.10以前で Z 付きを読んだ |
3.11以上にする、または Z を +00:00 に置換 |
day 31 must be in range 1..28 |
replace(month=) で存在しない日 |
relativedelta か add_months |
| 1日以上の差の秒数が小さい | .seconds を使った |
.total_seconds() |
ZoneInfoNotFoundError |
タイムゾーンデータがない(Windows等) | pip install tzdata |
よくある質問
Q. datetimeとtimeモジュールはどう使い分けますか?
A. 日付・時刻として扱う(表示・計算・変換)なら datetime、処理時間の計測や待機(time.sleep)なら time を使います。経過時間の計測は time.perf_counter() が向いています。
Q. 日本時間の現在時刻を確実に取るには?
A. datetime.now(ZoneInfo("Asia/Tokyo")) です。実行するサーバーのタイムゾーン設定に関係なく、日本時間の aware な日時が得られます。
Q. pytzは使わなくてよいですか?
A. Python 3.9以降は標準の zoneinfo で足ります。ZoneInfo は tzinfo= にそのまま渡せるので、pytzの localize() のような専用の書き方も不要です。
Q. データベースやAPIにはどの形式で保存・送信すればよいですか?
A. UTCの aware な日時を、ISO 8601形式(d.isoformat())かUNIX時間でやり取りし、表示するときに日本時間へ変換すると、地域やサーバーが変わっても意味がずれにくくなります。
まとめ
- 現在日時は
datetime.now(UTC)やnow(ZoneInfo("Asia/Tokyo"))のようにタイムゾーンを明示すると環境に左右されない utcnow()は3.12から非推奨で、実行すると DeprecationWarning が出る。now(UTC)に置き換える- naiveとawareを混ぜると引き算・比較は TypeError、
==は常に False。プログラム内は aware に統一する - 文字列変換は
strftime/strptime、ISO形式ならfromisoformat(3.11からZやISO週も可)。3.14ではdate.strptimeも追加 - 月単位の計算は
relativedelta、標準だけならcalendar.monthrangeで月末に丸める - 差の合計は
total_seconds()、処理時間はperf_counter()を使う
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Python datetimeの使い方|タイムゾーン・月末計算を実行結果で」
株式会社RJCでは、日付やタイムゾーンのような「境界で差が出る処理」を、実際に動かして確かめながら仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。