1

我得到一个以字符串形式传递给我的时间格式字符串。它可以是像“t”这样的标准字符串,但也可以是自定义字符串(包含“HH”等)。我怎样才能知道,如果显示它将是 12 小时或 24 小时格式?(取决于文化和一切......)

4

3 回答 3

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;
}
于 2012-09-12T11:10:10.950 回答
1

第 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反射获得的以下两个s:

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

第一个处理将单字符标准格式说明符转换为给定文化的多字符自定义格式说明符。第二个处理自定义格式说明符内的引用文字。

于 2012-09-12T10:27:50.917 回答
1

您可以使用字符串格式化已知日期,如果它使用 24 小时时间,您知道该日期将仅包含特定值:

if ((new DateTime(1, 1, 1, 23, 1, 1)).ToString(formatString).Contains("23"))
    Console.WriteLine("24");
else
    Console.WriteLine("12");
于 2012-09-12T10:46:07.270 回答