#pragma twice

KAB-studio > プログラミング > #pragma twice > 260 Version 13.24 日時の作成

#pragma twice 260 Version 13.24 日時の作成

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

 Version 13.24
日時の作成

今回は好きな日時を作る方法について説明します
好きな日時? 夕暮れ時の淡い雰囲気が好きとか?
いやそうじゃなくて、 time() 関数だけだと現在日時しか取得できないで
しょ。でもプログラムではどんな日時も tm 構造体に入れられないと
そか、それができないと現在日時しか扱えないもんね
そういうこと。だから、まずは任意の日時を作成できるようにします。基
本的に、任意の日時の作成方法は、次の3通り

1. time() → localtime() → 日時セット → mktime()
2. tm 構造体作成 → 日時セット → mktime()
3. 直接のべ秒を作成

なんか最後のはすごく力業っぽいね……
うん、上から順に簡単なものから並べているから。まずは

1. time() → localtime() → 日時セット → mktime()

から。これは、前回のプログラムとほとんど同じ

void MakeDate()
{
    // まずはのべ秒を取得。
    time_t lTime_t;
    time( &lTime_t );
    TRACE( "%u秒\n", lTime_t );
    // 1083123673秒

    // 次にローカル時間に変換します。
    tm *pstTm;
    pstTm = localtime( &lTime_t );
    setlocale( LC_ALL, "japanese" );
    char pchTime[256];
    strftime
        ( pchTime
        , 255
        , "%Y年%#m月%#d日%a曜日%H時%M分%S秒"
        , pstTm 
        );
    TRACE( "%s\n", pchTime );
    // 2004年5月11日火曜日12時42分46秒

    // 年を 2010 年にします。
    pstTm->tm_year = 110;
    strftime
        ( pchTime
        , 255
        , "%Y年%#m月%#d日%a曜日%H時%M分%S秒"
        , pstTm 
        );
    TRACE( "%s\n", pchTime );
    // 2010年5月11日火曜日12時42分46秒

    // 秒に変換します。
    time_t lTime_t2;
    lTime_t2 = mktime( pstTm );
    TRACE( "%u秒\n", lTime_t2 );
    // 1083123934秒
}

前回との大きな違いはここ

    // 年を 2010 年にします。
    pstTm->tm_year = 110;

こうやって年を変えれば

    // 2004年5月11日火曜日12時42分46秒
    // 2010年5月11日火曜日12時42分46秒

ちゃんと年だけ変わるわけねー、便利!
手っ取り早く変えるならこれが一番簡単かな。ただ、注意点がみっつあり
ます

・localtime() が返す tm 構造体はグローバル変数。
・計算には使わない方がいい。
・tm 構造体のすべてのメンバ変数は使わない。

まずひとつめから。前回説明したように、 localtime() が返す tm 構造
体は、グローバル変数です
そっか、こうやって年を変えると、他の tm 構造体も変わっちゃうかもし
れないんだ
そういうこと。必要なら複製を作った方がいいかもね。次の注意点は、こ
の方法は〈計算〉には使わない方がいい、ってこと
計算?
たとえば〈1時間後〉とか
え? だって tm_hour に 1 足せばいいだけじゃ……あ、繰り上がり
そういうこと。 tm_hour が 59 だったら、足した後 tm_wday も変えな
きゃいけない、それが 23 だったら
うわーきりないね
詳しくは次回説明するけど、基本的にはのべ秒で計算します。全部秒にし
て計算すれば、繰り上がりは考えなくていいからね
確かに……
最後の注意点は、 tm 構造体のすべてのメンバ変数を使うわけじゃない、
ってこと
そういえば、 tm 構造体ってメンバ変数いっぱいあるよね
でしょ。この中で、曜日の tm_wday や、1年間でののべ日の tm_yday は
使いません
セットするときにはこのふたつは無視していいってことね
そういうこと。以上を踏まえて、今度はいちから tm 構造体を作ってみま


2. tm 構造体作成 → 日時セット → mktime()

現在日付とは関係ない日時を作成したり、元々ある tm 構造体から作り直
すときにはこの方法。と言っても難しいところはなくて、年月日時分秒を
セットすればいいだけです

void MakeDateInDirect()
{
    // tm 構造体作成。
    tm stTm;
    // 0 で初期化。
    memset( &stTm, 0, sizeof( stTm ) );
    // 各データをセット。
    stTm.tm_year = 104; // 2004 年
    stTm.tm_mon  =   4; //    5 月
    stTm.tm_mday =   1; //    1 日
    stTm.tm_hour =  13; //   13 時
    stTm.tm_min  =  35; //   35 分
    stTm.tm_sec  =   2; //    2 秒
    
    setlocale( LC_ALL, "japanese" );
    char pchTime[256];
    strftime
        ( pchTime
        , 255
        , "%Y年%#m月%#d日%a曜日%H時%M分%S秒"
        , &stTm 
        );
    TRACE( "%s\n", pchTime );
    // 2004年5月1日日曜日13時35分02秒

    // 秒に変換します。
    time_t lTime_t;
    lTime_t = mktime( &stTm );
    TRACE( "%u秒\n", lTime_t );
    // 1083386102秒

    // 確認のため、もう一度 tm 構造体に。
    tm *pstTm;
    pstTm = localtime( &lTime_t );
    setlocale( LC_ALL, "japanese" );
    strftime
        ( pchTime
        , 255
        , "%Y年%#m月%#d日%a曜日%H時%M分%S秒"
        , pstTm 
        );
    TRACE( "%s\n", pchTime );
    // 2004年5月1日土曜日13時35分02秒
}

6個のメンバ変数に入れればいいわけね
注意点は3つ。まず、必要なのはこの6つのメンバ変数で、他は関係あり
ません
さっき言ってた、他のメンバ変数の話ね
でも、他のメンバ変数を放っておくと変な値が入ったままになるから、
memset() で初期化します
 Version 12.11 ( No.234 ) で使ったのだね
 memset() を使うことで全部の変数に 0 を入れて初期化できます。これ
をしないと危険だから注意
最後の注意点は?
年と月
あ、年は 1900 引いた数で、月は 0 〜 11 、ってヤツね
そう。特に月はとても危険です。この例みたいに数字で扱うならまだし


    stTm.tm_mon  = iMonth;

こういうふうに変数で渡す場合、 iMonth は 0 〜 11 なのか 1 〜 12 な
のか、ものすごく気をつかう必要があります
う”、確かに……変数名見ただけじゃわかんないし
一番安全なのは、 tm::tm_mon 以外ではすべて 1 〜 12 で扱うこと
 tm::tm_mon でしか 0 〜 11 にしないんだ
そう。だって、 0 〜 11 っていう規則は、 tm 構造体だけのルールなん
だもの
あ、そっか、他で 0 〜 11 を使う理由がないんだ……
画面から入力されるにしても、ファイルから入力されるにしても、当然月
は 1 〜 12 。だから、プログラム上ではほとんど 1 〜 12 しか使わないよ
うにして
 tm::tm_mon に入れるときだけ…… - 1 すればいいの?
そういうこと。専用の関数を用意するといいかもね。ここはとてもバグの
できやすい場所だから気を付け過ぎるくらい気を付けて
はーい
さて、日時の作成方法の最後

3. 直接のべ秒を作成

だけど、普通はこんな方法使わないから必要ありません
あらら
どうしてもしてみたい場合には mktime() のソースコードを参考にしてみ
てください
って、それじゃ mktime() 使った方が早いってことじゃん
ま、そういうこと

/*
    Preview Next Story!
*/
細かいルールや憶えることが多くて大変!
こういうノウハウは、本当は関数にしちゃうのが一番なんだけど
月の変換関数みたく?
そういうこと。全部は憶えきれないしね
だよねー
でもとりあえずは全部憶えてもらいます

というわけで次回
< Version 13.25 日時の計算 >
につづく!
引き続きノウハウ集!
全部憶えきれるかな
火美ちゃん、自分の設定忘れてない?
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。