【令和】Microsoft の元号対応が迷走している件

# はじめに

私は Delphi 使いです。なので、新元号対応は Win32 API に依存していることになります。

Delphi の FormatDateTime() / DateTimeToString() は元号レジストリを参照するので、レジストリに新しい元号が追加されれば新元号対応できる...はずでした。

 - [Era Handling for the Japanese Calendar (Microsoft)](https://docs.microsoft.com/ja-jp/windows/desktop/Intl/era-handling-for-the-japanese-calendar)
 - [元号が改正された場合の西暦と和暦の相互変換について \[JAPAN\] (Embarcadero)](https://community.idera.com/developer-tools/b/blog/posts/japan)
 - [Delphi／C++Builder 10.2.3 Tokyoの新元号対応について (Embarcadero)](https://community.idera.com/developer-tools/b/blog/posts/delphi-c-builder-10-2-3-tokyo)


# 事の始まり

4/10 の井之上@エンバカデロさんのツイートが発端でした。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Windows 10 1809 向けに今日付け(2019/04/10) でリリースされたアップデートのうち、KB4493509 がインストールされていると、元号の処理がおかしくなる気がする。</p>&mdash; 井之上@エンバカデロ (@kaz_inoue) <a href="https://twitter.com/kaz_inoue/status/1115956891849375744?ref_src=twsrc%5Etfw">2019年4月10日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 試してみる (元号レジストリ)

4/10 よりも前かつ元号レジストリで令和を追加している場合、次のコードは `令和01年05月01日` を表示していました。

```pascal
program EraTest;

{$APPTYPE CONSOLE}

uses
  System.SysUtils;

var
  s: string;
begin
  DateTimeToString(s, 'ggee年mm月dd日', Encodedate(2019, 05, 01));
  Writeln(s);
  Readln;
end.
```

ところが...

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">ぎゃあああああああぁぁぁぁぁぁぁぁ！ <a href="https://t.co/TWVpHkx8Ad">pic.twitter.com/TWVpHkx8Ad</a></p>&mdash; DEKO (@ht_deko) <a href="https://twitter.com/ht_deko/status/1115964931533201409?ref_src=twsrc%5Etfw">2019年4月10日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

4/10 のアップデートを適用すると元号レジストリを追加していても新元号が表示されなくなってしまいました。

システム日付を 2019/05/01 以降に変更すれば新元号が使えるようになります。つまり、2019/05/01 になるまで新元号が使えない事になります。

**これはバグなんですかね？仕様なんですかね？**

いずれにせよ一度リリースされてしまった以上、何らかの対策をするしかありません。


## Windows は？

Windows 自体は未来の日付の和暦を扱えます。Windows 7 SP1 以降で新元号に対応します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/d62a456e-5a76-0578-e79a-2b0c7adc2311.png)
元号のレジストリキーは `[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras]` です。ここに `令和` の値を書き込んでやれば新元号が使えるようになります。

```ini:SerNewEra.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese\Eras]
"2019 05 01"="令和_令_Reiwa_R"
```

2019/4/14 時点では、Windows Update を最新の状態にしてもこのレジストリエントリは追加されません。

**追記: 2019/04/26**
Windows 10 (1809) 以外に修正モジュールが公開されました。

Windows 8.1 以前用の修正モジュールはオプション扱いなので自動更新されませんが、Windows 10 は Windows Update の画面で`[更新プログラムのチェック]`ボタンを押すと更新されてしまいますので、ご注意ください。

| Windows | モジュール |モジュール<br>(SO) | 
|:-:|:-:|:-:|
| Windows 10 (1809) | [KB4495667](https://support.microsoft.com/ja-jp/help/4495667/windows-10-update-kb4495667) |
| Windows 10 (1803) | [KB4493437](https://support.microsoft.com/ja-jp/help/4493437/windows-10-update-kb4493437) | |
| Windows 10 (1709) | [KB4493440](https://support.microsoft.com/ja-jp/help/4493440/windows-10-update-kb4493440) | |
| Windows 10 (1703) | [KB4493436](https://support.microsoft.com/ja-jp/help/4493436/windows-10-update-kb4493436) | |
| Windows 10 (1607)<br>Windows Server 2016 | [KB4493473](https://support.microsoft.com/ja-jp/help/4493473/windows-10-update-kb4493473) | |
| Windows 10 (RTM) | [KB4498375](https://support.microsoft.com/ja-jp/help/4498375/windows-10-update-kb4498375) | [](https://support.microsoft.com/ja-jp/help/4498375/windows-10-update-kb4498375) |
| Windows 8.1<br>Windows Server 2012 R2 | [KB4493443](https://support.microsoft.com/ja-jp/help/4493443/windows-8-1-update-kb4493443) | [KB4496878](https://support.microsoft.com/ja-jp/help/4496878/windows-8-1-update-kb4496878) |
| Windows Server 2012 | [KB4493462](https://support.microsoft.com/ja-jp/help/4493462/windows-server-2012-update-kb4493462) | [KB4496877](https://support.microsoft.com/ja-jp/help/4496877/windows-server-2012-update-kb4496877) |
| Windows 7 SP1<br>Windows Server 2008 R2 SP1 | [KB4493453](https://support.microsoft.com/ja-jp/help/4493453/windows-7-update-kb4493453) | [KB4496880](https://support.microsoft.com/ja-jp/help/4496880/windows-7-update-kb4496880)  |
| Windows Server 2008 SP2 | [KB4493460](https://support.microsoft.com/ja-jp/help/4493460/windows-server-2008-update-kb4493460) | [KB4496879](https://support.microsoft.com/ja-jp/help/4496879/windows-server-2008-update-kb4496879)|

これらの修正モジュールをインストールすると元号レジストリに `令和` が追加されます。元年レジストリは更新されません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/eea7a8d2-3a2a-cecc-583c-d8d143787837.png)
日本語フォントに U+32FF の `令和` が追加されます。

**追記: 2019/05/02**
Windows 10 (1809) 用の修正モジュール [KB4501835](https://support.microsoft.com/ja-jp/help/4501835/windows-10-update-kb4501835) が公開されました...が、Windows Update の `[更新プログラムのチェック]` で出てくるようになるまで時間が掛かるかもしれません。WSUS で管理されていない PC は ["Microsoft Update カタログ" から修正モジュールをダウンロード](https://www.catalog.update.microsoft.com/Search.aspx?q=KB4501835)してインストールする必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/020d21ab-6d40-35a0-bdab-b81a62ce164d.png)

**追記: 2019/05/04**
Windows 10 (1809) 用の修正モジュール [KB4495667](https://support.microsoft.com/ja-jp/help/4495667/windows-10-update-kb4495667) が公開されました。Windows Update の `[更新プログラムのチェック]` でインストール可能です。[KB4501835](https://support.microsoft.com/ja-jp/help/4501835/windows-10-update-kb4501835) をインストールしていてもインストールされます。

 - [Windows 用の日本の新元号対応更新プログラムについて - KB4469068 (Microsoft)](https://support.microsoft.com/ja-jp/help/4469068/summary-of-new-japanese-era-updates-kb4469068)
 - [Summary of new Japanese era Windows updates - KB4469068 (Microsoft)](https://support.microsoft.com/en-us/help/4469068/summary-of-new-japanese-era-updates-kb4469068)
 - [Microsoft、新元号“令和”対応パッチを「Windows 10 バージョン 1809」にも提供 (窓の杜)](https://forest.watch.impress.co.jp/docs/news/1182904.html)
 - [「MS P ゴシック」「MS UI ゴシック」を使ったExcelシートのレイアウトが狂う問題 (窓の杜)](https://forest.watch.impress.co.jp/docs/news/1184046.html)

## Win32 API は？

先述の通り、Windows Update により一部の Win32 API が 2019/05/01 になるまで元号レジストリを見なくなります。Delphi だと FormatDateTime() や DateTimeToString() が Win32 API を利用しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/1677fc06-7b88-5b87-95f0-7c28473d2a20.png)
Microsoft の Visual C++ ももちろん影響を受けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/369eead0-0d02-efd5-60dd-483f6d474873.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/2849a9db-d1f6-7f64-b441-ef756f22ac03.png)

 - [関連する API - アプリケーションの新元号対応 (Microsoft)](https://docs.microsoft.com/ja-jp/windows/uwp/design/globalizing/japanese-era-change#%E9%96%A2%E9%80%A3%E3%81%99%E3%82%8B-api)

## OLE は？

あえて分けますが、Win32 API と OLE (Automation) の新元号対応状況は次のようになっています。

**4/10 のアップデート前:**

|   | Win32 API |OLE|
|:-:|:-:|:-:|
| レジストリ  | 参照 | 参照しない|
| 未来の和暦  | 〇 | × |

**4/10 のアップデート後:**

|   | Win32 API |OLE|
|:-:|:-:|:-:|
| レジストリ  | 参照 | 参照|
| 未来の和暦  | × | 〇 |

OLE は 4/10 のアップデート前まで元号レジストリを見ていなかったので `令和`に対応できていませんでした。アップデート後は新元号と未来の日付の和暦を扱えるようになります。

Delphi だと VarToDateTime() が OLE を利用しています。Visual Basic 6.0 の和暦対応ルーチンの一部も OLE を利用していると思われます。

 - [oleauto.h ヘッダ (Microsoft)](https://docs.microsoft.com/en-us/windows/desktop/api/oleauto/)
 - [【令和】新元号対応に関するMicrosoft Win32等の時限措置に関する検証について (Qiita)](https://qiita.com/tfukumori/items/db57e91743915abe52c8#_reference-ec5eaf337c07f101a789)
 - [VB6、およびOffice VBAの元号対応の状況について (Qiita)](https://qiita.com/tfukumori/items/aa9179f961eca86f192f)

## .NET は？

.NET (.NET Framework / .NET Core) は未来の日付の和暦を扱えます。サポートされているのは .NET Framework 3.5 以降です。

.NET Framework 3.5 は元号がハードコードされていましたが、Windows 7 以降であれば Windows Update を適用する事により、元号レジストリを参照するようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/e72930b6-fc1f-e6f6-df46-5e7310106516.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/823d295a-158b-e983-0f07-6e1ad475f6fe.png)
VB6 の互換関数は**元年問題**が出そうですが...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/ae2cb927-c3d7-5e00-5f56-cc30a95a4360.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/102e9089-ec49-9ec3-4a55-97eec5629532.png)

※ VB6.Format() 関数は[元年レジストリ](#windows)で元年 / 1年表記が切り替わります。

 - [.NET Framework 用の日本の新元号対応更新プログラムの概要 - KB4477957 (Microsoft)](https://support.microsoft.com/ja-jp/help/4477957/new-japanese-era-updates-for-net-framework)

## Office は？

Office は元号レジストリを参照し、未来の日付の和暦を扱えます。サポートされているのは Office 2010 以降です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/382ab301-8c6a-cea4-e69f-5c8f97c7b3ce.png)
...でもちょっと待ってくださいよ。少なくとも 4/11 の時点ではこうアナウンスしてましたよね？

**ちょっと前:**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/d19485fb-ec16-1044-e5df-dc55aeb9a574.png)

> Windows 上で実行されている Office 製品は 2019 年 5 月 1 日に新元号が開始されるまで、新元号を表示しませんのでご注意ください。

どうして今は変わってるのです？

**現状:**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/91a3fe81-1618-8f06-2436-ec3535219dc5.png)

> 元号開始時に、お客様に可能な限り最適なエクスペリエンスをご体験いただけるよう、 5 月 1 日に新元号が開始される前に、一部の Office 製品で新元号が表示されるようになります。

※ VBA に関しては基本的に OLE 準拠だと思われます。

 - [日本の新元号に関する Office の更新プログラム - KB4478844 (Microsoft)](https://support.microsoft.com/ja-jp/help/4478844/office-updates-for-new-japanese-era)

# 元年

元年の件でも Microsoft は文言の修正を行っています。

**ちょっと前:**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/f52eb29b-00aa-9a67-b9ee-3feb7b2789d7.png)

> 元年表記をデフォルトに変更 (1 年表記にも変更可能)

**現状:**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/54da9591-ca4d-40a6-c08e-ff36f16aa40f.png)

> 元年表記も選択できるよう変更

 - [新元号への対応について (Microsoft)](https://www.microsoft.com/ja-jp/mscorp/newera/default.aspx)
 - [日本マイクロソフト、新元号対応に関連する情報を集約したWebページを公開 (窓の杜)](https://forest.watch.impress.co.jp/docs/news/1173020.html)

## Windows

元年のレジストリは Windows 10 Insider Preview で元年デフォルト、それ以外の Windows 10 では 1年デフォルトになっているようです。つまり、次のリリースが 2019/05 と言われている新しいビルドでも元年のレジストリは元年デフォルトになると思われます。

元年のレジストリは `[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese]` にある `InitialEraYear` です。

```ini:FirstYear.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Calendars\Japanese]
"InitialEraYear"="元年"
```

...ただ、Windows での元年の扱いは 2019/04/10 時点ではバラバラのようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/0cc78cb2-20e6-e0a8-4664-5b0f6cb0b2a2.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/90d20d8f-320a-54c3-2c7c-8b2b3b50ede2.png)
~~※[「新元号への対応について」](https://www.microsoft.com/ja-jp/mscorp/newera/default.aspx) の文言変更を信じるならば、新しいビルドでも 1809 同様、1年デフォルトになる事もあり得ると思います。~~

**追記: 2019/06/06**
5/22 に Windows 10 May 2019 Update (1903) が一般公開されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/f2a0a027-e0e7-82d9-78e1-949fbc4092e0.png)
紆余曲折ありアップデートが降ってこない機種もあったようですが、6 月に入ってから順次アップデートが降ってくるようになったようです。

この 1903 へアップデートを行うと元年レジストリが**元年**に設定されます。

 - [Windows 用の日本の新元号対応更新プログラムについて - KB4469068 (Microsoft)](https://support.microsoft.com/ja-jp/help/4469068/summary-of-new-japanese-era-updates-kb4469068)

## Win32 API
GetDateFormat() や GetDateFormatEx() は元年レジストリを参照するようです。

 - [GetDateFormat() (Microsoft)](https://docs.microsoft.com/ja-jp/windows/desktop/api/datetimeapi/nf-datetimeapi-getdateformatw)
 - [GetDateFormatEx() (Microsoft)](https://docs.microsoft.com/ja-jp/windows/desktop/api/datetimeapi/nf-datetimeapi-getdateformatex)

```cpp:FirstEraYearTest.cpp
#include <iostream>
#include <windows.h>
#include <datetimeapi.h>
#include <winnls.h>

int main()
{
	WCHAR Buffer[256];
	SYSTEMTIME st;
	std::wcout.imbue(std::locale("JPN_JPN"));
	
	GetLocalTime(&st);

	GetDateFormatW(GetThreadLocale(), NULL, &st, L"yyyy/MM/dd", Buffer, _countof(Buffer));
	std::wcout << Buffer << std::endl;

	st.wYear = 2019;
	st.wMonth = 5;
	st.wDay = 1;

	GetDateFormatW(GetThreadLocale(), DATE_USE_ALT_CALENDAR, &st, L"ggy年M月d日", Buffer, _countof(Buffer));
	std::wcout << Buffer << std::endl;
	GetDateFormatW(GetThreadLocale(), DATE_USE_ALT_CALENDAR, &st, L"ggy'年'M月d日", Buffer, _countof(Buffer));
	std::wcout << Buffer << std::endl;

	GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_USE_ALT_CALENDAR, &st, L"ggy年M月d日", Buffer, _countof(Buffer), NULL);
	std::wcout << Buffer << std::endl;
	GetDateFormatEx(LOCALE_NAME_USER_DEFAULT, DATE_USE_ALT_CALENDAR, &st, L"ggy'年'M月d日", Buffer, _countof(Buffer), NULL);
	std::wcout << Buffer << std::endl;
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/1c291742-ec26-1f2e-a276-ae06316bbc6f.png)
`年`のクォーテーション関係なしに元年表示するようです。また、2019/05/01 を待たずとも元年レジストリが`元年`になっていれば平成等は元年表示されます。**テストは平成元年でやればよさそう**ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/52f094f4-e8a8-d72b-fe46-49a0c00e6961.png)
元年レジストリを参照しない設定で元年表示対応させたければ力業となります。`1年` とか `01年` を `元年` に置換すれば OK です。

釈迦に説法だとは思いますが、日付書式文字列をパースしてから置換する必要があります。単純置換してはいけません。

 - [世田谷区の通知書類に「平成3元年」と誤表示、改元前に早くもトラブル (日経 XTECH)](https://tech.nikkeibp.co.jp/atcl/nxt/news/18/04724/)

## OLE 
OLE は元年レジストリを参照するようです。

## .NET
.NET は Windows の元年レジストリを参照しません。

.NETFramework 4.52 以前は以下のレジストリを参照します。`Switch.System.Globalization.FormatJapaneseFirstYearAsANumber` の値が 1 だと`１年`表記になります。

```FormatJapaneseFirstYearAsANumber_x86_x64.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\AppContext]
"Switch.System.Globalization.FormatJapaneseFirstYearAsANumber"=dword:00000001
```

```FormatJapaneseFirstYearAsANumber_x64_WOW64.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\AppContext]
"Switch.System.Globalization.FormatJapaneseFirstYearAsANumber"=dword:00000001
```

.NET Framework 4.6 以降や .NET Core での元年対応 (1年表記) 方法はまた異なりますので、**このレジストリは見なかった事にした方が混乱しなくていい**かと思います。

また、.NET Framework は、**KB4489192 がインストールされると元年の扱いが変わってしまう**ようです。

>書式パターンに "年" の文字を囲む半角の引用符が含まれているかいないかに関係なく、1 年目の日付の書式が変更されている日本の元号の元年の文字を出力できます。

2019/04/14 時点では、まだ Windows Update に降ってきていませんが...KB4489192 がいきなりリリースされたら怖いですね。

なお、KB4489192 は Windows 10 (1809) 用のモジュールであり、[他のバージョンでは対応モジュールが異なります](https://support.microsoft.com/ja-jp/help/4477957/new-japanese-era-updates-for-net-framework)。

|  | Windows 10<br>(1809) |　Windows 10<br>(1803) | Windows 8.1 | Windows 7<br>SP1 |
|:-:|:-:|:-:|:-:|:-:|
| .NET Franework<br>3.5 | [KB4489192](https://support.microsoft.com/ja-jp/help/4489192/april-2-2019-kb4489192) | [KB4489894](https://support.microsoft.com/ja-jp/help/4489894/windows-10-update-kb4489894) | [KB4488663](https://support.microsoft.com/ja-jp/help/4488663/description-of-the-update-for-net-framework)  | [KB4488662](https://support.microsoft.com/ja-jp/help/4488662/description-of-the-update-for-net-framework)  |
| .NET Franework<br>4.5.2 | | | [KB4488667](https://support.microsoft.com/ja-jp/help/4488667/description-of-the-update-for-net-framework)  | [KB4488669](https://support.microsoft.com/ja-jp/help/4488669/description-of-the-update-for-net-framework)  |
| .NET Franework<br>4.6 以降 | [KB4489192](https://support.microsoft.com/ja-jp/help/4489192/april-2-2019-kb4489192) | [KB4489894](https://support.microsoft.com/ja-jp/help/4489894/windows-10-update-kb4489894) | [KB4488665](https://support.microsoft.com/ja-jp/help/4488665/description-of-the-update-for-net-framework)  | [KB4488666](https://support.microsoft.com/ja-jp/help/4488666/description-of-the-update-for-net-framework)  |

※[「新元号への対応について」](https://www.microsoft.com/ja-jp/mscorp/newera/default.aspx) の文言変更を信じるならば、これらのモジュールが Windows Update でリリースされない事もあり得ると思います。

**追記: 2019/04/30**

@CodeOne さんの記事を読みました。

 - [【警鐘】\[改元\]\[Windows\]\[.NET\] 「令和」対応パッチで画面が横に伸びる、文字が見切れる ― Windows Update 手動更新はちょっと待った方がいい　(Qiita)](https://qiita.com/CodeOne/items/22004635d3c7cc533e5e)

> Windows 10 Version 1803 に今回のパッチをあてたところ、シングルクォーテーションなしの書式 "y年" で「元年」と出力される変更も適用されていることが確認できました。

ぇ？

慌てて確認。検証コードは次の通り (対象フレームワーク: 4.5.2) で、これを EXE にし、4/26 の修正モジュールを適用した Windows 7 / 8.1 / 10 (1803) で実行してみました。

```c#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            var CultureInfo = new System.Globalization.CultureInfo("ja-JP", false);
            CultureInfo.DateTimeFormat.Calendar = new System.Globalization.JapaneseCalendar();

            Console.WriteLine(System.DateTime.Now.ToString("yyyy/MM/dd"));

            DateTime dt = new DateTime(2019, 5, 1);
            Console.WriteLine(dt.ToString("ggy'年'M'月'd'日'", CultureInfo));
            Console.WriteLine(dt.ToString("ggy年M月d日", CultureInfo));
            Console.ReadKey();
        }
    }
}
```

まずは Windows 7 (SP)。シングルクォーテーションで括られていなければ `1年` 表記でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/23d638dc-30d4-c963-4ca9-820216c4bacc.png)
次に Windows 8.1。こちらもシングルクォーテーションで括られていなければ `1年` 表記でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/21ab69a2-6e06-9401-4604-9f11c14f9a37.png)
そして Windows 10 (1803)。こちらはシングルクォーテーションに関係なく `元年` 表記でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/89ef92f2-d99e-b8eb-83b6-de0a9b2515e9.png)
どういう事なの？.NET の挙動は .NET の修正モジュールで変更になるんじゃなかったの？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/fad1a53d-1aad-0c91-0ccf-f05ad8097118.png)

**追記: 2019/05/02**
Windows 10 (1809) 用の新元号対応モジュール [KB4501835](https://support.microsoft.com/ja-jp/help/4501835/windows-10-update-kb4501835) の場合、シングルクォーテーションで括られていなければ `1年` 表記でした。Windows 10 (1803) 用の新元号対応モジュール [KB4493437](https://support.microsoft.com/ja-jp/help/4493437/windows-10-update-kb4493437) と挙動が違う...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/44ec4392-2465-9e8e-ffa1-e4b153e2b6a9.png)
またややこしい事に。

|  | Windows 10<br>1809 | Windows 10<br>1803 | Windows 8.1 | Windows 7 |
|:-:|:-:|:-:|:-:|:-:|
| 新元号対応<br>モジュール未適用 | 1年  | 1年 | 1年  | 1年 |
| 新元号対応<br>モジュール適用  | 1年 | 元年 | 1年  | 1年 |

**追記: 2019/05/04**
Windows 10 (1809) 用の新元号対応モジュール [KB4495667](https://support.microsoft.com/ja-jp/help/4495667/windows-10-update-kb4495667) も、シングルクォーテーションで括られていなければ `1年` 表記でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/550072d3-66ab-e172-c652-f7bd32c9e591.png)

**追記: 2019/06/06**
どの段階何のモジュールか不明ですが (2019/05 のマンスリーロールアップ？)、Windows 10 (1809) や Windows 8.1, Windows 7 もシングルクォーテーションに関係なく `元年` 表記されるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/89bc0cf1-d3d3-d8b7-cb43-73515397006b.png)

| Windows 10<br>1903 | Windows 10<br>1809 | Windows 10<br>1803 | Windows 8.1 | Windows 7 |
|:-:|:-:|:-:|:-:|:-:|
| 元年 | 元年 | 元年 | 元年  | 元年 |

 - [2019 年 4 月 3 日 — KB4489192 Windows 10 Version 1809 および Windows Server 2019 用の .NET Framework 3.5 および 4.7.2 の累積的な更新プログラム (Microsoft)](https://support.microsoft.com/ja-jp/help/4489192/april-2-2019-kb4489192)
 - [Working with calendars (Microsoft)](https://docs.microsoft.com/ja-jp/dotnet/standard/datetime/working-with-calendars)
 - [\[.NET\]\[改元\] 「元年」表記に変わる日付書式が今になって拡大！（フレームワーク別の対策が必要）――マイクロソフト様、重大な変更をしれっとリリースしないで (Qiita)](https://qiita.com/CodeOne/items/97c5a84cfa7376cbb629)

## Office
Excel や Access は元年レジストリを参照しないようです。Excel や Access は常に `1年` 表示です。
勝手に `01` -> `元` となる事はないのでトラブルは少ないと思いますが、元年表示対応は力業となります。

>[種類] テキスト ボックスに以下の文字列をコピーして貼り付けます。 
>[<=43585][$-ja-JP]ggge"年"m"月"d"日";[>=43831]ggge"年"m"月"d"日";ggg"元年"m"月"d"日"

Microsoft の **Excel での元年対応例は令和のみの対応**なのでこのやり方は評価しません。もう少しマトモな手段を提示すべきです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/0bd63218-c5ef-edf4-3123-79618ee0f869.png)
Access は VBA を使うでしょうから、テーブルでの和暦表示以外はどうとでもなると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/88e6a692-1d39-2469-ecba-5d093a931eb9.png)
Word や Power Point の日付挿入 (日付と時刻) は元年レジストリを参照するようです。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/9db1bfff-a44d-430b-2f8f-fb58a080b416.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/d87b38e8-329b-a2a5-03fe-954a3eaf9b30.png)
Excel と Access が `1年` 表記な理由ですが、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/64c8f6a5-ed55-1021-dca6-5d8f76777473.png)

> 互換性の観点から Excel, Access などにおいて 2019 年 4 月時点では「1年」を使用している。

へ、へぇ～...。

※ VBA に関しては基本的に OLE 準拠だと思われます。

 - [日本の年号変更と元年 (Microsoft)](https://support.office.com/ja-jp/article/%E6%97%A5%E6%9C%AC%E3%81%AE%E5%B9%B4%E5%8F%B7%E5%A4%89%E6%9B%B4%E3%81%A8%E5%85%83%E5%B9%B4-c52091af-848d-481f-a861-26ae170f8dbd)
 - [改元を目前に今すぐ準備すべき準備、対応とは (経済産業省 / 日本マイクロソフト)](https://www.meti.go.jp/policy/it_policy/kaigen/20190412_kaigen_2.pdf)

# おわりに

つまり 2019/04/14 の時点ではこういう事になります。

|   | Win32 API | OLE | .NET | Office |
|:-:|:-:|:-:|:-:|:-:|
| 元号レジストリ  | 参照 | 参照 | 参照 | 参照 |
| 未来の和暦  | × | 〇 | 〇 | 〇 |
| 元年レジストリ | 参照 | 参照 | 参照しない | Excel や Access <br>は参照しない|  

Win32 API で、未来の和暦 (新元号) を使うのなら、2019/05/01 までは次のアップデータを適用しないようにするしかありません。

| OS | KB |
|:--:|:--:|
| Windows 10 | [KB4493509](https://support.microsoft.com/ja-jp/help/4493509/windows-10-update-kb4493509) |
| Windows 8.1 | [KB4493446](https://support.microsoft.com/ja-jp/help/4493446/windows-8-1-update-kb4493446) |
| Windows 7 | [KB4493472](https://support.microsoft.com/ja-jp/help/4493472/windows-7-update-kb4493472) |

または Win32 API を使わずに独自実装するかです。

 - [Delphi での新元号対応 (Qiita)](https://qiita.com/ht_deko/items/72d245b0fc64a7ece7c5)

2019/05/01 を迎えれば殆どの問題は解決すると思われますが、検証するにも日本では GW 真っ只中なんですよね...。

**追記: 2019/5/1, 5/2, 5/4**
2019/05/01 を迎えましたので、Win32 API でもすべての API が元号レジストリを参照するようになりました。Windows Update を最新にした状態での時系列は次のようになります。

|   | Win32 API | OLE | .NET | Office |
|:-:|:-:|:-:|:-:|:-:|
| 2019/04/09 以前  | 参照 | 参照しない | 参照 | 参照 |
| 2019/04/10 以降<br>(マンスリーロールアップ) | 時限参照 | 参照 | 参照 | 参照 |  
| 2019/04/26 以降<br>(元号レジストリ追加)[^1] | 時限参照 | 参照 | 参照 | 参照 |  
| 2019/05/01 以降<br>(改元) | 参照 | 参照 | 参照 | 参照 |  
| 2019/05/02 以降<br>(元号レジストリ追加)[^2] | 参照 | 参照 | 参照 | 参照 |  
| 2019/05/04 以降<br>(元号レジストリ追加)[^3] | 参照 | 参照 | 参照 | 参照 |  

[^1]: 新元号対応モジュールがリリースされました。ただし Windows 10 (1809) を除きます。
[^2]: Windows 10 (1809) 用の新元号対応モジュール KB4501835 がリリースされました。
[^3]: Windows 10 (1809) 用の新元号対応モジュール KB4495667 がリリースされました。

## 新元号を事前に使う事の是非

経済産業省の資料にはこうあります。

> （３）元号法第１項に基づく政令の公布後の取扱い
> 元号法（昭和 54 年法律第 43 号）第１項に基づく政令の公布日から施行日前までの間において、各府省が作成し公にする文書に元号を用いて改元日以降の年を表示する場合は、「平成」を用いるものとする（注）。

しかしながら、これは**官公庁の公文書の話**であり、続けて次のような注意書きがあります。

> （注）改元日以降に国民からの申請等又は各府省の通知等に用いられる様式の変更、改元に伴う情報システムの改修等、国民に混乱や不便を生じさせない観点から必要な場合、公布等を除き、「令和」を用いて準備のための手続を行うことができる。 

つまり、官公庁であれ民間であれ新元号を用いた事前準備は OK なのです。

 - [改元に伴う元号による年表示の取扱いについて (経済産業省)](https://www.meti.go.jp/policy/it_policy/kaigen/20190402_kaigen_2.pdf)
 - [元号法 (e-Gov)](http://elaws.e-gov.go.jp/search/elawsSearch/elaws_search/lsg0500/detail?lawId=354AC0000000043)


## 改元後の初年を元年と表記する意味
元年表記に法的な根拠はありません。あくまで慣習です。経済産業省の資料にはこうあります。

>（２）予算
> 国の予算における会計年度の名称については、原則、改元日以降は、当年度全体を通じて「令和元年度」とし、これに伴い、当年度予算の名称は、各府省が改元日以降に作成する文書においては「令和元年度予算」と表示するものとする。 

これは**国の会計年度の話**であり「改元後の和暦の初年に元年を使わなければならない」という根拠ではありません。

`元年` の理屈で言えば、年の最初の日である 1 月 1 日は `元日` であるため、慣習と言うのなら "gggy'年'M'月'd'日'" に 2020/1/1 が渡されたら **令和 2 年元日** と表示しなくてはなりません。

書式指定が `yyyy` であっても `yyy` であっても `yy` であっても `y` であっても `元` って表示されるというのはおかしな話で、やはりコンピュータの処理としては間違っている気がします。元年を使用するにしても画面表示や帳票出力に留めるべきで、やりとりするデータや入力項目で元年を使うべきではないでしょう。

Win32API の GetDateFormat() や .NET の ToString() は表示用だけでなく**データ生成にも使われている**のですから、API やフレームワークの挙動を変更するのは悪手だと思います。Microsoft もその危険性を理解しているからこそ、Excel や Access では元年表記しないようにしているのだと思います。

...とはいえ**「日付書式文字列に `年` (という文字) を含めなければ必ず 1 年表記になる」**のですから、解っていれば対処は難しくありません。

 - [改元に伴う元号による年表示の取扱いについて (経済産業省)](https://www.meti.go.jp/policy/it_policy/kaigen/20190402_kaigen_2.pdf)
 - [元号法 (e-Gov)](http://elaws.e-gov.go.jp/search/elawsSearch/elaws_search/lsg0500/detail?lawId=354AC0000000043)

## おまけ
2019/05/01 時点での対応表です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21785/7d0018b3-aa75-60c2-46e1-a0bb943b34ce.png)
**<!>注意<!>**
Windows 10 (1803) は、4/26 の令和対応モジュール [KB4493437](https://support.microsoft.com/ja-jp/help/4493437/windows-10-update-kb4493437) または、.NET の修正モジュール [KB4489894](https://support.microsoft.com/ja-jp/help/4489894/windows-10-update-kb4489894) (1809 の KB4489192 に相当) が適用されていると、日付書式文字列内の `年` をシングルクォーテーションで括っていなくても `元年` 表記となります。

1803 よりも前の Windows 10 では未確認です。