|
分類:[.NET 全般]
お世話になっております、梅のど飴と申します。
現在 VS2005 C#2.0 で開発を行っているのですが、日付を入力する項目で
"2009/03/03"や"H21.3.3"や"3/3"と言った様々な入力様式をサポートして
日付型に変換すると要件が有ります。
そして以下の様なコーディングを行う事により、9割ほどの要件を満たす
事が出来たのですが、ただ一点…未来元号への対応がどうしても出来ずに
います。
※新元号への対応は Windows Update に任せればいいと言うのは重々承知
しているのですが、そこは大人の事情と言う事で追及しないで下さい。
どぼん.NETの過去ログにて JapaneseCalendar の内容を変更して未来元号
を表示すると言う記事を見つける事が出来たのですが、それを TryParse
の変換処理とどう組み合わせれば良いのかがわかりません。
DateTime.TryParse を使いつつも、新元号に自力で対応させる方法があり
ましたら教えて頂けないでしょうか。
[参考記事]
http://dobon.net/vb/bbs/log3-5/2481.html
新元号を追加した JapaneseCalendar(?) を一度でも作成すると、下記の
処理その物が正常に動作しなくなります。
"2009/3/3"を指定すると、期待値は"2009/03/03"なのですが(無変換)
"年号の値が有効ではありません。パラメータ名: era"と言うエラーが
発生します。
[現在のソース]
private bool DateTryParse(string text, out DateTime date)
{
// 2バイトの数字は1バイトに置換 ("平成21年3月3日"→"平成21年3月3日"で変換可能)
text = Microsoft.VisualBasic.Strings.StrConv(text, Microsoft.VisualBasic.VbStrConv.Narrow, 0);
System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
bool ret = DateTime.TryParse(text, culture, System.Globalization.DateTimeStyles.None, out date);
if (!ret)
{
// 特殊入力に対応 20090303, 090303, 0303, 033
string[] fmt = new string[4] { "yyyyMMdd", "yyMMdd", "MMdd", "MMd" };
ret = DateTime.TryParseExact(text, fmt, culture, System.Globalization.DateTimeStyles.None, out date);
}
return ret;
}
// 新元号を追加するテストメソッド フォームのOnLoadなどで実行?
private static DateTimeFormatInfo Test()
{
// DateTimeFormatInfo 作成
JapaneseCalendar japaneseCalendar = new JapaneseCalendar();
CultureInfo cultureInfo = new CultureInfo("ja-JP");
DateTimeFormatInfo dateTimeFormatInfo = cultureInfo.DateTimeFormat;
dateTimeFormatInfo.Calendar = japaneseCalendar;
// JapaneseCalendar の Type を取得
Type japaneseCalendarType = typeof(System.Globalization.JapaneseCalendar);
// helper を取得
FieldInfo helperFieldInfo = japaneseCalendarType.GetField("helper",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
object helper = helperFieldInfo.GetValue(dateTimeFormatInfo.Calendar);
// GregorianCalendarHelper の Type を取得
Type helperType = helperFieldInfo.FieldType;
// m_EraInfo を取得
FieldInfo eraInfoFieldInfo = helperType.GetField("m_EraInfo",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
Array eraInfo = (Array)eraInfoFieldInfo.GetValue(helper);
// EraInfo の Type を取得
Type eraInfoType = eraInfo.GetValue(0).GetType();
// m_EraInfo に設定する配列を作成
Array new_EraInfo = Array.CreateInstance(eraInfoType, 5);
// 要素 0 に新しく作成した EraInfo を設定
// 2010/7/30 から新しい元号に
new_EraInfo.SetValue(eraInfoType.Assembly.CreateInstance(
eraInfoType.FullName, false, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
null, new object[] { 5, (new DateTime(2010, 7, 30)).Ticks, 2009, 1, 7990 }, cultureInfo, null), 0);
// '平成' の最終年を 22 (= 2010 - 1989 + 1) に変更
FieldInfo maxEraYearFieldInfo = eraInfoType.GetField("maxEraYear",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
maxEraYearFieldInfo.SetValue(eraInfo.GetValue(0), 22);
// 明治〜平成の分をコピーして m_EraInfo (GregorianCalendarHelper) に設定
eraInfo.CopyTo(new_EraInfo, 1);
eraInfo = new_EraInfo;
eraInfoFieldInfo.SetValue(helper, eraInfo);
// m_EraInfo (JapaneseCalendar) に設定
FieldInfo eraInfoFieldInfo2 = japaneseCalendarType.GetField("m_EraInfo",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
eraInfoFieldInfo2.SetValue(japaneseCalendar, eraInfo);
// m_eras
FieldInfo erasFieldInfo = helperType.GetField("m_eras", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
int[] eras = (int[])erasFieldInfo.GetValue(helper); // 取得
eras = new int[] { 5, 4, 3, 2, 1 }; // 編集
erasFieldInfo.SetValue(helper, eras); // 設定
// DateTimeFormatInfo の Type を取得
Type dateTimeFormatInfoType = typeof(System.Globalization.DateTimeFormatInfo);
// m_eraNames を取得 (Porperty Get されるまで Null のようなのでプロパティから読み出し)
PropertyInfo eraNamesPropertyInfo = dateTimeFormatInfoType.GetProperty("EraNames",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
string[] eraNames = (string[])eraNamesPropertyInfo.GetValue(dateTimeFormatInfo, null);
// 新元号を追加
string[] new_eraNames = new string[5];
new_eraNames[4] = "○○";
eraNames.CopyTo(new_eraNames, 0);
// m_eraNames に設定
FieldInfo eraNamesFieldInfo = dateTimeFormatInfoType.GetField("m_eraNames",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
eraNamesFieldInfo.SetValue(dateTimeFormatInfo, new_eraNames);
// m_abbrevEraNames を取得 (Porperty Get されるまで Null のようなのでプロパティから読み出し)
PropertyInfo abbrevEraNamesPropertyInfo = dateTimeFormatInfoType.GetProperty("AbbreviatedEraNames",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
string[] abbrevEraNames = (string[])abbrevEraNamesPropertyInfo.GetValue(dateTimeFormatInfo, null);
// 新元号の略称を追加
string[] new_abbrevEraNames = new string[5];
new_abbrevEraNames[4] = "○";
abbrevEraNames.CopyTo(new_abbrevEraNames, 0);
// m_abbrevEraNames に設定
FieldInfo abbrevEraNamesFieldInfo = dateTimeFormatInfoType.GetField("m_abbrevEraNames",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
abbrevEraNamesFieldInfo.SetValue(dateTimeFormatInfo, new_abbrevEraNames);
// m_abbrevEnglishEraNames を取得 (Porperty Get されるまで Null のようなのでプロパティから読み出し)
PropertyInfo abbreviatedEnglishEraNamesPropertyInfo = dateTimeFormatInfoType.GetProperty("AbbreviatedEnglishEraNames",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
string[] abbreviatedEnglishEraNames = (string[])abbreviatedEnglishEraNamesPropertyInfo.GetValue(dateTimeFormatInfo, null);
// 新元号の略称(アルファベット)を追加
string[] new_abbreviatedEnglishEraNames = new string[5];
new_abbreviatedEnglishEraNames[4] = "Z";
abbreviatedEnglishEraNames.CopyTo(new_abbreviatedEnglishEraNames, 0);
// m_abbrevEnglishEraNames に設定
FieldInfo abbreviatedEnglishEraNamesFieldInfo = dateTimeFormatInfoType.GetField("m_abbrevEnglishEraNames",
BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
abbreviatedEnglishEraNamesFieldInfo.SetValue(dateTimeFormatInfo, new_abbreviatedEnglishEraNames);
//// Calendar の Type を取得
//Type calendarType = typeof(System.Globalization.Calendar);
//// m_currentEraValue を設定
//PropertyInfo currentEraValuePropertyInfo = calendarType.GetProperty("CurrentEraValue",
// BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
//int currentEraValue = (int)currentEraValuePropertyInfo.GetValue(japaneseCalendar, null);
//FieldInfo currentEraValueFieldInfo = japaneseCalendarType.GetField("m_currentEraValue",
// BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
//currentEraValueFieldInfo.SetValue(japaneseCalendar, 5);
return dateTimeFormatInfo;
}
|