【问题标题】:How can one parse a unknown datetime format in c#如何在 C# 中解析未知的日期时间格式
【发布时间】:2014-05-02 17:57:29
【问题描述】:

我正在尝试为 TV Schedule Pro (http://sourceforge.net/p/tvschedulerpro) 编写 XML 解析器。 一个特殊的挑战是解析由日期元素报告的 DateTime。

根据DTD文件:

此 DTD 中的所有日期和时间都遵循相同的格式,但基础松散 在 ISO 8601 上。它们可以是 'YYYYMMDDhhmmss' 或一些初始子字符串, 例如,如果您只知道年份和月份,则可以使用“YYYYMM”。 您还可以在末尾附加时区;如果没有明确的时区 给定,假设 UTC。示例:“200007281733 BST”、“200209”、 '19880523083000 +0300'。 (英国夏令时 == +0100。)

这是一个具有挑战性的情况,我最初考虑使用 DateTimeFormatInfo.GetAllDateTimePatterns 并使用 DateTime.TryParseExact,关于时区和带有任何分隔符的特定格式的最后一行使得无法使用上述内容。

是否有一种简洁的方法来解析上述日期时间规范,或者是否只需要在找到字符串时不断查找/添加各种模式来解析字符串(看起来几乎是无穷无尽的组合)

【问题讨论】:

  • 您可能仍然可以使用 DateTime.TryParseExact,但您可能必须在拨打电话之前自己提取时区信息。
  • 您是否尝试使用“YYYYMMDDhhmmss”作为 DateTime.TryParseExact 的模式参数?
  • 是的,我考虑过这一点,但它不会捕获所有可能的格式,正如您从 DTD 定义中看到的那样。我正在寻找有关处理此问题的最佳方法的意见

标签: c# parsing date datetime undefined


【解决方案1】:

好吧,您可能可以使用K 格式说明符来做这样的事情(有关详细信息,请参阅自定义日期时间格式字符串):

public static DateTimeOffset parseIso8601CompactForm( string text )
{
  DateTimeStyles options = DateTimeStyles.AllowWhiteSpaces
                         | DateTimeStyles.AssumeLocal
                         ;
  DateTimeOffset value = DateTimeOffset.ParseExact( text , formats , CultureInfo.CurrentCulture , options ) ;
  return value ;
}
static readonly string[] formats =
{
  "yyyyMMddHHmmssK" , "yyyyMMddHHmmss" ,
  "yyyyMMddHHmmK"   , "yyyyMMddHHmm"   ,
  "yyyyMMddHHK"     , "yyyyMMddHH"     ,
  "yyyyMMddK"       , "yyyyMMdd"       ,
  "yyyyMMK"         , "yyyyMM"         ,
  "yyyyK"           , "yyyy"           ,
} ;

但您可能会发现这样的东西更高效:

public static DateTimeOffset parseIso8601CompactForm( string text )
{
  if ( string.IsNullOrEmpty(text) ) throw new ArgumentException("text") ;
  if ( string.Length < 4 ) throw new ArgumentException("text") ;

  int            YYYY  = text.Length >=  4 ? int.Parse(text.Substring(  0 , 4 ) ) : 1    ;
  int            MM    = text.Length >=  6 ? int.Parse(text.Substring(  4 , 2 ) ) : 1    ;
  int            DD    = text.Length >=  8 ? int.Parse(text.Substring(  6 , 2 ) ) : 1    ;
  int            hh    = text.Length >= 10 ? int.Parse(text.Substring(  8 , 2 ) ) : 0    ;
  int            mm    = text.Length >= 12 ? int.Parse(text.Substring( 10 , 2 ) ) : 0    ;
  int            ss    = text.Length >= 14 ? int.Parse(text.Substring( 12 , 2 ) ) : 0    ;
  string         tzid  = text.Length >  14 ? text.Substring(14).Trim()            : null ;
  TimeZoneInfo   tz    = TimeZoneInfo.FindSystemTimeZoneById( tzid ) ;
  DateTimeOffset value = new DateTimeOffset( YYYY , MM , DD , hh , mm , ss , tz.BaseUtcOffset ) ;
  return value ;
}

不过,我确信在处理时区/与 UTC 的偏移量方面存在一些我没有正确考虑并且必须正确处理的奇怪之处。

【讨论】:

  • 我认为这是迄今为止最好的答案。这会处理字符串中的 +0300 还是 BST?
【解决方案2】:

也许可以试试DateTime.TryParseExact(time, ["yyyyMMddHHmmss K", "yyyyMMddHHmmss zzz"] ...的变体

可能无法全部了解,但请搜索 http://msdn.microsoft.com/en-us/library/8kb3ddd4%28v=vs.110%29.aspx#KSpecifier 以获取更多想法。

【讨论】:

  • 这就是整个问题,我想不出一种单一的格式/方法可以捕获上面 DTD 文件中定义的所有问题
  • 不,但是你能不使用string[]重载吗?它仍然是一个班轮。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-10
  • 2022-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多