DOBON.NET DOBON.NETプログラミング掲示板過去ログ

和暦の未来対応

  • 題名: 和暦の未来対応
  • 著者: チョコ
  • 日時: 2004/02/12 18:46:51
  • ID: 2481
  • この記事の返信元:
    • (なし)
  • この記事への返信:
  • ツリーを表示
環境/言語:[Windows2000sp4/VB.NET2003]
分類:[.NET]

日本語版Windows基本クラスの「JapaneseCalendar」クラスについて教えて下さい。

現在、このクラスを使用して年号表示を行っているのですが、
これに未来の元号に対応させてプログラムを追加させようと思っています。

調べてみたところ、未来の元号を追加するためにはWindowsUpdateで
対応できるらしいのですが、諸事情によりコードで作成する必要があります。

色々と調べているのですが、足がかりがなく困っていますので宜しくお願いします。
チョコさん、こんばんは。深山と申します。

 いろい試してみたのですけど、なかなか難しいようですね(^_^;)
 どうやったらいいのかは判りませんでしたけど、レスがつかないようなので参考までに。

http://www.ailight.jp/Wareki_2.aspx
の内容を参考にウォッチとにらめっこしたところ、

JapaneseCalendar クラス(というより GregorianCalendarHelper のかも?)
  ・m_EraInfo フィールド
      年号毎の期間(何年何月何日からその年号になるのか、
      その年号は何年まであるのか等)を保持
 ・m_eras フィールド
      Eras プロパティの値を保持

DateTimeFormatInfo クラス
 ・m_eraNames フィールド
      "明治" 、 "大正" 等の元号名を保持
  ・m_abbrevEraNames フィールド
      "明" 、 "大" 等の元号名略称を保持
  ・m_abbrevEnglishEraNames フィールド
      "M" 、 "T" 等の元号名略称(アルファベット)を保持

あたりに情報を追加できればなんとかなるかも知れないなぁ、という印象でした。
 なので、 DateTimeFormatInfo オブジェクトを作成、リフレクションを使ってこの辺を
書き換えてみるとかしたものを使用すれば、あるいは期待する動きになるかも知れません。
 ‥‥もちろん、ならないかも知れませんが。
# というよりならない可能性のが大きいですよね(汗)
# シェアードコードを落としてきて解析した方が確実な気も‥‥。


 以下、個人的で素朴な疑問なのですけども。

 この機能、ほんとに必要なのでしょうか?
 Windows Update ができる、できない以前に、元号なんて頻繁に増えるものではありません。
場合によっては十数年、数十年も変わらないこともあるわけです。
 マシンの耐用年数や OS の保障期間等よりも長い期間使用しないことになる可能性のある
機能って一体‥‥というのが正直な感想だったりします。
# それとも、そんなに長期の運用を求められるシステムなのでしょうか?

 それからもう一点。
 JapaneseCalendar クラスを使用して表示を行っている箇所というのはどの程度あるの
でしょう? 場合によっては、変換用の関数を自作した方が早いということもあります。
# もしかしたら、もうそのように対応されてるのかも知れませんけど(^_^;)
■No2607に返信(深山さんの記事)
>  チョコさん、こんばんは。深山と申します。
>
>  いろい試してみたのですけど、なかなか難しいようですね(^_^;)
>  どうやったらいいのかは判りませんでしたけど、レスがつかないようなので参考までに。
>
> http://www.ailight.jp/Wareki_2.aspx
> の内容を参考にウォッチとにらめっこしたところ、
>
> JapaneseCalendar クラス(というより GregorianCalendarHelper のかも?)
> ・m_EraInfo フィールド
> 年号毎の期間(何年何月何日からその年号になるのか、
> その年号は何年まであるのか等)を保持
>  ・m_eras フィールド
> Eras プロパティの値を保持
>
> DateTimeFormatInfo クラス
>  ・m_eraNames フィールド
> "明治" 、 "大正" 等の元号名を保持
> ・m_abbrevEraNames フィールド
> "明" 、 "大" 等の元号名略称を保持
> ・m_abbrevEnglishEraNames フィールド
> "M" 、 "T" 等の元号名略称(アルファベット)を保持
>
> あたりに情報を追加できればなんとかなるかも知れないなぁ、という印象でした。
>  なので、 DateTimeFormatInfo オブジェクトを作成、リフレクションを使ってこの辺を
> 書き換えてみるとかしたものを使用すれば、あるいは期待する動きになるかも知れません。
>  ‥‥もちろん、ならないかも知れませんが。
> # というよりならない可能性のが大きいですよね(汗)
> # シェアードコードを落としてきて解析した方が確実な気も‥‥。

調査ありがとうございます。
シェアードコード、、、やっぱりそうですよね。
この書き込みする前に私も落として調査したのですが
納期に追われ調査が続けられなく、書き込みさせて頂きました。

>  以下、個人的で素朴な疑問なのですけども。
>
>  この機能、ほんとに必要なのでしょうか?
>  Windows Update ができる、できない以前に、元号なんて頻繁に増えるものではありません。
> 場合によっては十数年、数十年も変わらないこともあるわけです。
>  マシンの耐用年数や OS の保障期間等よりも長い期間使用しないことになる可能性のある
> 機能って一体‥‥というのが正直な感想だったりします。
> # それとも、そんなに長期の運用を求められるシステムなのでしょうか?
>
>  それからもう一点。
>  JapaneseCalendar クラスを使用して表示を行っている箇所というのはどの程度あるの
> でしょう? 場合によっては、変換用の関数を自作した方が早いということもあります。
> # もしかしたら、もうそのように対応されてるのかも知れませんけど(^_^;)

実はInputManという市販ツールを使用して元号を未来に対応させようしています。
そこで調べてみたところ、このツールはカレンダ情報をJapaneseCalendarから
取得しているとわかり、今回の疑問に辿り着きました。

あと、なぜしなくてはいけないのか、、、大人の事情ってやつだそうです:;

今回頂いた情報をもとに再度調査してみようと思います。
本当にありがとうございました。
2004/02/25(Wed) 03:15:46 編集(投稿者)

 チョコさん、こんにちは。

> シェアードコード、、、やっぱりそうですよね。

 お力になれず申し訳ないですm(__)m

> 実はInputManという市販ツールを使用して元号を未来に対応させようしています。
> そこで調べてみたところ、このツールはカレンダ情報をJapaneseCalendarから
> 取得しているとわかり、今回の疑問に辿り着きました。

 .NET 用の InputMan は使用したことがないので兼ね合いは判らないのですけども。
 上記の方法で実験したら何となく上手くいったようですので、(参考にならないような気もしますけど/汗)
コードを掲載いたします。
 尚、この Test メソッドの最後で m_currentEraValue を変更する処理をコメントアウトしていますが、
これは '現在' が '平成' ではなくなったら加える必要があります。
# コードはあまり整理されておらず、コメントも先ほど追加したものなので間違ってるかも‥‥(^_^;)


■設定
 2010/7/30 から新元号 "どぼん" に変わった
# 管理人さま、勝手に屋号(?)を使用してごめんなさいm(__)m


        static void Main() 
        {
            DateTimeFormatInfo format = Form1.Test();
            DateTime dt1 = DateTime.Parse("どぼん3年 12月 3日", format);
            DateTime dt2 = new DateTime(2010, 7, 30);
            DateTime dt3 = new DateTime(2010, 7, 29);
            Console.WriteLine(dt1);                                     // 2012/12/03 0:00:00 と出力
            Console.WriteLine(dt2.ToString("gyy年MM月dd日", format));   // どぼん01年07月30日 と出力
            Console.WriteLine(dt3.ToString("gyy年MM月dd日", format));   // 平成22年07月29日   と出力
        }

        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);

            // 新元号の略称(アルファベット) "D" を追加
            string[] new_abbreviatedEnglishEraNames = new string[5];
            new_abbreviatedEnglishEraNames[4] = "D";
            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;
        }


> あと、なぜしなくてはいけないのか、、、大人の事情ってやつだそうです:;

 なるほど。なっとくです(^_^;;;)

# 関係ないリンクを入れてしまってたようなので削除(汗)
■No2663に返信(深山さんの記事)
> ■設定
>  2010/7/30 から新元号 "どぼん" に変わった
> # 管理人さま、勝手に屋号(?)を使用してごめんなさいm(__)m

出来ました!!(目から何かが出来そうです;;)
実はVBで開発しているので、VB化できたらこちらに記載しようと思います。

本当に有難うございました。
なんとお礼をもし上げたらいいのか;;

また何かありましたら宜しくお願いします。
私も皆さんのお力になれるよう頑張ります。
(いつも見てますが、力になれないことばかり;;)
  • 題名: Re[5]: 和暦の未来対応
  • 著者: 深山
  • 日時: 2004/02/26 12:52:46
  • ID: 2701
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
> 出来ました!!(目から何かが出来そうです;;)

 そうですか。よかったですね!(^^)v

> 実はVBで開発しているので、VB化できたらこちらに記載しようと思います。

 あ、そうでしたね(汗)<VBで開発
# 元々コードを掲載するつもりはなく、個人的な興味から実験してたもので(^_^;)

 VB化、頑張ってくださいませ。
# ところでこのコードには無駄も多いですし、年号を動的に追加するようにもなっていません。
# その辺りの修正も含めて報告して頂けたら個人的には嬉しいです(^^)

> 本当に有難うございました。
> なんとお礼をもし上げたらいいのか;;
>
> また何かありましたら宜しくお願いします。
> 私も皆さんのお力になれるよう頑張ります。
> (いつも見てますが、力になれないことばかり;;)

 そんなことないですよ。チョコさんがこうして質問されたことで、今回私も色々と
勉強させて頂きました。
 また、結果を報告してくださることで今後同様のことで悩む方がいたときの参考に
なりますから。
# 未来の元号という要求はあまりない気もしますけど(^_^;) それでも明治以前、あるいは
# 特殊な元号を使用したいという方がいるということはあり得ます。

DOBON.NET | プログラミング道 | プログラミング掲示板