見出し画像

Notes C API探訪: Notes日時とQDateTimeとの相互変換

以前の記事の「日時からテキスト」、「テキストから日時」これらのコンバートが宙ぶらりんになっています。これを実現するために、前々回の記事で、日時を時間要素に分けて保存し、Notes日時と他の日時オブジェクトとの相互変換できるクラス nxpp::Time をご紹介し、前回の記事でNotes日時構造体TIMEDATEをラップする nxpp::TimeDate クラスをご紹介しました。

Qtのアプリケーション内では、日時を扱うのにQDateTimeは欠かせません。今回は、ここまで紹介してきたクラスを使って、QDateTimeとTIMEDATEを相互変換する仕組みを作ってみます。

まず、TIMEDATEからQDateTimeに変換してみます。

// nxpp/include/nxpp/qt/nxpp_qt_timedate.hpp
// 2021/9/26 修正

#ifndef NXPP_QT_TIMEDATE_HPP
#define NXPP_QT_TIMEDATE_HPP

#include "../nxpp_timedate.hpp"
#include <QDateTime>
#include <QDate>
#include <QTime>
#include <QTimeZone>

namespace nxpp::qt {

/**
* @brief TIMEDATEからQDateTimeに変換する
* @param td TIMEDATE型データ
* @return QDateTimeデータ
*/
inline QDateTime fromTIMEDATE(const TIMEDATE &td) {
 // TIMEDATEからnxpp::Timeを作成
 nxpp::Time time = nxpp::Time::fromTimeDate(td);
 
 // 年、月、日からQDateを作成
 QDate qDate(time.year(), time.month(), time.day());
 
 // 時、分、秒、ミリ秒からQTimeを作成
 QTime qTime(time.hour(), time.minute(), time.second(), time.millisecond());
 
 // UTCオフセット秒を取得
 int offset = time.offsetSeconds();
 
  // QDate、QTime、UTCオフセット秒(タイムゾーン)でQDateTimeを作成
 auto dt = QDateTime(qDate, qTime, Qt::OffsetFromUTC, offset);

 // 夏時間がある場合
 if (time.isDaylightTime()) {

   // 1時間遅らせた時間を作成
   auto dt2 = dt.addSecs(-3600);

   // Qtのタイムゾーンで夏時間が有効なものを検索
   auto ids = QTimeZone::availableTimeZoneIds(dt2.offsetFromUtc());
   foreach (auto id, ids) {
     // 夏時間が有効ならそれを適用して返す
     QTimeZone timeZone(id);
     if (timeZone.isDaylightTime(dt2)) {
       return dt2.toTimeZone(timeZone);
     }
   }
 }

 // 夏時間が無効ならそのまま返す
 return dt;
}

// ...(続く)

QDateTimeは、QDate、QTimeそれぞれのオブジェクトを作成してから、タイムゾーンのデータを加えてオブジェクトを作成します。

※ 2021/9/26 修正
夏時間を含むQTimeZoneを適用できるように修正。

次に、QDateTimeからTIMEDATEに変換してみます。

// ...(続き)

/**
* @brief QDateTimeからTIMEDATEに変換する
* @param dateTime QDateTime型データ
* @return TIMEDATEデータ
*/
inline TIMEDATE toTIMEDATE(const QDateTime &dateTime) {
 // QDateTimeからQDateを作成
 QDate qDate = dateTime.date();
 
 // QDateTimeからQTimeを作成
 QTime qTime = dateTime.time();
 
 // QDateTimeからQTimeZoneを作成
 QTimeZone qZone = dateTime.timeZone();
 
 // 前述データからnxpp::Timeを作成
 nxpp::Time time(
       qDate.year(),
       qDate.month(),
       qDate.day(),
       qTime.hour(),
       qTime.minute(),
       qTime.second(),
       qTime.msec(),
       dateTime.isDaylightTime(),
       qZone.offsetFromUtc(dateTime)
       );
 
 // TIMEDATE型に変換して返す
 return time.toTimeDate();
}

} // namespace nxpp::qt

#endif // NXPP_QT_TIMEDATE_HPP

こちらでも、いったんQDateとQTime、加えてQTimeZoneにバラして、nxpp::Timeに各時間要素を設定、あとはnxpp::Time::toTimeDateを呼び出すという仕組みになります。

まとめ

なお、この仕組みを応用すれば、他の日時を扱う仕組みとも相互変換できるようになるのではと思います。

この記事が気に入ったらサポートをしてみませんか?