日時のカスタムするIFormatProviderを作成して使用するには?
-
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);
}
}