分析 .NET 中的日期和时间字符串

分析字符串以将其转换为 DateTime 对象需要你指定有关如何以文本格式表示日期和时间的信息。 不同的区域性所使用的日、月和年的顺序也不尽相同。 某些时间表示方法使用 24 小时制,其他时间表示方法则会指定“AM”和“PM”。某些应用程序仅需要日期。 其他应用程序仅需要时间。 还有其他应用程序需要同时指定日期和时间。 通过将字符串转换为 DateTime 对象的方法,你将能够提供有关你预期的格式和你的应用程序需要的日期和时间元素的详细信息。 将文本正确转换为 DateTime 需要执行三个子任务:

  1. 必须指定表示日期和时间的文本的预期格式。
  2. 你可以指定日期时间格式的区域性。
  3. 你可以指定如何在日期和时间中设置文本表示中缺少的组成部分。

ParseTryParse 方法可转换日期和时间的多个常见表示方法。 ParseExactTryParseExact 方法可转换符合日期和时间格式字符串指定的模式的字符串表示形式。 有关详细信息,请参阅标准日期和时间格式字符串自定义日期和时间格式字符串的文章。

当前的 DateTimeFormatInfo 对象提供对如何将文本解释为日期和时间的更好的控制。 DateTimeFormatInfo 的属性描述了日期和时间分隔符,以及月、日、年代的名称,还有“AM”和“PM”标志的格式。 CultureInfo.CurrentCulture 返回的 CultureInfo 具有表示当前区域性的 CultureInfo.DateTimeFormat 属性。 如果你希望使用特定区域性或自定义设置,请指定分析方法的 IFormatProvider 参数。 对于 IFormatProvider 参数,应指定表示区域性的 CultureInfo 对象,或指定 DateTimeFormatInfo 对象。

表示日期或时间的文本可能缺少某些信息。 例如,大多数人都会假定“3 月 12 日”这个日期表示当前年份。 同样,“2018 年 3 月”表示年份为 2018,月份为 3 月。 表示时间的文本通常只包括小时、分钟和 AM/PM 指示符。 分析方法通过使用合理的默认值处理此类缺少的信息:

  • 当仅存在时间时,日期部分将使用当前日期。
  • 当仅存在日期时,时间部分将是午夜。
  • 如果日期中未指定年份,则使用当前年份。
  • 如果未指定月份中的第几天,则使用该月的第一天。

如果字符串中存在日期,则它必须包括月份、某日或某年。 如果存在时间,则它必须包括小时和分钟或 AM/PM 标志。

你可以指定 NoCurrentDateDefault 常量,以覆盖这些默认值。 使用该常量时,任何缺少的年、月或天属性将设置为值 1。 使用 Parse最后一个示例对此行为进行了演示。

除了日期和时间组成部分,日期和时间的字符串表示形式还可以包含指示时间与协调世界时 (UTC) 相差多少的偏移量。 例如,字符串“2/14/2007 5:32:00 -7:00”定义比 UTC 早七个小时的时间。 如果在时间的字符串表示形式中省略了偏移,分析方法返回 DateTime 对象,它的 Kind 属性设置为 DateTimeKind.Unspecified。 如果指定了偏移,分析会返回 DateTime 对象,其 Kind 属性设置为 DateTimeKind.Local。 其值也会调整为计算机的本地时区。 可以通过结合使用 DateTimeStyles 值和分析方法来修改此行为。

格式提供程序还用于解释不明确的数字日期。 不清楚字符串“02/03/04”所表示的日期的哪些部分是月、日和年。 组成部分根据格式提供程序中相似日期格式的顺序进行解释。

Parse

下面的示例说明了如何使用 DateTime.Parse 方法将 string 转换为 DateTime。 此示例使用与当前线程关联的区域性。 如果与当前区域性关联的 CultureInfo 无法分析输入字符串,会引发 FormatException

提示

本文中的所有 C# 示例均在你的浏览器中运行。 按“运行”按钮查看输出。 你还可以对其进行编辑以自行实验。

注意

这些示例可在适用于 C#Visual Basic 的 GitHub 文档存储库中获取。

string dateInput = "Jan 1, 2009";
var parsedDate = DateTime.Parse(dateInput);
Console.WriteLine(parsedDate);
// Displays the following output on a system whose culture is en-US:
//       1/1/2009 00:00:00
Dim MyString As String = "Jan 1, 2009"
Dim MyDateTime As DateTime = DateTime.Parse(MyString)
Console.WriteLine(MyDateTime)
' Displays the following output on a system whose culture is en-US:
'       1/1/2009 00:00:00

你也可以显式定义分析字符串时将使用其格式设置约定的区域性。 指定 CultureInfo.DateTimeFormat 属性返回的一个标准 DateTimeFormatInfo 对象。 下面的示例使用格式提供程序将德语字符串分析为 DateTime。 它创建了一个表示 de-DE 区域性的 CultureInfoCultureInfo 对象可以确保成功分析此特定的字符串。 此过程排除在 CurrentThreadCurrentCulture 中的任何设置。

var cultureInfo = new CultureInfo("de-DE");
string dateString = "12 Juni 2008";
var dateTime = DateTime.Parse(dateString, cultureInfo);
Console.WriteLine(dateTime);
// The example displays the following output:
//       6/12/2008 00:00:00
Dim MyCultureInfo As New CultureInfo("de-DE")
Dim MyString As String = "12 Juni 2008"
Dim MyDateTime As DateTime = DateTime.Parse(MyString, MyCultureInfo)
Console.WriteLine(MyDateTime)
' The example displays the following output:
'       6/12/2008 00:00:00

但是,可以使用 Parse 方法的重载来指定自定义格式提供程序。 Parse 方法不支持分析非标准格式。 若要分析非标准格式的日期和时间,请改用 ParseExact 方法。

以下示例使用 DateTimeStyles 枚举,指定不应将当前日期和时间信息添加到未指定字段的 DateTime 中。

var cultureInfo = new CultureInfo("de-DE");
string dateString = "12 Juni 2008";
var dateTime = DateTime.Parse(dateString, cultureInfo,
                                DateTimeStyles.NoCurrentDateDefault);
Console.WriteLine(dateTime);
// The example displays the following output if the current culture is en-US:
//      6/12/2008 00:00:00
Dim MyCultureInfo As New CultureInfo("de-DE")
Dim MyString As String = "12 Juni 2008"
Dim MyDateTime As DateTime = DateTime.Parse(MyString, MyCultureInfo,
                           DateTimeStyles.NoCurrentDateDefault)
Console.WriteLine(MyDateTime)
' The example displays the following output if the current culture is en-US:
'       6/12/2008 00:00:00

ParseExact

DateTime.ParseExact 方法将符合其中一个指定字符串模式的字符串转换为 DateTime 对象。 将不是指定格式之一的字符串传递给此方法时,会引发 FormatException。 可以指定一种标准日期和时间格式说明符或自定义格式说明符的组合。 使用自定义格式说明符,你可以给构造自定义识别字符串。 有关说明符的说明,请参阅标准日期和时间格式字符串自定义日期和时间格式字符串的文章。

在下面的示例中,向 DateTime.ParseExact 方法传递了一个要分析的字符串对象,后跟一个格式说明符,再后跟一个 CultureInfo 对象。 此 ParseExact 方法只能分析在 en-US 区域性中遵循长日期模式的字符串。

var cultureInfo = new CultureInfo("en-US");
string[] dateStrings = { " Friday, April 10, 2009", "Friday, April 10, 2009" };
foreach (string dateString in dateStrings)
{
    try
    {
        var dateTime = DateTime.ParseExact(dateString, "D", cultureInfo);
        Console.WriteLine(dateTime);
    }
    catch (FormatException)
    {
        Console.WriteLine("Unable to parse '{0}'", dateString);
    }
}
// The example displays the following output:
//       Unable to parse ' Friday, April 10, 2009'
//       4/10/2009 00:00:00
Dim MyCultureInfo As New CultureInfo("en-US")
Dim MyString() As String = {" Friday, April 10, 2009", "Friday, April 10, 2009"}
For Each dateString As String In MyString
    Try
        Dim MyDateTime As DateTime = DateTime.ParseExact(dateString, "D",
                                                     MyCultureInfo)
        Console.WriteLine(MyDateTime)
    Catch e As FormatException
        Console.WriteLine("Unable to parse '{0}'", dateString)
    End Try
Next
' The example displays the following output:
'       Unable to parse ' Friday, April 10, 2009'
'       4/10/2009 00:00:00

ParseParseExact 方法的每个重载还包含 IFormatProvider 参数,用于提供有关字符串格式设置的区域性专用信息。 IFormatProvider 对象是表示标准区域性的 CultureInfo 对象,或是由 CultureInfo.DateTimeFormat 属性返回的 DateTimeFormatInfo 对象。 ParseExact 还使用定义一个或多个自定义日期和时间格式的其他字符串或字符串数组参数。

请参阅