Pythonでファイルのタイムスタンプを取得する|st_ctimeは作成日時ではない【実測】

Pythonでファイルの作成日時や更新日時を取得したい場面は多くあります。ログファイルの管理、バックアップ処理、ファイル整理など様々な用途で必要になります。この記事では、Pythonでファイルのタイムスタンプを取得・操作する方法を詳しく解説します。

ファイルのタイムスタンプ取得の基本

os.stat()を使った基本的な方法

ファイルのタイムスタンプを取得する最も基本的な方法はos.stat()関数です。

import os
import datetime

# ファイル統計情報を取得
stat_info = os.stat('sample.txt')

# タイムスタンプを取得(Unix時間)
access_time = stat_info.st_atime    # 最終アクセス時刻
modify_time = stat_info.st_mtime    # 最終更新時刻
create_time = stat_info.st_ctime    # 作成時刻(Windowsのみ)

print(f'最終アクセス時刻: {access_time}')
print(f'最終更新時刻: {modify_time}')
print(f'作成時刻: {create_time}')

Unix時間から日時形式への変換

import os
from datetime import datetime

stat_info = os.stat('sample.txt')
modify_time = stat_info.st_mtime

# Unix時間を日時オブジェクトに変換
dt = datetime.fromtimestamp(modify_time)
print(f'更新日時: {dt.strftime("%Y-%m-%d %H:%M:%S")}')

pathlib(Python 3.4以降推奨)での取得

from pathlib import Path
from datetime import datetime

# pathlibでタイムスタンプ取得
file_path = Path('sample.txt')
stat_info = file_path.stat()

# 日時形式で表示
modify_dt = datetime.fromtimestamp(stat_info.st_mtime)
print(f'最終更新: {modify_dt}')

os.stat() が返す値を実際に見る

import os, time, stat, pathlib

p = "f.txt"
st = os.stat(p)
fmt = lambda t: time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(t))

print("st_size     :", st.st_size, "バイト")
print("st_mtime    :", fmt(st.st_mtime))
print("st_atime    :", fmt(st.st_atime))
print("st_ctime    :", fmt(st.st_ctime))
print("st_mode     :", oct(stat.S_IMODE(st.st_mode)))

実行結果:

st_size     : 1 バイト
st_mtime    : 2026-10-02 22:11:09
st_atime    : 2026-10-02 22:11:09
st_ctime    : 2026-10-02 22:11:09
st_mode     : 0o644
属性意味注意
st_mtime内容を最後に変えた時刻ふだん使うのはこれ
st_atime最後に読んだ時刻更新されない設定のことがある
st_ctimeメタ情報が最後に変わった時刻Windowsでは作成日時。UnixとWindowsで意味が違う
st_birthtime作成日時macOSにはあるがLinuxには無い場合がある
st_sizeバイト数ディレクトリに対しては中身の合計ではない

st_ctime を「作成日時(creation time)」だと思うのが最大の落とし穴です。Unix系では「メタ情報の変更時刻(change time)」で、権限を変えただけでも更新されます。作成日時が必要なら st_birthtime を見ますが、これはOSによって存在しません。

import os, platform
st = os.stat("f.txt")
print("プラットフォーム:", platform.system())
print("st_birthtime があるか:", hasattr(st, "st_birthtime"))

実行結果:

プラットフォーム: Darwin
st_birthtime があるか: True

作成日時を扱うコードは、hasattr() で存在を確認してから使ってください。macOSで書いたコードがLinuxで動かない、という形で表面化します。

3つの書き方は同じ値を返す

import os, pathlib
p = "f.txt"
print(os.stat(p).st_mtime == os.path.getmtime(p) == pathlib.Path(p).stat().st_mtime)

実行結果:

True

どれを使っても結果は同じです。1つの値だけ欲しいなら os.path.getmtime()、複数の属性を使うなら os.stat() が無駄がありません(os.path.getmtime() は内部で毎回 stat を呼びます)。

ディレクトリの更新日時

ディレクトリの st_mtime は中のファイルが増減したときに変わります。既存ファイルの中身を書き換えただけでは変わりません。

import os, time
before = os.stat(".").st_mtime
open("g.txt", "w").write("y")          # ファイルを足す
print("mtime が変わった:", os.stat(".").st_mtime != before)

実行結果:

mtime が変わった: True

「フォルダの中が更新されたか」を知りたい場合、ディレクトリの mtime だけでは不十分です。中のファイルを走査して最大の mtime を取る必要があります。

os.path.getmtime()系の便利関数

より簡潔な取得方法

import os
from datetime import datetime

# 直接的な取得関数
modify_time = os.path.getmtime('sample.txt')  # 更新時刻
access_time = os.path.getatime('sample.txt')  # アクセス時刻
create_time = os.path.getctime('sample.txt')  # 作成時刻

# 日時形式で表示
print(f'更新: {datetime.fromtimestamp(modify_time)}')
print(f'アクセス: {datetime.fromtimestamp(access_time)}')
print(f'作成: {datetime.fromtimestamp(create_time)}')

実践的な使用例

ファイル一覧と更新日時の表示

import os
from datetime import datetime
from pathlib import Path

def list_files_with_dates(directory):
    for file_path in Path(directory).iterdir():
        if file_path.is_file():
            mtime = file_path.stat().st_mtime
            dt = datetime.fromtimestamp(mtime)
            print(f'{file_path.name}: {dt.strftime("%Y-%m-%d %H:%M:%S")}')

# カレントディレクトリのファイル一覧
list_files_with_dates('.')

新しいファイルの検索

from pathlib import Path
from datetime import datetime, timedelta

def find_recent_files(directory, days=7):
    cutoff_time = datetime.now() - timedelta(days=days)
    recent_files = []
    
    for file_path in Path(directory).rglob('*'):
        if file_path.is_file():
            mtime = datetime.fromtimestamp(file_path.stat().st_mtime)
            if mtime > cutoff_time:
                recent_files.append((file_path, mtime))
    
    return sorted(recent_files, key=lambda x: x[1], reverse=True)

# 過去7日間に更新されたファイル
recent_files = find_recent_files('.', 7)
for file_path, mtime in recent_files:
    print(f'{file_path}: {mtime.strftime("%Y-%m-%d %H:%M:%S")}')

古いファイルのクリーンアップ

import os
from pathlib import Path
from datetime import datetime, timedelta

def cleanup_old_files(directory, days=30, dry_run=True):
    cutoff_time = datetime.now() - timedelta(days=days)
    deleted_files = []
    
    for file_path in Path(directory).glob('*.log'):
        mtime = datetime.fromtimestamp(file_path.stat().st_mtime)
        if mtime < cutoff_time:
            if not dry_run:
                file_path.unlink()
            deleted_files.append(file_path)
    
    return deleted_files

# ドライラン(実際には削除しない)
old_files = cleanup_old_files('./logs', 30, dry_run=True)
print(f'削除対象ファイル数: {len(old_files)}')

タイムスタンプの比較と条件判定

ファイル同士の新旧比較

import os

def is_newer(file1, file2):
    mtime1 = os.path.getmtime(file1)
    mtime2 = os.path.getmtime(file2)
    return mtime1 > mtime2

# ファイルの新旧比較
if is_newer('new_file.txt', 'old_file.txt'):
    print('new_file.txt の方が新しい')
else:
    print('old_file.txt の方が新しいか同じ')

特定期間内のファイル抽出

from pathlib import Path
from datetime import datetime, timedelta

def files_in_date_range(directory, start_date, end_date):
    result_files = []
    
    for file_path in Path(directory).rglob('*'):
        if file_path.is_file():
            mtime = datetime.fromtimestamp(file_path.stat().st_mtime)
            if start_date <= mtime <= end_date:
                result_files.append((file_path, mtime))
    
    return result_files

# 1週間前から3日前までのファイル
start = datetime.now() - timedelta(days=7)
end = datetime.now() - timedelta(days=3)
files = files_in_date_range('.', start, end)

タイムスタンプの設定・変更

ファイルのタイムスタンプ変更

import os
import time
from datetime import datetime

# 現在時刻でタイムスタンプを更新
def touch_file(file_path):
    current_time = time.time()
    os.utime(file_path, (current_time, current_time))

# 指定日時でタイムスタンプを設定
def set_file_time(file_path, dt):
    timestamp = dt.timestamp()
    os.utime(file_path, (timestamp, timestamp))

# 使用例
touch_file('sample.txt')

# 特定日時に設定
target_date = datetime(2024, 1, 1, 12, 0, 0)
set_file_time('sample.txt', target_date)

pathlibでのタイムスタンプ変更

from pathlib import Path
import time
from datetime import datetime

# pathlibでタッチ操作
file_path = Path('sample.txt')
current_time = time.time()
file_path.touch()  # 現在時刻で更新

# os.utimeと組み合わせて特定時刻に設定
target_time = datetime(2024, 6, 1, 10, 30, 0).timestamp()
file_path.touch(exist_ok=True)
import os
os.utime(file_path, (target_time, target_time))

フォーマットとローカライゼーション

様々な日時フォーマット

from datetime import datetime
import os

def format_file_time(file_path, fmt='%Y-%m-%d %H:%M:%S'):
    mtime = os.path.getmtime(file_path)
    dt = datetime.fromtimestamp(mtime)
    return dt.strftime(fmt)

# 様々なフォーマットで表示
file_path = 'sample.txt'
print(f'標準: {format_file_time(file_path)}')
print(f'日付のみ: {format_file_time(file_path, "%Y-%m-%d")}')
print(f'時刻のみ: {format_file_time(file_path, "%H:%M:%S")}')
print(f'日本語: {format_file_time(file_path, "%Y年%m月%d日 %H時%M分")}')

タイムゾーン対応

※ datetime.utcfromtimestamp() はPython 3.12で非推奨になりました。datetime.fromtimestamp(ts, tz=timezone.utc) を使うと、最初からタイムゾーン情報を持つオブジェクトが得られます。また、タイムゾーンの指定には外部ライブラリのpytzではなく、Python 3.9以降の標準ライブラリ zoneinfo が使えます。

from datetime import datetime, timezone
from zoneinfo import ZoneInfo
import os

def get_file_time_with_timezone(file_path, tz_name='Asia/Tokyo'):
    mtime = os.path.getmtime(file_path)
    utc_dt = datetime.fromtimestamp(mtime, tz=timezone.utc)
    local_dt = utc_dt.astimezone(ZoneInfo(tz_name))
    return local_dt

# タイムゾーン付きで表示
local_time = get_file_time_with_timezone('sample.txt')
print(f'日本時間: {local_time}')

エラーハンドリング

安全なタイムスタンプ取得

import os
from datetime import datetime

def safe_get_file_time(file_path):
    try:
        mtime = os.path.getmtime(file_path)
        return datetime.fromtimestamp(mtime)
    except FileNotFoundError:
        print(f'ファイルが見つかりません: {file_path}')
        return None
    except PermissionError:
        print(f'アクセス権限がありません: {file_path}')
        return None
    except OSError as e:
        print(f'OSエラー: {e}')
        return None

# 安全な取得
file_time = safe_get_file_time('unknown_file.txt')
if file_time:
    print(f'更新日時: {file_time}')

プラットフォーム固有の違い

WindowsとUnix系の違い

import os
import platform
from datetime import datetime

def get_file_times_cross_platform(file_path):
    stat_info = os.stat(file_path)
    
    result = {
        'access_time': datetime.fromtimestamp(stat_info.st_atime),
        'modify_time': datetime.fromtimestamp(stat_info.st_mtime),
    }
    
    # Windowsでは作成時刻、Unix系では変更時刻
    if platform.system() == 'Windows':
        result['create_time'] = datetime.fromtimestamp(stat_info.st_ctime)
    else:
        result['change_time'] = datetime.fromtimestamp(stat_info.st_ctime)
    
    return result

# クロスプラットフォーム対応
times = get_file_times_cross_platform('sample.txt')
for key, value in times.items():
    print(f'{key}: {value}')

関連記事

あわせて読むと理解が深まります。

まとめ

Pythonでファイルのタイムスタンプを取得・操作する主な方法:

  • os.stat(): 詳細な統計情報を含む取得
  • os.path.getmtime()系: 直接的な取得関数
  • pathlib: Python 3.4以降の推奨方法
  • os.utime(): タイムスタンプの変更

プラットフォーム固有の違いやエラーハンドリングに注意しながら、用途に応じて適切な方法を選択することで、効率的なファイル管理が実現できます。

あわせて読みたい

学習の順序はPython学習のロードマップ、標準で使える機能の一覧はPython標準ライブラリのモジュール一覧にまとめています。

Pythonの関数・メソッドの全体像はPython基本関数・メソッド完全一覧にまとめています。

プログラミング学習に興味がある方は、まずは無料体験会へ

無料体験会・お申し込みはこちら