Freigeben über


DateTimeFormatInfo-Klasse

Dieser Artikel enthält ergänzende Hinweise zur Referenzdokumentation für diese API.

Die Eigenschaften der DateTimeFormatInfo-Klasse enthalten kulturspezifische Informationen zum Formatieren oder Analysieren von Datums- und Uhrzeitwerten. Beispiele:

  • Muster zum Formatieren von Datumswerten
  • Muster zum Formatieren von Uhrzeitwerten
  • Namen der Wochentage
  • Namen der Monate eines Jahres
  • Die A.M.- und P.M.-Kennzeichner, die in Uhrzeitwerten verwendet werden
  • Kalender, in dem Datumsangaben ausgedrückt werden

Instanziieren eines DateTimeFormatInfo-Objekts

Ein DateTimeFormatInfo-Objekt kann die Formatierungskonventionen der invarianten Kultur, einer spezifischen Kultur, einer neutralen Kultur oder der aktuellen Kultur darstellen. In diesem Abschnitt wird erläutert, wie Sie die einzelnen DateTimeFormatInfo-Objekttypen instanziieren.

Instanziieren eines DateTimeFormatInfo-Objekts für die invariante Kultur

Die invariante Kultur stellt eine Kultur dar, die kulturunabhängig ist. Sie basiert auf der Sprache „Englisch“, aber nicht auf einem bestimmten englischsprachigen Land bzw. einer bestimmten englischsprachigen Region. Obwohl die Daten spezifischer Kulturen dynamisch sind und geändert werden können, um neue kulturelle Konventionen oder Benutzerpräferenzen widerzuspiegeln, ändern sich die Daten der invarianten Kultur nicht. Sie können ein DateTimeFormatInfo-Objekt, das die Formatierungskonventionen der invarianten Kultur darstellt, wie folgt instanziieren:

Im folgenden Beispiel wird jede dieser Methoden verwendet, um ein DateTimeFormatInfo-Objekt zu instanziieren, das die invariante Kultur darstellt. Anschließend wird angegeben, ob das Objekt schreibgeschützt ist.

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

Instanziieren eines DateTimeFormatInfo-Objekts für eine spezifische Kultur

Eine spezifische Kultur stellt eine Sprache dar, die in einem bestimmten Land bzw. einer bestimmten Region gesprochen wird. Beispielsweise steht „en-US“ für eine spezifische Kultur, die die in den USA gesprochene englische Sprache darstellt. „en-CA“ ist eine spezifische Kultur, die die in Kanada gesprochene englische Sprache darstellt. Sie können ein DateTimeFormatInfo-Objekt, das die Formatierungskonventionen einer spezifischen Kultur darstellt, wie folgt instanziieren:

Das folgende Beispiel veranschaulicht jede dieser Methoden zum Instanziieren eines DateTimeFormatInfo-Objekts und gibt an, ob das resultierende Objekt schreibgeschützt ist.

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

Instanziieren eines DateTimeFormatInfo-Objekts für eine neutrale Kultur

Eine neutrale Kultur stellt eine Kultur oder Sprache dar, die unabhängig von einem Land bzw. einer Region ist. Hierbei handelt es sich in der Regel um die übergeordnete Kultur einer oder mehrerer spezifischen Kulturen. Beispielsweise ist "fr" eine neutrale Kultur für die Sprache „Französisch“ und die übergeordnete Kultur der Kultur "fr-FR". Sie können ein DateTimeFormatInfo-Objekt, das die Formatierungskonventionen einer neutralen Kultur darstellt, auf die gleiche Weise instanziieren, wie Sie ein DateTimeFormatInfo-Objekt erstellen, das die Formatierungskonventionen einer spezifischen Kultur darstellt. Darüber hinaus können Sie das DateTimeFormatInfo-Objekt einer neutralen Kultur abrufen, indem Sie eine neutrale Kultur über die CultureInfo.Parent-Eigenschaft einer spezifischen Kultur und das von der CultureInfo.DateTimeFormat-Eigenschaft zurückgegebene DateTimeFormatInfo-Objekt abrufen. Sofern die übergeordnete Kultur nicht die invariante Kultur darstellt, ist das zurückgegebene DateTimeFormatInfo-Objekt nicht lese- oder schreibgeschützt. Das folgende Beispiel veranschaulicht diese Methoden zum Instanziieren eines DateTimeFormatInfo-Objekts, das eine neutrale Kultur darstellt.

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

Einer neutralen Kultur fehlen jedoch kulturspezifische Formatierungsinformationen, da sie unabhängig von einem bestimmten Land bzw. einer bestimmten Region ist. Anstatt das DateTimeFormatInfo-Objekt mit generischen Werten zu füllen, gibt .NET ein DateTimeFormatInfo-Objekt zurück, das die Formatierungskonventionen einer spezifischen Kultur widerspiegelt, die eine untergeordnete Kultur der neutralen Kultur ist. Beispielsweise spiegelt das DateTimeFormatInfo-Objekt für die neutrale Kultur "en" die Formatierungskonventionen der Kultur "en-US" wider, und das DateTimeFormatInfo-Objekt für die Kultur "fr" spiegelt die Formatierungskonventionen der Kultur "fr-FR" wider.

Sie können Code wie den folgenden verwenden, um zu bestimmen, welche Formatierungskonventionen einer spezifischen Kultur eine neutrale Kultur darstellt. Im Beispiel wird die Reflexion verwendet, um die DateTimeFormatInfo-Eigenschaften einer neutralen Kultur mit den Eigenschaften einer untergeordneten spezifischen Kultur zu vergleichen. Dabei werden zwei Kalender als gleichwertig betrachtet, wenn sie denselben Kalendertyp aufweisen und (bei gregorianischen Kalendern) identische Werte für die GregorianCalendar.CalendarType-Eigenschaft aufweisen.

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();
    }
}

Instanziieren eines DateTimeFormatInfo-Objekts für die aktuelle Kultur

Sie können ein DateTimeFormatInfo-Objekt, das die Formatierungskonventionen der aktuellen Kultur darstellt, wie folgt instanziieren:

Im folgenden Beispiel wird jede dieser Methoden verwendet, um ein DateTimeFormatInfo-Objekt zu instanziieren, das die Formatierungskonventionen der aktuellen Kultur darstellt. Anschließend wird angegeben, ob das Objekt schreibgeschützt ist.

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

Sie können ein schreibbares DateTimeFormatInfo-Objekt, das die Konventionen der aktuellen Kultur darstellt, auf eine der folgenden Arten erstellen:

Das folgende Beispiel veranschaulicht jede Art der Instanziierung nicht lese- oder schreibgeschützten DateTimeFormatInfo-Objekts, und der Wert der IsReadOnly-Eigenschaft wird angezeigt.

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

Unter Windows können Benutzer*innen einige der DateTimeFormatInfo-Eigenschaftswerte, die in Formatierungs- und Analysevorgängen verwendet werden, über die Anwendung Sprache und Region in der Systemsteuerung außer Kraft setzen. Benutzer*innen, deren Kultur beispielsweise „Englisch (USA)“ entspricht, verwenden möglicherweise das 24-Stunden-Format (HH:mm:ss) anstelle des 12-Stunden-Formats (h:mm:ss tt) für die lange Uhrzeitangabe. Die DateTimeFormatInfo-Objekte, die wie zuvor beschrieben abgerufen wurden, spiegeln diese benutzerdefinierten Außerkraftsetzungen wider. Wenn dies nicht erwünscht ist, können Sie ein NumberFormatInfo-Objekt erstellen, das keine benutzerdefinierte Außerkraftsetzung widerspiegelt (und auch nicht lese- oder schreibgeschützt ist, anstatt schreibgeschützt zu sein), indem Sie den CultureInfo.CultureInfo(String, Boolean)-Konstruktor aufrufen und einen false-Wert für das useUserOverride-Argument angeben. Im folgenden Beispiel wird dies für ein System veranschaulicht, dessen aktuelle Kultur „Englisch (USA)“ entspricht und dessen Muster für die lange Uhrzeitangabe von der Standardeinstellung „h:mm:ss“ in „HH:mm:ss“ geändert wurde.

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

„DateTimeFormatInfo“ und dynamische Daten

Die kulturspezifischen Daten zum Formatieren von Datums- und Uhrzeitwerten, die von der DateTimeFormatInfo-Klasse bereitgestellt werden, sind wie die von der CultureInfo-Klasse bereitgestellten Daten dynamisch. Sie sollten keine Annahmen über die Stabilität von Werten für DateTimeFormatInfo-Objekte treffen, die bestimmten CultureInfo-Objekten zugeordnet sind. Nur die Daten, die von der invarianten Kultur und dem zugeordneten DateTimeFormatInfo-Objekt bereitgestellt werden, sind stabil. Andere Daten können zwischen Anwendungssitzungen oder sogar während der Ausführung der Anwendung geändert werden. Es gibt vier wichtige Ursachen für Änderungen:

  • Systemupdates: Kultureinstellungen wie beispielsweise der bevorzugte Kalender oder die üblichen Datums- und Uhrzeitformate ändern sich im Laufe der Zeit. In diesem Fall umfasst Windows Update Änderungen im Zusammenhang mit dem DateTimeFormatInfo-Eigenschaftswert für eine bestimmte Kultur.

  • Ersatzkulturen Die CultureAndRegionInfoBuilder-Klasse kann verwendet werden, um die Daten einer vorhandenen Kultur zu ersetzen.

  • Kaskadierende Änderungen an Eigenschaftswerten Einige kulturbezogenen Eigenschaften können sich zur Laufzeit ändern, was wiederum dazu führt, dass sich DateTimeFormatInfo-Daten ändern. Beispielsweise kann die aktuelle Kultur programmgesteuert oder durch eine Benutzeraktion geändert werden. In diesem Fall ändert sich das von der CurrentInfo-Eigenschaft zurückgegebene DateTimeFormatInfo-Objekt in ein Objekt, das der aktuellen Kultur zugeordnet ist. Ebenso kann der Kalender einer Kultur geändert werden, was zu Änderungen an zahlreichen DateTimeFormatInfo-Eigenschaftswerten führen kann.

  • Benutzereinstellungen: Benutzer*innen Ihrer Anwendung können über die Regions- und Sprachoptionen in der Systemsteuerung einige der Werte außer Kraft setzen, die der aktuellen Systemkultur zugeordnet sind. Beispielsweise können sie das Datum in einem anderen Format anzeigen. Wenn die CultureInfo.UseUserOverride-Eigenschaft auf true festgelegt ist, werden die Eigenschaften des DateTimeFormatInfo-Objekts auch über die Benutzereinstellungen abgerufen. Wenn die Benutzereinstellungen nicht mit der Kultur kompatibel sind, die dem CultureInfo-Objekt zugeordnet ist (z. B. wenn der ausgewählte Kalender nicht einer der durch die OptionalCalendars-Eigenschaft angegebenen Kalender ist), sind die Ergebnisse der Methoden und die Werte der Eigenschaften nicht definiert.

Um die Wahrscheinlichkeit von inkonsistenten Daten zu minimieren, werden alle Eigenschaften eines DateTimeFormatInfo-Objekts, die von Benutzer*innen außer Kraft gesetzt werden können, bei der Erstellung des Objekts initialisiert. Es besteht nach wie vor die Möglichkeit der Inkonsistenz, da weder die Objekterstellung noch Vorgänge für benutzerdefinierte Außerkraftsetzungen atomar sind. Die relevanten Werte können während der Objekterstellung geändert werden. Dieses Szenario sollte jedoch äußerst selten sein.

Sie können steuern, ob benutzerdefinierte Außerkraftsetzungen in DateTimeFormatInfo-Objekten widergespiegelt werden, die dieselbe Kultur wie die Systemkultur darstellen. In der folgenden Tabelle sind die Methoden aufgeführt, mit denen ein DateTimeFormatInfo-Objekt abgerufen werden kann. Zudem gibt die Tabelle an, ob das resultierende Objekt benutzerdefinierte Außerkraftsetzungen widerspiegelt.

Quelle des CultureInfo- und DateTimeFormatInfo-Objekts Spiegelt benutzerdefinierte Außerkraftsetzungen wider
CultureInfo.CurrentCulture.DateTimeFormat-Eigenschaft Ja
DateTimeFormatInfo.CurrentInfo-Eigenschaft Ja
CultureInfo.CreateSpecificCulture-Methode Ja
CultureInfo.GetCultureInfo-Methode Nein
CultureInfo.CultureInfo(String)-Konstruktor Ja
CultureInfo.CultureInfo(String, Boolean)-Konstruktor Hängt vom Wert des useUserOverride-Parameters ab

Bei Verwendung des DateTimeFormatInfo-Objekts in Clientanwendungen zum Formatieren und Parsen von Benutzereingaben oder zum Anzeigen von Daten sollten Sie benutzerdefinierte Außerkraftsetzungen beachten, es sei denn, es gibt einen zwingenden Grund dies nicht zu tun. Im Zusammenhang mit Serveranwendungen oder unbeaufsichtigten Anwendungen sollten Sie diese nicht beachten. Wenn Sie das DateTimeFormatInfo-Objekt jedoch explizit oder implizit zum Speichern von Datums- und Uhrzeitdaten in Zeichenfolgenform nutzen, sollten Sie entweder ein DateTimeFormatInfo-Objekt verwenden, das die Formatierungskonventionen der invarianten Kultur widerspiegelt, oder Sie sollten eine benutzerdefinierte Datums- und Uhrzeitformatzeichenfolge angeben, die Sie unabhängig von der Kultur verwenden.

Formatieren von Datums- und Uhrzeitangaben

Ein DateTimeFormatInfo-Objekt wird implizit oder explizit in allen Datums- und Uhrzeitformatierungsvorgängen verwendet. Dazu gehören Aufrufe der folgenden Methoden:

Bei allen Datums- und Uhrzeitformatierungsvorgängen wird eine IFormatProvider-Implementierung verwendet. Die IFormatProvider-Schnittstelle enthält eine einzelne Methode (IFormatProvider.GetFormat(Type)). Dieser Rückrufmethode wird ein Type-Objekt übergeben, das den Typ darstellt, der zum Bereitstellen von Formatierungsinformationen erforderlich ist. Die Methode gibt entweder eine Instanz dieses Typs oder null zurück, wenn sie keine Instanz des Typs bereitstellen kann. .NET enthält zwei IFormatProvider-Implementierungen zum Formatieren von Datums- und Uhrzeitangaben:

Wenn eine IFormatProvider-Implementierung nicht explizit für eine Formatierungsmethode bereitgestellt wird, wird das CultureInfo-Objekt verwendet, das von der CultureInfo.CurrentCulture-Eigenschaft zurückgegeben wird, die die aktuelle Kultur darstellt.

Im folgenden Beispiel wird die Beziehung zwischen der IFormatProvider-Schnittstelle und der DateTimeFormatInfo-Klasse in Formatierungsvorgängen veranschaulicht. Dabei wird eine benutzerdefinierte IFormatProvider-Implementierung definiert, deren GetFormat-Methode den Typ des Objekts anzeigt, das vom Formatierungsvorgang angefordert wird. Wenn ein DateTimeFormatInfo-Objekt angefordert wird, stellt die Methode das DateTimeFormatInfo-Objekt für die aktuelle Kultur bereit. Wie die Ausgabe des Beispiels zeigt, fordert die Decimal.ToString(IFormatProvider)-Methode ein DateTimeFormatInfo-Objekt auf, Formatierungsinformationen bereitzustellen, während die String.Format(IFormatProvider, String, Object[])-Methode NumberFormatInfo- und DateTimeFormatInfo-Objekte sowie eine ICustomFormatter-Implementierung anfordert.

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

Formatzeichenfolgen und DateTimeFormatInfo-Eigenschaften

Das DateTimeFormatInfo-Objekt enthält drei Arten von Eigenschaften, die in Formatierungsvorgängen mit Datums- und Uhrzeitwerten verwendet werden:

Die Standardformatzeichenfolgen für das Datum und die Uhrzeit (z. B. "d", "D", "f" und "F") sind Aliase, die bestimmten DateTimeFormatInfo-Formatmustereigenschaften entsprechen. Die meisten benutzerdefinierten Formatzeichenfolgen für das Datum und die Uhrzeit beziehen sich auf Zeichenfolgen oder Teilzeichenfolgen, die im Rahmen eines Formatierungsvorgangs in den Ergebnisdatenstrom eingefügt werden. In der folgenden Tabelle sind die Standardformatspezifizierer und benutzerdefinierten Formatspezifizierer für das Datum und die Uhrzeit sowie die zugehörigen DateTimeFormatInfo-Eigenschaften aufgeführt. Ausführliche Informationen zur Verwendung dieser Formatspezifizierer finden Sie unter Standardformatzeichenfolgen für Datum und Uhrzeit und Benutzerdefinierte Formatzeichenfolgen für Datum und Uhrzeit. Beachten Sie, dass jede Standardformatzeichenfolge einer DateTimeFormatInfo-Eigenschaft entspricht, deren Wert eine benutzerdefinierte Datums- und Uhrzeitformatzeichenfolge ist. Die einzelnen Spezifizierer in dieser benutzerdefinierten Formatzeichenfolge entsprechen wiederum anderen DateTimeFormatInfo-Eigenschaften. In der Tabelle sind nur die DateTimeFormatInfo-Eigenschaften aufgeführt, für die die Standardformatzeichenfolgen Aliase sind. Es werden keine Eigenschaften genannt, auf die benutzerdefinierte Formatzeichenfolgen zugreifen können, die diesen Aliaseigenschaften zugewiesen sind. Darüber hinaus sind in der Tabelle nur benutzerdefinierte Formatspezifizierer enthalten, die DateTimeFormatInfo-Eigenschaften entsprechen.

Formatbezeichner Zugeordnete Eigenschaften
"d" (kurzes Datumsformat; Standardformatzeichenfolge) ShortDatePattern zum Definieren des Gesamtformats der Ergebniszeichenfolge
"D" (langes Datumsformat; Standardformatzeichenfolge) LongDatePattern zum Definieren des Gesamtformats der Ergebniszeichenfolge
"f" (vollständiges Datum/kurzes Uhrzeitformat; Standardformatzeichenfolge) LongDatePattern zum Definieren des Formats der Datumskomponente der Ergebniszeichenfolge

ShortTimePattern zum Definieren des Formats der Uhrzeitkomponente der Ergebniszeichenfolge
"F" (vollständiges Datum/langes Uhrzeitformat; Standardformatzeichenfolge) LongDatePattern zum Definieren des Formats der Datumskomponente der Ergebniszeichenfolge

LongTimePattern zum Definieren des Formats der Uhrzeitkomponente der Ergebniszeichenfolge
"g" (allgemeines Datum/kurzes Uhrzeitformat; Standardformatzeichenfolge) ShortDatePattern zum Definieren des Formats der Datumskomponente der Ergebniszeichenfolge

ShortTimePattern zum Definieren des Formats der Uhrzeitkomponente der Ergebniszeichenfolge
"G" (allgemeines Datum/langes Uhrzeitformat; Standardformatzeichenfolge) ShortDatePattern zum Definieren des Formats der Datumskomponente der Ergebniszeichenfolge

LongTimePattern zum Definieren des Formats der Uhrzeitkomponente der Ergebniszeichenfolge
"M", "m" (Monat/Tag; Standardformatzeichenfolge) MonthDayPattern zum Definieren des Gesamtformats der Ergebniszeichenfolge
"O", "o" (Roundtrip-Datum/Uhrzeit; Standardformatzeichenfolge) Keine.
"R", "r" (RFC 1123; Standardformatzeichenfolge) RFC1123Pattern zum Definieren einer Ergebniszeichenfolge, die dem RFC 1123-Standard entspricht Die Eigenschaft ist schreibgeschützt.
"s" (sortierbare(s) Datum/Uhrzeit; Standardformatzeichenfolge) SortableDateTimePattern zum Definieren einer Ergebniszeichenfolge, die dem ISO 8601-Standard entspricht Die Eigenschaft ist schreibgeschützt.
"t" (kurzes Uhrzeitformat; Standardformatzeichenfolge) ShortTimePattern zum Definieren des Gesamtformats der Ergebniszeichenfolge
"T" (langes Uhrzeitformat; Standardformatzeichenfolge) LongTimePattern zum Definieren des Gesamtformats der Ergebniszeichenfolge
"u" (universelle(s) sortierbare(s) Datum/Uhrzeit; Standardformatzeichenfolge) UniversalSortableDateTimePattern zum Definieren einer Ergebniszeichenfolge, die dem ISO 8601-Standard für die koordinierte Weltzeit entspricht Die Eigenschaft ist schreibgeschützt.
"U" (universelle(s) vollständige(s) Datum/Uhrzeit; Standardformatzeichenfolge) FullDateTimePattern zum Definieren des Gesamtformats der Ergebniszeichenfolge
"Y", "y" (Monat des Jahres; Standardformatzeichenfolge) YearMonthPattern zum Definieren des Gesamtformats der Ergebniszeichenfolge
"ddd" (benutzerdefinierter Formatspezifizierer) AbbreviatedDayNames zum Einschließen des abgekürzten Namens des Wochentags in der Ergebniszeichenfolge
"g", "gg" (benutzerdefinierter Formatspezifizierer) Aufrufen der GetEraName-Methode, um den Namen des Zeitraums in die Ergebniszeichenfolge einzufügen
"MMM" (benutzerdefinierter Formularspezifizierer) AbbreviatedMonthNames oder AbbreviatedMonthGenitiveNames, um den abgekürzten Monatsnamen in die Ergebniszeichenfolge einzuschließen.
"MMMM" (benutzerdefinierter Formatspezifizierer) MonthNames oder MonthGenitiveNames zum Einschließen des vollständigen Monatsnamens in die Ergebniszeichenfolge
"t" (benutzerdefinierter Formatspezifizierer) AMDesignator oder PMDesignator zum Einschließen des ersten Zeichens des AM/PM-Kennzeichners in die Ergebniszeichenfolge
"tt" (benutzerdefinierter Formatspezifizierer) AMDesignator oder PMDesignator zum Einschließen des vollständigen AM/PM-Kennzeichners in die Ergebniszeichenfolge
":" (benutzerdefinierter Formatspezifizierer) TimeSeparator zum Einschließen des Zeittrennzeichens in die Ergebniszeichenfolge
"/" (benutzerdefinierter Formatspezifizierer) DateSeparator zum Einschließen des Datumstrennzeichens in die Ergebniszeichenfolge

Ändern von DateTimeFormatInfo-Eigenschaften

Sie können die Ergebniszeichenfolge ändern, die von Datums- und Uhrzeitformatzeichenfolgen erstellt wird, indem Sie die zugehörigen Eigenschaften eines schreibbaren DateTimeFormatInfo-Objekts ändern. Verwenden Sie die IsReadOnly-Eigenschaft, um zu ermitteln, ob ein DateTimeFormatInfo-Objekt schreibbar ist. Gehen Sie wie folgt vor, um ein DateTimeFormatInfo-Objekt auf diese Weise anzupassen:

  1. Erstellen Sie eine lesbare und schreibbare Kopie eines DateTimeFormatInfo-Objekts, dessen Formatierungskonventionen Sie ändern möchten.

  2. Ändern Sie die Eigenschaft oder Eigenschaften, die verwendet werden, um die gewünschte Ergebniszeichenfolge zu generieren. (Informationen dazu, wie Formatierungsmethoden DateTimeFormatInfo-Eigenschaften zum Definieren von Ergebniszeichenfolgen verwenden, finden Sie im vorherigen Abschnitt Formatzeichenfolgen und DateTimeFormatInfo-Eigenschaften.)

  3. Verwenden Sie das benutzerdefinierte DateTimeFormatInfo-Objekt, das Sie erstellt haben, als IFormatProvider-Argument in Aufrufen von Formatierungsmethoden.

Es gibt zwei weitere Möglichkeiten zum Ändern des Formats einer Ergebniszeichenfolge:

  • Sie können die CultureAndRegionInfoBuilder-Klasse verwenden, um entweder eine benutzerdefinierte Kultur (eine Kultur, die einen eindeutigen Namen aufweist und vorhandene Kulturen ergänzt) oder eine Ersatzkultur zu definieren (eine Kultur, die anstelle einer spezifischen Kultur verwendet wird). Wie bei jedem anderen von .NET unterstützten CultureInfo-Objekt können Sie diese Kultur programmgesteuert speichern und darauf zugreifen.

  • Wenn die Ergebniszeichenfolge nicht kulturabhängig ist und kein vordefiniertes Format befolgt, können Sie eine benutzerdefinierte Datums- und Uhrzeitformatzeichenfolge verwenden. Wenn Sie beispielsweise Datums- und Uhrzeitdaten im Format „YYYYMMDDHHmmss“ serialisieren, können Sie die Ergebniszeichenfolge generieren, indem Sie die benutzerdefinierte Formatzeichenfolge an die DateTime.ToString(String)-Methode übergeben. Sie können die Ergebniszeichenfolge durch Aufrufen der DateTime.ParseExact-Methode wieder in einen DateTime-Wert konvertieren.

Ändern des kurzen Datumsmusters

Im folgenden Beispiel wird das Format einer Ergebniszeichenfolge geändert, die von der Standardformatzeichenfolge "d" (kurzes Datumsformat) erstellt wird. Dabei wird die zugeordnete ShortDatePattern-Eigenschaft für die Kultur "en-US" bzw. „Englisch (USA)“ von der Standardeinstellung "M/d/yyyy" in "yyyy-MM-dd" geändert, und die Standardformatzeichenfolge "d" wird verwendet, um das Datum vor und nach dem Ändern der ShortDatePattern-Eigenschaft anzuzeigen.

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

Ändern des Datumstrennzeichens

Im folgenden Beispiel wird das Datumstrennzeichen in einem DateTimeFormatInfo-Objekt geändert, das die Formatierungskonventionen der Kultur "fr-FR" darstellt. Im Beispiel wird die Standardformatzeichenfolge "g" verwendet, um das Datum vor und nach dem Ändern der DateSeparator-Eigenschaft anzuzeigen.

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

Ändern der Abkürzungen für die Namen von Tagen und des langen Datumsmusters

In einigen Fällen kann es sein, dass das lange Datumsmuster zu lang ist, mit dem in der Regel der vollständige Wochentag- und Monatsname sowie die Tagnummer und das Jahr angezeigt werden. Im folgenden Beispiel wird das lange Datumsmuster für die Kultur "en-US" gekürzt, um eine Abkürzung für den Wochentag zurückzugeben, die aus einem oder zwei Zeichen besteht, gefolgt von der Tagnummer, der Abkürzung des Monatsnamens und dem Jahr. Hierfür werden dem AbbreviatedDayNames-Array kürzere Abkürzungen für die Tagnamen zugewiesen, und die der LongDatePattern-Eigenschaft zugewiesene benutzerdefinierte Formatzeichenfolge wird geändert. Dies wirkt sich auf die Ergebniszeichenfolgen aus, die von den Standardformatzeichenfolgen "D" und "f" zurückgegeben werden.

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

In der Regel wirkt sich die Änderung der LongDatePattern-Eigenschaft auch auf die FullDateTimePattern-Eigenschaft aus, die wiederum die von der Standardformatzeichenfolge "F" zurückgegebene Ergebniszeichenfolge definiert. Um das ursprüngliche vollständige Datums- und Uhrzeitmuster beizubehalten, wird im Beispiel die ursprüngliche benutzerdefinierte Formatzeichenfolge neu zugewiesen, die der FullDateTimePattern-Eigenschaft zugewiesen ist, nachdem die LongDatePattern-Eigenschaft geändert wurde.

Wechseln vom 12-Stunden-Format zum 24-Stunden-Format

Für viele Kulturen in .NET wird die Zeit mit einer Uhr im 12-Stunden-Format und einem AM/PM-Kennzeichner ausgedrückt. Im folgenden Beispiel wird eine ReplaceWith24HourClock-Methode definiert, die jedes Uhrzeitformat, das ein 12-Stunden-Format verwendet, durch ein Format ersetzt, das das 24-Stunden-Format verwendet.

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

Im Beispiel wird ein regulärer Ausdruck verwendet, um die Formatzeichenfolge zu ändern. Das Muster für den regulären Ausdruck (@"^(?<openAMPM>\s*t+\s*)? (?(openAMPM) h+(?<nonHours>[^ht]+)$ | \s*h+(?<nonHours>[^ht]+)\s*t+)) wird wie folgt definiert:

Muster Beschreibung
^ Beginnt die Suche am Anfang der Zeichenfolge.
(?<openAMPM>\s*t+\s*)? Führen Sie einen Abgleich durch, um zu ermitteln, ob null oder mehr Leerzeichen nicht oder einmal vorkommen, gefolgt vom Buchstaben „t“ (mindestens einmal), gefolgt von keinen oder mehreren Leerzeichen. Diese Erfassungsgruppe wird openAMPM genannt.
(?(openAMPM) h+(?<nonHours>[^ht]+)$ Wenn die openAMPM-Gruppe eine Übereinstimmung aufweist, gleichen Sie den Buchstaben „h“ mindestens einmal ab, gefolgt von mindestens einem Zeichen, das weder „h“ noch „t“ entspricht. Die Abgleichung endet am Ende der Zeichenfolge. Alle nach „h“ erfassten Zeichen sind in einer Erfassungsgruppe mit dem Namen nonHours enthalten.
&#124; \s*h+(?<nonHours>[^ht]+)\s*t+) Wenn die openAMPM-Gruppe keine Übereinstimmung aufweist, gleichen Sie den Buchstaben „h“ mindestens einmal ab, gefolgt von einem oder mehr Zeichen, die nicht „h“ oder „t“ entsprechen, gefolgt von keinem oder mehreren Leerzeichen. Führen Sie schließlich einen Abgleich durch, um zu ermitteln, ob der Buchstaben „t“ einmal oder häufiger vorkommt. Alle Zeichen, die nach „h“ sowie vor den Leerzeichen und „t“ erfasst werden, sind in einer Erfassungsgruppe namens nonHours enthalten.

Die Erfassungsgruppe nonHours enthält die Minuten- und möglicherweise die Sekundenkomponente einer benutzerdefinierten Datums- und Uhrzeitformatzeichenfolge sowie beliebige Zeittrennzeichensymbole. Das Ersatzmuster HH${nonHours} stellt diesen Elementen die Teilzeichenfolge „HH“ voran.

Anzeigen und Ändern des Zeitraums in einem Datum

Im folgenden Beispiel wird der benutzerdefinierte Formatspezifizierer "g" der LongDatePattern-Eigenschaft eines Objekts hinzugefügt, das die Formatierungskonventionen der Kultur "en-US" darstellt. Diese Ergänzung wirkt sich auf die folgenden drei Standardformatzeichenfolgen aus:

  • Standardformatzeichenfolge "D" (langes Datumsformat), die der LongDatePattern-Eigenschaft direkt zugeordnet ist

  • Standardformatzeichenfolge "f" (vollständiges Datum/kurzes Uhrzeitformat), die eine Ergebniszeichenfolge generiert, die die von den Eigenschaften LongDatePattern und ShortTimePattern generierten Teilzeichenfolgen verkettet

  • Standardformatzeichenfolge "F" (vollständiges Datum/langes Uhrzeitformat), die direkt der FullDateTimePattern-Eigenschaft zugeordnet ist. Da Sie diesen Eigenschaftswert nicht explizit festgelegt haben, wird er dynamisch generiert, indem die Eigenschaften LongDatePattern und LongTimePattern verkettet werden.

Das Beispiel zeigt auch, wie der Name des Zeitraums für eine Kultur geändert wird, deren Kalender einen einzelnen Zeitraum aufweist. In diesem Fall verwendet die Kultur "en-US" den gregorianischen Kalender, der durch ein GregorianCalendar-Objekt dargestellt wird. Die GregorianCalendar-Klasse unterstützt einen einzelnen Zeitraum, der „A.D.“ genannt wird (Anno Domini). Im Beispiel wird der Name des Zeitraums in „C.E.“ geändert (Common Era), indem der benutzerdefinierte Formatspezifizierer "g" in der Formatzeichenfolge, die der FullDateTimePattern-Eigenschaft zugewiesen ist, durch eine Literalzeichenfolge ersetzt wird. Die Verwendung einer Literalzeichenfolge ist erforderlich, da der Name des Zeitraums in der Regel von der GetEraName-Methode aus privaten Daten in den Kulturtabellen zurückgegeben wird, die entweder von .NET oder vom Betriebssystem bereitgestellt werden.

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

Analysieren von Datum- und Uhrzeitzeichenfolgen

Die Analyse umfasst das Konvertieren der Zeichenfolgendarstellung eines Datums und einer Uhrzeit in einen DateTime- oder DateTimeOffset-Wert. Beide Typen umfassen die Methoden Parse, TryParse, ParseExact und TryParseExact, um Analysevorgänge zu unterstützen. Die Methoden Parse und TryParse konvertieren eine Zeichenfolge, die eine Vielzahl von Formaten aufweisen kann, während ParseExact und TryParseExact erfordern, dass die Zeichenfolge ein definiertes Format oder definierte Formate aufweist. Wenn beim Analysevorgang ein Fehler auftritt, lösen Parse und ParseExact eine Ausnahme aus, während TryParse und TryParseExact false zurückgeben.

Die Parsingmethoden können implizit oder explizit einen DateTimeStyles-Enumerationswert verwenden, um zu bestimmen, welche Stilelemente (z. B. führende Leerzeichen, nachgestellte Leerzeichen oder Leerzeichen innen) in der zu parsenden Zeichenfolge vorhanden sein können und wie die geparste Zeichenfolge oder fehlenden Elemente interpretiert werden. Wenn Sie beim Aufrufen der Parse- oder TryParse-Methode keinen DateTimeStyles-Wert angeben, ist DateTimeStyles.AllowWhiteSpaces die Standardeinstellung. Dies entspricht einer zusammengesetzten Formatvorlage, die die Flags DateTimeStyles.AllowLeadingWhite, DateTimeStyles.AllowTrailingWhite und DateTimeStyles.AllowInnerWhite enthält. Für die Methoden ParseExact und TryParseExact ist DateTimeStyles.None die Standardeinstellung. Die Eingabezeichenfolge muss einer bestimmten benutzerdefinierten Datums- und Uhrzeitformatzeichenfolge genau entsprechen.

Bei den Parsingmethoden wird auch implizit oder explizit ein DateTimeFormatInfo-Objekt verwendet, das die spezifischen Symbole und Muster definiert, die in der zu parsenden Zeichenfolge auftreten können. Wenn Sie kein DateTimeFormatInfo-Objekt angeben, wird das DateTimeFormatInfo-Objekt für die aktuelle Kultur standardmäßig verwendet. Weitere Informationen zum Analysieren von Datums- und Uhrzeitzeichenfolgen finden Sie in den Artikeln zu den einzelnen Analysemethoden (z. B. DateTime.Parse, DateTime.TryParse, DateTimeOffset.ParseExact und DateTimeOffset.TryParseExact).

Im folgenden Beispiel wird die kulturabhängige Art der Analyse von Datums- und Uhrzeitzeichenfolgen veranschaulicht. Es versucht, zwei Datumszeichenfolgen mithilfe der Konventionen der Kulturen "en-US", "en-GB", "fr-FR" und "fi-FI" zu parsen. Das Datum, das in der Kultur "en-US" als "08/18/2014" interpretiert wird, löst in den anderen drei Kulturen eine FormatException-Ausnahme aus, da die Zahl „18“ als Monatszahl interpretiert wird. "01/02/2015" wird in der Kultur "en-US" als zweiter Tag des ersten Monats identifiziert, in den anderen Kulturen jedoch als erster Tag des zweiten Monats.

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

Datums- und Uhrzeitzeichenfolgen werden in der Regel aus zwei Gründen geparst:

  • Konvertieren von Benutzereingaben in einen Datums- und Uhrzeitwert
  • Roundtrip-Vorgänge für einen Datums- und Uhrzeitwert. Hierbei wird ein Datums- und Uhrzeitwert deserialisiert, der zuvor als Zeichenfolge serialisiert wurde.

In den folgenden Abschnitten werden diese beiden Vorgänge ausführlicher erläutert.

Parsen von Benutzerzeichenfolgen

Wenn Sie die von Benutzer*innen eingegebenen Datums- und Uhrzeitzeichenfolgen parsen, sollten Sie immer ein DateTimeFormatInfo-Objekt instanziieren, das die kulturellen Einstellungen der Benutzer*innen widerspiegelt (einschließlich aller von den Benutzer*innen vorgenommenen Anpassungen). Andernfalls weist das Datums- und Uhrzeitobjekt möglicherweise falsche Werte auf. Informationen zum Instanziieren eines DateTimeFormatInfo-Objekts, das benutzerdefinierte kulturelle Anpassungen widerspiegelt, finden Sie im Abschnitt „DateTimeFormatInfo“ und dynamische Daten.

Das folgende Beispiel veranschaulicht den Unterschied zwischen einem Analysevorgang, der benutzerdefinierte kulturelle Einstellungen widerspiegelt, und einem Analysevorgang, der keine benutzerdefinierten kulturellen Einstellungen widerspiegelt. In diesem Fall ist "en-US" die Standardsystemkultur, aber die Benutzer*innen haben die Option Sprache und Region in der Systemsteuerung verwendet, um das kurze Datumsmuster von der Standardeinstellung "M/d/yyyy" in "yy/MM/dd" zu ändern. Wenn die Benutzer*innen eine Zeichenfolge eingeben, die Benutzereinstellungen widerspiegelt, und die Zeichenfolge von einem DateTimeFormatInfo-Objekt geparst wird, das ebenfalls Benutzereinstellungen (Außerkraftsetzungen) widerspiegelt, gibt der Parsingvorgang ein richtiges Ergebnis zurück. Wenn die Zeichenfolge jedoch von einem DateTimeFormatInfo-Objekt geparst wird, das die kulturellen Standardeinstellungen der Kultur "en-US" widerspiegelt, löst die Parsingmethode eine FormatException-Ausnahme aus, da sie die Zahl „14“ als die Zahl des Monats und nicht als die letzten beiden Ziffern des Jahres interpretiert.

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

Serialisieren und Deserialisieren von Datums- und Uhrzeitdaten

Bei serialisierten Datums- und Uhrzeitdaten werden erfolgreiche Roundtrip-Vorgänge erwartet. Dies bedeutet, dass alle serialisierten und deserialisierten Werte identisch sein sollten. Wenn ein Datums- und Uhrzeitwert einen einzelnen Moment darstellt, sollte der deserialisierte Wert unabhängig von der Kultur oder Zeitzone des Systems, auf dem er wiederhergestellt wurde, denselben Zeitpunkt darstellen. Für erfolgreiche Roundtrip-Vorgänge für Datums- und Uhrzeitdaten müssen Sie die Konventionen der invarianten Kultur verwenden, die von der InvariantInfo-Eigenschaft zurückgegeben wird, um die Daten zu generieren und zu parsen. Die Formatierungs- und Analysevorgänge sollten niemals die Konventionen der Standardkultur widerspiegeln. Wenn Sie kulturelle Standardeinstellungen verwenden, ist die Portabilität der Daten streng begrenzt. Sie können nur für einen Thread erfolgreich deserialisiert werden, dessen kulturspezifische Einstellungen mit denen des Threads identisch sind, für den sie serialisiert wurden. In einigen Fällen bedeutet dies, dass die Daten nicht einmal erfolgreich serialisiert und auf demselben System deserialisiert werden können.

Wenn die Uhrzeitkomponente eines Datums- und Uhrzeitwerts signifikant ist, sollte sie auch in das UTC-Format konvertiert und mithilfe der Standardformatzeichenfolge "o" oder "r" serialisiert werden. Die Uhrzeitdaten können dann wiederhergestellt werden, indem eine Analysemethode aufgerufen und die entsprechende Formatzeichenfolge zusammen mit der invarianten Kultur als provider-Argument übergeben wird.

Das folgende Beispiel veranschaulicht den Roundtrip-Vorgang für einen Datums- und Uhrzeitwert. Dabei wird ein Datum bzw. eine Uhrzeit auf einem System serialisiert, dessen Zeitzone auf die Pazifik-Zeitzone (USA) festgelegt ist und dessen aktuelle Kultur der Kultur "en-US" entspricht.

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)

Dabei werden die Daten auf einem System in der Zeitzone für Brüssel, Kopenhagen, Madrid und Paris deserialisiert, und die aktuelle Kultur entspricht "fr-FR". Das wiederhergestellte Datum liegt neun Stunden hinter dem ursprünglichen Datum, was die Zeitzonenanpassung widerspiegelt (Uhrzeit acht Stunden hinter der koordinierten Weltzeit wird zu Uhrzeit eine Stunde vor der koordinierten Weltzeit). Sowohl das ursprüngliche Datum als auch das wiederhergestellte Datum stellen denselben Zeitpunkt dar.

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