2018年5月7日月曜日

[MQL4] string と datetime 型の相互変換方法5種

string と datetime の加算演算は strict モードかどうかで動作が変わる に書いたように datetime の string への変換は明示的に行ったほうが良いと思います。

基本的には、MQL4 の固定フォーマット "yyyy.mm.dd hh:mi" を使うのが簡単ですが、独自のフォーマットで出力することも可能です1

datetime を string にする方法1 (固定フォーマット)

TimeToString() もしくは TimeToStr() を使うのが簡単です2

1
2
3
4
5
6
7
datetime now = TimeLocal();
 
Print(TimeToString(now, TIME_DATE));               // 2018.05.04
Print(TimeToString(now, TIME_DATE|TIME_MINUTES));  // 2018.05.04 15:51
Print(TimeToString(now, TIME_DATE|TIME_SECONDS));  // 2018.05.04 15:51:12
Print(TimeToString(now, TIME_MINUTES));            // 15:51
Print(TimeToString(now, TIME_SECONDS));            // 15:51:12

datetime を string にする方法2 (任意フォーマット)

上記の方法では特定のフォーマットに決まってしまいますが、任意のフォーマットにしたい場合は、一度 MqlDateTime に変換してStringFormat() で整形すると良いでしょう。

1
2
3
4
5
6
7
8
9
10
11
datetime now = TimeLocal();
 
MqlDateTime now_struct;
TimeToStruct(now, now_struct);
 
Print(StringFormat("%4d/%02d/%02d %02d:%02d",
                   now_struct.year,
                   now_struct.mon,
                   now_struct.day,
                   now_struct.hour,
                   now_struct.min)); // 2018/05/04 16:03

datetime を string にする方法3 (任意フォーマット)

もしくは TimeXXX 関数を使って、datetime を直接各値に変換することも可能です。

1
2
3
4
5
6
7
8
datetime now = TimeLocal();
 
Print(StringFormat("%4d/%02d/%02d %02d:%02d",
                   TimeYear(now),
                   TimeMonth(now),
                   TimeDay(now),
                   TimeHour(now),
                   TimeMinute(now))); // 2018/05/04 16:42

一般的に、都度関数呼び出しの方がパフォーマンスが悪くなることが多いです。 ただ、MQL4 の仕様でどうなっているのかはわかりません3

string を datetime にする方法1 (固定文字列)

先頭に 'D' をつけたシングルクォートで囲まれた文字列は datetime とみなされます。

1
2
3
4
datetime date1 = D'2018.05.04 07:23:01';
 
// こちらはコンパイルエラー
datetime date2 = D'This is not a date string';

参考

Datetime Type - Integer Types - Data Types - Language Basics - MQL4 Reference

string を datetime にする方法2

動的な string を datetime に変換する場合は、 StringToTime() もしくは StrToTime() が使えます4

1
2
3
4
5
string date_string = "1970.01.01 01:00:00";
 
datetime date = StringToTime(date_string);
printf("%llu", date);                              // 3600
Print(TimeToString(date, TIME_DATE|TIME_SECONDS)); // 1970.01.01 01:00:00

参考

[MQL4] datetime を long にキャストすると 1970/1/1 からの秒になる | Strategy of C

この関数、下記のように多少フォーマットが異なっていても動作するようです。 しかし、公式のドキュメントに記述が無いので、使用する場合は慎重に確認した方が良いでしょう。

1
2
3
4
5
string date_string = "1970/01/01 01:00:00";
 
datetime date = StringToTime(date_string);
printf("%llu", date);                              // 3600
Print(TimeToString(date, TIME_DATE|TIME_SECONDS)); // 1970.01.01 01:00:00

なお、以下のように日付ではない文字列を変換した場合、実行時の日付、もしくは日時が入るようです5。 時刻が入るかどうかは文字列によるようで、動作が微妙です。公式のドキュメントにも記述はありません。

想定外の文字列が入力される可能性のある系では、気をつけた方が良いでしょう。

1
2
3
string no_date_string = "This is not a date string";
datetime date = StringToTime(no_date_string);
Print(TimeToString(date, TIME_DATE|TIME_SECONDS)); // 実行時の日時?
  1. 後述するように、独自フォーマットの string を datetime に変換する際は注意が必要 
  2. 多分、この2つの関数は全く同じだと思われる 
  3. コンパイラが優秀だと、差はほとんどなかったりします。どちらにせよ、全体のパフォーマンスにはあまり影響しないだろうと思います 
  4. 多分、この2つも全く同じ関数だと思われる 
  5. 本当はエラーを返してほしいが、MQL4 に例外は無いしな… 
?