C# 在C语言中将超长日期格式解析为DateTime#

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”

如何将以下字符串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”

我想一定有更优雅的方式吧?我无法让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);
    }
}