📅
明治6年より前の日付を西暦から和暦に変換した際の不正確な表現
日本では明治6年に改暦を行い、今の西暦に合わせた暦になりました。
参考(Wikipedia):明治改暦
これによって、以下のような対応になります。
- 明治5年12月2日 = 1872/12/31
- 明治6年1月1日 = 1873/01/01
プログラミング言語によって西暦を和暦で表現する機能が標準的なライブラリで用意されています。
以下に簡単ではあるが一部の言語とライブラリで確認した例を示します。
確認
実行環境
- Linux 6.12.34
- gcc 12.2
- Python 3.11.
- .NET 9.0
- Node.js 20.19
C言語
コード(抜粋)
setlocale(LC_ALL, "ja_JP.UTF-8");
// 1873年1月1日 明治6年1月1日
struct tm date = {0};
date.tm_year = 1873 - 1900;
date.tm_mon = 0;
date.tm_mday = 1;
date.tm_isdst = -1;
// 1873年12月31日 明治5年12月2日
struct tm date2 = {0};
date2.tm_year = 1872 - 1900;
date2.tm_mon = 11;
date2.tm_mday = 31;
date2.tm_isdst = -1;
char output[100];
strftime(output, sizeof(output), "%x\n%Ex", date);
printf("%s\n", output);
strftime(output, sizeof(output), "%x\n%Ex", date2);
printf("%s\n", output);
実行例
1873年01月01日
明治06年01月01日
1872年12月31日
西暦1872年12月31日
変換を諦めて西暦で表示します。
個人的にはこれはありだと思います。
MSVCだとまた違った表示になるかもしれません。
Python
コード
import locale
from datetime import datetime
locale.setlocale(locale.LC_TIME, 'ja_JP.UTF8')
# 1873年1月1日 明治6年1月1日
date1 = datetime(1873, 1, 1)
# 1873年12月31日 明治5年12月2日
date2 = datetime(1872, 12, 31)
print(date1.strftime("%x\n%Ex"))
print(date2.strftime("%x\n%Ex"))
実行例
1873年01月01日
明治06年01月01日
1872年12月31日
西暦1872年12月31日
C言語と同じ結果になります。実装を確認していませんが内部的Cのstrftimeが呼ばれている?
C#
コード
using System.Globalization;
CultureInfo jaJp = new CultureInfo("ja-JP");
var cal = new JapaneseCalendar();
jaJp.DateTimeFormat.Calendar = cal;
var date1 = new DateTime(1873, 1, 1, 0, 0, 0, 0); // 明治6年1月1日
var date2 = new DateTime(1872, 12, 31, 0, 0, 0, 0); // 明治5年12月2日
var eraIndex = cal.GetEra(date1);
var eraName = jaJp.DateTimeFormat.GetEraName(eraIndex);
Console.WriteLine(date1.ToShortDateString());
Console.WriteLine(eraName + date1.ToString("yy年MM月dd日", jaJp));
var eraIndex2 = cal.GetEra(date2);
var eraName2 = jaJp.DateTimeFormat.GetEraName(eraIndex2);
Console.WriteLine(date2.ToShortDateString());
Console.WriteLine(eraName + date2.ToString("yy年MM月dd日", jaJp));
実行例
1873/01/01
明治06年01月01日
1872/12/31
明治05年12月31日
年は正しく変換されているが、月日は変換されない。
Javascript(Node.js)
コード
const date1 = new Date(1873, 0, 1); // 月は0始まり
const date2 = new Date(1872, 11, 31);
console.log(date1.toLocaleDateString('ja-JP', { year: 'numeric', month: 'long', day: 'numeric' }));
console.log(date1.toLocaleDateString('ja-JP-u-ca-japanese', { era: 'long', year: 'numeric', month: 'long', day: 'numeric' }));
console.log(date2.toLocaleDateString('ja-JP', { year: 'numeric', month: 'long', day: 'numeric' }));
console.log(date2.toLocaleDateString('ja-JP-u-ca-japanese', { era: 'long', year: 'numeric', month: 'long', day: 'numeric' }));
実行例
1873年1月1日
明治6年1月1日
1872年12月31日
明治5年12月31日
C#と同様
結論
1873/01/01より以前の日付を西暦から和暦に変換することは避けたほうがよい。
変換する場合はライブラリが正しく変換できることを確認してから使用する。
また、ja-JP-u-ca-japaneseには他の問題があると思っていて別記事にするかもしれません。
Discussion