C# 在C语言中将超长日期格式解析为DateTime#
如何将以下字符串date解析为C#中的DateTime对象: 1970年1月1日星期四 这来自一个XML提要和DateTime。Parse似乎不喜欢在en GB语言环境中使用它。该提要将永远只来自英国服务器,所以我不担心全球化问题 我最初的暴力方法是:C# 在C语言中将超长日期格式解析为DateTime#,c#,parsing,datetime,C#,Parsing,Datetime,如何将以下字符串date解析为C#中的DateTime对象: 1970年1月1日星期四 这来自一个XML提要和DateTime。Parse似乎不喜欢在en GB语言环境中使用它。该提要将永远只来自英国服务器,所以我不担心全球化问题 我最初的暴力方法是: 删除逗号之前的所有内容,并删除尾随空格以留下“1970年1月1日” 然后删除“st”、“nd”、“rd”或“th”,以保留“1970年1月1日” 然后将月份转换为对应的数字,即“11970” 然后将空格替换为“/”以获得“1/1/1970”
- 删除逗号之前的所有内容,并删除尾随空格以留下“1970年1月1日”
- 然后删除“st”、“nd”、“rd”或“th”,以保留“1970年1月1日”
- 然后将月份转换为对应的数字,即“11970”
- 然后将空格替换为“/”以获得“1/1/1970”
我想一定有更优雅的方式吧?我无法让DateTime.Prse或DateTime.ParseExact正常工作我不相信
DateTime
解析对序数有任何了解,但它应该能够处理其他所有事情。因此,您可以使用:
public static string RemoveOrdinals(string input)
{
// Ugly but oh so simple.
return input.Replace("0th", "0")
.Replace("1st", "1")
.Replace("2nd", "2")
.Replace("3rd", "3")
.Replace("11th", "11") // Need to handle these separately...
.Replace("12th", "12")
.Replace("13th", "13")
.Replace("4th", "4")
.Replace("5th", "5")
.Replace("6th", "6")
.Replace("7th", "7")
.Replace("8th", "8")
.Replace("9th", "9");
}
然后:
(作为一个快速插件,您当然只需要一个日期而不是一个日期/时间。不幸的是.NET没有一个类型来表示它-但是您可以在我的库中使用
LocalDate
。我们也不处理序数-但是,无论如何-所以您仍然需要额外的方法。如果您想查看相关的代码,请告诉我。)使用DateTime。使用特定于区域性的格式化程序解析:
首先反向此答案中的逻辑,从月日起去除“st”、“nd”等:
然后只需使用DateTime.Parse
正常:
var result = DateTime.Parse("Thursday, 1 January 1970", new CultureInfo("en-GB"));
只是提供一个稍微不同的看法,并给你一些其他选择的想法;您可以将格式指定为DateTime.Parse(或我的示例中的TryParse)来解释这种情况,而无需尝试使用string将字符串“预格式化”为其他格式。替换调用等
public DateTime ParseOrdinalDateTime(string dt)
{
string[] expectedFormats =
DateTime d;
if (DateTime.TryParseExact(dt, "dddd, d\"st\" MMMM yyyy", null, DateTimeStyles.None, out d))
return d;
if (DateTime.TryParseExact(dt, "dddd, d\"nd\" MMMM yyyy", null, DateTimeStyles.None, out d))
return d;
if (DateTime.TryParseExact(dt, "dddd, d\"rd\" MMMM yyyy", null, DateTimeStyles.None, out d))
return d;
if (DateTime.TryParseExact(dt, "dddd, d\"th\" MMMM yyyy", null, DateTimeStyles.None, out d))
return d;
throw new InvalidOperationException("Not a valid DateTime string");
}
我之所以提出这种方法,是因为它非常清楚地列出了您的输入期望,并且包含了单个方法的行为。如果格式更改,您可以在此处指定不同的格式字符串,并说明新的日期时间字符串结构
或者,考虑到以下评论,对上述内容稍作改动
private static DateTime ParseOrdinalDateTime(string dt)
{
string[] expectedFormats = new[]
{
"dddd, d'st' MMMM yyyy",
"dddd, d'nd' MMMM yyyy",
"dddd, d'rd' MMMM yyyy",
"dddd, d'th' MMMM yyyy"
};
try
{
return DateTime.ParseExact(dt, expectedFormats, null, DateTimeStyles.None);
}
catch (Exception e)
{
throw new InvalidOperationException("Not a valid DateTime string", e);
}
}
注意:我捕获并抛出上面的InvalidOperationException的唯一原因是为了保护调用方不必捕获异常
来处理任何可能的异常DateTime.ParseExact
可能抛出的异常。您可以轻松修改此API。您链接到的答案将转换为顺序格式,而不是从顺序格式转换而来。我还建议使用特定的格式,而不仅仅是DateTime.Parse
,这对我来说就像是“命中并充满希望”。真的,对不起,我想说的是颠倒逻辑。。。更新:)只是一个关于序数的注释;“2d”和“3d”形式通常被认为是字典可接受的(如果不经常使用)而不是“第二”和“第三”。请确保它们也被正确解析。@Tenner:如果这些都是在这个上下文中出现的,我会感到惊讶。在我看来,只有那么多的角落案例值得担心。我想我知道的远不及你Jon,但如果只替换(“th”)和(“nd”)等,不是更简单吗?这也可以处理21、12、22等案件。或者开发人员希望为每个可能的日期编写代码Replace()
。@Evanlewis:你不会希望“星期一”被替换为“Moay”吧?有一种方法可以让我疯狂:)上面已经提到了“21”,因为它包含了“1”。。。这只是最后一个重要的数字。当然!哈,甚至没有想到星期几的问题。星期四也将成为星期二。试着分析一下!关于最后一个数字,你也是对的。谢谢你的教训;)为什么不使用采用多种模式的重载呢?此外,您还可以使用”
而不是“
引用一段模式,这将使其更简单。我还建议明确指定区域性-我们知道它的含义,所以为什么要依赖线程的当前区域性?我使用了第二个版本,其中根据Jon Skeets的建议,传入了一系列格式。我不知道你可以引用一段格式说明符。对我来说,这是最清晰的,允许的格式列表可以存储在DB或其他数据存储中。当格式错误时,它不应该抛出一个FormatException
?如果您希望在8月份删除“st”,请小心。尝试Regex.Replace(“2009年8月1日”([0-9])(圣安德鲁斯街第四街),“$1”);显然是用你的日期而不是我用的字符串作为例子。
private static DateTime ParseOrdinalDateTime(string dt)
{
string[] expectedFormats = new[]
{
"dddd, d'st' MMMM yyyy",
"dddd, d'nd' MMMM yyyy",
"dddd, d'rd' MMMM yyyy",
"dddd, d'th' MMMM yyyy"
};
try
{
return DateTime.ParseExact(dt, expectedFormats, null, DateTimeStyles.None);
}
catch (Exception e)
{
throw new InvalidOperationException("Not a valid DateTime string", e);
}
}