2013-03-07 35 views
2

看格式:​​3210Datetime.Parse()可交换格式?

这是工作

var t="Mar 2013 7"; 
DateTime dt=DateTime.Parse(t); 

also this :"Mar 7 2013" 
and this :"7 Mar 2013" 

工作

看:

new DateTimeFormatInfo() 
       .GetAllDateTimePatterns() 
       .Select((i,n)=>n+" "+i) 
       .ToList() 
       .ForEach(f=>Console.WriteLine(f)); 

这是格式化日期和时间值可以是 的所有标准模式。

结果是:

0 MM/dd/yyyy 
1 yyyy-MM-dd 
2 dddd, dd MMMM yyyy 
3 dddd, dd MMMM yyyy HH:mm 
4 dddd, dd MMMM yyyy hh:mm tt 
5 dddd, dd MMMM yyyy H:mm 
6 dddd, dd MMMM yyyy h:mm tt 
7 dddd, dd MMMM yyyy HH:mm:ss 
8 MM/dd/yyyy HH:mm 
9 MM/dd/yyyy hh:mm tt 
10 MM/dd/yyyy H:mm 
11 MM/dd/yyyy h:mm tt 
12 yyyy-MM-dd HH:mm 
13 yyyy-MM-dd hh:mm tt 
14 yyyy-MM-dd H:mm 
15 yyyy-MM-dd h:mm tt 
16 MM/dd/yyyy HH:mm:ss 
17 yyyy-MM-dd HH:mm:ss 
18 MMMM dd 
19 MMMM dd 
20 yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK 
21 yyyy'-'MM'-'dd'T'HH':'mm':'ss.fffffffK 
22 ddd, dd MMM yyyy HH':'mm':'ss 'GMT' 
23 ddd, dd MMM yyyy HH':'mm':'ss 'GMT' 
24 yyyy'-'MM'-'dd'T'HH':'mm':'ss 
25 HH:mm 
26 hh:mm tt 
27 H:mm 
28 h:mm tt 
29 HH:mm:ss 
30 yyyy'-'MM'-'dd HH':'mm':'ss'Z' 
31 dddd, dd MMMM yyyy HH:mm:ss 
32 yyyy MMMM 
33 yyyy MMMM 

问:

  • 我没有看到在列表中MMM d yyyy格式。那它是如何做到的?它尝试所有组合?

  • 如何添加时间格式MMM d yyyy[Mar 3 2007 13:13:13]它也可以工作,但没有特定的格式。那它怎么做呢?

+0

您认为DateTime.Parse()使用由GetAllDateTimePatterns()返回的模式是不正确的。我已经将你链接到参考源,看看System.DateTimeParse.Lex() – 2013-03-07 12:53:26

+0

@HansPassant你是对的。它似乎是所有与标准格式字符串对应的自定义格式字符串。和**不是**,因为我假设解析)。谢谢:-) – 2013-03-07 13:06:46

回答

2

我用Reflector来看看这个。数百行解析代码真的很复杂!

但是,最终它将标记输入字符串并尝试将标记分类为日期名称,月份名称,年份,日期编号等。

尤其是一个函数调用internal TokenHashValue[] CreateTokenHashTable()有这样的事情:

for (int i = 1; i <= 12; i++) 
{ 
    this.InsertHash(dtfiTokenHash, this.GetAbbreviatedMonthName(i), TokenType.MonthToken, i); 
} 

它使用这个(正如你可以看到有所有月份的缩写),以确定是否一个令牌是一个月的名称。日期名称也有类似的代码。

解析代码还会检查其中一个数字是否大于2位数。如果是这样,它假定它是一年。这意味着(你可以验证它),你可以有一个3位数的年份,它仍然可以解析它。但它变得更加复杂!它还检查数字是否大于12,如果是,则假定它是一年。

如果你把两个数字均小于或等于12,它仍然的作品,但它假定第一个是天,第二个月(为英国文化 - 我敢打赌,这是对其他文化的不同)。

这当然可以让它在没有警告的情况下解析模糊的日期。

结果是:NEVER解析的日期像这样

始终ParseExact()

1

我想它是使用格式说明符,而不是他们的安排。

从字面意思是“2013年3月7日”的写法,我怀疑它们在解析中可能会有歧义。

  • 匹配月确切MMM
  • 2003场比赛正好YYYY
  • 7场比赛正好Ð
+0

(另一个例子):DDD可以'Mon'(星期一),但MMM可以'Mar'(比赛),他们都长3.所以它是如何知道这是谁? – 2013-03-07 12:25:46

+0

@RoyiNamir我是指的你在上面“MMM d YYYY”指定的确切格式 – scartag 2013-03-07 12:27:58

+1

@RoyiNamir这可能是为什么ParseExact存在..在不确定性可能存在:) – scartag 2013-03-07 12:30:10

1

我找到了一个链接到DateTime.Parse源代码在这里: http://typedescriptor.net/name/members/5B57671F27DBC0AEA0EB9825243834CF-System.DateTime.Parse(String,IFormatProvider,DateTimeStyles)

你可以点击链接深入挖掘私有方法,但它变得复杂。但它看起来像一个编译器一样轻松和解析。该字符串被分解成部分(令牌),并试图识别每个是一年还是一个月。

当然可能有一些不明确的地方,例如,也许你的意思是dd-MM-yyyy,但它解析为MM-dd-yyyy。但这就是为什么你可以指定一个文化特定的IFormatProvider。