我的日期和时间的格式像这样:
"2011-03-21 13:26" //year-month-day hour:minute
我如何解析为System.DateTime
?
我想使用类似的功能DateTime.Parse()
(DateTime.ParseExact()
如果可能),以便能够手动指定日期的格式。
我的日期和时间的格式像这样:
"2011-03-21 13:26" //year-month-day hour:minute
我如何解析为System.DateTime
?
我想使用类似的功能DateTime.Parse()
(DateTime.ParseExact()
如果可能),以便能够手动指定日期的格式。
Answers:
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#中的字符串格式
s
。因此,最好使用TryParseExcact。我在下面的回答中指出了原因。
正如我稍后解释的那样,我将始终支持TryParse
和TryParseExact
方法。因为它们使用起来有点笨重,所以我写了一个扩展方法,使解析变得更加容易:
var dtStr = "2011-03-21 13:26";
DateTime? dt = dtStr.ToDate("yyyy-MM-dd HH:mm");
与Parse
,ParseExact
等不同,它不会引发异常,并允许您通过检查
if (dt.HasValue) { // continue processing } else { // do error handling }
转换是否成功(在这种情况下,dt
您可以通过访问一个值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?
// dateFmt is optional and allows to pass a parsing pattern array
// or one or more patterns passed as string parameters
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();
}
// Commented out below because it can be done shorter as shown below.
// For older C# versions (older than C#7) you need it like that:
// DateTime? result = null;
// DateTime dt;
// if (DateTime.TryParseExact(dateTimeStr, dateFmt,
// CultureInfo.InvariantCulture, style, out dt)) result = dt;
// In C#7 and above, we can simply write:
var result = DateTime.TryParseExact(dateTimeStr, dateFmt, CultureInfo.InvariantCulture,
style, out var dt) ? dt : null as DateTime?;
return result;
}
}
有关代码的一些信息
您可能会奇怪,为什么我使用了InvariantCulture
call 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 dt;
您只需一行代码即可。(如果您愿意,也可以写out DateTime dt
而不是写out var 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允许指定strict,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 patterns=new[] { "dd-MM-yyyy", "dd.MM.yyyy" };
(new[] { "15-01-2019", "15.01.2019" }).Select(s => s.ToDate(patterns)).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#编译器团队的首席开发人员工作了两年。
DateTime.Parse()应该适合该字符串格式。参考:
http://msdn.microsoft.com/zh-CN/library/1k1skd40.aspx#Y1240
它会为您抛出FormatException吗?
简单直接的答案->
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.
* */
您也可以使用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
试试下面的代码
Month = Date = DateTime.Now.Month.ToString();
Year = DateTime.Now.Year.ToString();
ViewBag.Today = System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat.GetMonthName(Int32.Parse(Month)) + Year;