伝説のツール「NotesPeek」をQtでリメイクする(その7・日時その2)

f:id:takahide-kondoh:20170510213941p:plain

この構造体「TIME」は、Notes APIの日時型(TIMEDATE構造体)と、C/C++言語を介した他の日時型と相互に変換するための媒介の役目をします。

上図のように、この構造体には以下のようなデータが含まれます。

このほかに「GM」という値がありますが、これはTIMEDATEになります。

TIMEDATE構造体が表す日時データを他の日時に変換するためには、まずTIME::GM変数にその日時を代入します。その後、TimeGMToLocal関数を呼び出します。

#include <misc.h>

// 前提としてnow変数に現在の日時が入っているものとする。
// TIMEDATE now;
// OSCurrentTIMEDATE(&now);

TIME time;
time.GM = now;
TimeGMToLocal(&time);

すると、TIME::GMに格納された日時に基づいて、年月日などの他のフィールドにデータがパースされます。後はこのフィールドデータを元に、他の日時データを構築すればいいわけです。

TIME構造体を元に、Qtの日時型であるQDateTimeを作るには、以下のようにします(ただし、サマータイムは考慮しません)。

QDate qDate(time.year, time.month, time.day);
QTime qTime(time.hour, time.minute, time.second, time.hundredth * 10);
QDateTime qDateTime(qDate, qTime, Qt::LocalTime, time.zone * -3600);
// OUTPUT: qDateTime

まず、日付型のQDate、時間型のQTimeを作ります。TIMEに保存される1秒以下の時間単位(TIME::hundredth)は10ミリ秒なので、10倍して1ミリ秒単位に変換します。次に、QDate、QTimeを元にQDateTimeを作ります。デフォルトでTIMEDATEが表す日時はローカル時間なので、ローカル時間であることを指定します(Qt::LocalTime定数)。最後にタイムゾーンの指定ですが、TIMEDATE構造体では時間(Hour)単位である一方、Qtのタイムゾーンは秒単位です。また正負も逆なので、60分×60秒×-1=-3600を掛けた値を指定します。

次は、他の日時データをTIMEDATEに変換するプロセスを見ていきます。

先ほどと同様にTIME構造体で変数を作り、今度はGM以外のフィールドに値を埋めていきます。その後で、TimeLocalToGM関数を呼び出します。QDateTimeに変換元の日時がある場合を見ていきます。

#include <misc.h>

// INPUT: const QDateTime& qDateTime

TIME time;
QDate qDate = qDateTime.date();
QTime qTime = qDateTime.time();
time.zone = qDateTime.offsetFromUtc() / -3600;
time.dst = qDateTime.isDaylightTime() ? 1 : 0;
time.year = qDate.year();
time.month = qDate.month();
time.day = qDate.day();
time.weekday = qDate.dayOfWeek() == 7 ? 1 : (qDate.dayOfWeek() + 1);
time.hour = qTime.hour();
time.minute = qTime.minute();
time.second = qTime.second();
time.hundredth = qTime.msec() / 10;
TimeLocalToGM(&time);
// OUTPUT: time.GM

基本的にはTimeGMToLocal関数の逆のことをしています。サマータイム(TIME::dst)については、日本がサマータイムではないのでぴんときませんので推測の域を出ません。あしからず。

以上が、TIMEDATE型と他の日時型との相互変換に関する基本的なプロセスです。次回は、ここまでのAPIをTimeDateクラスにまとめ、データベースに関する日時データ、文書に関する日時データを取得して、ツール上に表示するところまでを実装したいと思います。