恥は/dev/nullへ by 初心者

プログラミング素人がのろのろと学んだことをつづっています♪

現在日時がサマータイム期間かどうかを調べる関数

使うインディケーターによっては、ロンドンやNYがサマータイム期間かどうかで制御を変える場合があるので、各市場がサマータイム期間なのか調べる関数を書いてみました。

 

サマータイムの開始日時と終了日時

■ロンドン
開始日時は  3月最終日曜日 UTC 1:00
終了日時は 10月最終日曜日 UTC 1:00

■NY
開始日時は  3月第2日曜日 UTC 7:00
終了日時は 11月第1日曜日 UTC 6:00

 

MT4のTimeGMT関数の注意点

MT4のTimeGMT関数について。この関数は、サーバー時間ではなくPCの時間設定を元にGMT時刻を返します。たとえば、PCのタイムゾーンが「(UTC+09:00) 大阪、札幌、東京」になっている場合、PC時刻から見て9時間前を返します。
このため、PCのタイムゾーンや時刻がおかしいと計算に間違いが生じます。

 

サマータイムかどうかを調べる関数(2種類)

引数についてはコードの先頭のコメントのとおりです。たとえば、日本で使う場合の例としては・・・

LondonIsSummerTime(TimeLocal(), 9, false)


この例を実行すると(TimeLocal()は現在のPC時刻なので)現在の日本時間においてロンドンがサマータイム期間ならば true が返って来ます。サマータイム期間でなければ false が返ってきます。

なお、第2引数を9としているので、PCの時計が日本時間になっている必要があります。

//--------------------------------------------------------------------------
// ロンドンがサマータイム期間か調べる関数
//
// [説明]
//   引数として指定したローカル日時が英国のサマータイム期間ならtrueを返す。
//   サマータイム期間でない場合はfalseを返す。
// [引数]
//   第1引数:ローカル日時
//            【引数の例】TimeLocal()
//   第2引数:ローカル時間とUTCとの時差
//            【引数の例】日本時間は「UTC +9:00」なので、第2引数は 9
//   第3引数:サマータイムの開始日時と終了日時をエキスパートに表示する
//            【引数の例】表示するならtrue、表示しないならfalse
//--------------------------------------------------------------------------
bool LondonIsSummerTime(datetime localTime, int offset, bool printDate)
{
    // 現在のローカル時刻をUTCに変換したもの
    datetime currentUTC = localTime - (offset * 3600);  // 1時間は3600秒
    
    // 現在の「年」を文字列で表したもの
    string thisYear = IntegerToString(TimeYear(currentUTC));

    //--------------------------------------------------------
    // 3月最後の日曜日の1:00(UTC時刻)を求める
    //--------------------------------------------------------
    // 今年の3月31日
    datetime March31 = StringToTime(thisYear + ".03.31 01:00");
    // サマータイムUTC 1:00 に始まるので文字列の末尾は「01:00」

    // 3月31日の曜日
    int dayOfMarch31 = TimeDayOfWeek(March31);
    // TimeDayOfWeekの戻り値は0~6。0が日曜日、6が土曜日を表す。

    // 3月31日の曜日が日曜日から何秒ズレているか
    //   [備考] 1日は86400秒
    int diffFromSun = 0;

    if(dayOfMarch31) diffFromSun = dayOfMarch31 * 86400;
    // dayOfMarch31 == 0 なら 3月31日が3月最後の日曜日

    // 3月最後の日曜日のUTC 1:00
    datetime MarchLastSun = March31 - diffFromSun;

    // チェック用
    if(printDate) printf("ロンドンサマータイム開始日時(UTC時刻): " + TimeToStr(MarchLastSun));

    //--------------------------------------------------------
    // 10月最後の日曜日の1:00(UTC時刻)を求める
    //--------------------------------------------------------
    // 今年の10月31日
    datetime Oct31 = StringToTime(thisYear + ".10.31 01:00");
    // サマータイムUTC 1:00 に終わるので文字列の末尾は「01:00」

    // 10月31日の曜日
    int dayOfOct31 = TimeDayOfWeek(Oct31);

    // 10月31日の曜日が日曜日から何秒ズレているか
    if(dayOfOct31) diffFromSun = dayOfOct31 * 86400;
    else diffFromSun = 0; // 3月の計算でこの変数を使っているので上書きが必要
    // dayOfOct31 == 0 なら 10月31日が10月最後の日曜日

    // 10月最後の日曜日のUTC 1:00
    datetime OctLastSun = Oct31 - diffFromSun;

    // チェック用
    if(printDate) printf("ロンドンサマータイム終了日時(UTC時刻): " + TimeToStr(OctLastSun));

    //--------------------------------------------------------
    // 戻り値
    //--------------------------------------------------------
    bool res = false;

    // ロンドンがサマータイム中ならresにtrueを代入
    if(currentUTC >= MarchLastSun && currentUTC < OctLastSun){
        res = true;
    }

    return res;
}


//--------------------------------------------------------------------------
// NYがサマータイム期間か調べる関数
//
// [説明]
//   引数として指定したローカル日時が、NYのサマータイム期間ならtrueを返す。
//   サマータイム期間でない場合はfalseを返す。
// [引数]
//   第1引数:ローカル日時
//            【引数の例】TimeLocal()
//   第2引数:ローカル時間とUTCとの時差
//            【引数の例】日本時間は「UTC +9:00」なので、第2引数は 9
//   第3引数:サマータイムの開始日時と終了日時をエキスパートに表示する
//            【引数の例】表示するならtrue、表示しないならfalse
//--------------------------------------------------------------------------
bool NewYorkIsSummerTime(datetime localTime, int offset, bool printDate)
{
    // 現在のローカル時刻をUTCに変換したもの
    datetime currentUTC = localTime - (offset * 3600);  // 1時間は3600秒
    
    // 現在の「年」を文字列で表したもの
    string thisYear = IntegerToString(TimeYear(currentUTC));

    //--------------------------------------------------------
    // 3月第2日曜日の7:00(UTC時刻)を求める
    //--------------------------------------------------------
    // 今年の3月1日
    datetime MarchFirst = StringToTime(thisYear + ".03.01 07:00");
    // NYのサマータイムUTC 7:00 に始まるので文字列の末尾は「07:00」

    // 3月1日の曜日
    int dayOfMarchFirst = TimeDayOfWeek(MarchFirst);
    // TimeDayOfWeekの戻り値は0~6。0が日曜日、6が土曜日を表す。

    // 3月1日が第2日曜日から何秒ズレているかをdiffFromSunに代入
    //   [備考] 1日は86400秒
    int diffFromSun = 0;
    if(dayOfMarchFirst) diffFromSun = (14 - dayOfMarchFirst) * 86400;
    else diffFromSun = 7 * 86400;
    // [備考] dayOfMarchFirst == 0 の場合は、3月1日が第1日曜日
    //        なので、else行には(14ではなく)7を使う。

    // 3月第2日曜日のUTC 7:00
    datetime MarchSecondSun = MarchFirst + diffFromSun;

    // チェック用
    if(printDate) printf("NYサマータイム開始日時(UTC時刻): " + TimeToStr(MarchSecondSun));

    //--------------------------------------------------------
    // 11月第1日曜日の6:00(UTC時刻)を求める
    //--------------------------------------------------------
    // 今年の11月1日
    datetime NovFirst = StringToTime(thisYear + ".11.01 06:00");
    // NYのサマータイムUTC 6:00 に終わるので文字列の末尾は「06:00」

    // 11月1日の曜日
    int dayOfNovFirst = TimeDayOfWeek(NovFirst);

    // 11月1日が第1日曜日から何秒ズレているかをdiffFromSunに代入
    diffFromSun = 0; // 3月第2日曜日の処理にこの変数を使っているのでリセット
    if(dayOfNovFirst) diffFromSun = (7 - dayOfNovFirst) * 86400;
    // [備考] dayOfNovFirst == 0 なら 11月1日が第1日曜日

    // 11月第1日曜日のUTC 6:00
    datetime NovFirstSun = NovFirst + diffFromSun;

    // チェック用
    if(printDate) printf("NYサマータイム終了日時(UTC時刻): " + TimeToStr(NovFirstSun));

    //--------------------------------------------------------
    // 戻り値
    //--------------------------------------------------------
    bool res = false;

    // NYがサマータイム中ならresにtrueを代入
    if(currentUTC >= MarchSecondSun && currentUTC < NovFirstSun){
        res = true;
    }

    return res;
}