MQL4の時間・日付関数を体系的にまとめました。Year()・Month()・Day()・DayOfWeek()・Hour()・Minute()による日時要素の取得、TimeCurrent()・TimeLocal()・TimeGMT()によるサーバー時刻・ローカル時刻・GMT時刻の使い分け、TimeToStr()・StrToTime()による文字列変換、iBarShift()によるバーインデックス検索、五当日判定、取引セッションフィルター、夏時間対応まで、MT4 EA開発に必要な時間処理のすべてをコード付きで解説します。
MQL4とMQL5の時間関数の違い
| 機能 | MQL4 | MQL5 |
|---|---|---|
| 年の取得 | Year() | MqlDateTime構造体を使用 |
| 月の取得 | Month() | MqlDateTime.mon |
| 曜日の取得 | DayOfWeek() | MqlDateTime.day_of_week |
| 時刻の取得 | Hour(), Minute() | MqlDateTime.hour, MqlDateTime.min |
| 文字列変換 | TimeToStr() | TimeToString() |
| バー検索 | iBarShift() | Bars() + ループ |
| datetime型 | 4バイト整数(1970年基準) | 同じ(8バイトだが互換性あり) |
MQL4ではYear()、Month()、Hour()など直感的な関数で日時要素を取得できます。MQL5ではMqlDateTime構造体に変換してからメンバーを参照する方式に変わり、コードがやや冗長になります。
datetime型の基本
MQL4のdatetime型は、1970年1月1日0時0分0秒(Unix Epoch)からの経過秒数を格納する整数型です。
void DatetimeBasics()
{
// datetime リテラル
datetime dt1 = D'2024.01.15 09:30:00';
datetime dt2 = D'2024.12.31'; // 時刻省略=00:00:00
// 現在時刻
datetime serverTime = TimeCurrent(); // サーバー時刻
datetime localTime = TimeLocal(); // PCのローカル時刻
datetime gmtTime = TimeGMT(); // GMT/UTC時刻
Print("サーバー時刻: ", TimeToStr(serverTime, TIME_DATE|TIME_SECONDS));
Print("ローカル時刻: ", TimeToStr(localTime, TIME_DATE|TIME_SECONDS));
Print("GMT時刻: ", TimeToStr(gmtTime, TIME_DATE|TIME_SECONDS));
// 日時の差(秒単位)
int diffSeconds = (int)(dt2 - dt1);
int diffDays = diffSeconds / 86400;
Print("日数差: ", diffDays, "日");
}日時要素取得関数
| 関数 | 戻り値 | 範囲 | 説明 |
|---|---|---|---|
| Year() | int | 1970- | 最後のティックの年 |
| Month() | int | 1-12 | 月 |
| Day() | int | 1-31 | 日 |
| DayOfWeek() | int | 0-6 | 曜日(0=日曜) |
| DayOfYear() | int | 1-366 | 年初からの日数 |
| Hour() | int | 0-23 | 時 |
| Minute() | int | 0-59 | 分 |
| Seconds() | int | 0-59 | 秒 |
Year()、Month()、Hour()等は最後にティックを受信した時刻(サーバー時刻基準)を返します。バックテスト中はシミュレーション時刻が返ります。特定のdatetimeの要素を取得したい場合は、TimeYear()、TimeMonth()、TimeHour()等を使います。
特定datetimeの要素取得
| 関数 | 説明 |
|---|---|
| TimeYear(datetime) | 指定datetimeの年 |
| TimeMonth(datetime) | 指定datetimeの月 |
| TimeDay(datetime) | 指定datetimeの日 |
| TimeDayOfWeek(datetime) | 指定datetimeの曜日 |
| TimeDayOfYear(datetime) | 指定datetimeの年初からの日数 |
| TimeHour(datetime) | 指定datetimeの時 |
| TimeMinute(datetime) | 指定datetimeの分 |
| TimeSeconds(datetime) | 指定datetimeの秒 |
void PrintBarInfo(int barIndex)
{
datetime barTime = Time[barIndex];
Print("バー[", barIndex, "] の時刻: ", TimeToStr(barTime, TIME_DATE|TIME_MINUTES));
Print(" 年: ", TimeYear(barTime));
Print(" 月: ", TimeMonth(barTime));
Print(" 日: ", TimeDay(barTime));
Print(" 曜日: ", TimeDayOfWeek(barTime), " (0=日, 1=月, ... 5=金)");
Print(" 時: ", TimeHour(barTime));
Print(" 分: ", TimeMinute(barTime));
}TimeToStr / StrToTime — 文字列変換
string TimeToStr(
datetime value, // 変換するdatetime
int mode = TIME_DATE|TIME_MINUTES // 表示フォーマット
);
// mode: TIME_DATE(日付), TIME_MINUTES(時分), TIME_SECONDS(時分秒)
datetime StrToTime(
string value // "yyyy.mm.dd hh:mi" 形式の文字列
);
// 戻り値: 対応するdatetimevoid TimeStringExamples()
{
datetime now = TimeCurrent();
// 各フォーマット
Print(TimeToStr(now, TIME_DATE)); // "2024.06.15"
Print(TimeToStr(now, TIME_MINUTES)); // "14:30"
Print(TimeToStr(now, TIME_SECONDS)); // "14:30:45"
Print(TimeToStr(now, TIME_DATE|TIME_MINUTES)); // "2024.06.15 14:30"
Print(TimeToStr(now, TIME_DATE|TIME_SECONDS)); // "2024.06.15 14:30:45"
// 文字列からdatetimeに変換
datetime dt = StrToTime("2024.06.15 09:30");
Print("変換結果: ", TimeToStr(dt, TIME_DATE|TIME_SECONDS));
}- MT4のサーバー時刻はブローカーによって異なる(GMT+2, GMT+3が多い)
- 日本時間を計算するには
(Hour() - GMTOffset + 9 + 24) % 24とする - 夏時間の切り替え時はGMTオフセットが1時間変わる(年2回)
- バックテストではサーバー時刻がシミュレートされるため、TimeLocal()は使えない
- TimeCurrent()は最後のティック受信時刻。市場が閉まると更新されなくなる
- MT4のサーバー時刻はブローカーによって異なる(GMT+2, GMT+3が多い)
- 日本時間を計算するには
(Hour() - GMTOffset + 9 + 24) % 24とする - 夏時間の切り替え時はGMTオフセットが1時間変わる(年2回)
- バックテストではサーバー時刻がシミュレートされるため、TimeLocal()は使えない
- TimeCurrent()は最後のティック受信時刻。市場が閉まると更新されなくなる
iBarShift — バーインデックスの検索
int iBarShift(
string symbol, // 通貨ペア
int timeframe, // 時間軸
datetime time, // 検索する時刻
bool exact = false // 完全一致のみか
);
// 戻り値: バーインデックス(見つからない場合は-1)void BarShiftExamples()
{
// 昨日の始値を取得
datetime yesterday = TimeCurrent() - 86400;
int barIndex = iBarShift(NULL, PERIOD_D1, yesterday);
if(barIndex >= 0)
Print("昨日の始値: ", iOpen(NULL, PERIOD_D1, barIndex));
// 特定時刻のバーを検索
datetime targetTime = StrToTime("2024.06.15 10:00");
int bar = iBarShift(NULL, PERIOD_H1, targetTime, true);
if(bar >= 0)
Print("指定時刻のバー: ", bar);
else
Print("完全一致するバーなし");
}実践: 五当日(ゴトー日)判定
五当日(ゴトー日)は日本の輸出企業がドル買い需要を出す日として知られ、仲値(9:55前後)に向けてドル円が上昇しやすいアノマリーがあります。ただし100%ではなく、重要指標や地政学リスクの日は通常と異なる動きになります。
五当日とは、毎月5日・10日・15日・20日・25日・月末日のことで、輸出企業のドル売り需要から為替が動きやすいとされています。
bool IsGotobi()
{
int day = Day();
// 5の倍数の日
if(day % 5 == 0)
return true;
// 月末日の判定
int month = Month();
int year = Year();
int lastDay;
if(month == 2)
lastDay = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? 29 : 28;
else if(month == 4 || month == 6 || month == 9 || month == 11)
lastDay = 30;
else
lastDay = 31;
if(day == lastDay)
return true;
return false;
}
// 五当日が土日の場合、前営業日に振替
bool IsGotobiAdjusted()
{
// 金曜日かつ翌日/翌々日が五当日 → 振替
if(DayOfWeek() == 5)
{
int nextDay = Day() + 1;
int nextNextDay = Day() + 2;
if(nextDay % 5 == 0 || nextNextDay % 5 == 0)
return true;
}
return IsGotobi() && DayOfWeek() >= 1 && DayOfWeek() <= 5;
}実践: 取引セッションフィルター
// サーバー時刻のGMTオフセットを設定(ブローカーにより異なる)
input int GMTOffset = 2; // GMT+2(多くの海外ブローカー)
enum SESSION_TYPE
{
SESSION_TOKYO, // 東京(GMT 0:00-9:00)
SESSION_LONDON, // ロンドン(GMT 7:00-16:00)
SESSION_NEWYORK, // ニューヨーク(GMT 12:00-21:00)
SESSION_OVERLAP // ロンドン-NY重複(GMT 12:00-16:00)
};
bool IsInSession(SESSION_TYPE session)
{
int gmtHour = (Hour() - GMTOffset + 24) % 24;
switch(session)
{
case SESSION_TOKYO:
return (gmtHour >= 0 && gmtHour < 9);
case SESSION_LONDON:
return (gmtHour >= 7 && gmtHour < 16);
case SESSION_NEWYORK:
return (gmtHour >= 12 && gmtHour < 21);
case SESSION_OVERLAP:
return (gmtHour >= 12 && gmtHour < 16);
}
return false;
}
// 仲値時間判定(日本時間9:55前後)
bool IsNakaneTime()
{
int jpHour = (Hour() - GMTOffset + 9 + 24) % 24;
int jpMinute = Minute();
// 9:30〜10:00
if(jpHour == 9 && jpMinute >= 30)
return true;
if(jpHour == 10 && jpMinute == 0)
return true;
return false;
}実践: 夏時間(DST)対応
// 米国夏時間(3月第2日曜〜11月第1日曜)
bool IsUSDST()
{
int month = Month();
int day = Day();
int dow = DayOfWeek();
// 4月〜10月は確実に夏時間
if(month > 3 && month < 11) return true;
// 1月,2月,12月は確実に冬時間
if(month < 3 || month > 11) return false;
// 3月: 第2日曜以降
if(month == 3)
{
int secondSunday = 14 - (TimeDayOfWeek(StrToTime(StringConcatenate(Year(), ".03.01"))) % 7);
if(secondSunday > 14) secondSunday -= 7;
return (day >= secondSunday);
}
// 11月: 第1日曜まで
if(month == 11)
{
int firstSunday = 7 - (TimeDayOfWeek(StrToTime(StringConcatenate(Year(), ".11.01"))) % 7);
if(firstSunday > 7) firstSunday -= 7;
return (day < firstSunday);
}
return false;
}
// GMTオフセットを動的に計算
int GetGMTOffset()
{
// 多くの海外ブローカー: 夏=GMT+3, 冬=GMT+2
return IsUSDST() ? 3 : 2;
}実践: 新バー検出
bool IsNewBar()
{
static datetime lastBarTime = 0;
datetime currentBarTime = Time[0];
if(currentBarTime != lastBarTime)
{
lastBarTime = currentBarTime;
return true;
}
return false;
}
// 特定の時間軸の新バー検出
bool IsNewBar_TF(int timeframe)
{
static datetime lastBarTime = 0;
datetime currentBarTime = iTime(NULL, timeframe, 0);
if(currentBarTime != lastBarTime)
{
lastBarTime = currentBarTime;
return true;
}
return false;
}- static変数を使うことで、関数呼び出し間で値が保持される
- 複数の時間軸を監視する場合、それぞれに別の新バー検出関数が必要
- バックテストの「全ティック」モード以外(コントロールポイント等)では、ティックが間引かれるため新バー検出が正確でない場合がある
- 日足の新バー検出は、東京時間の早朝(サーバー時刻の0時)に発生する
- static変数を使うことで、関数呼び出し間で値が保持される
- 複数の時間軸を監視する場合、それぞれに別の新バー検出関数が必要
- バックテストの「全ティック」モード以外では、ティックが間引かれるため新バー検出が正確でない場合がある
- 日足の新バー検出は、東京時間の早朝(サーバー時刻の0時)に発生する
時間・日付関数一覧(MQL5対応表)
| MQL4関数 | MQL5対応 | 説明 |
|---|---|---|
| Year() | MqlDateTime.year | 年 |
| Month() | MqlDateTime.mon | 月 |
| Day() | MqlDateTime.day | 日 |
| DayOfWeek() | MqlDateTime.day_of_week | 曜日 |
| Hour() | MqlDateTime.hour | 時 |
| Minute() | MqlDateTime.min | 分 |
| Seconds() | MqlDateTime.sec | 秒 |
| TimeCurrent() | TimeCurrent() | サーバー時刻 |
| TimeLocal() | TimeLocal() | ローカル時刻 |
| TimeGMT() | TimeGMT() | GMT時刻 |
| TimeToStr() | TimeToString() | datetime→文字列 |
| StrToTime() | StringToTime() | 文字列→datetime |
| iBarShift() | Bars() + ループで代替 | バーインデックス検索 |
| TimeYear(dt) | TimeToStruct() + MqlDateTime | 指定datetimeの年 |
| TimeMonth(dt) | TimeToStruct() + MqlDateTime | 指定datetimeの月 |
| TimeHour(dt) | TimeToStruct() + MqlDateTime | 指定datetimeの時 |
まとめ
MQL4の時間・日付関数はEA開発でのタイミング制御に不可欠です。特に重要なポイントは以下の通りです。
- サーバー時刻はブローカーによって異なる — GMTオフセットを考慮して日本時間を計算する
- 五当日・セッションフィルターで取引精度を上げる — 時間帯による通貨ペアの動きの違いを活用
- 新バー検出はstatic変数で実装する — ティックごとの無駄な処理を防ぐ
- 夏時間の切り替えに対応する — 年に2回GMTオフセットが変わることを忘れない
次のステップとして、MQLリファレンス総合ガイドでイベントハンドラやエラーハンドリングと組み合わせた堅牢なEA開発を学びましょう。





