文字列で渡された時間形式の文字列を取得します。「t」のような標準の文字列の場合もありますが、カスタム文字列 (「HH」などを含む) の場合もあります。表示される場合、12 時間または 24 時間形式になることを確認するにはどうすればよいですか? (文化とすべてに依存します...)
3 に答える
最も簡単な方法は、文字列内の特定の数値を調べることができる日付を試すことです。たとえば、2000-01-01T19:00:00Z
結果が a7
または a9
または両方を含む文字列になるかどうか。
のような奇妙な文字列に直面しても確実にするには、"'This valid string will mess you up 79'"
必要に応じて特定のカルチャ情報の完全なバージョンを取得した後、文字列を調べる必要があります。
CultureInfo
以下は、 orの拡張メソッドとしても意味がありDateTimeFormatInfo
ます。
None
実際には、通常は日付情報のみを含む標準形式を、すぐに返されるグループに入れることで簡略化できますが、そこで奇妙ささえ捉えることにしました。
[Flags]
public enum HourRepType
{
None = 0,
Twelve = 1,
TwentyFour = 2,
Both = Twelve | TwentyFour
}
public static HourRepType FormatStringHourType(string format, CultureInfo culture = null)
{
if(string.IsNullOrEmpty(format))
format = "G";//null or empty is treated as general, long time.
if(culture == null)
culture = CultureInfo.CurrentCulture;//allow null as a shortcut for this
if(format.Length == 1)
switch(format)
{
case "O": case "o": case "R": case "r": case "s": case "u":
return HourRepType.TwentyFour;//always the case for these formats.
case "m": case "M": case "y": case "Y":
return HourRepType.None;//always the case for these formats.
case "d":
return CustomFormatStringHourType(culture.DateTimeFormat.ShortDatePattern);
case "D":
return CustomFormatStringHourType(culture.DateTimeFormat.LongDatePattern);
case "f":
return CustomFormatStringHourType(culture.DateTimeFormat.LongDatePattern + " " + culture.DateTimeFormat.ShortTimePattern);
case "F":
return CustomFormatStringHourType(culture.DateTimeFormat.FullDateTimePattern);
case "g":
return CustomFormatStringHourType(culture.DateTimeFormat.ShortDatePattern + " " + culture.DateTimeFormat.ShortTimePattern);
case "G":
return CustomFormatStringHourType(culture.DateTimeFormat.ShortDatePattern + " " + culture.DateTimeFormat.LongTimePattern);
case "t":
return CustomFormatStringHourType(culture.DateTimeFormat.ShortTimePattern);
case "T":
return CustomFormatStringHourType(culture.DateTimeFormat.LongTimePattern);
default:
throw new FormatException();
}
return CustomFormatStringHourType(format);
}
private static HourRepType CustomFormatStringHourType(string format)
{
format = new Regex(@"('.*')|("".*"")|(\\.)").Replace(format, "");//remove literals
if(format.Contains("H"))
return format.Contains("h") ? HourRepType.Both : HourRepType.TwentyFour;
return format.Contains("h") ? HourRepType.Twelve : HourRepType.None;
}
ステップ 1: 必要に応じて、標準の書式文字列を、選択したカルチャの同等のカスタム書式文字列に変換します。これは、反映されたロジックを使用して を模倣しDateTime.ToString
ます。
if (formatString.Length == 1)
{
// Get formatter for the culture of your choice - e.g. the current culture
DateTimeFormatInfo fi = CultureInfo.CurrentCulture.DateTimeFormat;
formatString = epf.Invoke(
null,
new object[]{
formatString,
DateTime.MinValue,
fi,
TimeSpan.MinValue});
}
ステップ 2: 文字列を解析して、12 時間または 24 時間の指定子が含まれているかどうかを確認します。DateTime.ToString
これは、リフレクト ロジックを使用して可能な限り模倣し、カスタム ロジックを使用できないという残念な組み合わせですが、問題なく動作するようです。
for (int i = 0; i < formatString.Length; i++)
{
char current = formatString[i];
if (current == '"' || current == '\'') // Skip literal quoted sections
{
i += (int)pqs.Invoke(
null,
new object[] {
formatString,
i,
new StringBuilder()});
}
else if (current == '\\') // Skip escaped characters
{
i+= 1;
}
else if (current == 'h')
{
is12Hour = true;
}
else if (current == 'H')
{
is24Hour = true;
}
}
MethodInfo
これは、リフレクションによって得られる次の 2 つに依存します。
var t = Assembly
.GetAssembly(typeof(System.DateTime))
.GetType("System.DateTimeFormat");
var epf = t.GetMethod(
"ExpandPredefinedFormat",
BindingFlags.Static | BindingFlags.NonPublic);
var pqs = t.GetMethod(
"ParseQuoteString",
BindingFlags.Static | BindingFlags.NonPublic);
1 つ目は、単一文字の標準書式指定子を特定のカルチャの複数文字のカスタム書式指定子に変換する処理を行います。2 番目は、カスタム書式指定子内の引用符で囲まれたリテラルを処理します。
文字列を使用して既知の日付をフォーマットできます.24時間の時間を使用している場合、特定の値のみが含まれることがわかっている日付:
if ((new DateTime(1, 1, 1, 23, 1, 1)).ToString(formatString).Contains("23"))
Console.WriteLine("24");
else
Console.WriteLine("12");