我有一个字符串格式的日期和时间:

"2011-03-21 13:26" //year-month-day hour:minute

如何将其解析为System.DateTime?

如果可能的话,我想使用DateTime.Parse()或DateTime.ParseExact()这样的函数,以便能够手动指定日期的格式。


DateTime.Parse()将尝试找出给定日期的格式,它通常做得很好。如果你能保证日期总是在一个给定的格式,那么你可以使用ParseExact():

string s = "2011-03-21 13:26";

DateTime dt = 
    DateTime.ParseExact(s, "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture);

(但请注意,在日期不是预期格式的情况下,使用TryParse方法之一通常更安全)

在构造格式字符串时,请务必检查自定义日期和时间格式字符串,特别是注意字母和大小写的数量(即。“MM”和“MM”的意思非常不同)。

c#格式字符串的另一个有用资源是c#中的字符串格式化


var dateStr = @"2011-03-21 13:26";
var dateTime = DateTime.ParseExact(dateStr, "yyyy-MM-dd HH:mm", CultureInfo.CurrentCulture);

查看其他格式字符串的链接!


DateTime.Parse()应该适用于该字符串格式。参考:

http://msdn.microsoft.com/en-us/library/1k1skd40.aspx#Y1240

它是否为你抛出FormatException ?


将一个人类可读的字符串的值放入.NET DateTime中,代码如下:

DateTime.ParseExact("April 16, 2011 4:27 pm", "MMMM d, yyyy h:mm tt", null);

正如我稍后解释的那样,我总是喜欢TryParse和TryParseExact方法。因为它们使用起来有点笨重,所以我写了一个扩展方法,使解析变得更容易:

var    dtStr = "2011-03-21 13:26";
DateTime? dt = dtStr.ToDate("yyyy-MM-dd HH:mm");

或者更简单地说,如果你想隐式地使用当前文化的日期模式,你可以这样使用:

 DateTime? dt = dtStr.ToDate();

在这种情况下,不需要指定特定的模式。

不像Parse, ParseExact等,它不会抛出异常,并允许您通过检查

if (dt.HasValue){//继续处理}否则{//进行错误处理}

转换是否成功(在这种情况下dt有一个可以通过dt. value访问的值)或不成功(在这种情况下,它是null)。

这甚至允许使用优雅的快捷方式,如“猫王”操作符?,例如:

int? year = dtStr?.ToDate("yyyy-MM-dd HH:mm")?.Year;

这里你也可以用year。HasValue检查转换是否成功,如果不成功则year将包含null,否则为日期的year部分。如果转换失败,则不会抛出异常。


解决方案:.ToDate()扩展方法

试试。net。fiddle

public static class Extensions
{
  /// Extension method parsing a date string to a DateTime? <para/>
  /// <summary>
  /// </summary>
  /// <param name="dateTimeStr">The date string to parse</param>
  /// <param name="dateFmt">dateFmt is optional and allows to pass 
  /// a parsing pattern array or one or more patterns passed 
  /// as string parameters</param>
  /// <returns>Parsed DateTime or null</returns>
  public static DateTime? ToDate(this string dateTimeStr, params string[] dateFmt)
  {
    // example: var dt = "2011-03-21 13:26".ToDate(new string[]{"yyyy-MM-dd HH:mm", 
    //                                                  "M/d/yyyy h:mm:ss tt"});
    // or simpler: 
    // var dt = "2011-03-21 13:26".ToDate("yyyy-MM-dd HH:mm", "M/d/yyyy h:mm:ss tt");
    const DateTimeStyles style = DateTimeStyles.AllowWhiteSpaces;
    if (dateFmt == null)
    {
      var dateInfo = System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat;
      dateFmt=dateInfo.GetAllDateTimePatterns();
    }
    var result = DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture,
                   style, out var dt) ? dt : null as DateTime?;
    return result;
  }
}

关于代码的一些信息

您可能想知道,为什么我使用InvariantCulture调用TryParseExact:这是为了迫使函数始终以相同的方式处理格式模式(否则,“.”在英语中可以解释为小数分隔符,而在德语中则是组分隔符或日期分隔符)。回想一下,我们已经在几行之前查询了基于区域性的格式字符串,所以这里没问题。

更新:. todate()(不带参数)现在默认为线程当前区域性的所有公共日期/时间模式。 注意,我们需要将结果和dt放在一起,因为TryParseExact不允许使用DateTime?,我们打算归还。 在c# Version 7中,你可以将ToDate函数简化如下:

 // in C#7 only: "DateTime dt;" - no longer required, declare implicitly
 if (DateTime.TryParseExact(dateTimeStr, dateFmt,
     CultureInfo.InvariantCulture, style, out var dt)) result = dt;

或者,如果你喜欢更短的发型:

 // in C#7 only: Declaration of result as a "one-liner" ;-)
 var result = DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture,
              style, out var dt) ? dt : null as DateTime?;

在这种情况下,你不需要两个声明DateTime?结果= null;和DateTime dt;你完全可以在一行代码中完成。 (如果你喜欢,也可以写出DateTime dt而不是var dt)。

旧风格的c#要求它以以下方式(我从上面的代码中删除了它):

  // DateTime? result = null;
  // DateTime dt;
  // if (DateTime.TryParseExact(dateTimeStr, dateFmt,
  //    CultureInfo.InvariantCulture, style, out dt)) result = dt;

我使用params关键字进一步简化了代码:现在您不再需要第二个重载方法了。


用法示例

var dtStr="2011-03-21 13:26";    
var dt=dtStr.ToDate("yyyy-MM-dd HH:mm");
if (dt.HasValue)
{
    Console.WriteLine("Successful!");
    // ... dt.Value now contains the converted DateTime ...
}
else
{
    Console.WriteLine("Invalid date format!");
}

如您所见,这个示例只是查询dt。HasValue来查看转换是否成功。作为额外的奖励,TryParseExact允许指定严格的DateTimeStyles,以便您确切地知道是否传递了正确的日期/时间字符串。


更多用法示例

重载函数允许您传递一个用于解析/转换日期的有效格式数组,如图所示(TryParseExact直接支持此功能)。

string[] dateFmt = {"M/d/yyyy h:mm:ss tt", "M/d/yyyy h:mm tt", 
                     "MM/dd/yyyy hh:mm:ss", "M/d/yyyy h:mm:ss", 
                     "M/d/yyyy hh:mm tt", "M/d/yyyy hh tt", 
                     "M/d/yyyy h:mm", "M/d/yyyy h:mm", 
                     "MM/dd/yyyy hh:mm", "M/dd/yyyy hh:mm"};
var dtStr="5/1/2009 6:32 PM"; 
var dt=dtStr.ToDate(dateFmt);

如果你只有几个模板模式,你也可以这样写:

var dateStr = "2011-03-21 13:26";
var dt = dateStr.ToDate("yyyy-MM-dd HH:mm", "M/d/yyyy h:mm:ss tt");

先进的例子

你可以使用??操作符默认为故障安全格式,例如:

var dtStr = "2017-12-30 11:37:00";
var dt = (dtStr.ToDate()) ?? dtStr.ToDate("yyyy-MM-dd HH:mm:ss");

在这种情况下,. todate()将使用常见的本地文化日期格式,如果所有这些都失败了,它将尝试使用ISO标准格式“yyyy-MM-dd HH:mm:ss”作为备用。这样,扩展函数允许轻松地“链接”不同的回退格式。

你甚至可以在LINQ中使用扩展,尝试一下(它在上面的。net fiddle中):

var strDateArray = new[] { "15-01-2019", "15.01.2021" };
var patterns=new[] { "dd-MM-yyyy", "dd.MM.yyyy" };
var dtRange = strDateArray.Select(s => s.ToDate(patterns));
dtRange.Dump(); 

它将使用模式动态地转换数组中的日期并将它们转储到控制台。


关于TryParseExact的一些背景知识

最后,这里有一些关于背景的评论(即我这样写的原因):

我更喜欢TryParseExact在这个扩展方法中,因为你避免了异常处理-你可以在Eric Lippert的文章中阅读关于为什么你应该使用TryParse而不是Parse的异常,我引用了他关于这个主题的内容:

这个不幸的设计决定[注释:to 让Parse方法抛出异常]是如此令人烦恼,当然 框架团队很快实现了TryParse,它做了正确的事情。

It does, but TryParse and TryParseExact both are still a lot less than comfortable to use: They force you to use an uninitialized variable as an out parameter which must not be nullable and while you're converting you need to evaluate the boolean return value - either you have to use an ifstatement immediately or you have to store the return value in an additional boolean variable so you're able to do the check later. And you can't just use the target variable without knowing if the conversion was successful or not.

在大多数情况下,您只是想知道转换是否成功(当然还想知道转换成功后的值),因此使用一个可空的目标变量来保存所有信息将是可取的,而且要优雅得多——因为整个信息只存储在一个地方:这是一致的、易于使用的,而且更不容易出错。

我所编写的扩展方法正是这样做的(它还向您展示了如果您不打算使用它,那么每次都必须编写什么样的代码)。

我相信. todate (strDateFormat)的好处是它看起来简单干净-就像原始的DateTime一样简单。Parse应该是-但是有能力检查转换是否成功,并且不会抛出异常。


1)这里的意思是异常处理(即try{…} catch(异常ex){…} block)——这在使用Parse时是必要的,因为如果解析了无效的字符串,它将抛出异常——在这种情况下不仅不必要,而且令人讨厌,并使代码复杂化。TryParse避免了所有这些问题,正如我提供的代码样例所示。


2) Eric Lippert是StackOverflow的著名成员,曾在微软的c#编译器团队担任过几年的首席开发人员。


还可以使用XmlConvert。ToDateString

var dateStr = "2011-03-21 13:26";
var parsedDate = XmlConvert.ToDateTime(dateStr, "yyyy-MM-dd hh:mm");

最好指定日期类型,代码为:

var anotherParsedDate = DateTime.ParseExact(dateStr, "yyyy-MM-dd hh:mm", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);

关于不同解析选项的更多详细信息http://amir-shenodua.blogspot.ie/2017/06/datetime-parsing-in-net.html


简单而直接的答案——>

using System;

namespace DemoApp.App

{
public class TestClassDate
{
    public static DateTime GetDate(string string_date)
    {
        DateTime dateValue;
        if (DateTime.TryParse(string_date, out dateValue))
            Console.WriteLine("Converted '{0}' to {1}.", string_date, dateValue);
        else
            Console.WriteLine("Unable to convert '{0}' to a date.", string_date);
        return dateValue;
    }
    public static void Main()
    {
        string inString = "05/01/2009 06:32:00";
        GetDate(inString);
    }
}
}

/**
 * Output:
 * Converted '05/01/2009 06:32:00' to 5/1/2009 6:32:00 AM.
 * */

试试下面的代码

Month = Date = DateTime.Now.Month.ToString();   
Year = DateTime.Now.Year.ToString(); 
ViewBag.Today = System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat.GetMonthName(Int32.Parse(Month)) + Year;

DateTime。DateTime, Format, DateTimeFormatInfo。InvariantInfo DateTimeStyles。allowtrailingwhite)

例如:

DateTime。ParseExact("2011-03-21 13:26", "yyyy-MM-dd hh:mm", DateTimeFormatInfo. "InvariantInfo DateTimeStyles。AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite;