在 C# 中使用 RFC-1123 日期格式,解析星期二日期的问题
我们在产品中遇到了一个错误,原因是对于某些区域性,如果将当前线程的区域性设置为该区域性,然后输出基于 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].
所以我的问题是,为什么这段代码不起作用?
We ran into a bug in our product caused by the fact that for certain cultures, if you set the current thread's culture to that culture and then output a string based on a DateTime in RFC1123 format and then try to convert it back to a DateTime, it fails. The most head-scratching failures are from a lot of cultures that have days of the week that translate it to a word that begins with mar, like martedi in Italian. I'm assuming that the parsing routines see "mar" and think it means March in English and everything fails, but that's just speculation. The best way I know of to describe exactly what I'm talking about is to provide code:
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));
}
}
}
}
}
The output is this:
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].
So my question is, why doesn't this code work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
RFC1123Pattern 的注释是要解析它使用不变的文化。以下内容应该有效:
输出的尾部:
The notes for RFC1123Pattern is that it is to be parsed using the invariant culture. The following should work:
Tail of your output:
尝试使用
DateTime.ParseExact
以及用于生成文本日期的相同格式提供程序:DateTime.ParseExact(rfc1123Date, CultureInfo.CurrentCulture.DateTimeFormat.RFC1123Pattern, CultureInfo.CurrentCulture).ToLocalTime()
Try using
DateTime.ParseExact
with the same format provider you used to generate the text date:DateTime.ParseExact(rfc1123Date, CultureInfo.CurrentCulture.DateTimeFormat.RFC1123Pattern, CultureInfo.CurrentCulture).ToLocalTime()