我得到一个以字符串形式传递给我的时间格式字符串。它可以是像"t"这样的标准字符串,但也可以是自定义字符串(包含"HH"等)。我如何才能发现如果显示,它将是12小时或24小时的格式?(取决于文化和一切…)
最简单的方法是尝试一个日期,然后可以检查字符串中的给定数字,这是你所期望的。例如,2000-01-01T19:00:00Z
是否导致包含7
或9
或两者的字符串。
为了确定在遇到像"'This valid string will mess you up 79'"
这样的奇怪字符串时,如果需要的话,在获得给定区域性信息的完整版本后,您需要检查该字符串。
以下内容作为CultureInfo
或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;
}
您可以使用字符串格式化已知日期,如果使用24小时时间,则该字符串只包含特定值:
if ((new DateTime(1, 1, 1, 23, 1, 1)).ToString(formatString).Contains("23"))
Console.WriteLine("24");
else
Console.WriteLine("12");
步骤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
:
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);
第一个处理将单个字符的标准格式说明符转换为给定区域性的多字符自定义格式说明符。第二个处理自定义格式说明符中引用的文字。