C# 日期时间解析器






4.72/5 (53投票s)
从字符串解析日期和(或)时间。
引言
我曾需要检测和识别互联网消息中包含的日期和/或时间。这些消息由不同的用户发送,因此无法遵循特定的格式。它们通常由一两句话组成,无法预测日期和/或时间在其中的位置。因此,.NET 内置的 DateTime.Parse()
方法无法提供帮助,因为该方法只能解析完全由日期/时间表示组成的 string
,它无法在文本中查找日期/时间。此外,DateTime.Parse()
无法识别一些仍然普遍存在的日期表示。
我需要一个 C# 函数,类似于 Perl 的通用 str2time()
或 PHP 的 strtotime()
。经过一番谷歌搜索,我惊讶地发现在 C# 中找不到这样的代码。因此,我编写了此处呈现的日期/时间解析类。
描述
DateTimeRoutines
类公开了几个日期/时间解析方法。基本思想是在 string
中查找日期和/或时间的第一个实例,并将其转换为 DateTime
。
方法 | 描述 |
TryParseDateTime() |
尝试在传入的 string 中查找日期和时间。如果未找到日期或时间,则返回 false 。 |
TryParseDate() |
尝试在传入的 string 中查找日期。它始终返回时间 0:0:0。如果未找到日期的年份,则默认接受当前年份;此规则可以通过指定 DefaultDate 来更改。如果未找到日期,则返回 false 。 |
TryParseTime() |
尝试在传入的 string 中查找时间。如果已在 string 中找到日期并将其作为参数传递,则它会在该日期附近查找时间。它始终返回日期 1/1/1。如果未找到时间,则返回 false 。 |
TryParseDateOrTime() |
尝试在传入的 string 中查找日期和/或时间。如果仅找到时间,则默认情况下,日期设置为当天的日期;此规则可以通过指定 DefaultDate 来更改。如果未找到日期或时间,则返回 false 。 |
这些方法接受 DateTimeFormat
参数,该参数指定在歧义情况下首选的识别格式。
这些方法返回一个 ParsedDateTime
对象。该对象描述了是否在 string
中找到日期(或时间),以及(如果找到)其位置,并且还包含一个 DateTime
结构作为解析结果。
此外,这些方法还有一些变体,它们直接返回 DateTime
而不是 ParsedDateTime
。不过,更推荐使用原始方法,因为它们的输出允许了解日期(或时间)是否真的被找到,还是由默认值设置的。
请注意,在 string
包含多个时间的情况下,TryParseDateTime()
和 TryParseTime()
可能会返回不同的时间。TryParseDateTime()
会查找日期附近的时间,而 TryParseTime()
返回找到的第一个时间。
本地时间和绝对时间
ParsedDateTime.DateTime
始终被视为本地时间,即它直接反映了所解析的 string
。如果时间字符串中包含表示时间是绝对时间的 UTC 偏移量或时区缩写,则 ParsedDateTime.IsUtcOffsetFound
为 true
,并且 ParsedDateTime.UtcDateTime
为 UTC 日期和时间。如果 ParsedDateTime.IsUtcOffsetFound
为 false
,则 ParsedDateTime.UtcDateTime
应被忽略,因为它未定义。
请注意,TryParseDate()
不会检测时区。
用法
DateTimeRoutines
可以识别的日期格式可以在下面的测试字符串中看到(完整的解析格式列表可以在随代码提供的 Test
项目中找到)
@"Member since: 10-Feb-2008"
@"Last Update: 18:16 11 Feb '08 "
@"date Tue, Feb 10, 2008 at 11:06 AM"
@"see at 12/31/2007 14:16:32"
@"sack finish 14:16:32 November 15 2008, 1-144 app"
@"Genesis Message - Wed 04 Feb 08 - 19:40"
@"The day 07/31/07 14:16:32 is "
@"Shipping is on us until December 24, 2008 within the U.S."
@" 2008 within the U.S. at 14:16:32"
@"5th November, 1994, 8:15:30 pm"
@"7 boxes January 31 , 14:16:32."
@"the blue sky of Sept 30th 2008 14:16:32"
@" e.g. 1997-07-16T19:20:30+01:00"
@"Apr 1st, 2008 14:16:32 tufa 6767"
@"wait for 07/31/07 14:16:32"
@"later 12.31.08 and before 1.01.09"
@"Expires: Sept 30th 2008 14:16:32"
@"Offer expires Apr 1st, 2007, 14:16:32"
@"Expires 14:16:32 January 31."
@"Expires 14:16:32 January 31-st."
@"Expires 23rd January 2010."
@"Expires January 22nd, 2010."
@"Expires DEC 22, 2010."
如果您只需要获取日期,可以使用以下代码示例:
string str = @"The last round was June 10, 2005; this time the unbroken record was held.";
DateTimeRoutines.ParsedDateTime pdt;
if (DateTimeRoutines.TryParseDate(str, DateTimeRoutines.DateTimeFormat.USA_DATE, out pdt))
Console.WriteLine("Date was found: " + pdt.DateTime.ToString());
如果您想获取日期,并在可能的情况下获取时间,可以使用以下代码示例:
string str = @"The last round was June 10, 2005; this time the unbroken record was held.";
DateTimeRoutines.ParsedDateTime pdt;
if (DateTimeRoutines.TryParse(str, DateTimeRoutines.DateTimeFormat.USA_DATE, out pdt)
&& pdt.IsDateFound
)
Console.WriteLine("Date was found: " + pdt.DateTime.ToString());
如果您想获取完全指定的日期和时间,可以使用以下代码示例:
string str = @"The last round was June 10, 2005 10:30AM; this time the unbroken record was held.";
DateTimeRoutines.ParsedDateTime pdt;
if(str.TryParseDateTime(DateTimeRoutines.DateTimeFormat.USA_DATE, out pdt))
Console.WriteLine("Date&time was found: " + pdt.DateTime.ToString());
如果您想获取 UTC 日期和时间,可以使用以下代码示例:
string str = @"Your program recognizes string : 21 Jun 2010 04:20:19 -0430 blah blah.";
DateTimeRoutines.ParsedDateTime pdt;
if(str.TryParseDateTime(DateTimeRoutines.DateTimeFormat.USA_DATE, out pdt) && pdt.IsUtcOffsetFound)
Console.WriteLine("UTC date&time was found: " + pdt.UtcDateTime.ToString());
.NET 版本一致性
DateTimeRoutines
被构建为一个 .NET 4 DLL,它将解析方法作为 string
类的扩展公开。该 DLL 也可以被 .NET 2 代码调用。但是,如果您想将 DateTimeRoutines
的源代码嵌入到您的 .NET 2 项目中,则需要从方法参数中删除 this
关键字。
结论
这段代码满足了我的需求。我不想实现过于宽泛的识别能力,例如 Perl 的 str2time()
所提供的能力,因为更宽泛的识别能力会导致解析器在尝试检测 string
的任何部分中的日期/时间时产生更高的错误率。
尽管如此,DateTimeRoutines
能够识别通信中常用的格式。如果您发现任何未被识别的普遍日期/时间格式,请告知我,我将更新代码。
代码
在附加的代码中,您可以找到包含以下内容的 DateTimeRoutines
项目:
- 一个被编译为 DLL 的
DateTimeRoutines
类 Test
项目
代码以公共域代码的形式获得许可。
最新版本可以在 SourceForge 上找到。
祝您开心!
历史
- 2009 年 2 月 11 日
- 初次发布
- 2009 年 2 月 14 日
- 添加了
TryParseDateTime()
- 添加了
- 2009 年 12 月 18 日
- 更新了
TryParseDate()
- 更新了
- 2010 年 3 月 3 日
- 更新了
TryParseDate()
- 更新了
- 2010 年 3 月 12 日
- 移除了
locks
- 移除了
- 2010 年 3 月 13 日
- 编译为 DLL
- 方法编译为
string
类的扩展 TryParse()
重命名为TryParseDateOrTime()
- 2010 年 7 月 13 日
- 更新了源代码
- 2011 年 5 月 15 日
- 修复了 12pm 和 12am 的问题
- 升级到 C# 4.0
- 2012 年 4 月 18 日
- 添加了另一种日期格式
- 2012 年 6 月 28 日
- 添加了 UTC 识别;