Clase DateTimeFormatInfo

En este artículo se proporcionan comentarios adicionales a la documentación de referencia de esta API.

Las propiedades de la clase DateTimeFormatInfo contienen información específica de la referencia cultural para dar formato o analizar valores de fecha y hora, como los siguientes:

  • Los patrones usados para dar formato a los valores de fecha.
  • Los patrones usados para dar formato a los valores de hora.
  • Los nombres de los días de la semana.
  • Los nombres de los meses del año.
  • Los designadores A.M. y P.M. usados en valores de tiempo.
  • El calendario en el que se expresan las fechas.

Creación de una instancia de un objeto DateTimeFormatInfo

Un objeto DateTimeFormatInfo puede representar las convenciones de formato de la referencia cultural invariable, una referencia cultural específica, una referencia cultural neutra o la referencia cultural actual. En esta sección se describe cómo crear instancias de cada tipo de objeto DateTimeFormatInfo.

Creación de una instancia de un objeto DateTimeFormatInfo para la referencia cultural invariable

La referencia cultural invariable representa una referencia cultural que no distingue la referencia cultural. Se basa en la lengua inglesa, pero no en ningún país o región específicos de habla inglesa. Aunque los datos de referencias culturales específicas pueden ser dinámicos y cambiar para reflejar nuevas convenciones culturales o preferencias de usuario, los datos de la referencia cultural invariable no cambian. Puede crear instancias de un objeto DateTimeFormatInfo que represente las convenciones de formato de la referencia cultural invariable de las siguientes maneras:

En el siguiente ejemplo se usa cada uno de estos métodos para crear instancias de un objeto DateTimeFormatInfo que representa la referencia cultural invariable. A continuación, indica si el objeto es de solo lectura.

System.Globalization.DateTimeFormatInfo dtfi;

dtfi = System.Globalization.DateTimeFormatInfo.InvariantInfo;
Console.WriteLine(dtfi.IsReadOnly);

dtfi = new System.Globalization.DateTimeFormatInfo();
Console.WriteLine(dtfi.IsReadOnly);

dtfi = System.Globalization.CultureInfo.InvariantCulture.DateTimeFormat;
Console.WriteLine(dtfi.IsReadOnly);
// The example displays the following output:
//       True
//       False
//       True

Creación de una instancia de un objeto DateTimeFormatInfo para una referencia cultural específica

Una referencia cultural específica representa un idioma que se habla en un país o región determinado. Por ejemplo, en-US es una referencia cultural específica que representa el inglés hablado en los Estados Unidos y en-CA es una referencia cultural específica que representa el inglés hablado en Canadá. Puede crear instancias de un objeto DateTimeFormatInfo que represente las convenciones de formato de una referencia cultural específica de las siguientes maneras:

El siguiente ejemplo muestra cada una de estas formas de crear una instancia de un objeto DateTimeFormatInfo e indica si el objeto resultante es de solo lectura.

System.Globalization.CultureInfo ci = null;
System.Globalization.DateTimeFormatInfo dtfi = null;

// Instantiate a culture using CreateSpecificCulture.
ci = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
dtfi = ci.DateTimeFormat;
Console.WriteLine("{0} from CreateSpecificCulture: {1}", ci.Name, dtfi.IsReadOnly);

// Instantiate a culture using the CultureInfo constructor.
ci = new System.Globalization.CultureInfo("en-CA");
dtfi = ci.DateTimeFormat;
Console.WriteLine("{0} from CultureInfo constructor: {1}", ci.Name, dtfi.IsReadOnly);

// Retrieve a culture by calling the GetCultureInfo method.
ci = System.Globalization.CultureInfo.GetCultureInfo("en-AU");
dtfi = ci.DateTimeFormat;
Console.WriteLine("{0} from GetCultureInfo: {1}", ci.Name, dtfi.IsReadOnly);

// Instantiate a DateTimeFormatInfo object by calling DateTimeFormatInfo.GetInstance.
ci = System.Globalization.CultureInfo.CreateSpecificCulture("en-GB");
dtfi = System.Globalization.DateTimeFormatInfo.GetInstance(ci);
Console.WriteLine("{0} from GetInstance: {1}", ci.Name, dtfi.IsReadOnly);

// The example displays the following output:
//      en-US from CreateSpecificCulture: False
//      en-CA from CultureInfo constructor: False
//      en-AU from GetCultureInfo: True
//      en-GB from GetInstance: False

Creación de una instancia de un objeto DateTimeFormatInfo para una referencia cultural neutra

Una referencia cultural neutra representa una referencia cultural o un idioma independiente de un país o región; normalmente es el elemento primario de una o varias referencias culturales específicas. Por ejemplo, Fr es una referencia cultural neutra para el idioma francés y el elemento primario de la referencia cultural fr-FR. Puede crear instancias de un objeto DateTimeFormatInfo que represente las convenciones de formato de una referencia cultural neutra de la misma manera en que cree un objeto DateTimeFormatInfo que represente las convenciones de formato de una referencia cultural específica. Además, puede recuperar el objeto DateTimeFormatInfo de una referencia cultural neutra recuperando una referencia cultural neutra de la propiedad CultureInfo.Parent de una referencia cultural específica y recuperando el objeto DateTimeFormatInfo devuelto por su propiedad CultureInfo.DateTimeFormat. A menos que la referencia cultural primaria represente la referencia cultural invariable, el objeto devuelto DateTimeFormatInfo es de lectura y escritura. En el siguiente ejemplo se muestran estas formas de crear instancias de un objeto DateTimeFormatInfo que representa una referencia cultural neutra.

System.Globalization.CultureInfo specific, neutral;
System.Globalization.DateTimeFormatInfo dtfi;

// Instantiate a culture by creating a specific culture and using its Parent property.
specific = System.Globalization.CultureInfo.GetCultureInfo("fr-FR");
neutral = specific.Parent;
dtfi = neutral.DateTimeFormat;
Console.WriteLine("{0} from Parent property: {1}", neutral.Name, dtfi.IsReadOnly);

dtfi = System.Globalization.CultureInfo.GetCultureInfo("fr-FR").Parent.DateTimeFormat;
Console.WriteLine("{0} from Parent property: {1}", neutral.Name, dtfi.IsReadOnly);

// Instantiate a neutral culture using the CultureInfo constructor.
neutral = new System.Globalization.CultureInfo("fr");
dtfi = neutral.DateTimeFormat;
Console.WriteLine("{0} from CultureInfo constructor: {1}", neutral.Name, dtfi.IsReadOnly);

// Instantiate a culture using CreateSpecificCulture.
neutral = System.Globalization.CultureInfo.CreateSpecificCulture("fr");
dtfi = neutral.DateTimeFormat;
Console.WriteLine("{0} from CreateSpecificCulture: {1}", neutral.Name, dtfi.IsReadOnly);

// Retrieve a culture by calling the GetCultureInfo method.
neutral = System.Globalization.CultureInfo.GetCultureInfo("fr");
dtfi = neutral.DateTimeFormat;
Console.WriteLine("{0} from GetCultureInfo: {1}", neutral.Name, dtfi.IsReadOnly);

// Instantiate a DateTimeFormatInfo object by calling GetInstance.
neutral = System.Globalization.CultureInfo.CreateSpecificCulture("fr");
dtfi = System.Globalization.DateTimeFormatInfo.GetInstance(neutral);
Console.WriteLine("{0} from GetInstance: {1}", neutral.Name, dtfi.IsReadOnly);

// The example displays the following output:
//       fr from Parent property: False
//       fr from Parent property: False
//       fr from CultureInfo constructor: False
//       fr-FR from CreateSpecificCulture: False
//       fr from GetCultureInfo: True
//       fr-FR from GetInstance: False

Sin embargo, una referencia cultural neutra carece de información de formato específica de la referencia cultural, ya que es independiente de un país o región específicos. En lugar de rellenar el objeto DateTimeFormatInfo con valores genéricos, .NET devuelve un objeto DateTimeFormatInfo que refleja las convenciones de formato de una referencia cultural específica que es un elemento secundario de la referencia cultural neutra. Por ejemplo, el objeto DateTimeFormatInfo de la referencia cultural neutra refleja las convenciones de formato de la referencia cultural en-US y el objeto DateTimeFormatInfo para la referencia cultural fr refleja las convenciones de formato de la referencia cultural fr-FR.

Puede usar un código como el siguiente para determinar qué convenciones de formato de una referencia cultural específica representa una referencia cultural neutra. En el ejemplo se usa la reflexión para comparar las propiedades DateTimeFormatInfo de una referencia cultural neutra con las propiedades de una referencia cultural secundaria específica. Considera que dos calendarios son equivalentes si son del mismo tipo y, para los calendarios gregorianos, si sus propiedades GregorianCalendar.CalendarType tienen valores idénticos.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;

public class InstantiateEx6
{
    public static void Main()
    {
        // Get all the neutral cultures
        List<String> names = new List<String>();
        Array.ForEach(CultureInfo.GetCultures(CultureTypes.NeutralCultures),
                      culture => names.Add(culture.Name));
        names.Sort();
        foreach (var name in names)
        {
            // Ignore the invariant culture.
            if (name == "") continue;

            ListSimilarChildCultures(name);
        }
    }

    private static void ListSimilarChildCultures(String name)
    {
        // Create the neutral DateTimeFormatInfo object.
        DateTimeFormatInfo dtfi = CultureInfo.GetCultureInfo(name).DateTimeFormat;
        // Retrieve all specific cultures of the neutral culture.
        CultureInfo[] cultures = Array.FindAll(CultureInfo.GetCultures(CultureTypes.SpecificCultures),
                                 culture => culture.Name.StartsWith(name + "-", StringComparison.OrdinalIgnoreCase));
        // Create an array of DateTimeFormatInfo properties
        PropertyInfo[] properties = typeof(DateTimeFormatInfo).GetProperties(BindingFlags.Instance | BindingFlags.Public);
        bool hasOneMatch = false;

        foreach (var ci in cultures)
        {
            bool match = true;
            // Get the DateTimeFormatInfo for a specific culture.
            DateTimeFormatInfo specificDtfi = ci.DateTimeFormat;
            // Compare the property values of the two.
            foreach (var prop in properties)
            {
                // We're not interested in the value of IsReadOnly.
                if (prop.Name == "IsReadOnly") continue;

                // For arrays, iterate the individual elements to see if they are the same.
                if (prop.PropertyType.IsArray)
                {
                    IList nList = (IList)prop.GetValue(dtfi, null);
                    IList sList = (IList)prop.GetValue(specificDtfi, null);
                    if (nList.Count != sList.Count)
                    {
                        match = false;
                        Console.WriteLine("   Different n in {2} array for {0} and {1}", name, ci.Name, prop.Name);
                        break;
                    }

                    for (int ctr = 0; ctr < nList.Count; ctr++)
                    {
                        if (!nList[ctr].Equals(sList[ctr]))
                        {
                            match = false;
                            Console.WriteLine("   {0} value different for {1} and {2}", prop.Name, name, ci.Name);
                            break;
                        }
                    }

                    if (!match) break;
                }
                // Get non-array values.
                else
                {
                    Object specificValue = prop.GetValue(specificDtfi);
                    Object neutralValue = prop.GetValue(dtfi);

                    // Handle comparison of Calendar objects.
                    if (prop.Name == "Calendar")
                    {
                        // The cultures have a different calendar type.
                        if (specificValue.ToString() != neutralValue.ToString())
                        {
                            Console.WriteLine("   Different calendar types for {0} and {1}", name, ci.Name);
                            match = false;
                            break;
                        }

                        if (specificValue is GregorianCalendar)
                        {
                            if (((GregorianCalendar)specificValue).CalendarType != ((GregorianCalendar)neutralValue).CalendarType)
                            {
                                Console.WriteLine("   Different Gregorian calendar types for {0} and {1}", name, ci.Name);
                                match = false;
                                break;
                            }
                        }
                    }
                    else if (!specificValue.Equals(neutralValue))
                    {
                        match = false;
                        Console.WriteLine("   Different {0} values for {1} and {2}", prop.Name, name, ci.Name);
                        break;
                    }
                }
            }
            if (match)
            {
                Console.WriteLine("DateTimeFormatInfo object for '{0}' matches '{1}'",
                                  name, ci.Name);
                hasOneMatch = true;
            }
        }
        if (!hasOneMatch)
            Console.WriteLine("DateTimeFormatInfo object for '{0}' --> No Match", name);

        Console.WriteLine();
    }
}

Creación de una instancia de un objeto DateTimeFormatInfo para la referencia cultural actual

Puede crear instancias de un objeto DateTimeFormatInfo que represente las convenciones de formato de la referencia cultural actual de las siguientes maneras:

En el siguiente ejemplo se usa cada uno de estos métodos para crear instancias de un objeto DateTimeFormatInfo que representa las convenciones de formato de la referencia cultural actual. A continuación, indica si el objeto es de solo lectura.

DateTimeFormatInfo dtfi;

dtfi = DateTimeFormatInfo.CurrentInfo;
Console.WriteLine(dtfi.IsReadOnly);

dtfi = CultureInfo.CurrentCulture.DateTimeFormat;
Console.WriteLine(dtfi.IsReadOnly);

dtfi = DateTimeFormatInfo.GetInstance(CultureInfo.CurrentCulture);
Console.WriteLine(dtfi.IsReadOnly);
// The example displays the following output:
//     True
//     True
//     True

Puede crear un objeto grabable DateTimeFormatInfo que represente las convenciones de la referencia cultural actual de una de estas maneras:

En el siguiente ejemplo se muestra cada forma de crear una instancia de un objeto DateTimeFormatInfo de lectura y escritura y se muestra el valor de su propiedad IsReadOnly.

using System;
using System.Globalization;

public class InstantiateEx1
{
    public static void Main()
    {
        DateTimeFormatInfo current1 = DateTimeFormatInfo.CurrentInfo;
        current1 = (DateTimeFormatInfo)current1.Clone();
        Console.WriteLine(current1.IsReadOnly);

        CultureInfo culture2 = CultureInfo.CreateSpecificCulture(CultureInfo.CurrentCulture.Name);
        DateTimeFormatInfo current2 = culture2.DateTimeFormat;
        Console.WriteLine(current2.IsReadOnly);
    }
}
// The example displays the following output:
//       False
//       False

En Windows, el usuario puede invalidar algunos de los valores de propiedad DateTimeFormatInfo usados en las operaciones de formato y análisis a través de la aplicación Región e idioma en Panel de control. Por ejemplo, un usuario cuya referencia cultural es inglés (Estados Unidos) puede optar por mostrar valores de tiempo largos mediante un reloj de 24 horas (con el formato HH:mm:ss) en lugar del reloj predeterminado de 12 horas (con el formato h:mm:ss tt). Los objetos DateTimeFormatInfo recuperados de las maneras descritas anteriormente reflejan estas invalidaciones de usuario. Si esto no es lo que quiere, puede crear un objeto NumberFormatInfo que no refleje las invalidaciones del usuario (y que también sea de lectura y escritura en lugar de solo lectura) llamando al constructor CultureInfo.CultureInfo(String, Boolean) y proporcionando un valor de false para el argumento useUserOverride. En el siguiente ejemplo se muestra esto para un sistema cuya referencia cultural actual es inglés (Estados Unidos) y cuyo patrón de tiempo largo se ha cambiado del valor predeterminado de h:mm:ss tt a HH:mm:ss.

using System;
using System.Globalization;

public class InstantiateEx3
{
    public static void Main()
    {
        CultureInfo culture;
        DateTimeFormatInfo dtfi;

        culture = CultureInfo.CurrentCulture;
        dtfi = culture.DateTimeFormat;
        Console.WriteLine("Culture Name:      {0}", culture.Name);
        Console.WriteLine("User Overrides:    {0}", culture.UseUserOverride);
        Console.WriteLine("Long Time Pattern: {0}\n", culture.DateTimeFormat.LongTimePattern);

        culture = new CultureInfo(CultureInfo.CurrentCulture.Name, false);
        Console.WriteLine("Culture Name:      {0}", culture.Name);
        Console.WriteLine("User Overrides:    {0}", culture.UseUserOverride);
        Console.WriteLine("Long Time Pattern: {0}\n", culture.DateTimeFormat.LongTimePattern);
    }
}
// The example displays the following output:
//       Culture Name:      en-US
//       User Overrides:    True
//       Long Time Pattern: HH:mm:ss
//
//       Culture Name:      en-US
//       User Overrides:    False
//       Long Time Pattern: h:mm:ss tt

Datos dinámicos y DateTimeFormatInfo

Los datos específicos de la referencia cultural para dar formato a los valores de fecha y hora proporcionados por la clase DateTimeFormatInfo son dinámicos, al igual que los datos culturales proporcionados por la clase CultureInfo. No debe realizar ninguna suposición sobre la estabilidad de los valores de los objetos DateTimeFormatInfo asociados a determinados objetos CultureInfo. Solo los datos proporcionados por la referencia cultural invariable y su objeto DateTimeFormatInfo asociado son estables. Otros datos pueden cambiar entre sesiones de aplicación o incluso mientras se ejecuta la aplicación. Hay cuatro orígenes principales de cambio:

  • Actualizaciones del sistema. Las preferencias culturales, como el calendario preferido o los formatos de fecha y hora habituales, cambian con el tiempo. Cuando esto sucede, Windows Update incluye cambios en el valor de propiedad DateTimeFormatInfo de una referencia cultural determinada.

  • Referencias culturales de reemplazo. La clase CultureAndRegionInfoBuilder se puede usar para reemplazar los datos de una referencia cultural existente.

  • Cambios en cascada en los valores de propiedad. Varias propiedades relacionadas con la referencia cultural pueden cambiar en tiempo de ejecución, lo que, a su vez, hace que los datos DateTimeFormatInfo cambien. Por ejemplo, la referencia cultural actual se puede cambiar mediante programación o a través de la acción del usuario. Cuando esto sucede, el objeto DateTimeFormatInfo devuelto por la propiedad CurrentInfo cambia a un objeto asociado a la referencia cultural actual. Del mismo modo, el calendario de una referencia cultural puede cambiar, lo que puede dar lugar a cambios en numerosos valores de propiedad DateTimeFormatInfo.

  • Preferencias del usuario. Los usuarios de la aplicación pueden optar por invalidar algunos de los valores asociados a la referencia cultural del sistema actual a través de las opciones regionales y de idioma de Panel de control. Por ejemplo, los usuarios pueden optar por mostrar la fecha en un formato diferente. Si la propiedad CultureInfo.UseUserOverride se establece en true, las propiedades del objeto DateTimeFormatInfo también se recuperan de la configuración del usuario. Si la configuración del usuario no es compatible con la referencia cultural asociada al objeto CultureInfo (por ejemplo, si el calendario seleccionado no es uno de los calendarios indicados por la propiedad OptionalCalendars), los resultados de los métodos y los valores de las propiedades no están definidos.

Para minimizar la posibilidad de datos incoherentes, todas las propiedades reemplazables por el usuario de un objeto DateTimeFormatInfo se inicializan cuando se crea el objeto. Todavía existe la posibilidad de incoherencia, ya que ni la creación de objetos ni el proceso de invalidación del usuario son atómicos y los valores pertinentes pueden cambiar durante la creación de objetos. Sin embargo, esta situación debe ser extremadamente rara.

Puede controlar si las invalidaciones de usuario se reflejan en objetos DateTimeFormatInfo que representan la misma referencia cultural que la referencia cultural del sistema. En la siguiente tabla se enumeran las formas en que se puede recuperar un objeto DateTimeFormatInfo e indica si el objeto resultante refleja las invalidaciones del usuario.

Origen del objeto CultureInfo y DateTimeFormatInfo Refleja las invalidaciones de usuario
PropiedadCultureInfo.CurrentCulture.DateTimeFormat
PropiedadDateTimeFormatInfo.CurrentInfo
Método CultureInfo.CreateSpecificCulture
Método CultureInfo.GetCultureInfo No
Constructor CultureInfo.CultureInfo(String)
Constructor CultureInfo.CultureInfo(String, Boolean) Depende del valor del parámetro useUserOverride

A menos que exista una razón de peso para hacer lo contrario, debe respetar las anulaciones de usuario cuando utilice el objeto DateTimeFormatInfo en aplicaciones cliente para formatear y analizar la entrada del usuario o para mostrar datos. En el caso de las aplicaciones de servidor o las aplicaciones desatendidas, no debe. Sin embargo, si usa el objeto DateTimeFormatInfo explícita o implícitamente para conservar datos de fecha y hora en forma de cadena, debe usar un objeto DateTimeFormatInfo que refleje las convenciones de formato de la referencia cultural invariable, o bien debe especificar una cadena de formato de fecha y hora personalizada que use independientemente de la referencia cultural.

Dar formato a fechas y horas

Un objeto DateTimeFormatInfo se usa implícita o explícitamente en todas las operaciones de formato de fecha y hora. Estas incluyen llamadas a los métodos siguientes:

Todas las operaciones de formato de fecha y hora usan una implementación IFormatProvider. La interfaz IFormatProvider incluye un único método, IFormatProvider.GetFormat(Type). Este método de devolución de llamada se pasa a un objeto Type que representa el tipo necesario para proporcionar información de formato. El método devuelve una instancia de ese tipo o null si no puede proporcionar una instancia del tipo. .NET incluye dos implementaciones IFormatProvider para dar formato a fechas y horas:

Si no se proporciona una implementación IFormatProvider a un método de formato explícitamente, se usa el objeto CultureInfo devuelto por la propiedad CultureInfo.CurrentCulture que representa la referencia cultural actual.

En el siguiente ejemplo se muestra la relación entre la interfaz IFormatProvider y la clase DateTimeFormatInfo en las operaciones de formato. Define una implementación personalizada IFormatProvider cuyo método GetFormat muestra el tipo del objeto solicitado por la operación de formato. Si solicita un objeto DateTimeFormatInfo, el método proporciona el objeto DateTimeFormatInfo para la referencia cultural actual. Como se muestra en la salida del ejemplo, el método Decimal.ToString(IFormatProvider) solicita un objeto DateTimeFormatInfo para proporcionar información de formato, mientras que el método String.Format(IFormatProvider, String, Object[]) solicita objetos NumberFormatInfo y DateTimeFormatInfo, así como una implementación ICustomFormatter.

using System;
using System.Globalization;

public class CurrentCultureFormatProvider : IFormatProvider
{
    public Object GetFormat(Type formatType)
    {
        Console.WriteLine("Requesting an object of type {0}",
                          formatType.Name);
        if (formatType == typeof(NumberFormatInfo))
            return NumberFormatInfo.CurrentInfo;
        else if (formatType == typeof(DateTimeFormatInfo))
            return DateTimeFormatInfo.CurrentInfo;
        else
            return null;
    }
}

public class FormatProviderEx1
{
    public static void Main()
    {
        DateTime dateValue = new DateTime(2013, 5, 28, 13, 30, 0);
        string value = dateValue.ToString("F", new CurrentCultureFormatProvider());
        Console.WriteLine(value);
        Console.WriteLine();
        string composite = String.Format(new CurrentCultureFormatProvider(),
                                         "Date: {0:d}   Amount: {1:C}   Description: {2}",
                                         dateValue, 1264.03m, "Service Charge");
        Console.WriteLine(composite);
        Console.WriteLine();
    }
}
// The example displays output like the following:
//       Requesting an object of type DateTimeFormatInfo
//       Tuesday, May 28, 2013 1:30:00 PM
//
//       Requesting an object of type ICustomFormatter
//       Requesting an object of type DateTimeFormatInfo
//       Requesting an object of type NumberFormatInfo
//       Date: 5/28/2013   Amount: $1,264.03   Description: Service Charge

Formato de cadenas y propiedades DateTimeFormatInfo

El objeto DateTimeFormatInfo incluye tres tipos de propiedades que se usan en operaciones de formato con valores de fecha y hora:

Las cadenas de formato de fecha y hora estándar, como "d", "D", "f" y "F", son alias que corresponden a propiedades DateTimeFormatInfo de patrón de formato concretas. La mayoría de las cadenas de formato de fecha y hora personalizadas están relacionadas con cadenas o substring que una operación de formato inserta en la secuencia de resultados. En la siguiente tabla se enumeran los especificadores de formato de fecha y hora estándar y personalizados y sus propiedades DateTimeFormatInfo asociadas. Para obtener más información sobre cómo usar estos especificadores de formato, consulte Cadenas de formato de fecha y hora estándar y Cadenas de formato de fecha y hora personalizadas. Tenga en cuenta que cada cadena de formato estándar corresponde a una propiedad DateTimeFormatInfo cuyo valor es una cadena de formato de fecha y hora personalizada. Los especificadores individuales de esta cadena de formato personalizado a su vez corresponden a otras propiedades DateTimeFormatInfo. La tabla muestra solo las propiedades DateTimeFormatInfo para las que las cadenas de formato estándar son alias y no enumera las propiedades a las que pueden tener acceso las cadenas de formato personalizado asignadas a esas propiedades con alias. Además, la tabla muestra solo especificadores de formato personalizados que corresponden a propiedades DateTimeFormatInfo.

Especificador de formato Propiedades asociadas
"d" (fecha corta; cadena de formato estándar) ShortDatePattern, para definir el formato general de la cadena de resultado.
"D" (fecha larga; cadena de formato estándar) LongDatePattern, para definir el formato general de la cadena de resultado.
"f" (fecha completa/hora corta; cadena de formato estándar) LongDatePattern, para definir el formato del componente de fecha de la cadena de resultado.

ShortTimePattern, para definir el formato del componente de hora de la cadena de resultado.
"F" (fecha completa/hora larga; cadena de formato estándar) LongDatePattern, para definir el formato del componente de fecha de la cadena de resultado.

LongTimePattern, para definir el formato del componente de hora de la cadena de resultado.
"g" (fecha general/hora corta; cadena de formato estándar) ShortDatePattern, para definir el formato del componente de fecha de la cadena de resultado.

ShortTimePattern, para definir el formato del componente de hora de la cadena de resultado.
"G" (fecha general/hora larga; cadena de formato estándar) ShortDatePattern, para definir el formato del componente de fecha de la cadena de resultado.

LongTimePattern, para definir el formato del componente de hora de la cadena de resultado.
"M", "m" (mes/día; cadena de formato estándar) MonthDayPattern, para definir el formato general de la cadena de resultado.
"O", "o" (fecha y hora de ida y vuelta; cadena de formato estándar) Ninguno.
"R", "r" (RFC1123; cadena de formato estándar) RFC1123Pattern, para definir una cadena de resultado que se ajuste al estándar RFC 1123. La propiedad es de solo lectura.
"s" (fecha y hora ordenables; cadena de formato estándar) SortableDateTimePattern, para definir una cadena de resultado que se ajuste al estándar ISO 8601. La propiedad es de solo lectura.
"t" (tiempo corto; cadena de formato estándar) ShortTimePattern, para definir el formato general de la cadena de resultado.
"T" (tiempo largo; cadena de formato estándar) LongTimePattern, para definir el formato general de la cadena de resultado.
"u" (fecha y hora ordenable universal; cadena de formato estándar) UniversalSortableDateTimePattern, para definir una cadena de resultado que se ajuste al estándar ISO 8601 para la hora universal coordinada. La propiedad es de solo lectura.
"U" (fecha y hora completa universal; cadena de formato estándar) FullDateTimePattern, para definir el formato general de la cadena de resultado.
"Y", "y" (mes de año; cadena de formato estándar) YearMonthPattern, para definir el formato general de la cadena de resultado.
"ddd" (especificador de formato personalizado) AbbreviatedDayNames, para incluir el nombre abreviado del día de la semana en la cadena de resultado.
"g", "gg" (especificador de formato personalizado) Llama al método GetEraName para insertar el nombre de la era en la cadena de resultado.
"MMM" (especificador de formato personalizado) AbbreviatedMonthNames, para incluir el nombre del mes abreviado en la cadena de resultado.
"MMMM" (especificador de formato personalizado) MonthNames o MonthGenitiveNames, para incluir el nombre de mes completo en la cadena de resultado.
"t" (especificador de formato personalizado) AMDesignator o PMDesignator, para incluir el primer carácter del designador AM/PM en la cadena de resultado.
"tt" (especificador de formato personalizado) AMDesignator o PMDesignator, para incluir el designador AM/PM completo en la cadena de resultado.
":" (especificador de formato personalizado) TimeSeparator, para incluir el separador de hora en la cadena de resultado.
"/" (especificador de formato personalizado) DateSeparator, para incluir el separador de fecha en la cadena de resultado.

Modificación de las propiedades DateTimeFormatInfo

Puede cambiar la cadena de resultado generada por cadenas de formato de fecha y hora modificando las propiedades asociadas de un objeto DateTimeFormatInfo grabable. Para determinar si un objeto DateTimeFormatInfo es grabable, use la propiedad IsReadOnly. Para personalizar un objeto DateTimeFormatInfo de esta manera:

  1. Cree una copia de lectura y escritura de un objeto DateTimeFormatInfo cuyas convenciones de formato quiera modificar.

  2. Modifique la propiedad o las propiedades que se usan para generar la cadena de resultado deseada. (Para obtener información sobre cómo los métodos de formato usan propiedades DateTimeFormatInfo para definir cadenas de resultados, consulte la sección anterior, Cadenas de formato y propiedades DateTimeFormatInfo).

  3. Use el objeto DateTimeFormatInfo personalizado que creó como argumento IFormatProvider en llamadas a métodos de formato.

Hay otras dos maneras de cambiar el formato de una cadena de resultado:

  • Puede usar la clase CultureAndRegionInfoBuilder para definir una referencia cultural personalizada (una referencia cultural que tenga un nombre único y que complemente las referencias culturales existentes) o una referencia cultural de reemplazo (una que se usa en lugar de una referencia cultural específica). Puede guardar y acceder a esta referencia cultural mediante programación, como haría con cualquier objeto CultureInfo compatible con .NET.

  • Si la cadena de resultado no distingue la referencia cultural y no sigue un formato predefinido, puede usar una cadena de formato de fecha y hora personalizada. Por ejemplo, si va a serializar datos de fecha y hora en el formato AAAAMMDDHHmmss, puede generar la cadena de resultado pasando la cadena de formato personalizado al método DateTime.ToString(String) y puede convertir la cadena de resultado en un valor DateTime llamando al método DateTime.ParseExact.

Cambio del patrón de fecha corta

En el siguiente ejemplo se cambia el formato de una cadena de resultado generada por la cadena de formato estándar "d" (fecha corta). Cambia la propiedad ShortDatePattern asociada para la referencia cultural en-US o inglés (Estados Unidos) de su valor predeterminado de "M/d/aaaa" a "aaaa"-"MM"-"dd" y usa la cadena de formato estándar "d" para mostrar la fecha antes y después de cambiar la propiedad ShortDatePattern.

using System;
using System.Globalization;

public class Example1
{
    public static void Main()
    {
        DateTime dateValue = new DateTime(2013, 8, 18);
        CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US");
        DateTimeFormatInfo dtfi = enUS.DateTimeFormat;

        Console.WriteLine("Before modifying DateTimeFormatInfo object: ");
        Console.WriteLine("{0}: {1}\n", dtfi.ShortDatePattern,
                                      dateValue.ToString("d", enUS));

        // Modify the short date pattern.
        dtfi.ShortDatePattern = "yyyy-MM-dd";
        Console.WriteLine("After modifying DateTimeFormatInfo object: ");
        Console.WriteLine("{0}: {1}", dtfi.ShortDatePattern,
                                      dateValue.ToString("d", enUS));
    }
}
// The example displays the following output:
//       Before modifying DateTimeFormatInfo object:
//       M/d/yyyy: 8/18/2013
//
//       After modifying DateTimeFormatInfo object:
//       yyyy-MM-dd: 2013-08-18

Cambio del carácter separador de fecha

En el siguiente ejemplo se cambia el carácter separador de fecha en un objeto DateTimeFormatInfo que representa las convenciones de formato de la referencia cultural fr-FR. En el ejemplo se usa la cadena de formato estándar "g" para mostrar la fecha antes y después de cambiar la propiedad DateSeparator.

using System;
using System.Globalization;

public class Example3
{
    public static void Main()
    {
        DateTime dateValue = new DateTime(2013, 08, 28);
        CultureInfo frFR = CultureInfo.CreateSpecificCulture("fr-FR");
        DateTimeFormatInfo dtfi = frFR.DateTimeFormat;

        Console.WriteLine("Before modifying DateSeparator property: {0}",
                          dateValue.ToString("g", frFR));

        // Modify the date separator.
        dtfi.DateSeparator = "-";
        Console.WriteLine("After modifying the DateSeparator property: {0}",
                          dateValue.ToString("g", frFR));
    }
}
// The example displays the following output:
//       Before modifying DateSeparator property: 28/08/2013 00:00
//       After modifying the DateSeparator property: 28-08-2013 00:00

Cambio de las abreviaturas de nombre del día y el patrón de fecha larga

En algunos casos, el patrón de fecha larga, que normalmente muestra el nombre completo del día y del mes junto con el número del día del mes y el año, puede ser demasiado largo. En el siguiente ejemplo se acorta el patrón de fecha larga de la referencia cultural en-US para devolver una abreviatura de nombre de día de uno o dos caracteres seguida del número de día, la abreviatura del nombre del mes y el año. Para ello, asigna abreviaturas de nombre de día más cortas a la matriz AbbreviatedDayNames y modifica la cadena de formato personalizada asignada a la propiedad LongDatePattern. Esto afecta a las cadenas de resultado devueltas por las cadenas de formato estándar "D" y "f".

using System;
using System.Globalization;

public class Example2
{
    public static void Main()
    {
        DateTime value = new DateTime(2013, 7, 9);
        CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US");
        DateTimeFormatInfo dtfi = enUS.DateTimeFormat;
        String[] formats = { "D", "F", "f" };

        // Display date before modifying properties.
        foreach (var fmt in formats)
            Console.WriteLine("{0}: {1}", fmt, value.ToString(fmt, dtfi));

        Console.WriteLine();

        // We don't want to change the FullDateTimePattern, so we need to save it.
        String originalFullDateTimePattern = dtfi.FullDateTimePattern;

        // Modify day name abbreviations and long date pattern.
        dtfi.AbbreviatedDayNames = new String[] { "Su", "M", "Tu", "W", "Th", "F", "Sa" };
        dtfi.LongDatePattern = "ddd dd-MMM-yyyy";
        dtfi.FullDateTimePattern = originalFullDateTimePattern;
        foreach (var fmt in formats)
            Console.WriteLine("{0}: {1}", fmt, value.ToString(fmt, dtfi));
    }
}
// The example displays the following output:
//       D: Tuesday, July 9, 2013
//       F: Tuesday, July 9, 2013 12:00:00 AM
//       f: Tuesday, July 9, 2013 12:00 AM
//
//       D: Tu 09-Jul-2013
//       F: Tuesday, July 9, 2013 12:00:00 AM
//       f: Tu 09-Jul-2013 12:00 AM

Normalmente, el cambio a la propiedad LongDatePattern también afecta a la propiedad FullDateTimePattern, que a su vez define la cadena de resultado devuelta por la cadena de formato estándar "F". Para conservar el patrón de fecha y hora completo original, el ejemplo reasigna la cadena de formato personalizado original asignada a la propiedad FullDateTimePattern después de modificar la propiedad LongDatePattern.

Cambio de un reloj de 12 horas a un reloj de 24 horas

Para muchas referencias culturales de .NET, el tiempo se expresa mediante un reloj de 12 horas y un designador AM/PM. En el siguiente ejemplo se define un método ReplaceWith24HourClock que reemplaza cualquier formato de hora que use un reloj de 12 horas con un formato que use un reloj de 24 horas.

using System;
using System.Globalization;
using System.Text.RegularExpressions;

public class Example5
{
    public static void Main()
    {
        CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US");
        DateTimeFormatInfo dtfi = enUS.DateTimeFormat;

        Console.WriteLine("Original Property Values:");
        Console.WriteLine("ShortTimePattern: " + dtfi.ShortTimePattern);
        Console.WriteLine("LongTimePattern: " + dtfi.LongTimePattern);
        Console.WriteLine("FullDateTimePattern: " + dtfi.FullDateTimePattern);
        Console.WriteLine();

        dtfi.LongTimePattern = ReplaceWith24HourClock(dtfi.LongTimePattern);
        dtfi.ShortTimePattern = ReplaceWith24HourClock(dtfi.ShortTimePattern);

        Console.WriteLine("Modififed Property Values:");
        Console.WriteLine("ShortTimePattern: " + dtfi.ShortTimePattern);
        Console.WriteLine("LongTimePattern: " + dtfi.LongTimePattern);
        Console.WriteLine("FullDateTimePattern: " + dtfi.FullDateTimePattern);
    }

    private static string ReplaceWith24HourClock(string fmt)
    {
        string pattern = @"^(?<openAMPM>\s*t+\s*)? " +
                         @"(?(openAMPM) h+(?<nonHours>[^ht]+)$ " +
                         @"| \s*h+(?<nonHours>[^ht]+)\s*t+)";
        return Regex.Replace(fmt, pattern, "HH${nonHours}",
                             RegexOptions.IgnorePatternWhitespace);
    }
}
// The example displays the following output:
//       Original Property Values:
//       ShortTimePattern: h:mm tt
//       LongTimePattern: h:mm:ss tt
//       FullDateTimePattern: dddd, MMMM dd, yyyy h:mm:ss tt
//
//       Modififed Property Values:
//       ShortTimePattern: HH:mm
//       LongTimePattern: HH:mm:ss
//       FullDateTimePattern: dddd, MMMM dd, yyyy HH:mm:ss

En el ejemplo se usa una expresión regular para modificar la cadena de formato. El patrón de expresión regular, @"^(?<openAMPM>\s*t+\s*)? (?(openAMPM) h+(?<nonHours>[^ht]+)$ | \s*h+(?<nonHours>[^ht]+)\s*t+), se define como se indica a continuación:

Modelo Descripción
^ Empieza la búsqueda de coincidencias en el principio de la cadena.
(?<openAMPM>\s*t+\s*)? Coincide con cero o una aparición de cero o más caracteres de espacio en blanco, seguidos de la letra "t" una o varias veces, seguidas de cero o más caracteres de espacio en blanco. Este grupo de captura se denomina openAMPM.
(?(openAMPM) h+(?<nonHours>[^ht]+)$ Si el grupo openAMPM tiene una coincidencia, coincide con la letra "h" una o varias veces, seguida de uno o más caracteres que no son "h" ni "t". La coincidencia finaliza al final de la cadena. Todos los caracteres capturados después de "h" se incluyen en un grupo de captura denominado nonHours.
&#124; \s*h+(?<nonHours>[^ht]+)\s*t+) Si el grupo openAMPM no tiene una coincidencia, coincide con la letra "h" una o varias veces, seguida de uno o más caracteres que no son "h" ni "t", seguidos de cero o más caracteres de espacio en blanco. Por último, coincide con una o varias apariciones de la letra "t". Todos los caracteres capturados después de "h" y antes de los espacios en blanco y "t" se incluyen en un grupo de captura denominado nonHours.

El grupo nonHours de captura contiene el minuto y, posiblemente, el segundo componente de una cadena de formato de fecha y hora personalizada, junto con cualquier símbolo separador de hora. El patrón de reemplazo HH${nonHours} antepone la substring "HH" a estos elementos.

Muestra y cambio de la era en una fecha

En el siguiente ejemplo se agrega el especificador de formato personalizado "g" a la propiedad LongDatePattern de un objeto que representa las convenciones de formato de la referencia cultural en-US. Esta adición afecta a las tres cadenas de formato estándar siguientes:

  • Cadena de formato estándar "D" (fecha larga), que se asigna directamente a la propiedad LongDatePattern.

  • Cadena de formato estándar "f" (fecha completa/hora corta), que genera una cadena de resultado que concatena las substring producidas por las propiedades LongDatePattern y ShortTimePattern.

  • Cadena de formato estándar "F" (fecha completa/tiempo largo), que se asigna directamente a la propiedad FullDateTimePattern. Dado que no hemos establecido explícitamente este valor de propiedad, se genera dinámicamente mediante la concatenación de las propiedades LongDatePattern y LongTimePattern.

En el ejemplo también se muestra cómo cambiar el nombre de la era de una referencia cultural cuyo calendario tiene una sola era. En este caso, la referencia cultural en-US usa el calendario gregoriano, que se representa mediante un objeto GregorianCalendar. La clase GregorianCalendar admite una sola era, que denomina A.D. (Anno Domini). En el ejemplo se cambia el nombre de la era a C.E. (era común) reemplazando el especificador de formato personalizado "g" en la cadena de formato asignada a la propiedad FullDateTimePattern por una cadena literal. El uso de una cadena literal es necesario, ya que el método GetEraName devuelve normalmente el nombre de la era de los datos privados de las tablas de referencia cultural proporcionadas por .NET o el sistema operativo.

using System;
using System.Globalization;

public class Example4
{
    public static void Main()
    {
        DateTime dateValue = new DateTime(2013, 5, 18, 13, 30, 0);
        String[] formats = { "D", "f", "F" };

        CultureInfo enUS = CultureInfo.CreateSpecificCulture("en-US");
        DateTimeFormatInfo dtfi = enUS.DateTimeFormat;
        String originalLongDatePattern = dtfi.LongDatePattern;

        // Display the default form of three long date formats.
        foreach (var fmt in formats)
            Console.WriteLine(dateValue.ToString(fmt, dtfi));

        Console.WriteLine();

        // Modify the long date pattern.
        dtfi.LongDatePattern = originalLongDatePattern + " g";
        foreach (var fmt in formats)
            Console.WriteLine(dateValue.ToString(fmt, dtfi));

        Console.WriteLine();

        // Change A.D. to C.E. (for Common Era)
        dtfi.LongDatePattern = originalLongDatePattern + @" 'C.E.'";
        foreach (var fmt in formats)
            Console.WriteLine(dateValue.ToString(fmt, dtfi));
    }
}
// The example displays the following output:
//       Saturday, May 18, 2013
//       Saturday, May 18, 2013 1:30 PM
//       Saturday, May 18, 2013 1:30:00 PM
//
//       Saturday, May 18, 2013 A.D.
//       Saturday, May 18, 2013 A.D. 1:30 PM
//       Saturday, May 18, 2013 A.D. 1:30:00 PM
//
//       Saturday, May 18, 2013 C.E.
//       Saturday, May 18, 2013 C.E. 1:30 PM
//       Saturday, May 18, 2013 C.E. 1:30:00 PM

Análisis de cadenas de fecha y hora

El análisis implica convertir la representación de cadena de una fecha y hora en un valor DateTime o DateTimeOffset. Ambos tipos incluyen los métodos Parse, TryParse, ParseExact y TryParseExact para admitir operaciones de análisis. Los métodos Parse y TryParse convierten una cadena que puede tener una variedad de formatos, mientras que ParseExact y TryParseExact requieren que la cadena tenga un formato o formato definidos. Si se produce un error en la operación de análisis, Parse y ParseExact inician una excepción, mientras que TryParse y TryParseExact devuelven false.

Los métodos de análisis usan implícita o explícitamente un valor de enumeración DateTimeStyles para determinar qué elementos de estilo (como el espacio en blanco inicial, final o interno) pueden estar presentes en la cadena que se va a analizar y cómo interpretar la cadena analizada o los elementos que faltan. Si no proporciona un valor DateTimeStyles al llamar al método Parse o TryParse, el valor predeterminado es DateTimeStyles.AllowWhiteSpaces, que es un estilo compuesto que incluye las marcas DateTimeStyles.AllowLeadingWhite, DateTimeStyles.AllowTrailingWhite y DateTimeStyles.AllowInnerWhite. Para los métodos ParseExact y TryParseExact, el valor predeterminado es DateTimeStyles.None; la cadena de entrada debe corresponder precisamente a una cadena de formato de fecha y hora personalizada determinada.

Los métodos de análisis también usan implícita o explícitamente un objeto DateTimeFormatInfo que define los símbolos y patrones específicos que pueden producirse en la cadena que se van a analizar. Si no proporciona un objeto DateTimeFormatInfo, el objeto DateTimeFormatInfo de la referencia cultural actual se usa de forma predeterminada. Para obtener más información sobre el análisis de cadenas de fecha y hora, consulte los métodos de análisis individuales, como DateTime.Parse, DateTime.TryParse, DateTimeOffset.ParseExact y DateTimeOffset.TryParseExact.

En el siguiente ejemplo se muestra la naturaleza sensible a la referencia cultural de analizar cadenas de fecha y hora. Intenta analizar dos cadenas de fecha mediante las convenciones de las referencias culturales en-US, en-GB, fr-FR y fi-FI. La fecha que se interpreta como 18/8/2014 en la referencia cultural en-US produce una excepción FormatException en las otras tres referencias culturales porque 18 se interpreta como el número de mes. 2/1/2015 se analiza como el segundo día del primer mes en la cultura en-US, pero como primer día del segundo mes en las referencias culturales restantes.

using System;
using System.Globalization;

public class ParseEx1
{
    public static void Main()
    {
        string[] dateStrings = { "08/18/2014", "01/02/2015" };
        string[] cultureNames = { "en-US", "en-GB", "fr-FR", "fi-FI" };

        foreach (var cultureName in cultureNames)
        {
            CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName);
            Console.WriteLine("Parsing strings using the {0} culture.",
                              culture.Name);
            foreach (var dateStr in dateStrings)
            {
                try
                {
                    Console.WriteLine(String.Format(culture,
                                      "   '{0}' --> {1:D}", dateStr,
                                      DateTime.Parse(dateStr, culture)));
                }
                catch (FormatException)
                {
                    Console.WriteLine("   Unable to parse '{0}'", dateStr);
                }
            }
        }
    }
}
// The example displays the following output:
//       Parsing strings using the en-US culture.
//          '08/18/2014' --> Monday, August 18, 2014
//          '01/02/2015' --> Friday, January 02, 2015
//       Parsing strings using the en-GB culture.
//          Unable to parse '08/18/2014'
//          '01/02/2015' --> 01 February 2015
//       Parsing strings using the fr-FR culture.
//          Unable to parse '08/18/2014'
//          '01/02/2015' --> dimanche 1 février 2015
//       Parsing strings using the fi-FI culture.
//          Unable to parse '08/18/2014'
//          '01/02/2015' --> 1. helmikuuta 2015

Normalmente, las cadenas de fecha y hora se analizan por dos motivos:

  • Para convertir la entrada del usuario en un valor de fecha y hora.
  • Para recorrer de ida y vuelta un valor de fecha y hora; es decir, para deserializar un valor de fecha y hora que se serializó previamente como una cadena.

En las siguientes secciones se describen estas dos operaciones con mayor detalle.

Análisis de cadenas de usuario

Al analizar las cadenas de fecha y hora que escribe el usuario, siempre debe crear una instancia de un objeto DateTimeFormatInfo que refleje la configuración cultural del usuario, incluidas las personalizaciones que el usuario haya realizado. De lo contrario, el objeto de fecha y hora puede tener valores incorrectos. Para obtener información sobre cómo crear instancias de un objeto DateTimeFormatInfo que refleje las personalizaciones culturales del usuario, consulte la sección DateTimeFormatInfo y datos dinámicos.

En el siguiente ejemplo se muestra la diferencia entre una operación de análisis que refleja la configuración cultural del usuario y otra que no lo hace. En este caso, la referencia cultural predeterminada del sistema es en-US, pero el usuario ha usado Panel de control, Región e Idioma para cambiar el patrón de fecha corta de su valor predeterminado de "M/d/aaaa" a "aaaa/MM/dd". Cuando el usuario escribe una cadena que refleja la configuración del usuario y la cadena se analiza mediante un objeto DateTimeFormatInfo que también refleja la configuración del usuario (invalidaciones), la operación de análisis devuelve un resultado correcto. Sin embargo, cuando un objeto DateTimeFormatInfo analiza la cadena que refleja la configuración cultural estándar en-US, el método de análisis produce una excepción FormatException porque interpreta 14 como el número del mes, no los dos últimos dígitos del año.

using System;
using System.Globalization;

public class ParseEx2
{
    public static void Main()
    {
        string inputDate = "14/05/10";

        CultureInfo[] cultures = { CultureInfo.GetCultureInfo("en-US"),
                                 CultureInfo.CreateSpecificCulture("en-US") };

        foreach (var culture in cultures)
        {
            try
            {
                Console.WriteLine("{0} culture reflects user overrides: {1}",
                                  culture.Name, culture.UseUserOverride);
                DateTime occasion = DateTime.Parse(inputDate, culture);
                Console.WriteLine("'{0}' --> {1}", inputDate,
                                  occasion.ToString("D", CultureInfo.InvariantCulture));
            }
            catch (FormatException)
            {
                Console.WriteLine("Unable to parse '{0}'", inputDate);
            }
            Console.WriteLine();
        }
    }
}
// The example displays the following output:
//       en-US culture reflects user overrides: False
//       Unable to parse '14/05/10'
//
//       en-US culture reflects user overrides: True
//       '14/05/10' --> Saturday, 10 May 2014

Serialización y deserialización de datos de fecha y hora

Se espera que los datos serializados de fecha y hora sean de ida y vuelta; es decir, todos los valores serializados y deserializados deben ser idénticos. Si un valor de fecha y hora representa un solo momento en el tiempo, el valor deserializado debe representar el mismo momento en el tiempo, independientemente de la referencia cultural o zona horaria del sistema en el que se restauró. Para realizar correctamente los datos de fecha y hora de ida y vuelta, debe usar las convenciones de la referencia cultural invariable, que devuelve la propiedad InvariantInfo, para generar y analizar los datos. Las operaciones de formato y análisis nunca deben reflejar las convenciones de la referencia cultural predeterminada. Si usa la configuración cultural predeterminada, la portabilidad de los datos es estrictamente limitada; solo se puede deserializar correctamente en un subproceso cuya configuración específica de la cultura es idéntica a la del subproceso en el que se serializó. En algunos casos, esto significa que los datos ni siquiera se pueden serializar y deserializar correctamente en el mismo sistema.

Si el componente de hora de un valor de fecha y hora es significativo, también debe convertirse a UTC y serializarse mediante la cadena de formato estándar "o" o "r". A continuación, los datos de hora se pueden restaurar llamando a un método de análisis y pasándole la cadena de formato adecuada junto con la referencia cultural invariable como argumento provider.

En el siguiente ejemplo se muestra el proceso de ida y vuelta de un valor de fecha y hora. Serializa una fecha y hora en un sistema que observa los EE.UU. Hora del Pacífico y cuya cultura actual es en-US.

using System;
using System.Globalization;
using System.IO;

public class SerializeEx1
{
    public static void Main()
    {
        StreamWriter sw = new StreamWriter(@".\DateData.dat");
        // Define a date and time to serialize.
        DateTime originalDate = new DateTime(2014, 08, 18, 08, 16, 35);
        // Display information on the date and time.
        Console.WriteLine("Date to serialize: {0:F}", originalDate);
        Console.WriteLine("Current Culture:   {0}",
                          CultureInfo.CurrentCulture.Name);
        Console.WriteLine("Time Zone:         {0}",
                          TimeZoneInfo.Local.DisplayName);
        // Convert the date value to UTC.
        DateTime utcDate = originalDate.ToUniversalTime();
        // Serialize the UTC value.
        sw.Write(utcDate.ToString("o", DateTimeFormatInfo.InvariantInfo));
        sw.Close();
    }
}
// The example displays the following output:
//       Date to serialize: Monday, August 18, 2014 8:16:35 AM
//       Current Culture:   en-US
//       Time Zone:         (UTC-08:00) Pacific Time (US & Canada)

Deserializa los datos de un sistema en la zona horaria Bruselas, Copenhague, Madrid y París, y cuya referencia cultural actual es fr-FR. La fecha restaurada es nueve horas más tarde que la fecha original, que refleja el ajuste de zona horaria de ocho horas detrás de UTC a una hora antes de UTC. Tanto la fecha original como la fecha restaurada representan el mismo momento en el tiempo.

using System;
using System.Globalization;
using System.IO;

public class SerializeEx2
{
    public static void Main()
    {
        // Open the file and retrieve the date string.
        StreamReader sr = new StreamReader(@".\DateData.dat");
        String dateValue = sr.ReadToEnd();

        // Parse the date.
        DateTime parsedDate = DateTime.ParseExact(dateValue, "o",
                              DateTimeFormatInfo.InvariantInfo);
        // Convert it to local time.
        DateTime restoredDate = parsedDate.ToLocalTime();
        // Display information on the date and time.
        Console.WriteLine("Deserialized date: {0:F}", restoredDate);
        Console.WriteLine("Current Culture:   {0}",
                          CultureInfo.CurrentCulture.Name);
        Console.WriteLine("Time Zone:         {0}",
                          TimeZoneInfo.Local.DisplayName);
    }
}
// The example displays the following output:
//    Deserialized date: lundi 18 août 2014 17:16:35
//    Current Culture:   fr-FR
//    Time Zone:         (UTC+01:00) Brussels, Copenhagen, Madrid, Paris