gpt4 book ai didi

c# - 当给定的区域性不知道格式时,Convert.ToDateTime() 如何解析给定的字符串

转载 作者:行者123 更新时间:2023-11-30 15:29:59 24 4
gpt4 key购买 nike

我有以下代码,它有效。

string testDateStr = "2009.7.28 05:23:15";
DateTime testDateObj = Convert.ToDateTime(testDateStr, CultureInfo.GetCultureInfo("fr-FR"));

然后我检查了适合我的文化的有效格式:

string[] validFormats = testDateObj.GetDateTimeFormats(CultureInfo.GetCultureInfo("fr-FR"));

并且它们都不符合“2009.7.28 05:23:15”格式。我想知道如何在不抛出格式异常的情况下解析它,以及当我们调用 Convert.ToDateTime() 时进行了什么样的隐藏解析。

更新:在 LakshmiNarayanan 的回答之后,我尝试了以下操作。

foreach(var culture in CultureInfo.GetCultures(CultureTypes.AllCultures))
{
foreach(var format in testDateObj.GetDateTimeFormats(culture))
{
if (format == testDateStr)
{
Console.WriteLine(culture.DisplayName);
}
}
}

有些文化实际上包含我的字符串的格式,但它仍然无法解释为什么当我们要求它使用特定文化进行转换时它不会抛出异常,而该文化不知道字符串的格式中。

最佳答案

Convert.ToDateTime 方法内部使用了DateTime.Parse 方法,该方法基于内部复杂的Lex 方法。有一堆规则适用于传递的字符串。它被分成 token ,每个 token 都被分析。分析非常复杂,我将只展示几条规则。

如果token由数字组成,长度为3~8,那么这个token就是年份,所以可以解析01.2014.01字符串,得到2014 年 1 月 1 日结果。请注意,您还可以解析类似 01 2014 0101\n2014\n01 的字符串,得到相同的结果。您可以使用空格或 . 符号分隔标记。

如果 token 是月份的名称,那么它将是月份(表或 token 在内部 DateTimeFormatInfo.CreateTokenHashTable 方法中构建)。因此,将 FebFebruary 定位在何处并不重要。您同样可以解析 2014 1 Jan2014.Jan.12014...,Jan..,..1 甚至 5Jan2014 字符串(最后一个不使用任何分隔符,但会检查数字在哪里结束,因此成功拆分为5Jan2014 代币)。

如果我们有不明确的字符串 01/04,那么将使用文化中的信息来解析日/月的顺序。订单摘自DateTimeFormatInfo.MonthDayPattern .例如,对于 en-US,它是 MMMM dd,对于 en-GB,它是 dd MMMM。内部System.DateTimeParse类中有private static bool GetMonthDayOrder(string pattern, DateTimeFormatInfo dtfi, out int order)方法,用于提取顺序。如果order变量取值为6,则为MM/dd,如果取值为7,则它是 dd/MM。请注意,它不会尝试对 01/31 进行一些试探,只会考虑从文化中提取的顺序。下面是测试代码:

CultureInfo ci = CultureInfo.GetCultureInfo("en-US");

DateTimeFormatInfo dtfi = ci.DateTimeFormat;
Assembly coreAssembly = Assembly.ReflectionOnlyLoad("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
Type dateTimeParseType = coreAssembly.GetType("System.DateTimeParse");
MethodInfo getMonthDayOrderMethodInfo = dateTimeParseType.GetMethod("GetMonthDayOrder", BindingFlags.Static | BindingFlags.NonPublic);
object[] parameters = new object[] { dtfi.MonthDayPattern, dtfi, null };
getMonthDayOrderMethodInfo.Invoke(null, parameters);
int order = (int)parameters[2];
switch (order)
{
case -1:
Console.WriteLine("Cannot extract information");
break;
case 6:
Console.WriteLine("MM/dd");
break;
case 7:
Console.WriteLine("dd/MM");
break;
}

还有许多其他针对 AM/PM 模式、星期几、时间后缀(例如,对于韩语,考虑了 后缀,意思是小时)等的检查。

以下代码将生成有关文化特定标记的信息:

DateTimeFormatInfo dti = CultureInfo.InvariantCulture.DateTimeFormat;
dynamic hashes = dti.GetType().GetMethod("CreateTokenHashTable", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(dti, null);
var tokens = Enumerable.Repeat(new { str = "", type = "", value = "" }, 0).ToList();
foreach (dynamic hash in hashes)
if (hash != null)
{
Type hashType = hash.GetType();
tokens.Add(new { str = (string)hashType.GetField("tokenString", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(hash).ToString(),
type = (string)hashType.GetField("tokenType", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(hash).ToString(),
value = (string)hashType.GetField("tokenValue", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(hash).ToString() });
}
foreach (var token in tokens.Distinct().OrderBy(t => t.type).ThenBy(t => t.value))
Console.WriteLine("{0,10} {1} {2}", token.str, token.type, token.value);

对于InvariantCulture,输出是:

        AM 1027 0
PM 1284 1
Sunday DayOfWeekToken 0
Sun DayOfWeekToken 0
Monday DayOfWeekToken 1
Mon DayOfWeekToken 1
Tuesday DayOfWeekToken 2
Tue DayOfWeekToken 2
Wednesday DayOfWeekToken 3
Wed DayOfWeekToken 3
Thu DayOfWeekToken 4
Thursday DayOfWeekToken 4
Friday DayOfWeekToken 5
Fri DayOfWeekToken 5
Sat DayOfWeekToken 6
Saturday DayOfWeekToken 6
AD EraToken 1
A.D. EraToken 1
, IgnorableSymbol 0
. IgnorableSymbol 0
January MonthToken 1
Jan MonthToken 1
October MonthToken 10
Oct MonthToken 10
November MonthToken 11
Nov MonthToken 11
December MonthToken 12
Dec MonthToken 12
February MonthToken 2
Feb MonthToken 2
March MonthToken 3
Mar MonthToken 3
Apr MonthToken 4
April MonthToken 4
May MonthToken 5
June MonthToken 6
Jun MonthToken 6
Jul MonthToken 7
July MonthToken 7
Aug MonthToken 8
August MonthToken 8
September MonthToken 9
Sep MonthToken 9
/ SEP_Date 0
- SEP_DateOrOffset 0
日 SEP_DaySuff 0
일 SEP_DaySuff 0
时 SEP_HourSuff 0
時 SEP_HourSuff 0
T SEP_LocalTimeMark 0
分 SEP_MinuteSuff 0
月 SEP_MonthSuff 0
월 SEP_MonthSuff 0
秒 SEP_SecondSuff 0
: SEP_Time 0
년 SEP_YearSuff 0
年 SEP_YearSuff 0
GMT TimeZoneToken 0
Z TimeZoneToken 0

对于 fr-FR 文化(请注意 July 以及来自 InvariantCulture 的其他标记都包含在列表中)

        AM 1027 0
PM 1284 1
h DateWordToken 0
dimanche DayOfWeekToken 0
Sun DayOfWeekToken 0
dim. DayOfWeekToken 0
Sunday DayOfWeekToken 0
lundi DayOfWeekToken 1
Monday DayOfWeekToken 1
lun. DayOfWeekToken 1
Mon DayOfWeekToken 1
Tuesday DayOfWeekToken 2
Tue DayOfWeekToken 2
mardi DayOfWeekToken 2
mar. DayOfWeekToken 2
mercredi DayOfWeekToken 3
Wednesday DayOfWeekToken 3
mer. DayOfWeekToken 3
Wed DayOfWeekToken 3
jeudi DayOfWeekToken 4
Thursday DayOfWeekToken 4
Thu DayOfWeekToken 4
jeu. DayOfWeekToken 4
ven. DayOfWeekToken 5
vendredi DayOfWeekToken 5
Friday DayOfWeekToken 5
Fri DayOfWeekToken 5
samedi DayOfWeekToken 6
sam. DayOfWeekToken 6
Sat DayOfWeekToken 6
Saturday DayOfWeekToken 6
ap. J.-C. EraToken 1
, IgnorableSymbol 0
. IgnorableSymbol 0
January MonthToken 1
janv. MonthToken 1
janvier MonthToken 1
Jan MonthToken 1
oct. MonthToken 10
Oct MonthToken 10
octobre MonthToken 10
October MonthToken 10
nov. MonthToken 11
Nov MonthToken 11
novembre MonthToken 11
November MonthToken 11
déc. MonthToken 12
December MonthToken 12
Dec MonthToken 12
décembre MonthToken 12
févr. MonthToken 2
février MonthToken 2
February MonthToken 2
Feb MonthToken 2
mars MonthToken 3
March MonthToken 3
Mar MonthToken 3
Apr MonthToken 4
avr. MonthToken 4
avril MonthToken 4
April MonthToken 4
mai MonthToken 5
May MonthToken 5
June MonthToken 6
juin MonthToken 6
Jun MonthToken 6
July MonthToken 7
juil. MonthToken 7
juillet MonthToken 7
Jul MonthToken 7
Aug MonthToken 8
août MonthToken 8
August MonthToken 8
sept. MonthToken 9
Sep MonthToken 9
septembre MonthToken 9
September MonthToken 9
/ SEP_Date 0
- SEP_DateOrOffset 0
日 SEP_DaySuff 0
일 SEP_DaySuff 0
时 SEP_HourSuff 0
時 SEP_HourSuff 0
T SEP_LocalTimeMark 0
分 SEP_MinuteSuff 0
月 SEP_MonthSuff 0
월 SEP_MonthSuff 0
秒 SEP_SecondSuff 0
: SEP_Time 0
년 SEP_YearSuff 0
年 SEP_YearSuff 0
GMT TimeZoneToken 0
Z TimeZoneToken 0

关于c# - 当给定的区域性不知道格式时,Convert.ToDateTime() 如何解析给定的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22809884/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com