使用RFC-1123日期格式与C#,解析星期二的日期问题

时间:2011-07-12 17:55:15

标签: c# rfc1123

我们在产品中遇到了一个错误,因为对于某些文化,如果您将当前线程的文化设置为该文化,然后根据RFC1123格式的DateTime输出字符串,然后尝试将其转换回一个DateTime,它失败了。最令人头疼的失败来自许多文化,这些文化将一周中的几天翻译成一个以mar开头的词,就像意大利语中的martedi一样。我假设解析程序看到“mar”并认为它意味着三月用英语,一切都失败了,但这只是猜测。我所知道的最好的方式是描述我正在谈论的是提供代码:

using System;
using System.Globalization;
using System.Threading;

namespace RFC1123Test
{
    class Program
    {
    static void Main(string[] args)
    {
        //list taken from http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo(v=vs.71).aspx
        var culturesToTest = new string[] { String.Empty /*invariant culture*/, "af", "af-ZA", 
        "sq", "sq-AL", "ar", "ar-DZ", "ar-BH", "ar-EG", "ar-IQ", "ar-JO", "ar-KW", 
        "ar-LB", "ar-LY", "ar-MA", "ar-OM", "ar-QA", "ar-SA", "ar-SY", "ar-TN", 
        "ar-AE", "ar-YE", "hy", "hy-AM", "az", "az-AZ-Cyrl", "az-AZ-Latn", "eu", "eu-ES", 
        "be", "be-BY", "bg", "bg-BG", "ca", "ca-ES", "zh-HK", "zh-MO", "zh-CN", "zh-CHS", 
        "zh-SG", "zh-TW", "zh-CHT", "hr", "hr-HR", "cs", "cs-CZ", "da", "da-DK", "div", 
        "div-MV", "nl", "nl-BE", "nl-NL", "en", "en-AU", "en-BZ", "en-CA", "en-CB", 
        "en-IE", "en-JM", "en-NZ", "en-PH", "en-ZA", "en-TT", "en-GB", "en-US", "en-ZW", 
        "et", "et-EE", "fo", "fo-FO", "fa", "fa-IR", "fi", "fi-FI", "fr", "fr-BE", "fr-CA",
        "fr-FR", "fr-LU", "fr-MC", "fr-CH", "gl", "gl-ES", "ka", "ka-GE", "de", "de-AT", 
        "de-DE", "de-LI", "de-LU", "de-CH", "el", "el-GR", "gu", "gu-IN", "he", "he-IL", 
        "hi", "hi-IN", "hu", "hu-HU", "is", "is-IS", "id", "id-ID", "it", "it-IT", 
        "it-CH", "ja", "ja-JP", "kn", "kn-IN", "kk", "kk-KZ", "kok", "kok-IN", "ko",
        "ko-KR", "ky", "ky-KZ", "lv", "lv-LV", "lt", "lt-LT", "mk", "mk-MK", "ms", 
        "ms-BN", "ms-MY", "mr", "mr-IN", "mn", "mn-MN", "no", "nb-NO", "nn-NO", "pl",
        "pl-PL", "pt", "pt-BR", "pt-PT", "pa", "pa-IN", "ro", "ro-RO", "ru", "ru-RU", 
        "sa", "sa-IN", "sr-SP-Cyrl", "sr-SP-Latn", "sk", "sk-SK", "sl", "sl-SI", "es",
        "es-AR", "es-BO", "es-CL", "es-CO", "es-CR", "es-DO", "es-EC", "es-SV", "es-GT",
        "es-HN", "es-MX", "es-NI", "es-PA", "es-PY", "es-PE", "es-PR", "es-ES", "es-UY",
        "es-VE", "sw", "sw-KE", "sv", "sv-FI", "sv-SE", "syr", "syr-SY", "ta", "ta-IN", 
        "tt", "tt-RU", "te", "te-IN", "th", "th-TH", "tr", "tr-TR", "uk", "uk-UA", "ur", 
        "ur-PK", "uz", "uz-UZ-Cyrl", "uz-UZ-Latn", "vi", "vi-VN" };

        //2:30 PM local time
        var timeOfDayForTest = TimeSpan.FromHours(14).Add(TimeSpan.FromMinutes(30));

        CultureInfo cultureForTest = null;
        foreach (var culture in culturesToTest)
        {
        bool suitableForTest = true;
        try
        {
            cultureForTest = new CultureInfo(culture);
            Thread.CurrentThread.CurrentCulture = cultureForTest;
            Thread.CurrentThread.CurrentUICulture = cultureForTest;
        }
        catch
        {
            suitableForTest = false;
        }
        if (suitableForTest)
        {
            //be sure to do a date for every day of the week
            for (int i = 0; i < 7; i++)
            {
            runTest(cultureForTest, DateTime.Now.Date.Add(timeOfDayForTest).AddDays(i));
            }
        }
        }
    }

    private static void runTest(CultureInfo culture, DateTime dt)
    {
        //string representation of RFC1123 pattern
        string rfc1123Date = dt.ToUniversalTime().ToString(CultureInfo.CurrentCulture.DateTimeFormat.RFC1123Pattern);

        bool parseFails = false;
        DateTime parsedDt = DateTime.MinValue;
        try
        {
        parsedDt = Convert.ToDateTime(rfc1123Date);
        }
        catch
        {
        parseFails = true;
        }
        if (parseFails)
        {
        Console.WriteLine(String.Format("ERROR: {0} [{1}] parse failed for [{2}].",
            culture.Name, culture.NativeName, rfc1123Date));
        }
        else
        {
        if (parsedDt.Ticks == dt.Ticks)
        {
            //success!
            //Console.WriteLine(String.Format("SUCCESS: {0} [{1}] worked just fine for {2}.",
            //culture.Name, culture.NativeName, rfc1123Date));
        }
        else
        {
            Console.WriteLine(String.Format("ERROR: {0} [{1}] parsed successfully for {2} but parsed date does not match.",
            culture.Name, culture.NativeName, rfc1123Date));
        }
        }
    }
    }
}

输出是这样的:

ERROR: af-ZA [Afrikaans (Suid Afrika)] parse failed for [Dins, 12 Jul 2011 18:30:00 GMT].
ERROR: af-ZA [Afrikaans (Suid Afrika)] parse failed for [Woen, 13 Jul 2011 18:30:00 GMT].
ERROR: af-ZA [Afrikaans (Suid Afrika)] parse failed for [Dond, 14 Jul 2011 18:30:00 GMT].
ERROR: af-ZA [Afrikaans (Suid Afrika)] parse failed for [Vry, 15 Jul 2011 18:30:00 GMT].
ERROR: af-ZA [Afrikaans (Suid Afrika)] parse failed for [Sat, 16 Jul 2011 18:30:00 GMT].
ERROR: af-ZA [Afrikaans (Suid Afrika)] parse failed for [Son, 17 Jul 2011 18:30:00 GMT].
ERROR: af-ZA [Afrikaans (Suid Afrika)] parse failed for [Maan, 18 Jul 2011 18:30:00 GMT].
ERROR: sq-AL [shqipe (Shqip‰ria)] parse failed for [Mar, 12 Kor 2011 18:30:00 GMT].
ERROR: sq-AL [shqipe (Shqip‰ria)] parse failed for [Sht, 16 Kor 2011 18:30:00 GMT].
ERROR: gl-ES [galego (galego)] parse failed for [mar, 12 xull 2011 18:30:00 GMT].
ERROR: it-IT [italiano (Italia)] parse failed for [mar, 12 lug 2011 18:30:00 GMT].
ERROR: it-CH [italiano (Svizzera)] parse failed for [mar, 12 lug 2011 18:30:00 GMT].
ERROR: it-CH [italiano (Svizzera)] parse failed for [gio, 14 lug 2011 18:30:00 GMT].
ERROR: ja-JP [??? (??)] parse failed for [?, 12 7 2011 18:30:00 GMT].
ERROR: ja-JP [??? (??)] parse failed for [?, 13 7 2011 18:30:00 GMT].
ERROR: ja-JP [??? (??)] parse failed for [?, 14 7 2011 18:30:00 GMT].
ERROR: ja-JP [??? (??)] parse failed for [?, 15 7 2011 18:30:00 GMT].
ERROR: ja-JP [??? (??)] parse failed for [?, 16 7 2011 18:30:00 GMT].
ERROR: ja-JP [??? (??)] parse failed for [?, 17 7 2011 18:30:00 GMT].
ERROR: ja-JP [??? (??)] parse failed for [?, 18 7 2011 18:30:00 GMT].
ERROR: ko-KR [??? (????)] parse failed for [?, 12 7 2011 18:30:00 GMT].
ERROR: ko-KR [??? (????)] parse failed for [?, 13 7 2011 18:30:00 GMT].
ERROR: ko-KR [??? (????)] parse failed for [?, 14 7 2011 18:30:00 GMT].
ERROR: ko-KR [??? (????)] parse failed for [?, 15 7 2011 18:30:00 GMT].
ERROR: ko-KR [??? (????)] parse failed for [?, 16 7 2011 18:30:00 GMT].
ERROR: ko-KR [??? (????)] parse failed for [?, 17 7 2011 18:30:00 GMT].
ERROR: ko-KR [??? (????)] parse failed for [?, 18 7 2011 18:30:00 GMT].
ERROR: es-AR [Espa¤ol (Argentina)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-BO [Espa¤ol (Bolivia)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-CL [Espa¤ol (Chile)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-CO [Espa¤ol (Colombia)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-CR [Espa¤ol (Costa Rica)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-DO [Espa¤ol (Rep£blica Dominicana)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-EC [Espa¤ol (Ecuador)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-SV [Espa¤ol (El Salvador)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-GT [Espa¤ol (Guatemala)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-HN [Espa¤ol (Honduras)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-MX [Espa¤ol (M‚xico)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-NI [Espa¤ol (Nicaragua)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-PA [Espa¤ol (Panam )] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-PY [Espa¤ol (Paraguay)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-PE [Espa¤ol (Per£)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-PR [Espa¤ol (Puerto Rico)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-ES [espa¤ol (Espa¤a)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-UY [Espa¤ol (Uruguay)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].
ERROR: es-VE [Espa¤ol (Republica Bolivariana de Venezuela)] parse failed for [mar, 12 jul 2011 18:30:00 GMT].

所以我的问题是,为什么这段代码不起作用?

2 个答案:

答案 0 :(得分:7)

尝试使用DateTime.Parse与您用于生成文本日期的格式提供程序相同:

DateTime.Parse(rfc1123Date, CultureInfo.CurrentCulture.DateTimeFormat.RFC1123Pattern)

答案 1 :(得分:5)

RFC1123Pattern的注释是使用不变文化来解析它。以下应该有效:

string rfc1123Date = dt.ToUniversalTime().ToString("R");

...

parsedDt = Convert.ToDateTime(rfc1123Date);

输出的尾巴:

  

成功:vi-VN [Tiê'ngVi?t(Vi?t Nam)]工作得很好,周三,13   2011年7月18:30:00 GMT。成功:vi-VN [Tiê'ngVi?t(Vi?t Nam)]工作   对于星期四,2011年7月14日18:30:00 GMT来说很好。成功:vi-VN [Tiê'ng   Vi?t(Vi?t Nam)]工作得很好,2011年7月15日星期五18:30:00 GMT。   成功:vi-VN [Tiê'ngVi?t(Vi?t Nam)]在星期六,16岁时工作得很好   2011年7月18:30:00 GMT。成功:vi-VN [Tiê'ngVi?t(Vi?t Nam)]工作   对于Sun来说很好,2011年7月17日18:30:00 GMT。成功:vi-VN [Tiê'ng   Vi?t(Vi?t Nam)]在2011年7月18日星期一18:30:00 GM时工作得很好。