Поделиться через


В этой статье приводятся дополнительные замечания к справочной документации по этому API.

Свойства DateTimeFormatInfo класса содержат культурно-специфическую информацию для форматирования или анализа значений даты и времени, таких как:

  • Шаблоны, используемые для форматирования значений дат.
  • Шаблоны, используемые для форматирования значений времени.
  • Имена дней недели.
  • Имена месяцев года.
  • Обозначения A.M. и P.M. используются в значениях времени.
  • Календарь, в котором выражаются даты.

Создание экземпляра объекта DateTimeFormatInfo

Объект DateTimeFormatInfo может представлять правила форматирования инвариантной культуры, определенной культуры, нейтральной культуры или текущей культуры. В этом разделе рассматривается процесс создания экземпляра объекта каждого типа.

Создание экземпляра объекта DateTimeFormatInfo для инвариантного языка и региональных параметров

Инвариантная культура представляет собой культуру, которая не зависит от специфических культурных параметров. Он основан на английском языке, но не на каком-либо конкретном английском языке или регионе. Хотя данные конкретных языков и региональных параметров могут быть динамическими и могут изменяться в соответствии с новыми культурными соглашениями или предпочтениями пользователей, данные инвариантного языка и региональных параметров не изменяются. Вы можете создать экземпляр DateTimeFormatInfo объекта, представляющего соглашения о форматировании инвариантной культуры следующим образом:

В следующем примере каждый из этих методов используется для создания объекта DateTimeFormatInfo, представляющего инвариантную культуру. Затем он указывает, доступен ли объект только для чтения.

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

Создать экземпляр объекта DateTimeFormatInfo для конкретной культуры

Определенная культура представляет язык, на котором говорят в конкретной стране или регионе. Например, en-US — это определенная культура, представляющая английский язык, который говорится в США, а en-CA — это определенная культура, представляющая английский язык, который говорится в Канаде. Вы можете создать экземпляр DateTimeFormatInfo объекта, представляющего соглашения о форматировании определенной культуры следующим образом:

В следующем примере показано каждое из этих способов создания экземпляра DateTimeFormatInfo объекта и указывает, доступен ли полученный объект только для чтения.

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($"{ci.Name} from CreateSpecificCulture: {dtfi.IsReadOnly}");

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

// Retrieve a culture by calling the GetCultureInfo method.
ci = System.Globalization.CultureInfo.GetCultureInfo("en-AU");
dtfi = ci.DateTimeFormat;
Console.WriteLine($"{ci.Name} from GetCultureInfo: {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($"{ci.Name} from GetInstance: {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

Создание экземпляра объекта DateTimeFormatInfo для нейтральной культуры

Нейтральная культура представляет язык или культуру, не зависящие от страны или региона; обычно это основа для одной или нескольких конкретных культур. Например, Fr является нейтральной культурой для французского языка и родительской культурой fr-FR. Вы можете создать DateTimeFormatInfo объект, представляющий соглашения о форматировании нейтральной культуры, так же как создать DateTimeFormatInfo объект, представляющий соглашения о форматировании определенной культуры. Кроме того, вы можете получить объект DateTimeFormatInfo нейтральной культуры, извлекая нейтральную культуру из свойства CultureInfo.Parent конкретной культуры и извлекая объект DateTimeFormatInfo, возвращаемый его свойством CultureInfo.DateTimeFormat. Если родительский язык и региональные параметры не представляют инвариантный язык и региональные параметры, возвращаемый DateTimeFormatInfo объект считывается или записывается. В следующем примере показано, как создать экземпляр объекта DateTimeFormatInfo, представляющего нейтральную культуру.

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($"{neutral.Name} from Parent property: {dtfi.IsReadOnly}");

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

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

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

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

// Instantiate a DateTimeFormatInfo object by calling GetInstance.
neutral = System.Globalization.CultureInfo.CreateSpecificCulture("fr");
dtfi = System.Globalization.DateTimeFormatInfo.GetInstance(neutral);
Console.WriteLine($"{neutral.Name} from GetInstance: {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

Однако нейтральная культура не содержит информации о форматировании, так как она не зависит от конкретной страны или региона. Вместо заполнения DateTimeFormatInfo объекта универсальными значениями .NET возвращает DateTimeFormatInfo объект, который отражает соглашения о форматировании конкретной культуры, являющейся дочерней культурой нейтральной культуры. Например, объект DateTimeFormatInfo для нейтральной культуры отражает правила форматирования культуры en-US, а объект DateTimeFormatInfo для культуры fr отражает правила форматирования культуры fr-FR.

Вы можете использовать такой код, чтобы определить форматирование каких конкретных культурных соглашений представляет нейтральная культура. В примере используется рефлексия для сравнения DateTimeFormatInfo свойств нейтральной культуры со свойствами определенной дочерней культуры. Он считает, что два календаря эквивалентны, если они являются одинаковыми типами календарей и для григорианских календарей, если их GregorianCalendar.CalendarType свойства имеют одинаковые значения.

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 {prop.Name} array for {name} and {ci.Name}");
                        break;
                    }

                    for (int ctr = 0; ctr < nList.Count; ctr++)
                    {
                        if (!nList[ctr].Equals(sList[ctr]))
                        {
                            match = false;
                            Console.WriteLine($"   {prop.Name} value different for {name} and {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 {name} and {ci.Name}");
                            match = false;
                            break;
                        }

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

        Console.WriteLine();
    }
}

Создайте экземпляр объекта DateTimeFormatInfo для текущей культуры

Вы можете создать объект DateTimeFormatInfo, который представлял бы соглашения о форматировании в текущей локали, следующим образом:

  • Извлекая значение CurrentInfo свойства. Возвращаемый DateTimeFormatInfo объект доступен только для чтения.

  • Извлекая значение DateTimeFormat свойства из CultureInfo объекта, возвращаемого свойством CultureInfo.CurrentCulture . Возвращаемый DateTimeFormatInfo объект доступен только для чтения.

  • Вызывая метод GetInstance с объектом CultureInfo, который представляет текущую культуру. Возвращаемый DateTimeFormatInfo объект доступен только для чтения.

В следующем примере используется каждый из этих методов для создания экземпляра объекта DateTimeFormatInfo, представляющего стандарты форматирования текущей культуры. Затем он указывает, доступен ли объект только для чтения.

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

Вы можете создать объект, доступный DateTimeFormatInfo для записи, который представляет соглашения текущего языка и региональных параметров одним из следующих способов:

  • Извлекая объект любым из трех предыдущих способов и вызывая метод Clone для возвращенного объекта DateTimeFormatInfo. При этом создается копия исходного DateTimeFormatInfo объекта, за исключением того, что его IsReadOnly свойство имеет falseзначение.

  • Вызывая CultureInfo.CreateSpecificCulture метод для создания CultureInfo объекта, представляющего текущую культуру, а затем используя его CultureInfo.DateTimeFormat свойство для получения DateTimeFormatInfo объекта.

В следующем примере показано, как создать экземпляр объекта чтения и записи DateTimeFormatInfo и отобразить значение его 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

В Windows пользователь может переопределить некоторые DateTimeFormatInfo значения свойств, используемые в операциях форматирования и синтаксического анализа с помощью приложения "Регион" и "Язык" в панель управления. Например, пользователь, язык и региональные параметры которого — английский (США) могут отображать длинные значения времени, используя 24-часовые часы (в формате HH:mm:ss) вместо 12-часовых часов (в формате h:mm:ss tt). Объекты DateTimeFormatInfo, полученные описанными ранее способами, отражают переопределения этих пользователей. Если это нежелательно, можно создать NumberFormatInfo объект, который не отражает переопределения пользователя (и является доступным для чтения и записи, а не только для чтения) путем вызова конструктора CultureInfo.CultureInfo(String, Boolean) и указания значения false для аргумента useUserOverride. В следующем примере показано это для системы, у которой текущая культура — английский (Соединенные Штаты), и у которой длинный формат времени был изменен с значения по умолчанию h:mm:ss tt на 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:      {culture.Name}");
        Console.WriteLine($"User Overrides:    {culture.UseUserOverride}");
        Console.WriteLine($"Long Time Pattern: {culture.DateTimeFormat.LongTimePattern}\n");

        culture = new CultureInfo(CultureInfo.CurrentCulture.Name, false);
        Console.WriteLine($"Culture Name:      {culture.Name}");
        Console.WriteLine($"User Overrides:    {culture.UseUserOverride}");
        Console.WriteLine($"Long Time Pattern: {culture.DateTimeFormat.LongTimePattern}\n");
    }
}
// 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

DateTimeFormatInfo и динамические данные

Данные, зависящие от культурных особенностей, для форматирования значений даты и времени, предоставляемых классом DateTimeFormatInfo, являются динамичными, как и культурные данные, предоставляемые классом CultureInfo. Не следует делать никаких предположений о стабильности значений для DateTimeFormatInfo объектов, связанных с конкретными CultureInfo объектами. Только данные, предоставляемые инвариантной культурой и связанным DateTimeFormatInfo объектом, стабильны. Другие данные могут изменяться между сеансами приложений или даже во время работы приложения. Существует четыре основных источника изменений:

  • Обновления системы. Культурные предпочтения, такие как предпочтительный календарь или обычные форматы даты и времени, меняются со временем. В этом случае Обновление Windows включает изменения DateTimeFormatInfo в значение свойства для определенной культуры.

  • Культуры замены. Класс CultureAndRegionInfoBuilder можно использовать для замены данных существующей культуры.

  • Каскадные изменения значений свойств. Некоторые свойства, связанные с культурой, могут изменяться во время выполнения, что, в свою очередь, вызывает DateTimeFormatInfo изменение данных. Например, текущую культуру можно изменить программным способом или с помощью действия пользователя. Когда это происходит, объект, возвращаемый свойством DateTimeFormatInfo, изменяется на объект, связанный с текущей культурой. Аналогичным образом календарь культуры может измениться, что может привести к изменению многочисленных DateTimeFormatInfo значений свойств.

  • Параметры пользователя. Пользователи вашего приложения могут переопределить некоторые значения, связанные с текущими языковыми и региональными параметрами системы, с помощью региональных и языковых параметров в Панель управления. Например, пользователи могут выбрать отображение даты в другом формате. CultureInfo.UseUserOverride Если для свойства задано trueзначение, свойства DateTimeFormatInfo объекта также извлекаются из параметров пользователя. Если параметры пользователя несовместимы с культурой, связанной с объектом CultureInfo (например, если выбранный календарь не является одним из календарей, указанных в свойстве OptionalCalendars), результаты методов и значения свойств не определены.

Чтобы свести к минимуму возможность несогласованных данных, все свойства DateTimeFormatInfo объекта, которые могут быть изменены пользователем, инициализируются при его создании. По-прежнему существует вероятность несоответствия, поскольку ни создание объекта, ни процесс переопределения пользователем не являются атомарными, а соответствующие значения могут изменяться во время создания объекта. Однако эта ситуация должна быть крайне редкой.

Вы можете контролировать, отражаются ли пользовательские переопределения в DateTimeFormatInfo объектах, представляющих ту же культуру, что и системная. В следующей таблице перечислены способы извлечения объекта с помощью DateTimeFormatInfo, а также указывается, отражает ли результирующий объект пользовательские переопределения.

Источник объекта CultureInfo и DateTimeFormatInfo Отражает изменения, внесённые пользователями
Свойство CultureInfo.CurrentCulture.DateTimeFormat Да
Свойство DateTimeFormatInfo.CurrentInfo Да
CultureInfo.CreateSpecificCultureМетод Да
CultureInfo.GetCultureInfoМетод Нет
Конструктор CultureInfo.CultureInfo(String) Да
Конструктор CultureInfo.CultureInfo(String, Boolean) Зависит от значения useUserOverride параметра

Если нет убедительных причин поступать иначе, следует соблюдать переопределения пользователей при использовании объекта DateTimeFormatInfo в клиентских приложениях для форматирования и анализа входных данных пользователей или отображения данных. Для серверных или необслуживаемых приложений это делать не следует. Однако, если вы используете объект DateTimeFormatInfo явно или неявно для сохранения данных даты и времени в строковой форме, следует либо использовать объект DateTimeFormatInfo, который отражает соглашения о форматировании инвариантной культуры, либо указать настраиваемую строку формата даты и времени, которая используется независимо от культуры.

Форматирование дат и времени

DateTimeFormatInfo Объект используется неявно или явно во всех операциях форматирования даты и времени. К ним относятся вызовы следующих методов:

Все операции форматирования даты и времени используют реализацию IFormatProvider . Интерфейс IFormatProvider включает один метод. IFormatProvider.GetFormat(Type) Этот метод обратного вызова получает объект Type, представляющий тип, необходимый для предоставления сведений о форматировании. Метод возвращает либо экземпляр этого типа, либо null если он не может предоставить экземпляр типа. .NET включает две IFormatProvider реализации для форматирования дат и времени:

  • Класс CultureInfo, представляющий определенную культуру (или определенный язык в конкретной стране или регионе). В операции форматирования даты и времени метод возвращает объект CultureInfo.GetFormat, который связан с его свойством CultureInfo.DateTimeFormat.
  • Класс DateTimeFormatInfo, предоставляющий сведения о соглашениях форматирования соответствующей культуры. Метод DateTimeFormatInfo.GetFormat возвращает экземпляр самого класса.

IFormatProvider Если реализация явно не предоставляется методу форматирования, используется объект CultureInfo, возвращаемый свойством CultureInfo.CurrentCulture, представляющим текущий язык и региональные параметры.

В следующем примере показана связь между интерфейсом IFormatProvider и DateTimeFormatInfo классом в операциях форматирования. Он определяет пользовательскую IFormatProvider реализацию, метод которой GetFormat отображает тип объекта, запрошенного операцией форматирования. Если запрашивается DateTimeFormatInfo объект, метод предоставляет DateTimeFormatInfo объект для текущей культуры. Как показано в выходных данных из примера, метод Decimal.ToString(IFormatProvider) запрашивает объект DateTimeFormatInfo для предоставления сведений о форматировании, в то время как метод String.Format(IFormatProvider, String, Object[]) запрашивает объекты NumberFormatInfo и DateTimeFormatInfo, а также реализацию ICustomFormatter.

using System;
using System.Globalization;

public class CurrentCultureFormatProvider : IFormatProvider
{
    public Object GetFormat(Type formatType)
    {
        Console.WriteLine($"Requesting an object of type {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

Форматирование строк и свойств DateTimeFormatInfo

Объект DateTimeFormatInfo включает три типа свойств, которые используются в операциях форматирования со значениями даты и времени:

  • Свойства, связанные с календарем. Такие свойства, как AbbreviatedDayNames, AbbreviatedMonthNames, DayNames, и MonthNames, связаны с календарем, который используется в данной культуре и определяется свойством Calendar. Эти свойства используются для длинных форматов дат и времени.

  • Свойства, которые создают определяемую стандартами строку результата. Свойства RFC1123Pattern, SortableDateTimePattern и UniversalSortableDateTimePattern содержат пользовательские строки форматирования, которые создают результирующие строки, определенные международными стандартами. Эти свойства доступны только для чтения и не могут быть изменены.

  • Свойства, определяющие строки результатов с учетом языка и региональных параметров. Некоторые свойства, такие как FullDateTimePattern и, содержат ShortDatePattern форматирования, которые указывают формат строки результата. Другие, такие как AMDesignator, DateSeparator, PMDesignator и TimeSeparator, определяют символы или подстроки, чувствительные к культурным особенностям, которые можно включить в результирующую строку.

Стандартные строки формата даты и времени, такие как "d", "D", "f" и "F", являются псевдонимами, соответствующими определенным DateTimeFormatInfo свойствам шаблона формата. Большинство строк пользовательского формата даты и времени связаны со строками или подстроками, которые операция форматирования вставляет в результирующий поток. В следующей таблице перечислены стандартные и настраиваемые описатели формата даты и времени и связанные DateTimeFormatInfo с ними свойства. Дополнительные сведения об использовании этих описателей формата см. в разделе "Стандартные строки формата даты и времени" и "Настраиваемые строки формата даты и времени". Обратите внимание, что каждая строка стандартного DateTimeFormatInfo формата соответствует свойству, значение которого является настраиваемой строкой формата даты и времени. Отдельные описатели в этой строке настраиваемого формата, в свою очередь, соответствуют другим DateTimeFormatInfo свойствам. В таблице перечислены только те свойства DateTimeFormatInfo, для которых стандартные строки формата выступают в качестве псевдонимов, и не включены свойства, к которым обращаются пользовательские строки формата, назначенные этим псевдонимам. Кроме того, в таблице перечислены только настраиваемые описатели формата, соответствующие DateTimeFormatInfo свойствам.

Спецификатор формата Связанные свойства
"d" (короткая дата; строка стандартного формата) ShortDatePattern, чтобы определить общий формат строки результата.
"D" (длинная дата; строка стандартного формата) LongDatePattern, чтобы определить общий формат строки результата.
"f" (полная дата / короткое время; стандартная строка форматирования) LongDatePattern, чтобы определить формат компонента даты результирующих строк.

ShortTimePattern, чтобы определить формат компонента времени результирующих строк.
"F" (полная дата / долгое время; строка стандартного формата) LongDatePattern, чтобы определить формат компонента даты результирующих строк.

LongTimePattern, чтобы определить формат компонента времени результирующих строк.
"g" (общая дата / короткое время; строка стандартного формата) ShortDatePattern, чтобы определить формат компонента даты результирующих строк.

ShortTimePattern, чтобы определить формат компонента времени результирующих строк.
"G" (общая дата/ долгое время; строка стандартного формата) ShortDatePattern, чтобы определить формат компонента даты результирующих строк.

LongTimePattern, чтобы определить формат компонента времени результирующих строк.
"M", "m" (месяц/день; стандартная строка формата) MonthDayPattern, чтобы определить общий формат строки результата.
"O", "o" (дата и время кругового пути; строка стандартного формата) Нет.
"R", "r" (RFC1123; строка стандартного формата) RFC1123Pattern, чтобы определить строку результатов, соответствующую стандарту RFC 1123. свойство доступно только для чтения.
"s" (сортировка даты и времени; строка стандартного формата) SortableDateTimePattern, чтобы определить строку результатов, соответствующую стандарту ISO 8601. свойство доступно только для чтения.
"t" (короткое время; строка стандартного формата) ShortTimePattern, чтобы определить общий формат строки результата.
"T" (долгое время; строка стандартного формата) LongTimePattern, чтобы определить общий формат строки результата.
"u" (универсальная сортировка даты и времени; стандартная строка форматирования) UniversalSortableDateTimePattern, чтобы определить строку результатов, соответствующую стандарту ISO 8601 для согласованного универсального времени. свойство доступно только для чтения.
"U" (универсальная полная дата и время; строка стандартного формата) FullDateTimePattern, чтобы определить общий формат строки результата.
"Y", "y" (месяц года; стандартная строка формата) YearMonthPattern, чтобы определить общий формат строки результата.
"ddd" (настраиваемый описатель формата) AbbreviatedDayNames, чтобы включить сокращенное имя дня недели в результирующем строке.
"g", "gg" (настраиваемый описатель формата) GetEraName Вызывает метод для вставки имени эры в результируемую строку.
MMM (описатель пользовательского формата) AbbreviatedMonthNames или AbbreviatedMonthGenitiveNames, чтобы включить сокращенное имя месяца в строку результата.
MMMM (описатель пользовательского формата) MonthNames или MonthGenitiveNames, чтобы включить полное имя месяца в строку результата.
"t" (спецификатор пользовательского формата) AMDesignator или PMDesignator, для включения первого символа обозначения AM/PM в строку результата.
"tt" (описатель пользовательского формата) AMDesignator или PMDesignator, чтобы включить полное обозначение AM/PM в строку результата.
":" (описатель пользовательского формата) TimeSeparator, чтобы включить разделитель времени в результирующую строку.
"/" (описатель пользовательского формата) DateSeparator, чтобы включить разделитель даты в результирующую строку.

Изменение свойств DateTimeFormatInfo

Вы можете изменить строку результатов, созданную строками формата даты и времени, изменив связанные свойства записываемого DateTimeFormatInfo объекта. Чтобы определить, является ли DateTimeFormatInfo объект записываемым, используйте IsReadOnly свойство. Чтобы настроить DateTimeFormatInfo объект таким образом, выполните указанные ниже действия.

  1. Создайте копию объекта DateTimeFormatInfo с возможностью чтения и записи, соглашения о форматировании которого необходимо изменить.

  2. Измените свойство или свойства, используемые для создания требуемой строки результата. (Сведения о том, как методы форматирования используют DateTimeFormatInfo свойства для определения строк результатов, см. в предыдущем разделе, Формат строк и свойства DateTimeFormatInfo.)

  3. Используйте пользовательский DateTimeFormatInfo объект, созданный в качестве аргумента IFormatProvider в вызовах методов форматирования.

Существует два других способа изменить формат результирующих строк:

  • Класс CultureAndRegionInfoBuilder можно использовать для определения пользовательской культуры (культуры, которая имеет уникальное имя и дополняет существующие культуры) или замещающей культуры (которая используется вместо конкретной культуры). Вы можете сохранять и получать доступ к этой культуре программно, как и к любому объекту CultureInfo, поддерживаемому .NET.

  • Если результируемая строка не учитывает язык и региональные параметры и не соответствует заданному формату, можно использовать настраиваемую строку формата даты и времени. Например, если вы сериализуете данные даты и времени в формате YYYYMMDDHHmmss, можно создать строку результата, передав строку настраиваемого формата DateTime.ToString(String) в метод, и можно преобразовать строку результата обратно в DateTime значение, вызвав DateTime.ParseExact метод.

Изменение шаблона короткой даты

В следующем примере изменяется формат строки результата, созданной строкой стандартного формата "d" (short date). Он изменяет связанное ShortDatePattern свойство для языка en-US или английского (США) со значения по умолчанию "M/d/yyyy" на "yyyy'-"MM"-"dd" и использует стандартную строку формата "d" для отображения даты как до изменения 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($"{dtfi.ShortDatePattern}: {dateValue.ToString("d", enUS)}\n");

        // Modify the short date pattern.
        dtfi.ShortDatePattern = "yyyy-MM-dd";
        Console.WriteLine("After modifying DateTimeFormatInfo object: ");
        Console.WriteLine($"{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

Изменение символа разделителя дат

В следующем примере изменяется символ разделителя даты в объекте DateTimeFormatInfo, который представляет соглашения о форматировании культуры fr-FR. В примере используется строка стандартного формата "g" для отображения даты как до, так и после 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: {dateValue.ToString("g", frFR)}");

        // Modify the date separator.
        dtfi.DateSeparator = "-";
        Console.WriteLine($"After modifying the DateSeparator property: {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

Изменение аббревиаций имени дня и шаблона длинной даты

В некоторых случаях шаблон длинной даты, который обычно отображает полное название дня и месяца вместе с числом дня месяца и года, может быть слишком длинным. В следующем примере сокращается шаблон длинной даты для культуры en-US, чтобы вернуть сокращенное название дня из одной или двух букв, за которым следуют число, сокращенное название месяца и год. Это делается путем назначения более коротких названий дней массиву AbbreviatedDayNames, а также изменения строки настраиваемого формата, назначенной свойству LongDatePattern. Это влияет на строки результатов, возвращаемые строками стандартного формата "D" и "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($"{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($"{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

Как правило, изменение LongDatePattern свойства также влияет на FullDateTimePattern свойство, которое, в свою очередь, определяет строку результата, возвращаемую строкой стандартного формата F. Чтобы сохранить исходный шаблон полной даты и времени, пример переназначает исходную строку пользовательского формата, назначенную свойству FullDateTimePattern, после того как свойство LongDatePattern было изменено.

Изменение с 12-часовых часов на 24-часовые часы

Для многих культур в .NET время выражается с помощью 12-часового формата и указателя AM/PM. В следующем примере определяется ReplaceWith24HourClock метод, который заменяет любой формат времени, использующий 12-часовые часы форматом, использующим 24-часовые часы.

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

В примере используется регулярное выражение для изменения строки форматирования. Шаблон @"^(?<openAMPM>\s*t+\s*)? (?(openAMPM) h+(?<nonHours>[^ht]+)$ | \s*h+(?<nonHours>[^ht]+)\s*t+) регулярного выражения определяется следующим образом:

Расписание Описание
^ Начните совпадение с начала строки.
(?<openAMPM>\s*t+\s*)? Соответствует нулю или одному вхождению одного или нескольких пробельных символов, за которым следует буква "t" один или несколько раз, за которой могут идти ноль или несколько пробельных символов. Эта группа записи называется openAMPM.
(?(openAMPM) h+(?<nonHours>[^ht]+)$ Если в группе openAMPM найдено совпадение, ищите букву "h" один или несколько раз, за которой следуют один или несколько символов, которые не являются ни "h", ни "t". Совпадение заканчивается в конце строки. Все символы, захваченные после "h", включаются в группу записи с именем nonHours.
&#124; \s*h+(?<nonHours>[^ht]+)\s*t+) openAMPM Если у группы нет совпадений, совпадает буква "h" один или несколько раз, а затем один или несколько символов, которые не являются "h" или "t", за которым следует ноль или более пробелов. Наконец, совпадает с одним или несколькими появлениями буквы "t". Все символы, захваченные после "h" и до пробелов и t, включаются в группу записи с именем nonHours.

Группа nonHours записи содержит минуту и, возможно, второй компонент настраиваемой строки формата даты и времени, а также символы разделителя времени. Шаблон замены HH${nonHours} добавляет подстроку "HH" к этим элементам.

Отображение и изменение эпохи в дате

В следующем примере в свойство LongDatePattern объекта, представляющего соглашения о форматировании в культуре en-US, добавляется спецификатор пользовательского формата "g". Это дополнение влияет на следующие три стандартные строки формата:

  • Строка стандартного формата "D" (long date), которая сопоставляется непосредственно с свойством LongDatePattern .

  • Строка стандартного формата "f" (полная дата или короткое время), которая создает строку результата, которая объединяет подстроки, созданные свойствами LongDatePattern и ShortTimePattern свойствами.

  • Строка стандартного формата "F" (полная дата или долгое время), которая сопоставляется непосредственно с свойством FullDateTimePattern . Так как мы явно не задали это значение свойства, он создается динамически путем объединения LongDatePattern свойств и LongTimePattern свойств.

В примере также показано, как изменить имя эпохи для культуры, календарь которого имеет одну эру. В этом случае культура en-US использует григорианский календарь, который представлен объектом GregorianCalendar. Класс GregorianCalendar поддерживает одну эру, которая называется A.D. (Anno Domini). Пример изменяет имя эры на C.E. (Common Era), заменив описатель пользовательского формата g в строке формата, назначенной FullDateTimePattern свойству литеральной строкой. Необходимо использовать литеральную строку, так как имя эпохи обычно возвращается методом GetEraName из приватных данных в таблицах культур, предоставляемых .NET или операционной системой.

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

Анализ строк даты и времени

Синтаксический анализ включает преобразование строкового представления даты и времени в DateTime или DateTimeOffset значение. Оба этих типа включают методы Parse, TryParse, ParseExact и TryParseExact для поддержки операций синтаксического анализа. Методы Parse и TryParse преобразуют строку, которая может иметь различные форматы, в то время как методы ParseExact и TryParseExact требуют, чтобы строка имела определенный формат или форматы. Если операция синтаксического анализа завершается ошибкой, Parse и ParseExact выбрасывают исключение, тогда как TryParse и TryParseExact возвращают false.

Методы синтаксического анализа неявно или явно используют DateTimeStyles значение перечисления, чтобы определить, какие элементы стиля (например, начальные, конечные или внутренние пробелы) могут присутствовать в строке для анализа, а также как интерпретировать разобранную строку или любые отсутствующие элементы. Если вы не указываете значение DateTimeStyles при вызове метода Parse или TryParse, по умолчанию используется DateTimeStyles.AllowWhiteSpaces, что является составным стилем, включающим флаги DateTimeStyles.AllowLeadingWhite, DateTimeStyles.AllowTrailingWhite и DateTimeStyles.AllowInnerWhite. Для методов ParseExact и TryParseExact используется значение DateTimeStyles.None по умолчанию; входная строка должна точно соответствовать определенному пользовательскому формату строки даты и времени.

Методы синтаксического анализа также неявно или явно используют DateTimeFormatInfo объект, определяющий определенные символы и шаблоны, которые могут возникать в строке для анализа. Если вы не предоставите объект DateTimeFormatInfo, по умолчанию используется объект DateTimeFormatInfo для текущей культуры. Дополнительные сведения о синтаксическом анализе строк даты и времени см. в отдельных методах синтаксического анализа, таких как DateTime.Parse, DateTime.TryParseи DateTimeOffset.ParseExactDateTimeOffset.TryParseExact.

В следующем примере показан характер анализа строк даты и времени с учетом языка и региональных параметров. Он пытается разобрать две строки даты, используя форматы культур en-US, en-GB, fr-FR и fi-FI. Дата, интерпретируемая как 8/18/2014 в языковых и региональных параметрах en-US, вызывает FormatException исключение в других трех языковых и региональных параметрах, так как 18 трактуется как номер месяца. 1/2.2015 анализируется как второй день первого месяца в культуре en-US, но как первый день второго месяца в остальных культурах.

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 {culture.Name} culture.");
            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 '{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

Строки даты и времени обычно анализируются по двум причинам:

  • Преобразование входных данных пользователя в значение даты и времени.
  • Для обхода значения даты и времени; То есть для десериализации значения даты и времени, ранее сериализованного в виде строки.

В следующих разделах подробно рассматриваются эти две операции.

Анализ строк пользователей

При синтаксическом анализе строк даты и времени, введенных пользователем, всегда следует создать экземпляр DateTimeFormatInfo объекта, который отражает культурные параметры пользователя, включая любые настройки, которые пользователь мог сделать. В противном случае объект даты и времени может иметь неправильные значения. См. раздел DateTimeFormatInfo и динамических данных для получения информации о том, как создать экземпляр DateTimeFormatInfo объекта, который отражает пользовательские культурные настройки.

В следующем примере показано различие между операцией синтаксического анализа, которая отражает культурные настройки пользователя, и той, которая их не отражает. В этом случае системные языковые параметры по умолчанию — en-US, однако пользователь использовал Панель управления, Регион и язык, чтобы изменить краткий шаблон даты с шаблона по умолчанию "M/d/гггг" на "гг/ММ/дд". Когда пользователь вводит строку, которая отражает параметры пользователя, и строка анализируется объектом, который также отражает параметры пользователя (переопределяет), операция синтаксического DateTimeFormatInfo анализа возвращает правильный результат. Однако при разборе строки объектом, который соответствует стандартным культурным и региональным параметрам en-US, метод синтаксического DateTimeFormatInfo анализа вызывает FormatException исключение, так как он интерпретирует 14 как число месяца, а не последние две цифры года.

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($"{culture.Name} culture reflects user overrides: {culture.UseUserOverride}");
                DateTime occasion = DateTime.Parse(inputDate, culture);
                Console.WriteLine($"'{inputDate}' --> {occasion.ToString("D", CultureInfo.InvariantCulture)}");
            }
            catch (FormatException)
            {
                Console.WriteLine($"Unable to parse '{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

Сериализация и десериализация данных даты и времени

Сериализованные данные даты и времени, как ожидается, будут циклизированы; То есть все сериализованные и десериализированные значения должны совпадать. Если значение даты и времени представляет собой единичный момент времени, десериализированное значение должно отражать тот же момент времени, независимо от языковых и региональных параметров или часового пояса той системы, на которой оно было восстановлено. Для успешного полного переноса данных даты и времени необходимо использовать соглашения инвариантной культуры, которые возвращаются свойством InvariantInfo, для генерации и разбора данных. Операции форматирования и синтаксического анализа никогда не должны отражать соглашения региональных стандартов по умолчанию. Если вы используете параметры культуры по умолчанию, переносимость данных строго ограничена; она может быть успешно десериализирована только в потоке, параметры которого соответствуют параметрам, зависящим от культуры, идентичным параметрам потока, на котором она была сериализована. В некоторых случаях это означает, что данные даже не могут быть успешно сериализованы и десериализированы в той же системе.

Если компонент времени значения даты и времени имеет значительное значение, его также следует преобразовать в формате UTC и сериализовать с помощью строки стандартного формата "o" или "r". Затем данные времени можно восстановить, вызвав метод парсинга и передав соответствующую строку формата с использованием инвариантной языковой культуры в качестве аргумента provider.

В следующем примере показано, как обойти значение даты и времени. Сериализует дату и время в системе, настроенной на тихоокеанское время США и с текущей языковой и региональной настройкой 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: {originalDate:F}");
        Console.WriteLine($"Current Culture:   {CultureInfo.CurrentCulture.Name}");
        Console.WriteLine($"Time Zone:         {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)

Он десериализует данные в системе в зоне времени Брюсселя, Копенгагена, Мадрида и Парижа, а текущая культура — fr-FR. Восстановленная дата на девять часов позже исходной даты, что отражает корректировку часового пояса от восьми часов позади относительно UTC до одного часа впереди UTC. Исходная дата и восстановленная дата представляют один и тот же момент времени.

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: {restoredDate:F}");
        Console.WriteLine($"Current Culture:   {CultureInfo.CurrentCulture.Name}");
        Console.WriteLine($"Time Zone:         {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