Qtの基礎 - 日時

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要

Qtにおいて、QDateクラスまたはQTimeクラスを使用して、日付および時刻の有効性を確認する。


日本時間の取得

PCのシステム環境のロケールやタイムゾーン設定に基づいて日付を取得しているため、システムが日本時間に設定されている場合は、
QDate::currentDateメソッドにより取得される日付は現地の日付となる。

タイムゾーンを考慮した日時の操作が必要な場合は、QDateTimeクラスおよびQTimeZoneクラスを使用することにより、より詳細な制御が可能となる。

また、日付のみが必要な場合でも、タイムゾーンを考慮するにはQDateTimeクラスが適している。

 #include <QDateTime>
 #include <QTimeZone>
 
 // 日本のタイムゾーンを設定
 QDateTime now = QDateTime::currentDateTime();
 now.setTimeZone(QTimeZone("Asia/Tokyo"));
 
 // 日本時間での日付と時刻を表示
 std::cout << QString("日本時間での現在の日付と時刻 : %1").arg(now.toString()) << std::endl;
 
 // 現在の年、月、日を取得
 QDate currentDate = now.date();
 int year = currentDate.year();
 int month = currentDate.month();
 int day = currentDate.day();
 
 std::cout << QString("年 : %1, 月 : %2, 日 : %3").arg(year, month, day).toStdString() << std::endl;



エポックタイムの取得

エポックタイム (UNIXタイムやPOSIXタイムとも呼ばれる) を取得する場合、QDateTimeクラスを使用する。
エポックタイムは、1970年1月1日00:00:00 UTCからの経過秒数を示しており、多くのプログラミング環境で日付と時刻を扱う際の基準である。

 #include <QDateTime>
 
 // 現在の日時を取得
 QDateTime now = QDateTime::currentDateTime();
 
 // エポックタイム (UNIXタイム) を秒単位で取得
 // toSecsSinceEpochメソッドは、Qt 5.8以降で使用可能
 // Qt 5.8以前を使用している場合は、toTime_tメソッドを使用することもできるが、2038年問題に対応していないため注意する必要がある
 qint64 epochTime = now.toSecsSinceEpoch();



ISO 8601

ISO 8601では、日付と時刻は"YYYY-MM-DDTHH:MM:SS"で表現される。
例えば、2024年3月15日 0時14分44秒の場合は、"2024-03-15T00:14:44"のように表す。 ("T"は、日付と時刻の区切りを示す)

ISO 8601は国際標準化機構(ISO)により定められた日付と時刻の表記に関する国際規格であり、主にデータ交換の文脈で利用される。

UTC時間を日本時間に変換

以下の例では、"2024-03-01T16:24:32Z"というUTCの日時 (文字列) を日本時間に変換して、"yyyy年M月d日 H時m分"という形式に変換している。

 #include <QDateTime>
 #include <QTimeZone>
 
 // UTCの日時を表す文字列
 QString utcDateTimeStr = "2024-03-01T16:24:32Z";
 
 // UTCの日時をQDateTimeに変換
 // Qt::ISODateにZを含むことでUTCとして解釈される
 QDateTime utcDateTime = QDateTime::fromString(utcDateTimeStr, Qt::ISODate);
 
 // UTC時間を明示的に設定
 utcDateTime.setTimeSpec(Qt::UTC);
 
 // 日本のタイムゾーンオブジェクト
 QTimeZone jpTimeZone("Asia/Tokyo");
 
 // UTCから日本時間へ変換
 QDateTime jpDateTime = utcDateTime.toTimeZone(jpTimeZone);
 
 // 日本時間に変換された日時を指定のフォーマットで出力
 QString formattedDateTime = jpDateTime.toString("yyyy年M月d日 H時m分");
 
 std::cout << formattedDateTime.toStdString() << std::endl;
 }


文字列を日時に変換

まず、QDateTime::fromStringメソッドを使用して文字列をQDateTimeクラスのオブジェクトに変換する。
次に、QDateTime::toStringメソッドを使用して任意の形式 (カスタムの日付フォーマットも指定可能) に変換する。

 #include <QDateTime>
 
 // ISO 8601形式の日本時間
 QString isoDateStr = "2024-03-02T17:17:00+09:00";
 
 QDateTime dateTime = QDateTime::fromString(isoDateStr, Qt::ISODate);
 
 if (!dateTime.isValid()) {
    std::cerr << QString("日付の変換に失敗しました").toStdString() << std::endl;
    return -1;
 }
 
 // "yyyy年M月d日 H時m分"形式に変換
 // 時間の表記を"M月d日"や"H時m分"とすることにより、0を付加しない日時に変換できる
 QString formattedDateStr = dateTime.toString("yyyy年M月d日 H時m分");
 std::cout << QString("変換後の日付と時間 : %1").arg(formattedDateStr).toStdString() << std::endl;



その他の時刻形式

yyyy/MM/dd HH:mm:ss形式

この形式は特定の国や地域でよく使用されるが、厳密に定義された国際規格が存在するわけではない。
しかし、他のソフトウェアやデータベースシステムで日付と時刻を表現するために使用されることがある。

以下の例では、yyyy/MM/dd HH:mm:ss形式からHH:mm:ssの部分 (時刻) のみを取得している。

 #include <QDateTime>
 #include <QTime>
 
 QString originalDateTimeString = "2024/03/15 00:14:44";
 QDateTime dateTime             = QDateTime::fromString(originalDateTimeString, "yyyy/MM/dd HH:mm:ss");
 
 if (dateTime.isValid()) {
    QString timeString = dateTime.time().toString("HH:mm:ss");
    std::cout << QString("Converted Time : %1").arg(timeString).toStdString() << std::endl;
 }
 else {
    std::cout << QString("Error: Invalid date/time format.").toStdString() << std::endl;
 }



日付および時刻の有効性の確認

以下の例では、閏年の判定等も含めて、入力された日付および時刻の有効性を確認している。

  • 日付
    QDateクラスのコンストラクタに年月日を代入して、isValidメソッドで判定する。
  • 時刻
    QTimeクラスのコンストラクタに時分秒を代入して、isValidメソッドで判定する。


 // 日付
 
 #include <QDate>
 
 qDebug() << QDate(2019, 2, 28).isValid();  // true
 
 qDebug() << QDate(2019, 2, 29).isValid();  // false(閏年ではないため)
 
 qDebug() << QDate(2020, 2, 28).isValid();  // true
 
 qDebug() << QDate(2020, 2, 29).isValid();  // true(閏年のため)


 // 時刻
 
 #include <QTime>
 
 qDebug() << QTime(23, 59, 59).isValid();  // true
 
 qDebug() << QTime(0, 0, 0).isValid();     // true
 
 qDebug() << QTime(25, 0, 0).isValid();    // false
 
 qDebug() << QTime(0, 60, 0).isValid();    // false
 
 qDebug() << QTime(0, 0, 60).isValid();    // false


日付の形式が"yyyy/MM/dd"と指定されている場合、該当する形式に適合されているかどうかを確認する。

 // 確認する日付文字列
 QString dateString = "2023/03/04";
 
 // 無効な日付の例
 //QString dateString = "2023/02/30";
 
 // QDate::fromStringメソッドを使用して日付の文字列を解析して、QDateオブジェクトを生成
 // なお、第2引数には、解析する日付の形式を指定する
 QDate date = QDate::fromString(dateString, "yyyy/MM/dd");
 
 // QDate::isValidメソッドを使用して、生成されたQDateオブジェクトが有効かどうかを確認
 if (date.isValid()) qDebug() << dateString << "は有効な日付フォーマットです";
 else                qDebug() << dateString << "は無効な日付フォーマットです";


また、QDateTimeクラスというQDateクラスとQTimeクラスの両方を取得するクラスもあるが、
"日付が正常かつ時刻が異常の場合、時刻を00:00:00にする仕様"のため、(その結果、QDateTime::isValidメソッドはtrueを返すため)
時刻の有効性が確認できない。


日付の比較

Qtでは、日時の比較にQDateTimeクラスを使用するのが一般的である。
文字列として比較するのではなく、比較する日時文字列をQDateTimeクラスに変換して比較することが推奨される。

以下の例では、現在の日本時間を取得して、"yyyy年M月d日 H時m分"という形式に変換した後、"2024年3月4日 9時5分"と比較している。

 #include <QDateTime>
 #include <QTimeZone>
 
 // 現在の日時を取得して、タイムゾーンを日本に設定
 QDateTime now = QDateTime::currentDateTime();
 now.setTimeZone(QTimeZone("Asia/Tokyo"));
 
 // 日時を指定のフォーマットに変換
 QString formattedNow = now.toString("yyyy年M月d日 H時m分");
 
 // 比較する日時文字列をQDateTimeオブジェクトに変換
 QDateTime compareDate = QDateTime::fromString("2024年3月4日 9時5分", "yyyy年M月d日 H時m分");
 compareDate.setTimeZone(QTimeZone("Asia/Tokyo"));
 
 // 日時を比較
 if (now > compareDate)      qDebug() << "指定の日時より後です";
 else if (now < compareDate) qDebug() << "指定の日時より前です";
 else                        qDebug() << "指定の日時と同じです";


以下の例では、現在の日本時間と比較して2日以内かどうかを確認している。

 #include <QDateTime>
 
 QString dateString = "2024年3月31日 12時35分";
 QDateTime date = QDateTime::fromString(dateString, "yyyy年M月d日 h時m分");
 
 QDateTime nowDate = QDateTime::currentDateTime();
 nowDate.setTimeZone(QTimeZone("Asia/Tokyo"));
 
 // 現在の日付から2日以内かどうかを確認
 if (date.daysTo(nowDate) <= 2) {
    std::cout << QString("2日以内です").toStdString() << std::endl;
 }