Convert.ToDateTime
的方法在內部使用DateTime.Parse
方法,它是基於內部複雜Lex
方法。有一些規則適用於傳遞的字符串。它被分成令牌,每個令牌都被分析。分析非常複雜,我只會展示幾條規則。
如果令牌由數字組成並且長度爲3〜8,那麼這個令牌將是年份,這就是爲什麼可以解析01.2014.01
字符串,這將產生01 Jan 2014
結果。請注意,您也可以解析字符串,如01 2014 01
或01\n2014\n01
,以獲得相同的結果。您可以使用空格或,
或.
符號分隔令牌。
如果令牌是月份的名稱,那麼它將是月份(該表或令牌構建在內部DateTimeFormatInfo.CreateTokenHashTable
方法中)。所以,你在哪裏找到Feb
或February
並不重要。您可以平等解析2014 1 Jan
或2014.Jan.1
,2014...,Jan..,..1
或甚至5Jan2014
字符串(最後一個不使用任何分隔符,但會檢查數字結束的位置,因此它已成功分割爲5
,Jan
和2014
令牌)。
如果我們有不明確的字符串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
這很有道理。所以基本上你是說我們傳遞的文化實際上沒有任何價值,除了使匹配邏輯更快? –
@ΕГИІИО我們傳遞的文化是月份名稱,月份縮寫,日期名稱,各種滿足等的來源。格式字符串不被使用。 –
然後我猜DateSeparator/TimeSeparator也不是它的一部分。 –