2

如何将以下字符串日期解析为 C# 中的 DateTime 对象:

“1970 年 1 月 1 日,星期四”

这来自 XML 提要,而 DateTime.Parse 在 en-GB 语言环境中似乎不喜欢它。提要只会来自英国服务器,所以我不必担心全球化问题

我最初的蛮力方法是:

  • 删除逗号之前的所有内容,包括逗号和尾随空格以留下“1st January 1970”
  • 然后酌情删除“st”、“nd”、“rd”或“th”,留下“1 January 1970”
  • 然后将月份转换为其等值的数字,留下“1 1 1970”
  • 然后用“/”替换空格得到“1/1/1970”

我确定一定有一种更优雅的方式吗?我无法让 DateTime.Prse 或 Datetime.ParseExact 工作

4

3 回答 3

6

我不相信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");
}

然后:

string text = RemoveOrdinals(text);
DateTime date = DateTime.ParseExact(text, "dddd, d MMMM yyyy",
                                    CultureInfo.GetCulture("en-GB"));

(作为一个快速插件,您当然只需要一个日期而不是日期/时间。不幸的是 .NET 没有表示它的类型 - 但您可以LocalDate在我的Noda Time库中使用。我们也不处理序数- 然而,无论如何 - 所以你仍然需要额外的方法。如果你想查看相关代码,请告诉我。)

于 2013-07-17T21:32:33.090 回答
5

只是提供一个稍微不同的看法,并让您了解您拥有的其他一些选择;您可以将格式指定为 DateTime.Parse (或我的示例中的 TryParse )以解决此类情况,而无需尝试通过String.Replace调用等将字符串“预格式化”为其他内容;

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 的唯一原因是为了保护调用者不必catch Exception处理任何可能DateTime.ParseExact抛出的异常。您可以轻松修改此 API。

于 2013-07-17T21:44:58.297 回答
0

DateTime.Parse与特定于文化的格式化程序一起使用:

http://msdn.microsoft.com/en-us/library/kc8s65zs.aspx

首先反转这个答案的逻辑,从月份中删除“st”、“nd”等:

https://stackoverflow.com/a/4544313/2420979

然后DateTime.Parse正常使用:

var result = DateTime.Parse("Thursday, 1 January 1970", new CultureInfo("en-GB"));
于 2013-07-17T21:36:31.527 回答