C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[1]: DateTime.TryParse と新元号について


(過去ログ 59 を表示中)

[トピック内 2 記事 (1 - 2 表示)]  << 0 >>

■33545 / inTopicNo.1)  DateTime.TryParse と新元号について
  
□投稿者/ 梅のど飴 (4回)-(2009/03/03(Tue) 17:59:25)

分類:[.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;
}

引用返信 編集キー/
■33594 / inTopicNo.2)  Re[1]: DateTime.TryParse と新元号について
□投稿者/ 梅のど飴 (5回)-(2009/03/05(Thu) 11:01:13)
梅のど飴 さんの Web サイト
「梅のど飴」の名前でまったく同じ内容が「どぼん!のプログラミング道掲示板」に
投稿されているのを見つけたのですが、これは私がマルチポストした物では有りません。

本件に関しての書込みは「C# と VB.NET の質問掲示板」でのみ行って頂きますよう
お願い致します。
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -