#pragma twice

KAB-studio > プログラミング > #pragma twice > 265 Version 13.29 日時の変更

#pragma twice 265 Version 13.29 日時の変更

前のページへ 表紙・目次へ 次のページへ

 Version 13.29
日時の変更

日時編の最後は、日時の変更方法について説明します
日時の変更……それってつまり、コンピューターの、ってことだよね
そういうこと。なぜ日時の変更方法について説明するかというと、テスト
プログラムで必要になるから
テストプログラム?
たとえば〈今月の月末を取得する関数〉のテストをしたい場合とか
あ……テストする日付によって、月末って違っちゃうもんね
ちゃんとテストする場合には、最低12ヶ月+うるう年の場合のテストが
必要になります。こういった場合にはテストプログラムを作った方が楽なん
だけど
そのためには日時をプログラムで変られなきゃいけない
そういうこと。実際のテストプログラムでは

1.現在日時を取得して、取っておく。
2.目的の日時に変更する。
3.テストする。
4.元の日時に戻す。

というパターンになります
でも……これだと、 1 から 4 になるまでの間に時間が進んじゃわな
い?
うん、だからこれは厳密にはちゃんと戻すことはできないんです。もっと
厳密にするのなら、 1 から 4 までの秒数を数えてそれを加える、っていう
こともできるけど
それはそれで大変ね……
それ自体も本当の意味では厳密じゃないしね。ま、今回は手っ取り早く、
現在日時を変更する方法を紹介します
はーい
さて、まず現在日時の取得方法について。前にファイル入出力の時にも説
明したけど、ウィンドウズの機能を使用する場合には API を使う必要があ
ります
ファイル入出力……あ、あのときはランタイム使ってても結局は API 
使ってるんだったよね。それと同じで、 time() とかも実は API 使って
る?
そういうこと。まず、現在日時を取得する場合には GetLocalTime() とい
う API を使用します

void Use_GetLocalTime()
{
    SYSTEMTIME stSystemTime;
    GetLocalTime( &stSystemTime );

    TRACE
        ( "%d年%d月%d日%d曜日%d時%d分%d秒(%dミリ秒)\n"
        , stSystemTime.wYear
        , stSystemTime.wMonth
        , stSystemTime.wDay
        , stSystemTime.wDayOfWeek
        , stSystemTime.wHour
        , stSystemTime.wMinute
        , stSystemTime.wSecond
        , stSystemTime.wMilliseconds
        );
    // 2004年6月23日3曜日13時2分55秒(250ミリ秒)
}

なんか localtime() に似てるね
現在日時を取得する機能もあるから、 time() と localtime() が組み合
わさったようなものかな
なるほど
ただ、 localtime() とは結構違うから注意した方がいいかも

・西暦が4桁。
・月が 1 - 12 。
ミリ秒がある。

月が 1 から……ややこしい
って思うのようになるっていうのもちょっとアレだけど
う”
それと、あまり使わないと思うけど【ミリ秒】があるから
本当に使わなさそう……
まぁ、どちらかというとこの API 自体、そもそも使わないかも
使い道ないの?
日時関係はランタイムの方が便利だからね。 API には mktime() に当た
る関数がないから
のべ秒に変換できない……
そういうこと。プログラムではのべ秒と各桁に分けてあるのをそれぞれ使
い分けるから、それがしにくい GetLocalTime() は使う必要ないかな
むー
それより重要なのは、現在日時を変える方
対になってるんなら、 SetLocalTime() って API ?
そういうこと

void Use_SetLocalTime()
{
    SYSTEMTIME stSystemTime;
    GetLocalTime( &stSystemTime );

    TRACE
        ( "%d年%d月%d日%d曜日%d時%d分%d秒(%dミリ秒)\n"
        , stSystemTime.wYear
        , stSystemTime.wMonth
        , stSystemTime.wDay
        , stSystemTime.wDayOfWeek
        , stSystemTime.wHour
        , stSystemTime.wMinute
        , stSystemTime.wSecond
        , stSystemTime.wMilliseconds
        );
    // 2004年6月24日4曜日12時41分14秒(950ミリ秒)

    // 1年進めます。
    stSystemTime.wYear += 1;

    TRACE
        ( "%d年%d月%d日%d曜日%d時%d分%d秒(%dミリ秒)\n"
        , stSystemTime.wYear
        , stSystemTime.wMonth
        , stSystemTime.wDay
        , stSystemTime.wDayOfWeek
        , stSystemTime.wHour
        , stSystemTime.wMinute
        , stSystemTime.wSecond
        , stSystemTime.wMilliseconds
        );
    // 2005年6月24日4曜日12時41分14秒(950ミリ秒)

    SetLocalTime( &stSystemTime );
}

 API の SetLocalTime() で、ウィンドウズの日時を変更できます
渡すのは SetLocalTime() と同じ SYSTEMTIME なんだ
だから GetLocalTime() で取ってきたものを少し変えて SetLocalTime() 
に渡すのが楽かな
べたべたに作りたいときは、べたべたにセットしなきゃダメ?
そうだね。のべ秒から作りたいときのために、 tm 構造体からコピーする
関数とか用意しておくといいかもね
んー、この前のブロック選択とか使えば楽勝っぽいね
でも年と月は間違えないように気を付けてね
あ”
間違えそうだったね……年は 1900 、月は 1 を足さなきゃいけないんだ
からね。曜日の SYSTEMTIME::wDayOfWeek はセットしなくてもOK
これは無視されるんだね、ランタイムと同じで
ちゃんとリファレンスに書いてあるから大丈夫。 API ってソースがない
から、こういうふうにちゃんと書いてないとわからないかな
あ! 質問!
はい火美ちゃん
さっきと日付が違う!
そんなことは気にしなくていいです!
じゃあちゃんとした質問。テストするときって、これで変えたあとテスト
して、また元に戻すんだよね
そうなるね。そのためにも、 GetLocalTime() で取得した現在日時は取っ
ておいて、任意の日付に変えてテストした後、取っておいた日時で元に戻
す、っていう形になるかな
変え忘れたら?
ウィンドウズの日時が変えたままになる……
……って、それってどのくらい困る?
日時を変更してプログラムの修正はしない方がいいかな。ファイルが古い
か新しいかで〈更新されたか〉を判定してるから、場合によっては〈常に
リビルド〉みたいな状態になっちゃいます
げ、かなり迷惑!
それ以外にもログを取ってたりするときの日時が違ったりするかな。他に
は……ビデオのタイマー録画とかずれるかも
それは色々イタイね……
そういうのを防ぐためにも、デストラクタで対処する、っていうのがひと
つの方法かな
デストラクタって、 Version 11.11 ( No.211 ) でやった、クラスがなく
なるときに呼ばれる関数だよね
そう。 SYSTEMTIME をメンバ変数に持っておいて、コンストラクタで現在
日時を取得、デストラクタで 現在日時を元に戻す、ってすれば
自動的に元に戻る!
まぁそれでもデバッグ実行して途中で止めたり assert したりするとダメ
なんだけど
あらら
それでもそういう方法はあるってことで。実際に作るとこんな感じかな

class CTimeReseter
{
private:
    SYSTEMTIME m_stSystemTime;

public:
    CTimeReseter()
    {
        GetLocalTime( &m_stSystemTime );
    }

    ~CTimeReseter()
    {
        SetLocalTime( &m_stSystemTime );
    }
};

コンストラクタで取得して、デストラクタでセット、ね
使用例はこんな感じ

void Use_CTimeReseter()
{
    CTimeReseter cTimeReseter;

    // ここで任意の日時に変更します。
    // そしてテストをします。

    // この関数を抜けるとデストラクタが呼ばれて
    // 自動的に日時が戻ります。
}

戻さなくていいっていうのが便利よねー

/*
    Preview Next Story!
*/
さて、今回で日時編は終了です
次のアルゴリズムは?
もうありません
え”?
ソートと日時を見ればだいたいはできるようになるから
というわけで次回
< Version 13.30 計算量と時間 >
につづく!
うわ、なんか難しそうなのが出てるっ!!
うん、ちょっと難しいかも
げ!
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。