c++ builder > Windows 8.1 English だけ abnormal program terminationが起きる > static const TDateTime kDt = StrToDateTime(L"2000/1/1 00:00:01"); はだめ > 代替案: static const TDateTime kDt = VarToDateTime("2000/1/1 00:00:01"); / リモートデバッグ

```txt:ビルド環境
C++ builder XE4
```

ビルドした.exeファイルを実行した時、なぜか以下の違いが出た。

- Windows 7Pro (32bit, 日本語版) : OK
- Windows 8.1Pro (64bit, 日本語版) : OK
- Windows 8.1Pro (64bit, English) : Abnormal program termination


下記を参考にリモートデバッグでチェック
http://www.gesource.jp/weblog/?p=4889

(なおXE4では以下のファイルをコピー)

```
bccide.dll
bordbk180.dll
bordbk180N.dll
comp32x.dll
dcc32180.dll
rmtdbg180.exe
```

実行 > プロセスの読込み において「プログラムエントリポイントまで実行する(E)」をチェックしてもAbnormal program terminationが起きる。

このため、リモートデバッグはあきらめた。


##以下、調査した

### 自動生成フォームの変更 (結果:x)

1. オプション > フォーム 
において、「自動生成フォーム」にリストアップされているものすべてを「使用可能フォーム」に移す。
2. 一番シンプルなフォームだけ「自動生成フォーム」にして、かつ「メインフォーム」にする。

結果、ダメだった。

### cppとhをプロジェクトから順次削除 (原因特定できた)

複雑なcppとhを順次プロジェクトから削除して、エラーが出なくなる地点を見つける。

実際、一番シンプルなフォームだけ残してビルドしたらエラーが出なくなったので、この方法でなんらかの結果が出るだろう。


1. Mxxx.cpp, MxxxIxxxs.cpp をプロジェクトから削除 >> ダメ
2. OpxxxxLxxxSxxx.cpp をプロジェクトから削除 > ダメ
3. CxxxdOxxx.cpp をプロジェクトから削除 > ダメ
4. IxxxOxxxx.cpp, LoxxxRxxOxxx.cppを削除 > ダメ
5. ThxxxMxxx.cpp, MxPxxxUxxx.cpp, MxxDxx.cppを削除 > 動いた

5番目の手順で削除したファイルが関係あるのだろうか。

5番目で削除したファイルを順次戻して、エラーが発生するファイルは MxPxxxUxxx.cpp であることがわかった。

あとは、このファイルの何が問題か見つけないといけない。


## エラーコード

MxPxxxUxxx.cpp に定義していた以下のコードが Abnormal Program Terminationを発生するということが特定できた。

```
static const TDateTime kReturnInError_TDateTime = StrToDateTime(L"2000/1/1 00:00:01");
```

以下は問題ない。

```
static const TDateTime kReturnInError_TDateTime = (TDateTime)0;
```

日時の解釈が英語圏でちょっと違うのかもしれない。

以下もOKなので、constで日時を指定したい場合は、StrToDateTime()でなく以下のようにしておいたほうが英語OS対応にもいいのかもしれない。

```
static const TDateTime kReturnInError_TDateTime = EncodeDate(2000, 1, 1) + EncodeTime(0, 0, 1, 0);
```

調査完了。
結構、はまってしまった。


### エラーの詳細

ButtonClickにて`TDateTime dt = StrToDateTime(L"2000/1/1 00:00:01");`を実行すると「日付または時刻ではありません。」のエラーがでる。

該当の英語版WindowsのControl Panel > Regionを見たときに、日付表記が`M/d/yyyy`のようになっているので、上記のフォーマットではだめになるのだろう。

こういうことがあるということは、安易にStrToDateTime()を使っていると、英語OS上で問題が起きてしまうのかもしれない。


###対策

StrToDateTime()でなくVarToDateTime()を使えば上記の問題は回避できるようだ。

参考1: http://www2.big.or.jp/~osamu/Delphi/Tips/key.cgi?key=42
> 文字通り StrToDateTime という関数もあるんですが、これは yyyy/mm/dd などの形式にしか対応していません。ちょっとひねって VarToDateTime を使えば、ほぼどんな形式でもうまく変換できます。string -> Variant は自動で変換されるので、そのまま文字列を渡すだけで使えます。

参考2: [SO](http://stackoverflow.com/questions/13308472/conversion-with-strtodatetime-and-tformatsettings-does-not-work/13314385#13314385)

> If you want to convert some special DateTime-Formats you should better use VarToDateTime instead of StrToDateTime.


以下を試した。

```
	TDateTime dt1 = VarToDateTime(L"2000/1/1 00:00:01");
	ShowMessage(dt1.FormatString(L"yyyy/mm/dd hh:nn:ss"));

	TDateTime dt2 = StrToDateTime(L"2000/1/1 00:00:01");
	ShowMessage(dt2.FormatString(L"yyyy/mm/dd hh:nn:ss"));
```

上記のコードでdt1の結果は英語版Windowsにおいて意図通りの日時として認識された。

VarToDateTime()を使う時の注意点はよくわからないが、とりあえずはStrToDateTime()よりはよさそう。

<hr>
## VarToDateTimeのエラー

<font color=red>(2015/10/05 追記)</font>

```
	TDateTime dt1 = VarToDateTime(L"2000/1/1 00:00:01");
```
は

```
	TDateTime dt1 = VarToDateTime("2000/1/1 00:00:01");
```
のようにLプリフィックスなしでないとエラーがでるかもしれない。