为什么AD3AD08代表.NET框架中的有效日期?

Fra*_*tha 32 .net c# datetime

DateTime.Parse("AD3AD08")

[2017-08-03 12:00:00 AM]
Run Code Online (Sandbox Code Playgroud)

为什么这个字符串(看起来只是一个普通的十六进制字符串给我)作为日期成功解析?我可以看到3和8被解析为几个月和几天.但除此之外它对我没有意义.

Tim*_*ter 20

tl; dr:您可以使用DateTimeFormatInfo.GetEraName/ GetAbbreviatedEraNamereturn作为分隔符,忽略大小写.订单是:日,月,年(可选).


看来你总是可以使用日历的当前时代的缩写名称完整的时代名称作为DateTime标记的分隔符.对于英国文化来说,它是AD或者A.D.,例如对于德国文化来说n. Chr..

var enCulture = new CultureInfo("en-GB");
System.Threading.Thread.CurrentThread.CurrentCulture = enCulture;
var fi = enCulture.DateTimeFormat;
int currentEra = enCulture.Calendar.GetEra(DateTime.Now);
var eraName = fi.GetEraName(currentEra);
var shortEra = fi.GetAbbreviatedEraName(currentEra);
var date = DateTime.Parse($"{shortEra}3{shortEra}08"); // AD or A.D. works

var deCulture = new CultureInfo("de-DE");
System.Threading.Thread.CurrentThread.CurrentCulture = deCulture;
fi = deCulture.DateTimeFormat;
currentEra = deCulture.Calendar.GetEra(DateTime.Now);
eraName = fi.GetEraName(currentEra);
shortEra = fi.GetAbbreviatedEraName(currentEra);
date = DateTime.Parse($"{shortEra}3{shortEra}08");  // n. Chr. works
Run Code Online (Sandbox Code Playgroud)

有趣的是,它不区分大小写,所以ad也有效.这记录在DateTimeFormatInfo.GetEra:

时代名称是日历用于表示从固定点或事件计算的一段时间的名称.例如,"AD"或"CE"是格里高利历中的当前时代.与eraName的比较不区分大小写,例如,"AD"相当于"ad".

格里高利历只有一个时代,所以Calendar.GetEra(DateTime.Now)没有必要.我还没有找到任何进一步的文档.

以下是一些所有工作的样本,将被解析为2017年圣诞节:

DateTime christmas  = DateTime.Parse("ad25ad12ad2017ad");
christmas = DateTime.Parse("AD25ad12ad2017");
christmas = DateTime.Parse("25ad12ad2017AD");
christmas = DateTime.Parse("25ad12ad2017");
christmas = DateTime.Parse("A.D.25ad12ad2017");
christmas = DateTime.Parse("A.D.25ad12ad");  // current year is used
christmas = DateTime.Parse("A.D.25ad12");    // current year is used
Run Code Online (Sandbox Code Playgroud)

  • @Damien_The_Unbeliever:只能使用`GetEraName`或`GetAbbreviatedEraName`返回`AD` /`AD`. (2认同)

Evk*_*Evk 9

您可以确认这是时代的,而不是通过修改文化简称年号有些UTF编码的字符(年号存储在DateTimeFormatInfo.m_abbrevEraNamesDateTimeFormatInfo.m_abbrevEnglishEraNames私人领域,并简称年号不变的文化是字符串数组只用一个价值- "AD").m_eraNames字段还存储完整(非缩写)时代名称(不变文化的"AD"),也可以代替"AD"使用.

var cul = (CultureInfo) CultureInfo.InvariantCulture.Clone();                        
// set DateTimeFormatInfo.AbbreviatedEraNames to "BLA"
typeof(DateTimeFormatInfo).GetField("m_abbrevEraNames", BindingFlags.Instance | BindingFlags.NonPublic)
    .SetValue(cul.DateTimeFormat, new string[] {"BLA"});
// set DateTimeFormatInfo.AbbreviatedEnglishEraNames to "BLA"
typeof(DateTimeFormatInfo).GetField("m_abbrevEnglishEraNames", BindingFlags.Instance | BindingFlags.NonPublic)
    .SetValue(cul.DateTimeFormat, new string[] { "BLA" });

var date = DateTime.Parse("AD03AD08", cul); // now it fails
var date = DateTime.Parse("A.D.03A.D.08", cul); // still works because we
// did not modify non-abbreviated era name
var date = DateTime.Parse("BLA03BLA08", cul); // this one works
Run Code Online (Sandbox Code Playgroud)

现在为什么它对待这样的时代名称并不是很明显...可能在遇到这样的标记之后它设置了日期时代并继续解析,所以它在某种意义上用作分隔符,它只是在此之后移动到解析下一个标记.DateTime.Parse各州的文件:

此方法尝试完全解析字符串并避免抛出FormatException.如果可能,它会忽略无法识别的数据,并使用当前日期填写缺少的月,日和年信息

虽然这没有提及任何关于时代的事情 - 这种行为与"尽可能避免抛出FormatException"设计一致.