valid - see cref c#
¿Por qué AD3AD08 representa una fecha válida en el marco.NET? (2)
Puede confirmar que esto es una era y no un carácter codificado en UTF modificando el nombre de la era de abreviatura cultural (el nombre de la era se almacena en los campos privados DateTimeFormatInfo.m_abbrevEraNames
y DateTimeFormatInfo.m_abbrevEnglishEraNames
, y el nombre de era abreviado cultural invariante es una matriz de cadenas con un solo valor - "ANUNCIO"). m_eraNames
campo m_eraNames
también almacena el nombre completo (no abreviado) de la era ("AD" para la cultura invariante) que también se puede usar en lugar de "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
Ahora, por qué trata el nombre de la era de esa manera no es del todo obvio ... Probablemente después de conocer dicho token establece la fecha y continúa el análisis, por lo que sirve como separador en cierto sentido, simplemente se mueve al siguiente token de análisis después de este. La documentación para DateTime.Parse
declara que:
Este método intenta analizar la cadena por completo y evitar arrojar una FormatException. Ignora los datos no reconocidos si es posible y completa la información faltante de mes, día y año con la fecha actual
Si bien esto no menciona nada sobre eras, este comportamiento se alinea con el diseño de "evitar lanzar FormatException siempre que sea posible".
DateTime.Parse("AD3AD08")
[2017-08-03 12:00:00 AM]
¿Por qué esa cadena (que me parece una cadena hexagonal normal para mí) se analiza correctamente como una fecha? Puedo ver que el 3 y el 8 se analizan como meses y días. Pero de lo contrario no tiene sentido para mí.
tl; dr : puede usar lo que DateTimeFormatInfo.GetEraName
/ GetAbbreviatedEraName
devuelve como delimitador, ignorando el caso. El orden es: día, mes, año (opcional).
Parece que siempre puedes usar el GetAbbreviatedEraName actual del calendario o el GetAbbreviatedEraName DateTimeFormatInfo.GetEraName como delimitador para los tokens de DateTime. Para las culturas inglesas es AD
o AD
, por ejemplo, para las culturas alemanas es n. Chr.
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
Resulta interesante que no distingue entre mayúsculas y minúsculas, así que los ad
también funcionan. Eso está documentado en DateTimeFormatInfo.GetEra
:
El nombre de la era es el nombre que un calendario usa para referirse a un período de tiempo estimado desde un punto fijo o evento. Por ejemplo, "AD" o "CE" es la era actual en el calendario gregoriano. La comparación con eraName no distingue entre mayúsculas y minúsculas , por ejemplo, "AD" es equivalente a "ad".
El calendario gregoriano solo tiene una era, por lo que Calendar.GetEra(DateTime.Now)
no es realmente necesario. No he encontrado ninguna documentación adicional todavía.
Aquí hay algunas muestras que funcionan y serán analizadas en Navidad 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