QFileInfo::fileTime()の落とし穴?Qtでファイル時刻情報取得時のエラーと解決策

2025-05-31

QFileInfo::fileTime() とは?

QFileInfo::fileTime() は、Qt の QFileInfo クラスのメンバ関数で、ファイルに関する特定の時刻情報を取得するために使用されます。ファイルシステムは、ファイルの作成日時、最終変更日時、最終アクセス日時など、複数の時刻情報を保持している場合があります。QFileInfo::fileTime() は、これらの異なる種類の時刻情報の中から、指定した種類の時刻を取得するために使われます。

使い方

QFileInfo::fileTime() は、引数として QFileDevice::FileTime 型の enum を取ります。この enum は、取得したい時刻の種類を指定します。

取得可能な時刻の種類は以下の通りです。

  • QFileDevice::FileMetadataChangeTime: ファイルのメタデータ(パーミッション、所有者など)が最後に変更された日時。
  • QFileDevice::FileAccessTime: ファイルが最後に読み取りまたは書き込みでアクセスされた日時。
  • QFileDevice::FileModificationTime: ファイルの内容が最後に変更された日時。
  • QFileDevice::FileBirthTime: ファイルが作成された日時 (誕生日)。すべてのファイルシステムでサポートされているわけではありません。サポートされていない場合は、無効な QDateTime オブジェクトが返されます。

この関数は、指定された種類の時刻を表す QDateTime オブジェクトを返します。QDateTime オブジェクトは、日付と時刻の両方を含む情報を扱います。

#include <QCoreApplication>
#include <QFileInfo>
#include <QDateTime>
#include <QFileDevice> // QFileDevice::FileTime を使うために必要

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString filePath = "C:/path/to/your/file.txt"; // 調べたいファイルのパス
    QFileInfo fileInfo(filePath);

    if (fileInfo.exists()) {
        qDebug() << "ファイルパス:" << fileInfo.filePath();

        // ファイル作成日時 (誕生日)
        QDateTime birthTime = fileInfo.fileTime(QFileDevice::FileBirthTime);
        if (birthTime.isValid()) {
            qDebug() << "作成日時 (Birth Time):" << birthTime.toString(Qt::SystemLocaleLongDate);
        } else {
            qDebug() << "作成日時 (Birth Time): 取得できませんでした (ファイルシステムがサポートしていない可能性があります)";
        }

        // 最終変更日時
        QDateTime modificationTime = fileInfo.fileTime(QFileDevice::FileModificationTime);
        qDebug() << "最終変更日時 (Modification Time):" << modificationTime.toString(Qt::SystemLocaleLongDate);

        // 最終アクセス日時
        QDateTime accessTime = fileInfo.fileTime(QFileDevice::FileAccessTime);
        qDebug() << "最終アクセス日時 (Access Time):" << accessTime.toString(Qt::SystemLocaleLongDate);

        // メタデータ変更日時
        QDateTime metadataChangeTime = fileInfo.fileTime(QFileDevice::FileMetadataChangeTime);
        qDebug() << "メタデータ変更日時 (Metadata Change Time):" << metadataChangeTime.toString(Qt::SystemLocaleLongDate);

    } else {
        qDebug() << "ファイルが存在しません:" << filePath;
    }

    return 0;
}

ポイント

  • QDateTime::toString() を使用して、取得した日時を人間が読みやすい形式に整形して表示できます。Qt::SystemLocaleLongDate は、システムのロケール設定に基づいた長い日付と時刻の形式で表示します。
  • QDateTime オブジェクトは、isValid() で取得が成功したかを確認できます。特に FileBirthTime は、オペレーティングシステムやファイルシステムによってはサポートされていない場合があります。
  • exists() 関数でファイルが存在するかどうかを確認することが重要です。
  • QFileInfo オブジェクトを作成する際に、ファイルのパスを渡します。

QFileInfo には、特定の時刻情報を直接取得できる便利な関数も用意されています。

  • QDateTime QFileInfo::metadataChangeTime() const: fileTime(QFileDevice::FileMetadataChangeTime) と同じ。
  • QDateTime QFileInfo::lastRead() const: fileTime(QFileDevice::FileAccessTime) と同じ。
  • QDateTime QFileInfo::lastModified() const: fileTime(QFileDevice::FileModificationTime) と同じ。
  • QDateTime QFileInfo::birthTime() const: fileTime(QFileDevice::FileBirthTime) と同じ。Qt 5.10 で導入されました。

これらの関数は fileTime() のラッパーであり、より直感的に特定の時刻情報を取得したい場合に利用すると便利です。



QFileInfo::fileTime() はファイルの時刻情報を取得するための便利な関数ですが、いくつかの一般的な落とし穴や、予期せぬ挙動につながる状況があります。

ファイルが存在しない、またはパスが不正な場合

エラー/挙動
fileTime() を呼び出しても、常に無効な QDateTime オブジェクト (QDateTime::isValid()false を返す) が返される。または、ファイルが存在しないという情報がデバッグ出力される。

原因

  • ネットワークドライブ上のファイルで、接続が切れている、またはアクセスできない。
  • ファイルパスのスペルミス、大文字・小文字の区別(特に Linux/macOS の場合)、あるいはパス区切り文字(\ vs /)の問題。
  • QFileInfo オブジェクトが指しているファイルが、実際にそのパスに存在しない。

トラブルシューティング

  • 絶対パスを使用する
    相対パスはアプリケーションの実行ディレクトリに依存するため、デバッグが難しくなることがあります。可能な限り絶対パスを使用するか、QCoreApplication::applicationDirPath() などで基準となるパスを確立してください。

  • ファイルパスを正確に確認する
    IDE のデバッガで filePath の値を確認したり、qDebug() << fileInfo.filePath(); で出力したりして、パスが正しいことを確認します。

  • QFileInfo::exists() を常にチェックする
    fileTime() を呼び出す前に、QFileInfo::exists() を使ってファイルが存在するかどうかを確認するのが最も重要です。

    QFileInfo fileInfo(filePath);
    if (!fileInfo.exists()) {
        qWarning() << "Error: File does not exist:" << filePath;
        // 処理を中断するか、エラーメッセージを表示する
        return;
    }
    // ここから fileTime() を呼び出す
    QDateTime modTime = fileInfo.fileTime(QFileDevice::FileModificationTime);
    if (modTime.isValid()) {
        qDebug() << "Modification Time:" << modTime.toString();
    } else {
        qDebug() << "Failed to get modification time.";
    }
    

特定の時刻情報がファイルシステムでサポートされていない場合 (FileBirthTime など)

エラー/挙動
QFileDevice::FileBirthTime を使用した場合にのみ、isValid()false を返す QDateTime オブジェクトが返される。他の時刻情報(最終変更日時など)は正しく取得できる。

原因

  • すべてのオペレーティングシステムやファイルシステムが、ファイルの「作成日時 (Birth Time)」などの特定の時刻情報をサポートしているわけではありません。例えば、一部の古い Linux ファイルシステムでは birthTime の情報がない場合があります。

トラブルシューティング

  • 代替手段を検討する
    birthTime が必須要件でない場合は、lastModified() など、より確実に取得できる時刻情報で代替することを検討します。

  • isValid() で確認する
    これが最も確実な方法です。特に FileBirthTime を取得する際は、常に QDateTime::isValid() をチェックし、無効な場合はその情報がないものとして処理します。

    QDateTime birthTime = fileInfo.fileTime(QFileDevice::FileBirthTime);
    if (birthTime.isValid()) {
        qDebug() << "Birth Time:" << birthTime.toString();
    } else {
        qWarning() << "Birth time not available for this file system or OS.";
    }
    

ファイルへのアクセス権限がない場合

エラー/挙動
fileTime() を呼び出しても、無効な QDateTime オブジェクトが返される。QFileInfo::exists()true を返す場合があるが、QFile::open() は失敗する可能性がある。

原因

  • セキュリティソフトウェアやアンチウイルスソフトがアクセスをブロックしている。
  • 現在のユーザーアカウントに、ファイルを読み取るための適切な権限がない。

トラブルシューティング

  • QFile::errorString() を確認する(直接ではないが関連)
    QFileInfo はファイルオープンを直接行いませんが、もしファイルをオープンして読み書きする必要があるなら、QFile を使ってオープンを試み、QFile::errorString() でエラーの詳細を確認することができます。これにより、ファイルアクセスにおける権限の問題が明らかになる場合があります。
  • 管理者権限で実行する
    テストのために、アプリケーションを管理者権限(Windows)または sudo(Linux/macOS)で実行してみる。これは根本的な解決策ではありませんが、権限の問題であるかの切り分けに役立ちます。
  • 権限を確認する
    ファイルが置かれているディレクトリとファイル自体のアクセス権限(Windows の場合はセキュリティタブ、Linux/macOS の場合は ls -lchmod)を確認します。

シンボリックリンクの扱い

エラー/挙動
シンボリックリンクのターゲットファイルの時刻ではなく、シンボリックリンク自体の時刻情報が返される、またはその逆。

原因



QFileInfo::fileTime() はファイルの様々な時刻情報を取得するために使用されます。ここでは、一般的な使用例をいくつか紹介します。

例 1: 基本的なファイル時刻情報の取得

この例では、指定されたファイルの作成日時、最終変更日時、最終アクセス日時を取得し、表示します。

#include <QCoreApplication>
#include <QFileInfo>
#include <QDateTime>
#include <QDebug> // qDebug() を使うために必要
#include <QFileDevice> // QFileDevice::FileTime を使うために必要

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    // 存在するファイルのパスを指定してください。
    // 例: "C:/Users/YourUser/Documents/test_file.txt" (Windows)
    // 例: "/home/youruser/test_file.txt" (Linux)
    // 例: "/Users/youruser/test_file.txt" (macOS)
    QString filePath = "example_file.txt";

    // まず、テスト用のファイルを作成します(既に存在する場合は上書きされます)。
    // このステップは、コードをテストするためにのみ必要です。
    // 実際のアプリケーションでは、既存のファイルを調べます。
    QFile file(filePath);
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        file.write("This is a test file for QFileInfo::fileTime().");
        file.close();
        qDebug() << "Created test file:" << filePath;
    } else {
        qCritical() << "Failed to create test file:" << file.errorString();
        return -1; // エラー終了
    }

    QFileInfo fileInfo(filePath);

    if (fileInfo.exists()) {
        qDebug() << "\n--- ファイル情報 ---";
        qDebug() << "ファイルパス:" << fileInfo.filePath();
        qDebug() << "ファイル名:" << fileInfo.fileName();
        qDebug() << "ディレクトリ:" << fileInfo.dir().path();

        // 1. ファイル作成日時 (Birth Time)
        // 注意: 一部のOSやファイルシステムではサポートされていません。
        QDateTime birthTime = fileInfo.fileTime(QFileDevice::FileBirthTime);
        if (birthTime.isValid()) {
            qDebug() << "作成日時 (Birth Time):" << birthTime.toString(Qt::SystemLocaleLongDate);
        } else {
            qWarning() << "作成日時 (Birth Time): 取得できませんでした (OS/ファイルシステムがサポートしていない可能性があります)。";
        }

        // 2. 最終変更日時 (Modification Time)
        // これはファイルの内容が最後に変更された日時です。
        QDateTime modificationTime = fileInfo.fileTime(QFileDevice::FileModificationTime);
        if (modificationTime.isValid()) {
            qDebug() << "最終変更日時 (Modification Time):" << modificationTime.toString(Qt::SystemLocaleLongDate);
        } else {
            qWarning() << "最終変更日時 (Modification Time): 取得できませんでした。";
        }

        // 3. 最終アクセス日時 (Access Time)
        // これはファイルが最後に読み取られたり、書き込まれたりした日時です。
        QDateTime accessTime = fileInfo.fileTime(QFileDevice::FileAccessTime);
        if (accessTime.isValid()) {
            qDebug() << "最終アクセス日時 (Access Time):" << accessTime.toString(Qt::SystemLocaleLongDate);
        } else {
            qWarning() << "最終アクセス日時 (Access Time): 取得できませんでした。";
        }

        // 4. メタデータ変更日時 (Metadata Change Time)
        // これはファイルのパーミッション、所有者などのメタデータが最後に変更された日時です。
        QDateTime metadataChangeTime = fileInfo.fileTime(QFileDevice::FileMetadataChangeTime);
        if (metadataChangeTime.isValid()) {
            qDebug() << "メタデータ変更日時 (Metadata Change Time):" << metadataChangeTime.toString(Qt::SystemLocaleLongDate);
        } else {
            qWarning() << "メタデータ変更日時 (Metadata Change Time): 取得できませんでした。";
        }

    } else {
        qCritical() << "エラー: ファイルが存在しません:" << filePath;
    }

    // テストファイルを削除します (オプション)
    if (QFile::remove(filePath)) {
        qDebug() << "\nDeleted test file:" << filePath;
    } else {
        qWarning() << "Failed to delete test file:" << filePath << file.errorString();
    }

    return 0;
}

出力例 (環境によって異なります)

Created test file: "example_file.txt"

--- ファイル情報 ---
ファイルパス: "C:/Users/YourUser/Projects/QtApp/example_file.txt"
ファイル名: "example_file.txt"
ディレクトリ: "C:/Users/YourUser/Projects/QtApp"
作成日時 (Birth Time): 2025年5月31日 07時06分57秒
最終変更日時 (Modification Time): 2025年5月31日 07時06分57秒
最終アクセス日時 (Access Time): 2025年5月31日 07時06分57秒
メタデータ変更日時 (Metadata Change Time): 2025年5月31日 07時06分57秒

Deleted test file: "example_file.txt"

例 2: 特定の時刻情報を取得する(より簡潔な関数を使用)

Qt 5.10 以降では、特定の時刻情報を取得するためのより簡潔なラッパー関数が提供されています。

#include <QCoreApplication>
#include <QFileInfo>
#include <QDateTime>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString filePath = "example_file_2.txt";

    QFile file(filePath);
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        file.write("Another test file.");
        file.close();
        qDebug() << "Created test file:" << filePath;
    } else {
        qCritical() << "Failed to create test file:" << file.errorString();
        return -1;
    }

    QFileInfo fileInfo(filePath);

    if (fileInfo.exists()) {
        qDebug() << "\n--- ファイル情報 (簡潔な関数) ---";
        qDebug() << "ファイルパス:" << fileInfo.filePath();

        // birthTime() は fileTime(QFileDevice::FileBirthTime) と同じ
        QDateTime birthTime = fileInfo.birthTime();
        if (birthTime.isValid()) {
            qDebug() << "作成日時:" << birthTime.toString(Qt::SystemLocaleLongDate);
        } else {
            qWarning() << "作成日時: 取得できませんでした。";
        }

        // lastModified() は fileTime(QFileDevice::FileModificationTime) と同じ
        QDateTime modifiedTime = fileInfo.lastModified();
        if (modifiedTime.isValid()) {
            qDebug() << "最終変更日時:" << modifiedTime.toString(Qt::SystemLocaleLongDate);
        } else {
            qWarning() << "最終変更日時: 取得できませんでした。";
        }

        // lastRead() は fileTime(QFileDevice::FileAccessTime) と同じ
        QDateTime readTime = fileInfo.lastRead();
        if (readTime.isValid()) {
            qDebug() << "最終アクセス日時:" << readTime.toString(Qt::SystemLocaleLongDate);
        } else {
            qWarning() << "最終アクセス日時: 取得できませんでした。";
        }
        
        // metadataChangeTime() は fileTime(QFileDevice::FileMetadataChangeTime) と同じ
        QDateTime metaChangeTime = fileInfo.metadataChangeTime();
        if (metaChangeTime.isValid()) {
            qDebug() << "メタデータ変更日時:" << metaChangeTime.toString(Qt::SystemLocaleLongDate);
        } else {
            qWarning() << "メタデータ変更日時: 取得できませんでした。";
        }

    } else {
        qCritical() << "エラー: ファイルが存在しません:" << filePath;
    }

    if (QFile::remove(filePath)) {
        qDebug() << "\nDeleted test file:" << filePath;
    } else {
        qWarning() << "Failed to delete test file:" << filePath << file.errorString();
    }

    return 0;
}

この例の出力は、最初の例とほぼ同じになります。

例 3: タイムゾーンの変換

QDateTime オブジェクトは、デフォルトでシステムのローカルタイムゾーンで解釈されることがほとんどですが、UTC 時間に変換したり、その逆を行ったりすることができます。

#include <QCoreApplication>
#include <QFileInfo>
#include <QDateTime>
#include <QDebug>
#include <QFileDevice>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QString filePath = "example_file_3.txt";

    QFile file(filePath);
    if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        file.write("Time zone test file.");
        file.close();
        qDebug() << "Created test file:" << filePath;
    } else {
        qCritical() << "Failed to create test file:" << file.errorString();
        return -1;
    }

    QFileInfo fileInfo(filePath);

    if (fileInfo.exists()) {
        qDebug() << "\n--- タイムゾーン変換 ---";
        QDateTime modificationTime = fileInfo.fileTime(QFileDevice::FileModificationTime);

        if (modificationTime.isValid()) {
            qDebug() << "元の変更日時 (QDateTimeそのまま):" << modificationTime.toString(Qt::ISODateWithMs); // ISO 8601 形式でミリ秒まで表示

            // ローカルタイムゾーンに変換して表示
            qDebug() << "ローカルタイムゾーンの変更日時:" << modificationTime.toLocalTime().toString(Qt::SystemLocaleLongDate);

            // UTC (協定世界時) に変換して表示
            qDebug() << "UTC の変更日時:" << modificationTime.toUTC().toString(Qt::ISODateWithMs);

            // エポックからの秒数 (UTC)
            qDebug() << "エポック秒 (UTC):" << modificationTime.toSecsSinceEpoch();

        } else {
            qWarning() << "変更日時を取得できませんでした。";
        }
    } else {
        qCritical() << "エラー: ファイルが存在しません:" << filePath;
    }

    if (QFile::remove(filePath)) {
        qDebug() << "\nDeleted test file:" << filePath;
    } else {
        qWarning() << "Failed to delete test file:" << filePath << file.errorString();
    }

    return 0;
}

出力例 (現在の時刻が 2025年5月31日 07:06:57 PDT (UTC-7) の場合)

Created test file: "example_file_3.txt"

--- タイムゾーン変換 ---
元の変更日時 (QDateTimeそのまま): "2025-05-31T07:06:57.123"
ローカルタイムゾーンの変更日時: 2025年5月31日 07時06分57秒
UTC の変更日時: "2025-05-31T14:06:57.123Z"
エポック秒 (UTC): 1748729217

この例では、QDateTime::toLocalTime()QDateTime::toUTC() を使って、取得した時刻を異なるタイムゾーンでどのように表現できるかを示しています。ファイルシステムが提供する時刻情報が、システムのローカルタイムに自動的に調整される場合と、UTC で提供される場合があります。QDateTime は通常、これを適切に処理し、toLocalTime()toUTC() を使って必要な形式に変換できます。



QFileInfo::fileTime() は Qt でファイルの時刻情報を取得するための標準的で推奨される方法ですが、特定の状況や、より低レベルな制御が必要な場合、あるいは Qt 以外のライブラリを使用したい場合に代替手段を検討することがあります。

主な代替方法は以下の通りです。

QFileInfo のラッパー関数 (Qt 5.10 以降で推奨)

これは厳密には「代替方法」というよりも、「QFileInfo::fileTime() をより簡潔に呼び出す方法」ですが、非常に重要なので最初に挙げます。Qt 5.10 以降では、特定の時刻情報 (FileBirthTime, FileModificationTime, FileAccessTime, FileMetadataChangeTime) を直接取得するための便利なラッパー関数が QFileInfo に追加されました。

利点

  • Qt のクロスプラットフォーム抽象化レイヤーを介しているため、OS間の違いを意識する必要がない。
  • コードがより読みやすく、直感的になる。
  • fileTime()QFileDevice::FileTime enum を覚える必要がない。

使用例

#include <QCoreApplication>
#include <QFileInfo>
#include <QDateTime>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QString filePath = "my_document.txt"; // 調べたいファイルパス

    // ファイル作成(例示のため)
    QFile file(filePath);
    if (file.open(QIODevice::WriteOnly)) {
        file.write("Hello Qt!");
        file.close();
    }

    QFileInfo info(filePath);
    if (info.exists()) {
        qDebug() << "ファイルパス:" << info.filePath();
        qDebug() << "作成日時:" << info.birthTime().toString(Qt::SystemLocaleLongDate); // Qt 5.10+
        qDebug() << "最終変更日時:" << info.lastModified().toString(Qt::SystemLocaleLongDate);
        qDebug() << "最終アクセス日時:" << info.lastRead().toString(Qt::SystemLocaleLongDate);
        qDebug() << "メタデータ変更日時:" << info.metadataChangeTime().toString(Qt::SystemLocaleLongDate); // Qt 5.10+
    } else {
        qDebug() << "ファイルが存在しません。";
    }

    QFile::remove(filePath); // クリーンアップ

    return 0;
}

C++ 標準ライブラリ (<filesystem>) (C++17 以降)

C++17 から標準ライブラリにファイルシステム操作のための <filesystem> ヘッダが追加されました。これには、ファイルの時刻情報を取得する機能も含まれています。Qt に依存しない、純粋な C++ ソリューションを求める場合に非常に強力です。

利点

  • C++ の標準機能であり、将来的な互換性が高い。
  • Qt に依存しないため、Qt を使用しないプロジェクトでも利用可能。

欠点

  • エラーハンドリングやパスの扱いが Qt とは異なる。
  • Qt の QDateTime のような便利な日時クラスは提供されないため、別途時間変換のロジックが必要になる場合がある。
  • C++17 コンパイラが必要。

使用例

#include <iostream>
#include <filesystem>
#include <chrono> // 時間を扱うために必要

// C++20からはstd::formatが使えるが、ここではC++17互換の出力
#include <ctime>   // std::localtime, std::gmtime, std::mktime
#include <iomanip> // std::put_time

namespace fs = std::filesystem;

// chrono::file_time を readable string に変換するヘルパー関数
std::string to_string(const fs::file_time_type& ft) {
    auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(ft - fs::file_time_type::clock::now() + std::chrono::system_clock::now());
    std::time_t c_time = std::chrono::system_clock::to_time_t(sctp);
    std::tm* p_tm = std::localtime(&c_time); // ローカルタイムに変換
    if (p_tm) {
        std::stringstream ss;
        ss << std::put_time(p_tm, "%Y-%m-%d %H:%M:%S");
        return ss.str();
    }
    return "Invalid time";
}

int main() {
    std::string filePath = "my_document_cpp17.txt";

    // ファイル作成(例示のため)
    std::ofstream ofs(filePath);
    ofs << "Hello C++17 Filesystem!";
    ofs.close();

    fs::path p = filePath;

    if (fs::exists(p)) {
        std::cout << "ファイルパス: " << p << std::endl;
        
        try {
            // 最終変更日時
            fs::file_time_type last_write_time = fs::last_write_time(p);
            std::cout << "最終変更日時: " << to_string(last_write_time) << std::endl;

            // 最終アクセス日時(一部のOS/ファイルシステムでは更新されない場合がある)
            // std::filesystem::last_access_time は C++20 で非推奨になり、remove() が推奨される
            // 多くのファイルシステムでは、アクセス時間が信頼できないため、通常は使用しない
            // C++17でもlast_access_timeの直接取得は提供されていないことが多い
            // POSIXのstat構造体からst_atimeを取得するような低レベルAPIが必要になる
            // std::cout << "最終アクセス日時: " << to_string(fs::last_access_time(p)) << std::endl; // この行はコンパイルエラーになるか、機能しない可能性が高い

            // 作成日時 (birth_time) - C++20 で追加された機能
            // C++17では直接アクセスできません。OS固有のAPIが必要です。
            // if (fs::is_regular_file(p)) { // C++20 以降
            //     fs::file_time_type birth_time = fs::creation_time(p); // C++20
            //     std::cout << "作成日時: " << to_string(birth_time) << std::endl;
            // }

        } catch (const fs::filesystem_error& ex) {
            std::cerr << "ファイルシステムエラー: " << ex.what() << std::endl;
        }

    } else {
        std::cout << "ファイルが存在しません。" << std::endl;
    }

    fs::remove(p); // クリーンアップ

    return 0;
}

注意
C++17 の <filesystem>last_write_time は提供しますが、creation_time (作成日時) や last_access_time (最終アクセス日時) は C++20 からの機能であるか、標準では直接提供されていないため、OS固有の API を使う必要があります。

OS 固有の API

これは最も低レベルな方法であり、Qt や C++ 標準ライブラリではカバーされないような、非常に特殊な要件がある場合にのみ検討されます。異なる OS ごとに異なるコードを書く必要があります。

  • Linux/macOS (POSIX)
    stat() または lstat() システムコール
  • Windows
    GetFileTime() (WinAPI)

利点

  • 非常に高いパフォーマンスが必要な場合に、直接システムコールを呼び出せる。
  • OS が提供するすべての情報にアクセスできる。

欠点

  • 日時変換の手間
    OS から取得した生の時間情報を、人間が読める形式や QDateTime のような便利な形式に変換する手間がかかる。
  • 複雑さが増す
    API の呼び出し、エラーハンドリング、結果の解釈が複雑になる。
  • クロスプラットフォームではない
    各 OS ごとに異なるコードを書く必要があり、コードの移植性が大幅に低下する。
// これはあくまで概念的な例であり、Qtアプリケーションで直接使うことは稀です。
// 通常はQtのQFileInfo::fileTime()を使うべきです。

#include <iostream>
#include <string>
#include <sys/stat.h> // stat() のために必要
#include <ctime>      // ctime() のために必要

#ifdef _WIN32
// Windowsのコードはここに書く
#else
// POSIX (Linux/macOS) のコード
std::string getFileLastModifiedPOSIX(const std::string& filePath) {
    struct stat fileStat;
    if (stat(filePath.c_str(), &fileStat) == 0) {
        // st_mtime: 最終変更日時
        // st_atime: 最終アクセス日時
        // st_ctime: inode 変更日時 (Windowsの作成日時とは異なる)
        return std::string(std::ctime(&fileStat.st_mtime)); // タイムスタンプを文字列に変換
    }
    return "Error getting file info.";
}
#endif

int main() {
    std::string filePath = "my_document_os_api.txt";

    // ファイル作成(例示のため)
    std::ofstream ofs(filePath);
    ofs << "Hello OS API!";
    ofs.close();

#ifdef _WIN32
    // WindowsのGetFileTime()の呼び出し例をここに書く
    std::cout << "Windows GetFileTime() example (not implemented here)." << std::endl;
#else
    std::cout << "ファイルパス: " << filePath << std::endl;
    std::cout << "最終変更日時 (POSIX stat): " << getFileLastModifiedPOSIX(filePath) << std::endl;
#endif

    fs::remove(filePath); // クリーンアップ

    return 0;
}
  • 特殊な要件や低レベルな制御が必要な場合
    OS 固有の API を検討しますが、その複雑さとクロスプラットフォーム性の欠点を理解しておく必要があります。
  • Qt に依存しない C++17 以降のプロジェクトでは
    <filesystem> ライブラリが優れた選択肢です。
  • ほとんどのQtプロジェクトでは
    QFileInfo::fileTime() またはそのラッパー関数 (lastModified(), birthTime() など) を使用するのが最も簡単で、クロスプラットフォームであり、推奨される方法です。