日時のカスタムするIFormatProviderを作成して使用するには?

StackOverflow https://stackoverflow.com/questions/2382154

  •  24-09-2019
  •  | 
  •  

質問

私は、DateTimeオブジェクトのカスタム書式指定文字列を認識することになるIFormatProvider実装を作成しようとしていました。ここに私の実装は次のとおりです。

 public class MyDateFormatProvider : IFormatProvider, ICustomFormatter
 {
  public object GetFormat(Type formatType)
  {
   if (formatType == typeof(ICustomFormatter))
   {
    return this;
   }
   return null;
  }

  public string Format(string format, object arg, IFormatProvider formatProvider)
  {
   if(arg == null) throw new ArgumentNullException("arg");
   if (arg.GetType() != typeof(DateTime)) return arg.ToString();
   DateTime date = (DateTime)arg;
   switch(format)
   {
    case "mycustomformat":
     switch(CultureInfo.CurrentCulture.Name)
     {
      case "en-GB":
       return date.ToString("ddd dd MMM");
      default:
       return date.ToString("ddd MMM dd");
     }
    default:
     throw new FormatException();
   }
  } 

私はそうのようなDateTime.ToString(string format, IFormatProvider provider)方法でそれを使用できるように期待していたがます:

DateTime d = new DateTime(2000, 1, 2);
string s = d.ToString("mycustomformat", new MyDateFormatProvider());

この例では、米国文化で実行、結果は標準DateTime書式文字列が解釈されて明らかにので、"00cu0Ao00or0aA"である。

しかし、私は次のように同じクラスを使用する場合:

DateTime d = new DateTime(2000, 1, 2);
string s = String.Format(new MyDateFormatProvider(), "{0:mycustomformat}", d);

私はつまり、私が期待するものを手に入れる"Sun Jan 02"

私は別の結果を理解していません。誰かが説明してもらえますか?

ありがとうございます。

役に立ちましたか?

解決

DateTime.ToString構造は、書式設定に使用するプロバイダを取得するためにDateTimeメソッドを使用していることリフレクターショーでDateTimeFormatInfo.GetInstance方法を確認します。何のプロバイダが見つからない場合にのみDateTimeFormatInfo.GetInstanceまたはDateTimeFormatInfoのインスタンスを返すようICustomFormmaterは、DateTimeFormatInfoのために、渡されたプロバイダから型CultureInfoのフォーマッタを決して要求しません。 DateTime.ToString方法は、あなたのICustomFormatterの例が示すように、ないようStringBuilder.Format方法はString.Formatインターフェイスを尊重していないようです。

私はDateTime.ToString方法はICustomFormatterインタフェースをサポートしなければならないことに同意し、それが現在はしていないようです。これは、すべての変更された可能性があるか、.NET 4.0に変更されます。

他のヒント

短い説明がその中にある

DateTime.ToString(string format, IFormatProvider provider)

は、あなたがそれのパラメータの1つとしてIFormatProviderを実装何かを渡すことができます、それは実際にはそれだけのコードの中IFormatProviderを実装する2つの可能なタイプをサポートしています

DateTimeFormatInfoまたはCultureInfo

あなたのパラメータはどちらかとしてまたはそれら(asを使用して)キャストすることができない場合は、この方法はCurrentCultureがデフォルトになります。

String.Formatそのような範囲に限定されるものではない。

使用拡張方法:)

public static class FormatProviderExtension
    {
        public static string FormatIt(string format, object arg, IFormatProvider formatProvider)
        {
            if (arg == null) throw new ArgumentNullException("arg");
            if (arg.GetType() != typeof(DateTime)) return arg.ToString();
            DateTime date = (DateTime)arg;
            switch (format)
            {
                case "mycustomformat":
                    switch (CultureInfo.CurrentCulture.Name)
                    {
                        case "en-GB":
                            return date.ToString("ddd dd MMM");
                        default:
                            return date.ToString("ddd MMM dd");
                    }
                default:
                    throw new FormatException();
            }
        }

        public static string ToString(this DateTime d, IFormatProvider formatProvider, string format)
        {
            return FormatIt(format, d, formatProvider);
        }
    }
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top