DateTime.Parse("AD3AD08")
[2017-08-03 12:00:00 AM]
为什么这个字符串(看起来只是一个普通的十六进制字符串给我)成功解析为日期?我可以看到3和8被解析为几个月和几天。但是否则对我来说没有意义。
答案 0 :(得分:20)
tl; dr :您可以使用DateTimeFormatInfo.GetEraName
/ GetAbbreviatedEraName
作为分隔符返回,忽略大小写。订单是:日,月,年(可选)。
似乎您始终可以使用日历的当前era's abbreviated name或full era-name作为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
有趣的是它不区分大小写,所以ad
也有效。这在DateTimeFormatInfo.GetEra
:
时代名称是日历用于指代一段时间的名称 从一个固定的点或事件计算。例如," A.D。"或" C.E。"是 格里高利历中的当代时代。与eraName的比较 不区分大小写,例如" A.D。"相当于" a.d。"。
格里高利历只有一个时代,所以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
答案 1 :(得分:9)
您可以通过修改文化缩写时代名称(时代名称存储在DateTimeFormatInfo.m_abbrevEraNames
和DateTimeFormatInfo.m_abbrevEnglishEraNames
私有字段中来确认这是时代而不是某些UTF编码字符,并且对于不变文化缩写时代名称是字符串数组只有一个值 - " AD")。 m_eraNames
字段还存储完整(非缩写)时代名称(" A.D。"用于不变文化),也可用于代替" 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
现在为什么它对待那个时代名称并不是很明显...可能在遇到这样的标记之后它会设置日期时间并继续解析,因此它在某种意义上用作分隔符,它只是在此之后转移到解析下一个标记。 DateTime.Parse
的文档声明:
此方法尝试完全解析字符串并避免抛出字符串 出现FormatException。如果可能,它会忽略无法识别的数据并填写 缺少当前日期的月,日和年信息
虽然这没有提及任何关于时代的事情 - 这种行为与"一致;尽可能避免抛出FormatException"设计。