[英]Parse string to DateTime in C#
我的日期和时间格式如下:
"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 方法通常更安全)
构造格式字符串时一定要检查Custom Date and Time Format Strings ,尤其要注意字母的数量和大小写(即“MM”和“mm”的意思非常不同)。
C# 格式字符串的另一个有用资源是 C# 中的字符串格式
正如我稍后解释的那样,我总是喜欢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) { // continue processing } else { // do error handling }
转换是否成功(在这种情况下dt
有一个您可以通过dt.Value
访问的值)或dt.Value
(在这种情况下,它是null
)。
这甚至允许使用优雅的快捷方式,如“Elvis”-operator ?.
, 例如:
int? year = dtStr?.ToDate("yyyy-MM-dd HH:mm")?.Year;
在这里,您还可以使用year.HasValue
来检查转换是否成功,如果没有成功,则year
将包含null
,否则为日期的年份部分。 如果转换失败,则不会抛出异常。
解决方案: .ToDate() 扩展方法
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()
(不带参数)现在默认为线程当前文化的所有常见日期/时间模式。
请注意,我们需要将result
和dt
放在一起,因为TryParseExact
不允许使用DateTime?
,我们打算返回。 在C# 版本 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? result = null;
DateTime? result = null;
和DateTime dt;
完全 - 您可以在一行代码中完成。 (如果您愿意,也可以写出out DateTime dt
而不是out 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 中使用扩展,试试这个(它在上面的 .NetFiddle 中):
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 的异常,我引用了他关于该主题的内容: 2)
这个不幸的设计决定1) [注释:让 Parse 方法抛出异常] 非常令人烦恼,当然框架团队在此后不久就实现了 TryParse,它做了正确的事情。
确实如此,但TryParse
和TryParseExact
使用起来仍然不太舒服:它们强制您使用未初始化的变量作为out
参数,该参数不能为空,并且在转换时您需要评估布尔返回值 -要么必须立即使用if
语句,要么必须将返回值存储在附加的布尔变量中,以便稍后进行检查。 并且您不能在不知道转换是否成功的情况下只使用目标变量。
在大多数情况下,您只想知道转换是否成功(当然还有成功时的值) ,因此保留所有信息的可为空的目标变量将是可取的且更加优雅 - 因为整个信息是只存储在一个地方:这是一致且易于使用的,而且不容易出错。
我编写的扩展方法正是这样做的(它还向您展示了如果您不打算使用它,则每次都必须编写什么样的代码)。
我相信.ToDate(strDateFormat)
的好处是它看起来简单干净 - 就像原来的DateTime.Parse
应该是一样简单 - 但能够检查转换是否成功,并且不会抛出异常。
1)这里的意思是异常处理(即try { ... } catch(Exception ex) { ...}
块) - 当您使用 Parse 时这是必要的,因为如果无效,它将抛出异常字符串被解析 - 在这种情况下不仅是不必要的,而且很烦人,并使您的代码复杂化。 TryParse 避免了所有这些,因为我提供的代码示例正在显示。
2) Eric Lippert 是一位著名的StackOverflow 研究员,曾在 Microsoft 作为 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);
您还可以使用 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.ParseExact(日期时间,格式,DateTimeFormatInfo.InvariantInfo,DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite)
例如:
DateTime.ParseExact("2011-03-21 13:26", "yyyy-MM-dd hh:mm", DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.