Udostępnij za pośrednictwem


System.DateTime struktura

Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.

Ważne

Era w japońskich kalendarzach opiera się na panowaniu cesarza i dlatego oczekuje się, że się zmieni. Na przykład 1 maja 2019 r. oznaczało początek ery Reiwa w JapaneseCalendar i JapaneseLunisolarCalendar. Taka zmiana ery wpływa na wszystkie aplikacje korzystające z tych kalendarzy. Aby uzyskać więcej informacji i określić, czy twoje aplikacje mają wpływ, zobacz Obsługa nowej ery w kalendarzu japońskim na platformie .NET. Aby uzyskać informacje na temat testowania aplikacji w systemach Windows w celu zapewnienia gotowości do zmiany ery, zobacz Przygotowanie aplikacji do zmiany w erze japońskiej. Aby uzyskać informacje o funkcjach na platformie .NET, które obsługują kalendarze z wieloma epokami i aby uzyskać najlepsze rozwiązania dotyczące pracy z kalendarzami obsługującymi wiele epok, zobacz Praca z erami.

Przegląd

Typ DateTime wartości reprezentuje daty i godziny z wartościami od 00:00:00 (północ), 1 stycznia 0001 roku naszej ery (n.e.) do 23:59:59, 31 grudnia 9999 roku n.e. w kalendarzu gregoriańskim.

Wartości czasu są mierzone w 100-nanosekundowych jednostkach nazywanych tikami. Konkretna data to liczba kleszczy od 12:00 północy, 1 stycznia 0001 R. (C.E.) w kalendarzu GregorianCalendar . Liczba nie obejmuje tików, które zostałyby dodane przez sekundy przestępne. Na przykład wartość znaczników 31241376000000000L reprezentuje datę piątek, 01 stycznia 0100 12:00:00 północy. DateTime Wartość jest zawsze wyrażana w kontekście jawnego lub domyślnego kalendarza.

Uwaga

Jeśli pracujesz z wartością znaczników, którą chcesz przekonwertować na inny interwał czasu, taki jak minuty lub sekundy, należy użyć zmiennej TimeSpan.TicksPerDay, TimeSpan.TicksPerHour, TimeSpan.TicksPerMinute, TimeSpan.TicksPerSecondlub TimeSpan.TicksPerMillisecond stałej, aby wykonać konwersję. Aby na przykład dodać liczbę sekund reprezentowanych przez określoną liczbę taktów do składnika Second wartości DateTime, możesz użyć wyrażenia dateValue.Second + nTicks/Timespan.TicksPerSecond.

Źródło całego zestawu przykładów można wyświetlić w tym artykule w języku Visual Basic, F# lub C#.

Uwaga

Alternatywą dla struktury DateTime, używanej do pracy z wartościami daty i czasu w określonych strefach czasowych, jest struktura DateTimeOffset. Struktura DateTimeOffset przechowuje informacje o dacie i godzinie w polu prywatnym DateTime oraz liczbę minut, w których data i godzina różnią się od czasu UTC w polu prywatnym Int16 . Dzięki temu wartość DateTimeOffset może odzwierciedlać czas w określonej strefie czasowej, natomiast DateTime wartość może jednoznacznie odzwierciedlać tylko czas UTC i czas lokalnej strefy czasowej. Aby dowiedzieć się, kiedy używać struktury DateTime lub struktury DateTimeOffset podczas pracy z wartościami daty i godziny, zobacz Wybieranie między DateTime, DateTimeOffset, TimeSpan i TimeZoneInfo.

Uwaga

Niektóre przykłady języka C# w tym artykule są uruchamiane w Try.NET wbudowanym module uruchamiania kodu i środowisku. Wybierz przycisk Uruchom, aby uruchomić przykład w oknie interaktywnym. Po wykonaniu kodu można go zmodyfikować i uruchomić zmodyfikowany kod, wybierając ponownie Uruchom. Zmodyfikowany kod jest uruchamiany w oknie interaktywnym lub, jeśli kompilacja zakończy się niepowodzeniem, w oknie interaktywnym zostaną wyświetlone wszystkie komunikaty o błędach kompilatora języka C#.

Lokalna strefa czasowa wbudowanego uruchamiającego kod Try.NET i placu zabaw to uniwersalny czas koordynowany, czyli UTC. Może to mieć wpływ na zachowanie i dane wyjściowe przykładów ilustrujących DateTime, DateTimeOffset, i TimeZoneInfo typy oraz ich członków.

Ten artykuł zawiera kilka przykładów, które używają DateTime typu:

Przykłady inicjowania

Formatowanie obiektów DateTime jako ciągi - przykłady

Parsowanie ciągów jako przykłady obiektów DateTime

DateTime przykłady rozwiązywania problemów

Przykłady kultur i kalendarzy

Przykłady trwałości

Inicjowanie obiektu DateTime

Wartość początkową można przypisać do nowej DateTime wartości na wiele różnych sposobów:

  • Wywołanie konstruktora, w którym można określić argumenty dla wartości lub użyć niejawnego konstruktora bez parametrów.
  • Przypisywanie elementu DateTime do wartości zwracanej właściwości lub metody.
  • Analizowanie DateTime wartości z jej reprezentacji w postaci ciągu znaków.
  • Używanie funkcji specyficznych dla języka Visual Basic w celu utworzenia wystąpienia elementu DateTime.

Poniższe fragmenty kodu pokazują przykłady każdego z nich.

Wywoływanie konstruktorów

Wywołujesz dowolne przeciążenia DateTime konstruktora, dzięki którym można określać elementy wartości daty i godziny (takie jak rok, miesiąc i dzień lub liczba tików). Poniższy kod tworzy określoną datę przy użyciu konstruktora określającego DateTime rok, miesiąc, dzień, godzinę, minutę i sekundę.

Dim date1 As New Date(2008, 5, 1, 8, 30, 52)
var date1 = new DateTime(2008, 5, 1, 8, 30, 52);
Console.WriteLine(date1);
let date1 = DateTime(2008, 5, 1, 8, 30, 52)
printfn $"{date1}"

Wywołujesz niejawny konstruktor bez parametrów struktury DateTime, gdy chcesz, aby DateTime został zainicjowany do jego wartości domyślnej. (Aby uzyskać szczegółowe informacje na temat niejawnego konstruktora bez parametrów typu wartości, zobacz Typy wartości). Niektóre kompilatory obsługują również deklarowanie DateTime wartości bez jawnego przypisania do niej wartości. Utworzenie wartości bez jawnej inicjalizacji również skutkuje wartością domyślną. W poniższym przykładzie przedstawiono DateTime niejawny konstruktor bez parametrów w języku C# i Visual Basic, a także deklarację DateTime bez przypisania w języku Visual Basic.

Dim dat1 As DateTime
' The following method call displays 1/1/0001 12:00:00 AM.
Console.WriteLine(dat1.ToString(System.Globalization.CultureInfo.InvariantCulture))
' The following method call displays True.
Console.WriteLine(dat1.Equals(Date.MinValue))

Dim dat2 As New DateTime()
' The following method call displays 1/1/0001 12:00:00 AM.
Console.WriteLine(dat2.ToString(System.Globalization.CultureInfo.InvariantCulture))
' The following method call displays True.
Console.WriteLine(dat2.Equals(Date.MinValue))
var dat1 = new DateTime();
// The following method call displays 1/1/0001 12:00:00 AM.
Console.WriteLine(dat1.ToString(System.Globalization.CultureInfo.InvariantCulture));
// The following method call displays True.
Console.WriteLine(dat1.Equals(DateTime.MinValue));
let dat1 = DateTime()

// The following method call displays 1/1/0001 12:00:00 AM.
printfn $"{dat1.ToString System.Globalization.CultureInfo.InvariantCulture}"

// The following method call displays True.
printfn $"{dat1.Equals DateTime.MinValue}"

Przypisywanie obliczonej wartości

Można przypisać obiektowi DateTime wartość daty i godziny zwracaną przez właściwość lub metodę. Poniższy przykład przypisuje bieżącą datę i godzinę, bieżącą datę i godzinę uniwersalnej koordynowanej (UTC) oraz bieżącą datę do trzech nowych DateTime zmiennych.

Dim date1 As Date = Date.Now
Dim date2 As Date = Date.UtcNow
Dim date3 As Date = Date.Today
DateTime date1 = DateTime.Now;
DateTime date2 = DateTime.UtcNow;
DateTime date3 = DateTime.Today;
let date1 = DateTime.Now
let date2 = DateTime.UtcNow
let date3 = DateTime.Today

Analizowanie ciągu reprezentującego wartość DateTime

Metody Parse, ParseExact, TryParsei TryParseExact konwertują ciąg na równoważną wartość daty i godziny. W poniższych przykładach używane są metody Parse i ParseExact, aby przeanalizować ciąg i przekonwertować go na wartość DateTime. Drugi format używa formy obsługiwanej przez standard ISO 8601 do reprezentowania daty i godziny w formacie ciągu. Ta standardowa reprezentacja jest często używana do transferu informacji o dacie w usługach internetowych.

Dim dateString As String = "5/1/2008 8:30:52 AM"
Dim date1 As Date = Date.Parse(dateString,
                       System.Globalization.CultureInfo.InvariantCulture)
Dim iso8601String As String = "20080501T08:30:52Z"
Dim dateISO8602 As Date = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ",
                              System.Globalization.CultureInfo.InvariantCulture)
Console.WriteLine(dateISO8602)
var dateString = "5/1/2008 8:30:52 AM";
DateTime date1 = DateTime.Parse(dateString,
                          System.Globalization.CultureInfo.InvariantCulture);
var iso8601String = "20080501T08:30:52Z";
DateTime dateISO8602 = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ",
                                System.Globalization.CultureInfo.InvariantCulture);
let dateString = "5/1/2008 8:30:52 AM"
let date1 = DateTime.Parse(dateString, System.Globalization.CultureInfo.InvariantCulture)
let iso8601String = "20080501T08:30:52Z"
let dateISO8602 = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ", System.Globalization.CultureInfo.InvariantCulture)

Metody TryParse i TryParseExact wskazują, czy ciąg jest prawidłową reprezentacją DateTime wartości, a jeśli tak, wykonuje konwersję.

Składnia specyficzna dla Visual Basic

Poniższa instrukcja języka Visual Basic inicjuje nową DateTime wartość.

Dim date1 As Date = #5/1/2008 8:30:52AM#

Wartości DateTime i ich reprezentacje jako ciągi znaków

Wewnętrznie wszystkie DateTime wartości są reprezentowane jako liczba tyknięć (liczba interwałów po 100 nanosekund), które upłynęły od północy o godzinie 00:00:00, 1 stycznia roku 0001. Rzeczywista DateTime wartość jest niezależna od sposobu, w jaki ta wartość jest przedstawiana. Wygląd DateTime wartości jest wynikiem operacji formatowania, która konwertuje wartość na jej reprezentację ciągu.

Wygląd wartości daty i godziny zależy od kultury, standardów międzynarodowych, wymagań aplikacji i preferencji osobistych. Struktura DateTime zapewnia elastyczność formatowania wartości daty i godziny poprzez przeciążenia ToString. Metoda domyślna DateTime.ToString() zwraca ciąg reprezentujący wartość daty i godziny, używając krótkiego wzorca daty i długiego wzorca czasu bieżącej kultury. W poniższym przykładzie użyto metody domyślnej DateTime.ToString() . Wyświetla datę i godzinę przy użyciu wzorca daty krótkiej i godziny długiej zgodnie z bieżącą kulturą. Kultura systemu en-US jest bieżącą kulturą na komputerze, na którym uruchomiono przykład.

var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString());
// For en-US culture, displays 3/1/2008 7:00:00 AM
let date1 = DateTime(2008, 3, 1, 7, 0, 0)
printfn $"{date1.ToString()}"
// For en-US culture, displays 3/1/2008 7:00:00 AM
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString())
' For en-US culture, displays 3/1/2008 7:00:00 AM

Może być konieczne sformatowanie dat w określonej kulturze w celu obsługi scenariuszy internetowych, w których serwer może znajdować się w innej kulturze niż klient. Należy określić kulturę za pomocą metody DateTime.ToString(IFormatProvider), aby utworzyć skróconą datę oraz długie przedstawienie czasu w tej kulturze. W poniższym przykładzie użyto DateTime.ToString(IFormatProvider) metody do wyświetlenia daty i godziny przy użyciu wzorca daty krótkiej i długiej dla kultury fr-FR.

var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString(System.Globalization.CultureInfo.CreateSpecificCulture("fr-FR")));
// Displays 01/03/2008 07:00:00
let date1 = DateTime(2008, 3, 1, 7, 0, 0)
printfn $"""{date1.ToString(System.Globalization.CultureInfo.CreateSpecificCulture "fr-FR")}"""
// Displays 01/03/2008 07:00:00
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString(System.Globalization.CultureInfo.CreateSpecificCulture("fr-FR")))
' Displays 01/03/2008 07:00:00

Inne aplikacje mogą wymagać różnych reprezentacji ciągów daty. Metoda DateTime.ToString(String) zwraca reprezentację ciągu zdefiniowaną przez specyfikator formatu standardowego lub niestandardowego przy użyciu konwencji formatowania bieżącej kultury. W poniższym przykładzie metoda DateTime.ToString(String) jest używana do wyświetlania wzorca pełnej daty i czasu dla kultury en-US, obecnej kultury na komputerze, na którym uruchomiono przykład.

var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString("F"));
// Displays Saturday, March 01, 2008 7:00:00 AM
let date1 = DateTime(2008, 3, 1, 7, 0, 0)
printfn $"""{date1.ToString "F"}"""
// Displays Saturday, March 01, 2008 7:00:00 AM
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString("F"))
' Displays Saturday, March 01, 2008 7:00:00 AM

Na koniec można określić zarówno kulturę, jak i format przy użyciu DateTime.ToString(String, IFormatProvider) metody . W poniższym przykładzie użyto metody DateTime.ToString(String, IFormatProvider), aby wyświetlić pełny wzorzec daty i czasu dla kultury fr-FR.

var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString("F", new System.Globalization.CultureInfo("fr-FR")));
// Displays samedi 1 mars 2008 07:00:00
let date1 = DateTime(2008, 3, 1, 7, 0, 0)
printfn $"""{date1.ToString("F", new System.Globalization.CultureInfo "fr-FR")}"""
// Displays samedi 1 mars 2008 07:00:00
Dim date1 As Date = #3/1/2008 7:00AM#
Console.WriteLine(date1.ToString("F", New System.Globalization.CultureInfo("fr-FR")))
' Displays samedi 1 mars 2008 07:00:00

Przeciążenie DateTime.ToString(String) może być również używane z ciągiem formatu niestandardowego, aby określić inne formaty. W poniższym przykładzie pokazano, jak sformatować ciąg przy użyciu standardowego formatu ISO 8601 często używanego dla usług internetowych. Format Iso 8601 nie ma odpowiedniego standardowego ciągu formatu.

var date1 = new DateTime(2008, 3, 1, 7, 0, 0, DateTimeKind.Utc);
Console.WriteLine(date1.ToString("yyyy-MM-ddTHH:mm:sszzz", System.Globalization.CultureInfo.InvariantCulture));
// Displays 2008-03-01T07:00:00+00:00
let date1 = DateTime(2008, 3, 1, 7, 0, 0, DateTimeKind.Utc)
printfn $"""{date1.ToString("yyyy-MM-ddTHH:mm:sszzz", System.Globalization.CultureInfo.InvariantCulture)}"""
// Displays 2008-03-01T07:00:00+00:00
Dim date1 As DateTime = New DateTime(2008, 3, 1, 7, 0, 0, DateTimeKind.Utc)
Console.WriteLine(date1.ToString("yyyy-MM-ddTHH:mm:sszzz", System.Globalization.CultureInfo.InvariantCulture))
' Displays 2008-03-01T07:00:00+00:00

Aby uzyskać więcej informacji na temat formatowania DateTime wartości, zobacz Standardowe ciągi formatu daty i godziny oraz niestandardowe ciągi formatu daty i godziny.

Analizowanie wartości DateTime z ciągów

Analizowanie konwertuje ciąg reprezentujący datę i godzinę na DateTime wartość. Zazwyczaj ciągi daty i godziny mają dwa różne zastosowania w aplikacjach:

  • Data i godzina mają różne formy i odzwierciedlają konwencje bieżącej kultury lub konkretnej kultury. Na przykład aplikacja umożliwia użytkownikowi, którego bieżąca kultura jest en-US wprowadzić wartość daty jako "12/15/2013" lub "15 grudnia 2013". Umożliwia to użytkownikowi, którego bieżąca kultura jest en-gb, aby wprowadzić wartość daty jako "15/12/2013" lub "15 grudnia 2013 r.".

  • Data i godzina są reprezentowane w wstępnie zdefiniowanym formacie. Na przykład aplikacja serializuje datę jako "20130103" niezależnie od kultury, na której działa aplikacja. Aplikacja może wymagać wprowadzania dat w formacie krótkiej daty zgodnym z bieżącą kulturą.

Metoda Parse lub TryParse służy do konwertowania ciągu z jednego z typowych formatów daty i godziny używanych przez kulturę na wartość DateTime. Poniższy przykład przedstawia sposób zamiany ciągów dat TryParse w różnych formatach charakterystycznych dla różnych kultur na wartość DateTime. Zmienia bieżącą kulturę ustawień na angielski (Wielka Brytania) i wywołuje metodę GetDateTimeFormats() aby wygenerować tablicę ciągów daty i godziny. Następnie przekazuje każdy element w tablicy do metody TryParse. Dane wyjściowe z przykładu pokazują, że metoda analizowania mogła pomyślnie przekonwertować każdy ciąg daty i godziny specyficzny dla kultury.

System.Threading.Thread.CurrentThread.CurrentCulture =
    System.Globalization.CultureInfo.CreateSpecificCulture("en-GB");

var date1 = new DateTime(2013, 6, 1, 12, 32, 30);
var badFormats = new List<String>();

Console.WriteLine($"{"Date String",-37} {"Date",-19}\n");
foreach (var dateString in date1.GetDateTimeFormats())
{
    DateTime parsedDate;
    if (DateTime.TryParse(dateString, out parsedDate))
        Console.WriteLine($"{dateString,-37} {DateTime.Parse(dateString),-19}");
    else
        badFormats.Add(dateString);
}

// Display strings that could not be parsed.
if (badFormats.Count > 0)
{
    Console.WriteLine("\nStrings that could not be parsed: ");
    foreach (var badFormat in badFormats)
        Console.WriteLine($"   {badFormat}");
}
// Press "Run" to see the output.
System.Threading.Thread.CurrentThread.CurrentCulture <-
    System.Globalization.CultureInfo.CreateSpecificCulture "en-GB"

let date1 = DateTime(2013, 6, 1, 12, 32, 30)
let badFormats = ResizeArray<String>()

printfn "%-37s %-19s\n" "Date String" "Date"
for dateString in date1.GetDateTimeFormats() do
    match DateTime.TryParse dateString with
    | true, parsedDate ->
        printfn $"%-37s{dateString} %-19O{parsedDate}\n" 
    | _ ->
        badFormats.Add dateString

// Display strings that could not be parsed.
if badFormats.Count > 0 then
    printfn "\nStrings that could not be parsed: "
    for badFormat in badFormats do
        printfn $"   {badFormat}"
// Press "Run" to see the output.
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB")

Dim date1 As New DateTime(2013, 6, 1, 12, 32, 30)
Dim badFormats As New List(Of String)

Console.WriteLine($"{"Date String",-37} {"Date",-19}")
Console.WriteLine()
For Each dateString As String In date1.GetDateTimeFormats()
    Dim parsedDate As DateTime
    If DateTime.TryParse(dateString, parsedDate) Then
        Console.WriteLine($"{dateString,-37} {DateTime.Parse(dateString),-19:g}")
    Else
        badFormats.Add(dateString)
    End If
Next

' Display strings that could not be parsed.
If badFormats.Count > 0 Then
    Console.WriteLine()
    Console.WriteLine("Strings that could not be parsed: ")
    For Each badFormat In badFormats
        Console.WriteLine($"   {badFormat}")
    Next
End If
' The example displays the following output:
'       Date String                           Date               
'       
'       01/06/2013                            01/06/2013 00:00:00
'       01/06/13                              01/06/2013 00:00:00
'       1/6/13                                01/06/2013 00:00:00
'       1.6.13                                01/06/2013 00:00:00
'       2013-06-01                            01/06/2013 00:00:00
'       01 June 2013                          01/06/2013 00:00:00
'       1 June 2013                           01/06/2013 00:00:00
'       01 June 2013 12:32                    01/06/2013 12:32:00
'       01 June 2013 12:32                    01/06/2013 12:32:00
'       01 June 2013 12:32 PM                 01/06/2013 12:32:00
'       01 June 2013 12:32 PM                 01/06/2013 12:32:00
'       1 June 2013 12:32                     01/06/2013 12:32:00
'       1 June 2013 12:32                     01/06/2013 12:32:00
'       1 June 2013 12:32 PM                  01/06/2013 12:32:00
'       1 June 2013 12:32 PM                  01/06/2013 12:32:00
'       01 June 2013 12:32:30                 01/06/2013 12:32:30
'       01 June 2013 12:32:30                 01/06/2013 12:32:30
'       01 June 2013 12:32:30 PM              01/06/2013 12:32:30
'       01 June 2013 12:32:30 PM              01/06/2013 12:32:30
'       1 June 2013 12:32:30                  01/06/2013 12:32:30
'       1 June 2013 12:32:30                  01/06/2013 12:32:30
'       1 June 2013 12:32:30 PM               01/06/2013 12:32:30
'       1 June 2013 12:32:30 PM               01/06/2013 12:32:30
'       01/06/2013 12:32                      01/06/2013 12:32:00
'       01/06/2013 12:32                      01/06/2013 12:32:00
'       01/06/2013 12:32 PM                   01/06/2013 12:32:00
'       01/06/2013 12:32 PM                   01/06/2013 12:32:00
'       01/06/13 12:32                        01/06/2013 12:32:00
'       01/06/13 12:32                        01/06/2013 12:32:00
'       01/06/13 12:32 PM                     01/06/2013 12:32:00
'       01/06/13 12:32 PM                     01/06/2013 12:32:00
'       1/6/13 12:32                          01/06/2013 12:32:00
'       1/6/13 12:32                          01/06/2013 12:32:00
'       1/6/13 12:32 PM                       01/06/2013 12:32:00
'       1/6/13 12:32 PM                       01/06/2013 12:32:00
'       1.6.13 12:32                          01/06/2013 12:32:00
'       1.6.13 12:32                          01/06/2013 12:32:00
'       1.6.13 12:32 PM                       01/06/2013 12:32:00
'       1.6.13 12:32 PM                       01/06/2013 12:32:00
'       2013-06-01 12:32                      01/06/2013 12:32:00
'       2013-06-01 12:32                      01/06/2013 12:32:00
'       2013-06-01 12:32 PM                   01/06/2013 12:32:00
'       2013-06-01 12:32 PM                   01/06/2013 12:32:00
'       01/06/2013 12:32:30                   01/06/2013 12:32:30
'       01/06/2013 12:32:30                   01/06/2013 12:32:30
'       01/06/2013 12:32:30 PM                01/06/2013 12:32:30
'       01/06/2013 12:32:30 PM                01/06/2013 12:32:30
'       01/06/13 12:32:30                     01/06/2013 12:32:30
'       01/06/13 12:32:30                     01/06/2013 12:32:30
'       01/06/13 12:32:30 PM                  01/06/2013 12:32:30
'       01/06/13 12:32:30 PM                  01/06/2013 12:32:30
'       1/6/13 12:32:30                       01/06/2013 12:32:30
'       1/6/13 12:32:30                       01/06/2013 12:32:30
'       1/6/13 12:32:30 PM                    01/06/2013 12:32:30
'       1/6/13 12:32:30 PM                    01/06/2013 12:32:30
'       1.6.13 12:32:30                       01/06/2013 12:32:30
'       1.6.13 12:32:30                       01/06/2013 12:32:30
'       1.6.13 12:32:30 PM                    01/06/2013 12:32:30
'       1.6.13 12:32:30 PM                    01/06/2013 12:32:30
'       2013-06-01 12:32:30                   01/06/2013 12:32:30
'       2013-06-01 12:32:30                   01/06/2013 12:32:30
'       2013-06-01 12:32:30 PM                01/06/2013 12:32:30
'       2013-06-01 12:32:30 PM                01/06/2013 12:32:30
'       01 June                               01/06/2013 00:00:00
'       01 June                               01/06/2013 00:00:00
'       2013-06-01T12:32:30.0000000           01/06/2013 12:32:30
'       2013-06-01T12:32:30.0000000           01/06/2013 12:32:30
'       Sat, 01 Jun 2013 12:32:30 GMT         01/06/2013 05:32:30
'       Sat, 01 Jun 2013 12:32:30 GMT         01/06/2013 05:32:30
'       2013-06-01T12:32:30                   01/06/2013 12:32:30
'       12:32                                 22/04/2013 12:32:00
'       12:32                                 22/04/2013 12:32:00
'       12:32 PM                              22/04/2013 12:32:00
'       12:32 PM                              22/04/2013 12:32:00
'       12:32:30                              22/04/2013 12:32:30
'       12:32:30                              22/04/2013 12:32:30
'       12:32:30 PM                           22/04/2013 12:32:30
'       12:32:30 PM                           22/04/2013 12:32:30
'       2013-06-01 12:32:30Z                  01/06/2013 05:32:30
'       01 June 2013 19:32:30                 01/06/2013 19:32:30
'       01 June 2013 19:32:30                 01/06/2013 19:32:30
'       01 June 2013 07:32:30 PM              01/06/2013 19:32:30
'       01 June 2013 7:32:30 PM               01/06/2013 19:32:30
'       1 June 2013 19:32:30                  01/06/2013 19:32:30
'       1 June 2013 19:32:30                  01/06/2013 19:32:30
'       1 June 2013 07:32:30 PM               01/06/2013 19:32:30
'       1 June 2013 7:32:30 PM                01/06/2013 19:32:30
'       June 2013                             01/06/2013 00:00:00
'       June 2013                             01/06/2013 00:00:00

Używasz metody ParseExact i TryParseExact do konwertowania ciągu, który musi być zgodny z określonym formatem lub formatami na wartość DateTime. Należy określić co najmniej jeden ciąg formatu daty i godziny jako parametr metody analizowania. W poniższym przykładzie użyto metody TryParseExact(String, String[], IFormatProvider, DateTimeStyles, DateTime), aby przekonwertować ciągi, które muszą mieć format "rrrrMMdd" lub "HHmmss", na wartości DateTime.

string[] formats = { "yyyyMMdd", "HHmmss" };
string[] dateStrings = { "20130816", "20131608", "  20130816   ",
                   "115216", "521116", "  115216  " };
DateTime parsedDate;

foreach (var dateString in dateStrings)
{
    if (DateTime.TryParseExact(dateString, formats, null,
                               System.Globalization.DateTimeStyles.AllowWhiteSpaces |
                               System.Globalization.DateTimeStyles.AdjustToUniversal,
                               out parsedDate))
        Console.WriteLine($"{dateString} --> {parsedDate:g}");
    else
        Console.WriteLine($"Cannot convert {dateString}");
}
// The example displays the following output:
//       20130816 --> 8/16/2013 12:00 AM
//       Cannot convert 20131608
//         20130816    --> 8/16/2013 12:00 AM
//       115216 --> 4/22/2013 11:52 AM
//       Cannot convert 521116
//         115216   --> 4/22/2013 11:52 AM
let formats = [| "yyyyMMdd"; "HHmmss" |]
let dateStrings = 
    [ "20130816"; "20131608"; "  20130816   "
      "115216"; "521116"; "  115216  " ]

for dateString in dateStrings do
    match DateTime.TryParseExact(dateString, formats, null,
                                System.Globalization.DateTimeStyles.AllowWhiteSpaces |||
                                System.Globalization.DateTimeStyles.AdjustToUniversal) with
    | true, parsedDate ->
        printfn $"{dateString} --> {parsedDate:g}"
    | _ ->
        printfn $"Cannot convert {dateString}"

// The example displays the following output:
//       20130816 --> 8/16/2013 12:00 AM
//       Cannot convert 20131608
//         20130816    --> 8/16/2013 12:00 AM
//       115216 --> 4/22/2013 11:52 AM
//       Cannot convert 521116
//         115216   --> 4/22/2013 11:52 AM
Dim formats() As String = {"yyyyMMdd", "HHmmss"}
Dim dateStrings() As String = {"20130816", "20131608",
                              "  20130816   ", "115216",
                              "521116", "  115216  "}
Dim parsedDate As DateTime

For Each dateString As String In dateStrings
    If DateTime.TryParseExact(dateString, formats, Nothing,
                           DateTimeStyles.AllowWhiteSpaces Or
                           DateTimeStyles.AdjustToUniversal,
                           parsedDate) Then
        Console.WriteLine($"{dateString} --> {parsedDate:g}")
    Else
        Console.WriteLine($"Cannot convert {dateString}")
    End If
Next
' The example displays the following output:
'       20130816 --> 8/16/2013 12:00 AM
'       Cannot convert 20131608
'         20130816    --> 8/16/2013 12:00 AM
'       115216 --> 4/22/2013 11:52 AM
'       Cannot convert 521116
'         115216   --> 4/22/2013 11:52 AM

Jednym z typowych zastosowań ParseExact jest konwersja reprezentacji ciągu znaków z usługi internetowej, zazwyczaj w formacie standardowym ISO 8601. Poniższy kod przedstawia prawidłowy ciąg formatu do użycia:

var iso8601String = "20080501T08:30:52Z";
DateTime dateISO8602 = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ",
    System.Globalization.CultureInfo.InvariantCulture);
Console.WriteLine($"{iso8601String} --> {dateISO8602:g}");
let iso8601String = "20080501T08:30:52Z"
let dateISO8602 = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ", System.Globalization.CultureInfo.InvariantCulture)

printfn $"{iso8601String} --> {dateISO8602:g}"
Dim iso8601String As String = "20080501T08:30:52Z"
Dim dateISO8602 As DateTime = DateTime.ParseExact(iso8601String, "yyyyMMddTHH:mm:ssZ", CultureInfo.InvariantCulture)
Console.WriteLine($"{iso8601String} --> {dateISO8602:g}")

Jeśli nie można przeanalizować ciągu, Parse metody i ParseExact zgłaszają wyjątek. Metody TryParse i TryParseExact zwracają wartość wskazującą Boolean , czy konwersja powiodła się, czy nie powiodła się. Powinieneś używać metod TryParse lub TryParseExact w scenariuszach, w których wydajność jest ważna. Operacja parsowania ciągów daty i godziny ma tendencję do wysokiego wskaźnika niepowodzenia, a obsługa wyjątków jest kosztowna. Użyj tych metod, jeśli ciągi są wprowadzane przez użytkowników lub pochodzące z nieznanego źródła.

Aby uzyskać więcej informacji na temat analizowania wartości daty i godziny, zobacz Analizowanie ciągów daty i godziny.

Wartości typu DateTime

Opisy wartości czasu w typie DateTime są często wyrażane przy użyciu standardu uniwersalnego czasu koordynowanego (UTC). Uniwersalny czas koordynowany jest międzynarodowo rozpoznaną nazwą Greenwich Mean Time (GMT). Uniwersalny czas koordynowany to czas mierzony o długości geograficznej zero stopni, punkt początkowy UTC. Czas letni nie ma zastosowania do czasu UTC.

Czas lokalny jest względny dla określonej strefy czasowej. Strefa czasowa jest skojarzona z przesunięciem strefy czasowej. Przesunięcie strefy czasowej to przesunięcie strefy czasowej mierzone w godzinach od punktu początkowego UTC. Ponadto czas lokalny jest opcjonalnie objęty zmianą czasu letniego, co powoduje dodanie lub odejmowanie korekty interwału czasu. Czas lokalny jest obliczany przez dodanie przesunięcia strefy czasowej do czasu UTC i uwzględnienie czasu letniego w razie potrzeby. Przesunięcie strefy czasowej w punkcie początkowym UTC wynosi zero.

Czas UTC nadaje się do obliczeń, porównań i przechowywania dat i godzin w plikach. Czas lokalny jest odpowiedni do wyświetlania w interfejsach użytkownika aplikacji pulpitowych. Aplikacje obsługujące strefę czasową (takie jak wiele aplikacji internetowych) muszą również współpracować z wieloma innymi strefami czasowymi.

Kind Jeśli właściwość DateTime obiektu to DateTimeKind.Unspecified, nie jest określona, czy czas reprezentowany to czas lokalny, czas UTC, czy czas w innej strefie czasowej.

Precyzja daty i godziny

Uwaga

Alternatywą dla przeprowadzania operacji na wartościach DateTime w celu mierzenia upływu czasu może być zastosowanie klasy Stopwatch.

Właściwość Ticks wyraża wartości daty i godziny w jednostkach jednej dziesiątej części sekundy. Właściwość Millisecond zwraca tysięczne części sekundy w wartości daty i czasu. Używanie powtarzających się wywołań do DateTime.Now właściwości w celu pomiaru czasu, który upłynął, zależy od zegara systemowego. Zegar systemowy w systemach Windows 7 i Windows 8 ma rozdzielczość około 15 milisekund. Ta rozdzielczość ma wpływ na małe interwały czasowe mniejsze niż 100 milisekund.

Poniższy przykład ilustruje zależność bieżących wartości daty i godziny od rozdzielczości zegara systemowego. W tym przykładzie pętla zewnętrzna powtarza się 20 razy, a pętla wewnętrzna służy do opóźnienia pętli zewnętrznej. Jeśli wartość licznika pętli zewnętrznej wynosi 10, wywołanie Thread.Sleep metody wprowadza pięć milisekund opóźnienia. W poniższym przykładzie pokazano, że liczba milisekund zwrócona przez właściwość DateTime.Now.Milliseconds zmienia się dopiero po wywołaniu Thread.Sleep.

string output = "";
for (int ctr = 0; ctr <= 20; ctr++)
{
    output += String.Format($"{DateTime.Now.Millisecond}\n");
    // Introduce a delay loop.
    for (int delay = 0; delay <= 1000; delay++)
    { }

    if (ctr == 10)
    {
        output += "Thread.Sleep called...\n";
        System.Threading.Thread.Sleep(5);
    }
}
Console.WriteLine(output);
// Press "Run" to see the output.
let mutable output = ""
for i = 0 to 20 do
    output <- output + $"{DateTime.Now.Millisecond}\n"
    // Introduce a delay loop.
    for _ = 0 to 1000 do ()

    if i = 10 then
        output <- output + "Thread.Sleep called...\n"
        System.Threading.Thread.Sleep 5

printfn $"{output}"
// Press "Run" to see the output.
Dim output As String = ""
For ctr As Integer = 0 To 20
    output += Date.Now.Millisecond.ToString() + vbCrLf
    ' Introduce a delay loop.
    For delay As Integer = 0 To 1000
    Next

    If ctr = 10 Then
        output += "Thread.Sleep called..." + vbCrLf
        Thread.Sleep(5)
    End If
Next
Console.WriteLine(output)
' The example displays output like the following:
'       111
'       111
'       111
'       111
'       111
'       111
'       111
'       111
'       111
'       111
'       111
'       Thread.Sleep called...
'       143
'       143
'       143
'       143
'       143
'       143
'       143
'       143
'       143
'       143

Operacje datetime

Obliczenie przy użyciu DateTime struktury, takiej jak Add lub Subtract, nie modyfikuje wartości struktury. Zamiast tego obliczenie zwraca nową DateTime strukturę, której wartość jest wynikiem obliczenia.

Operacje konwersji między strefami czasowymi (na przykład między czasem UTC a czasem lokalnym lub między jedną strefą czasową a drugą) uwzględniają czas letni, ale operacje arytmetyczne i porównawcze nie.

Sama DateTime struktura oferuje ograniczoną obsługę konwersji z jednej strefy czasowej na inną. Możesz użyć ToLocalTime metody , aby przekonwertować czas UTC na lokalny lub użyć ToUniversalTime metody do konwersji z czasu lokalnego na UTC. Jednak w klasie jest dostępny pełny zestaw metod konwersji strefy czasowej TimeZoneInfo . Czas można przekonwertować w dowolnej ze stref czasowych na czas w dowolnej innej strefie czasowej przy użyciu tych metod.

Obliczenia i porównania DateTime obiektów mają znaczenie tylko wtedy, gdy obiekty reprezentują czas w tej samej strefie czasowej. Można użyć TimeZoneInfo obiektu do reprezentowania DateTime strefy czasowej wartości, chociaż te dwa są luźno powiązane. Obiekt DateTime nie ma właściwości zwracającej obiekt reprezentujący strefę czasową tej wartości daty i godziny. Właściwość Kind wskazuje, czy DateTime reprezentuje czas UTC, czas lokalny lub jest nieokreślony. W aplikacji obsługującej strefy czasowej należy opierać się na pewnym mechanizmie zewnętrznym, aby określić strefę czasową DateTime , w której został utworzony obiekt. Możesz użyć struktury, która obejmuje zarówno wartość DateTime, jak i obiekt TimeZoneInfo, który reprezentuje strefę czasową wartości DateTime. Aby uzyskać szczegółowe informacje na temat używania czasu UTC w obliczeniach i porównaniach z wartościami DateTime , zobacz Wykonywanie operacji arytmetycznych przy użyciu dat i godzin.

Każdy element DateTime niejawnie używa kalendarza gregoriańskiego do operacji. Wyjątki to metody, które niejawnie określają kalendarz. Obejmują one konstruktory, które określają kalendarz, i metody z parametrem pochodzącym z klasy IFormatProvider, takich jak System.Globalization.DateTimeFormatInfo.

Operacje wykonywane przez członków typu DateTime uwzględniają szczegóły, takie jak lata przestępne i liczba dni w miesiącu.

Wartości daty i czasu oraz kalendarze

Biblioteka klas platformy .NET zawiera wiele klas kalendarza, z których wszystkie pochodzą z Calendar klasy . Są to:

Ważne

Era w japońskich kalendarzach opiera się na panowaniu cesarza i dlatego oczekuje się, że się zmieni. Na przykład 1 maja 2019 r. oznaczało początek ery Reiwa w JapaneseCalendar i JapaneseLunisolarCalendar. Taka zmiana ery wpływa na wszystkie aplikacje korzystające z tych kalendarzy. Aby uzyskać więcej informacji i określić, czy twoje aplikacje mają wpływ, zobacz Obsługa nowej ery w kalendarzu japońskim na platformie .NET. Aby uzyskać informacje na temat testowania aplikacji w systemach Windows w celu zapewnienia gotowości do zmiany ery, zobacz Przygotowanie aplikacji do zmiany w erze japońskiej. Aby uzyskać informacje o funkcjach na platformie .NET, które obsługują kalendarze z wieloma epokami i aby uzyskać najlepsze rozwiązania dotyczące pracy z kalendarzami obsługującymi wiele epok, zobacz Praca z erami.

Każda kultura używa domyślnego kalendarza zdefiniowanego przez jej właściwość tylko do odczytu CultureInfo.Calendar. Każda kultura może obsługiwać jeden lub więcej kalendarzy zdefiniowanych przez swoją właściwość tylko do odczytu CultureInfo.OptionalCalendars. Kalendarz używany obecnie przez określony CultureInfo obiekt jest definiowany przez jego DateTimeFormatInfo.Calendar właściwość. Musi to być jeden z kalendarzy znalezionych w tablicy CultureInfo.OptionalCalendars .

Bieżący kalendarz kultury jest używany we wszystkich operacjach formatowania dla tej kultury. Na przykład domyślny kalendarz tajskiej kultury buddyjskiej to kalendarz tajskiej ery buddyjskiej, który jest reprezentowany przez klasę ThaiBuddhistCalendar . CultureInfo Gdy obiekt reprezentujący tajlandzką kulturę buddyjską jest używany w operacji formatowania daty i godziny, kalendarz tajskiej ery buddyjskiej jest domyślnie używany. Kalendarz gregoriański jest używany tylko wtedy, gdy właściwość kultury DateTimeFormatInfo.Calendar zostanie zmieniona, jak pokazano w poniższym przykładzie.

var thTH = new System.Globalization.CultureInfo("th-TH");
var value = new DateTime(2016, 5, 28);

Console.WriteLine(value.ToString(thTH));

thTH.DateTimeFormat.Calendar = new System.Globalization.GregorianCalendar();
Console.WriteLine(value.ToString(thTH));
// The example displays the following output:
//       28/5/2559 0:00:00
//       28/5/2016 0:00:00
let thTH = System.Globalization.CultureInfo "th-TH"
let value = DateTime(2016, 5, 28)

printfn $"{value.ToString thTH}"

thTH.DateTimeFormat.Calendar <- System.Globalization.GregorianCalendar()

printfn $"{value.ToString thTH}"

// The example displays the following output:
//       28/5/2559 0:00:00
//       28/5/2016 0:00:00
Dim thTH As New CultureInfo("th-TH")
Dim value As New DateTime(2016, 5, 28)

Console.WriteLine(value.ToString(thTH))

thTH.DateTimeFormat.Calendar = New GregorianCalendar()
Console.WriteLine(value.ToString(thTH))
' The example displays the following output:
'       28/5/2559 0:00:00
'       28/5/2016 0:00:00

Bieżący kalendarz kultury jest również używany we wszystkich operacjach analizowania dla tej kultury, jak pokazano w poniższym przykładzie.

var thTH = new System.Globalization.CultureInfo("th-TH");
var value = DateTime.Parse("28/05/2559", thTH);
Console.WriteLine(value.ToString(thTH));

thTH.DateTimeFormat.Calendar = new System.Globalization.GregorianCalendar();
Console.WriteLine(value.ToString(thTH));
// The example displays the following output:
//       28/5/2559 0:00:00
//       28/5/2016 0:00:00
let thTH = System.Globalization.CultureInfo "th-TH"
let value = DateTime.Parse("28/05/2559", thTH)
printfn $"{value.ToString thTH}"

thTH.DateTimeFormat.Calendar <- System.Globalization.GregorianCalendar()
printfn $"{value.ToString thTH}"

// The example displays the following output:
//       28/5/2559 0:00:00
//       28/5/2016 0:00:00
Private Sub ThaiBuddhistEraParse()
    Dim thTH As New CultureInfo("th-TH")
    Dim value As DateTime = DateTime.Parse("28/5/2559", thTH)
    Console.WriteLine(value.ToString(thTH))

    thTH.DateTimeFormat.Calendar = New GregorianCalendar()
    Console.WriteLine(value.ToString(thTH))
    ' The example displays the following output:
    '       28/5/2559 0:00:00
    '       28/5/2016 0:00:00
End Sub

Tworzysz instancję DateTime wartości, korzystając z elementów daty i godziny (liczba roku, miesiąca i dnia) określonego kalendarza, poprzez wywołanie konstruktora DateTime, który zawiera calendar parametr i przekazaniu mu obiektu reprezentującego ten Calendar kalendarz. W poniższym przykładzie użyto elementów daty i godziny z kalendarza ThaiBuddhistCalendar.

var thTH = new System.Globalization.CultureInfo("th-TH");
var dat = new DateTime(2559, 5, 28, thTH.DateTimeFormat.Calendar);
Console.WriteLine($"Thai Buddhist era date: {dat.ToString("d", thTH)}");
Console.WriteLine($"Gregorian date:   {dat:d}");
// The example displays the following output:
//       Thai Buddhist Era Date:  28/5/2559
//       Gregorian Date:     28/05/2016
let thTH = System.Globalization.CultureInfo "th-TH"
let dat = DateTime(2559, 5, 28, thTH.DateTimeFormat.Calendar)

printfn $"""Thai Buddhist era date: {dat.ToString("d", thTH)}"""
printfn $"Gregorian date:   {dat:d}"

// The example displays the following output:
//       Thai Buddhist Era Date:  28/5/2559
//       Gregorian Date:     28/05/2016
Dim thTH As New CultureInfo("th-TH")
Dim dat As New DateTime(2559, 5, 28, thTH.DateTimeFormat.Calendar)
Console.WriteLine($"Thai Buddhist Era date: {dat.ToString("d", thTH)}")
Console.WriteLine($"Gregorian date:   {dat:d}")
' The example displays the following output:
'       Thai Buddhist Era Date:  28/5/2559
'       Gregorian Date:     28/05/2016

DateTime konstruktory, które nie zawierają parametru calendar , zakładają, że elementy daty i godziny są wyrażone jako jednostki w kalendarzu gregoriańskim.

Wszystkie inne DateTime właściwości i metody używają kalendarza gregoriańskiego. Na przykład DateTime.Year właściwość zwraca rok w kalendarzu gregoriańskim, a DateTime.IsLeapYear(Int32) metoda zakłada, że year parametr jest rokiem w kalendarzu gregoriańskim. Każdy DateTime element członkowski używający kalendarza gregoriańskiego ma odpowiedni element członkowski Calendar klasy używającej określonego kalendarza. Na przykład Calendar.GetYear metoda zwraca rok w określonym kalendarzu, a Calendar.IsLeapYear metoda interpretuje year parametr jako numer roku w określonym kalendarzu. W poniższym przykładzie użyto zarówno DateTime, jak i odpowiadających im elementów klasy ThaiBuddhistCalendar.

var thTH = new System.Globalization.CultureInfo("th-TH");
var cal = thTH.DateTimeFormat.Calendar;
var dat = new DateTime(2559, 5, 28, cal);
Console.WriteLine("Using the Thai Buddhist Era calendar:");
Console.WriteLine($"Date: {dat.ToString("d", thTH)}");
Console.WriteLine($"Year: {cal.GetYear(dat)}");
Console.WriteLine($"Leap year: {cal.IsLeapYear(cal.GetYear(dat))}\n");

Console.WriteLine("Using the Gregorian calendar:");
Console.WriteLine($"Date: {dat:d}");
Console.WriteLine($"Year: {dat.Year}");
Console.WriteLine($"Leap year: {DateTime.IsLeapYear(dat.Year)}");
// The example displays the following output:
//       Using the Thai Buddhist Era calendar
//       Date :   28/5/2559
//       Year: 2559
//       Leap year :   True
//
//       Using the Gregorian calendar
//       Date :   28/05/2016
//       Year: 2016
//       Leap year :   True
let thTH = System.Globalization.CultureInfo "th-TH"
let cal = thTH.DateTimeFormat.Calendar
let dat = DateTime(2559, 5, 28, cal)
printfn "Using the Thai Buddhist Era calendar:"
printfn $"""Date: {dat.ToString("d", thTH)}"""
printfn $"Year: {cal.GetYear dat}"
printfn $"Leap year: {cal.IsLeapYear(cal.GetYear dat)}\n"

printfn "Using the Gregorian calendar:"
printfn $"Date: {dat:d}"
printfn $"Year: {dat.Year}"
printfn $"Leap year: {DateTime.IsLeapYear dat.Year}"

// The example displays the following output:
//       Using the Thai Buddhist Era calendar
//       Date :   28/5/2559
//       Year: 2559
//       Leap year :   True
//
//       Using the Gregorian calendar
//       Date :   28/05/2016
//       Year: 2016
//       Leap year :   True
Dim thTH As New CultureInfo("th-TH")
Dim cal As Calendar = thTH.DateTimeFormat.Calendar
Dim dat As New DateTime(2559, 5, 28, cal)
Console.WriteLine("Using the Thai Buddhist Era calendar:")
Console.WriteLine($"Date: {dat.ToString("d", thTH)}")
Console.WriteLine($"Year: {cal.GetYear(dat)}")
Console.WriteLine($"Leap year: {cal.IsLeapYear(cal.GetYear(dat))}")
Console.WriteLine()

Console.WriteLine("Using the Gregorian calendar:")
Console.WriteLine($"Date: {dat:d}")
Console.WriteLine($"Year: {dat.Year}")
Console.WriteLine($"Leap year: {DateTime.IsLeapYear(dat.Year)}")
' The example displays the following output:
'       Using the Thai Buddhist Era calendar
'       Date :   28/5/2559
'       Year: 2559
'       Leap year :   True
'
'       Using the Gregorian calendar
'       Date :   28/05/2016
'       Year: 2016
'       Leap year :   True

Struktura DateTime zawiera właściwość zwracającą DayOfWeek dzień tygodnia w kalendarzu gregoriańskim. Nie zawiera elementu, który umożliwia odczytanie numeru tygodnia roku. Aby pobrać tydzień roku, wywołaj metodę poszczególnego kalendarza Calendar.GetWeekOfYear. Poniższy przykład stanowi ilustrację.

var thTH = new System.Globalization.CultureInfo("th-TH");
var thCalendar = thTH.DateTimeFormat.Calendar;
var dat = new DateTime(1395, 8, 18, thCalendar);
Console.WriteLine("Using the Thai Buddhist Era calendar:");
Console.WriteLine($"Date: {dat.ToString("d", thTH)}");
Console.WriteLine($"Day of Week: {thCalendar.GetDayOfWeek(dat)}");
Console.WriteLine($"Week of year: {thCalendar.GetWeekOfYear(dat, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Sunday)}\n");

var greg = new System.Globalization.GregorianCalendar();
Console.WriteLine("Using the Gregorian calendar:");
Console.WriteLine($"Date: {dat:d}");
Console.WriteLine($"Day of Week: {dat.DayOfWeek}");
Console.WriteLine($"Week of year: {greg.GetWeekOfYear(dat, System.Globalization.CalendarWeekRule.FirstDay,DayOfWeek.Sunday)}");
// The example displays the following output:
//       Using the Thai Buddhist Era calendar
//       Date :  18/8/1395
//       Day of Week: Sunday
//       Week of year: 34
//
//       Using the Gregorian calendar
//       Date :  18/08/0852
//       Day of Week: Sunday
//       Week of year: 34
let thTH = System.Globalization.CultureInfo "th-TH"
let thCalendar = thTH.DateTimeFormat.Calendar
let dat = DateTime(1395, 8, 18, thCalendar)
printfn "Using the Thai Buddhist Era calendar:"
printfn $"""Date: {dat.ToString("d", thTH)}"""
printfn $"Day of Week: {thCalendar.GetDayOfWeek dat}"
printfn $"Week of year: {thCalendar.GetWeekOfYear(dat, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Sunday)}\n"

let greg = System.Globalization.GregorianCalendar()
printfn "Using the Gregorian calendar:"
printfn $"Date: {dat:d}"
printfn $"Day of Week: {dat.DayOfWeek}"
printfn $"Week of year: {greg.GetWeekOfYear(dat, System.Globalization.CalendarWeekRule.FirstDay, DayOfWeek.Sunday)}"

// The example displays the following output:
//       Using the Thai Buddhist Era calendar
//       Date :  18/8/1395
//       Day of Week: Sunday
//       Week of year: 34
//
//       Using the Gregorian calendar
//       Date :  18/08/0852
//       Day of Week: Sunday
//       Week of year: 34
Dim thTH As New CultureInfo("th-TH")
Dim thCalendar As Calendar = thTH.DateTimeFormat.Calendar
Dim dat As New DateTime(1395, 8, 18, thCalendar)
Console.WriteLine("Using the Thai Buddhist Era calendar:")
Console.WriteLine($"Date: {dat.ToString("d", thTH)}")
Console.WriteLine($"Day of Week: {thCalendar.GetDayOfWeek(dat)}")
Console.WriteLine($"Week of year: {thCalendar.GetWeekOfYear(dat, CalendarWeekRule.FirstDay, DayOfWeek.Sunday)}")
Console.WriteLine()

Dim greg As Calendar = New GregorianCalendar()
Console.WriteLine("Using the Gregorian calendar:")
Console.WriteLine($"Date: {dat:d}")
Console.WriteLine($"Day of Week: {dat.DayOfWeek}")
Console.WriteLine($"Week of year: {greg.GetWeekOfYear(dat, CalendarWeekRule.FirstDay, DayOfWeek.Sunday)}")
' The example displays the following output:
'       Using the Thai Buddhist Era calendar
'       Date :  18/8/1395
'       Day of Week: Sunday
'       Week of year: 34
'       
'       Using the Gregorian calendar
'       Date :  18/08/0852
'       Day of Week: Sunday
'       Week of year: 34

Aby uzyskać więcej informacji na temat dat i kalendarzy, zobacz Praca z kalendarzami.

Utrwalanie wartości daty/godziny

Wartości można utrwalać DateTime na następujące sposoby:

Należy upewnić się, że rutyna, która przywraca DateTime wartości, nie traci danych ani nie zgłasza wyjątku niezależnie od wybranej techniki. DateTime wartości powinny pozostać niezmienione po powrocie. Oznacza to, że oryginalna wartość i przywrócona wartość powinny być takie same. A jeśli oryginalna DateTime wartość reprezentuje pojedynczy moment w czasie, powinna identyfikować ten sam moment w czasie, gdy zostanie przywrócona.

Utrwalaj wartości jako ciągi znaków

Aby pomyślnie przywrócić DateTime wartości utrwalone jako ciągi, wykonaj następujące reguły:

  • Należy przyjąć te same założenia dotyczące formatowania specyficznego dla kultury podczas przywracania ciągu, co podczas jego utrwalania. Aby upewnić się, że ciąg można przywrócić w systemie, którego bieżąca kultura różni się od kultury systemu, na którym został zapisany, wywołaj wersję przeciążonej funkcji ToString, aby zapisać ciąg według konwencji niezmiennej kultury. Wywołaj metodę Parse(String, IFormatProvider, DateTimeStyles) lub TryParse(String, IFormatProvider, DateTimeStyles, DateTime), aby przywrócić tekst zgodnie z zasadami kultury niezmiennej. Nigdy nie używaj przeciążeń ToString(), Parse(String) lub TryParse(String, DateTime), które wykorzystują konwencje bieżącej kultury.

  • Jeśli data reprezentuje pojedynczą chwilę czasu, upewnij się, że reprezentuje ona ten sam moment w czasie, gdy zostanie przywrócona, nawet w innej strefie czasowej. Przekonwertuj DateTime wartość na uniwersalny czas koordynowany (UTC) przed zapisaniem go lub użyj polecenia DateTimeOffset.

Najczęstszym błędem występującym podczas utrwalania DateTime wartości jako ciągów jest poleganie na konwencjach formatowania domyślnej lub bieżącej kultury. Występują problemy, jeśli bieżąca kultura jest inna podczas zapisywania lub przywracania ciągów. Poniższy przykład ilustruje te problemy. Zapisuje pięć dat przy użyciu konwencji formatowania bieżącej kultury, która w tym przypadku jest angielska (Stany Zjednoczone). Przywraca daty przy użyciu konwencji formatowania innej kultury, która w tym przypadku jest angielska (Wielka Brytania). Ponieważ konwencje formatowania dwóch kultur są różne, nie można przywrócić dwóch dat, a pozostałe trzy daty są interpretowane niepoprawnie. Ponadto jeśli oryginalne wartości daty i godziny reprezentują pojedyncze momenty w czasie, przywrócone czasy są niepoprawne, ponieważ informacje o strefie czasowej zostaną utracone.

public static void PersistAsLocalStrings()
{
    SaveLocalDatesAsString();
    RestoreLocalDatesFromString();
}

private static void SaveLocalDatesAsString()
{
    DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0),
                   new DateTime(2014, 7, 10, 23, 49, 0),
                   new DateTime(2015, 1, 10, 1, 16, 0),
                   new DateTime(2014, 12, 20, 21, 45, 0),
                   new DateTime(2014, 6, 2, 15, 14, 0) };
    string? output = null;

    Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
    Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
    for (int ctr = 0; ctr < dates.Length; ctr++)
    {
        Console.WriteLine(dates[ctr].ToString("f"));
        output += dates[ctr].ToString() + (ctr != dates.Length - 1 ? "|" : "");
    }
    var sw = new StreamWriter(filenameTxt);
    sw.Write(output);
    sw.Close();
    Console.WriteLine("Saved dates...");
}

private static void RestoreLocalDatesFromString()
{
    TimeZoneInfo.ClearCachedData();
    Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
    Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
    StreamReader sr = new StreamReader(filenameTxt);
    string[] inputValues = sr.ReadToEnd().Split(new char[] { '|' },
                                                StringSplitOptions.RemoveEmptyEntries);
    sr.Close();
    Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
    foreach (var inputValue in inputValues)
    {
        DateTime dateValue;
        if (DateTime.TryParse(inputValue, out dateValue))
        {
            Console.WriteLine($"'{inputValue}' --> {dateValue:f}");
        }
        else
        {
            Console.WriteLine($"Cannot parse '{inputValue}'");
        }
    }
    Console.WriteLine("Restored dates...");
}
// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       Cannot parse //6/14/2014 6:32:00 AM//
//       //7/10/2014 11:49:00 PM// --> 07 October 2014 23:49
//       //1/10/2015 1:16:00 AM// --> 01 October 2015 01:16
//       Cannot parse //12/20/2014 9:45:00 PM//
//       //6/2/2014 3:14:00 PM// --> 06 February 2014 15:14
//       Restored dates...
let saveLocalDatesAsString () =
    let dates = 
        [ DateTime(2014, 6, 14, 6, 32, 0)
          DateTime(2014, 7, 10, 23, 49, 0)
          DateTime(2015, 1, 10, 1, 16, 0)
          DateTime(2014, 12, 20, 21, 45, 0)
          DateTime(2014, 6, 2, 15, 14, 0) ]

    printfn $"Current Time Zone: {TimeZoneInfo.Local.DisplayName}"
    printfn $"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:"

    let output =
        [ for date in dates do
            printfn $"{date}"
            string date ]
        |> String.concat "|"

    use sw = new StreamWriter(filenameTxt)
    sw.Write output
    printfn "Saved dates..."

let restoreLocalDatesFromString () =
    TimeZoneInfo.ClearCachedData()
    printfn $"Current Time Zone: {TimeZoneInfo.Local.DisplayName}"
    Thread.CurrentThread.CurrentCulture <- CultureInfo.CreateSpecificCulture "en-GB"

    use sr = new StreamReader(filenameTxt)
    let inputValues = 
        sr.ReadToEnd().Split('|', StringSplitOptions.RemoveEmptyEntries)

    printfn $"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:"

    for inputValue in inputValues do
        match DateTime.TryParse inputValue with
        | true, dateValue ->
            printfn $"'{inputValue}' --> {dateValue:f}"
        | _ ->
            printfn $"Cannot parse '{inputValue}'"

    printfn "Restored dates..."

let persistAsLocalStrings () =
    saveLocalDatesAsString ()
    restoreLocalDatesFromString ()

// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       Cannot parse //6/14/2014 6:32:00 AM//
//       //7/10/2014 11:49:00 PM// --> 07 October 2014 23:49
//       //1/10/2015 1:16:00 AM// --> 01 October 2015 01:16
//       Cannot parse //12/20/2014 9:45:00 PM//
//       //6/2/2014 3:14:00 PM// --> 06 February 2014 15:14
//       Restored dates...

Aby pomyślnie zaokrąglić DateTime wartości, wykonaj następujące kroki:

  1. Jeśli wartości reprezentują pojedyncze chwile czasu, przekonwertuj je z czasu lokalnego na UTC, wywołując metodę ToUniversalTime .
  2. Przekonwertuj daty na ich reprezentacje łańcuchów, wywołując przeciążenie ToString(String, IFormatProvider) lub String.Format(IFormatProvider, String, Object[]). Użyj konwencji formatowania niezmiennej kultury, podając CultureInfo.InvariantCulture jako argument provider. Określ, że wartość powinna być zaokrąglana przy użyciu standardowego ciągu formatu "O" lub "R".

Aby przywrócić utrwalone DateTime wartości bez utraty danych, wykonaj następujące kroki:

  1. Przeanalizuj dane, wywołując przeciążenie ParseExact lub TryParseExact. Określ CultureInfo.InvariantCulture jako provider argument i użyj tego samego standardowego ciągu formatu, który został użyty dla argumentu format podczas konwersji. Uwzględnij wartość DateTimeStyles.RoundtripKind w argumencie styles.
  2. DateTime Jeśli wartości reprezentują pojedyncze momenty w czasie, wywołaj metodę ToLocalTime , aby przekonwertować przeanalizowaną datę z czasu UTC na czas lokalny.

W poniższym przykładzie użyto niezmiennej kultury i standardowego ciągu formatu "O", aby upewnić się, że DateTime wartości zapisane i przywrócone reprezentują ten sam moment w czasie, niezależnie od systemu, kultury lub strefy czasowej systemów źródłowych i docelowych.

public static void PersistAsInvariantStrings()
{
    SaveDatesAsInvariantStrings();
    RestoreDatesAsInvariantStrings();
}

private static void SaveDatesAsInvariantStrings()
{
    DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0),
                   new DateTime(2014, 7, 10, 23, 49, 0),
                   new DateTime(2015, 1, 10, 1, 16, 0),
                   new DateTime(2014, 12, 20, 21, 45, 0),
                   new DateTime(2014, 6, 2, 15, 14, 0) };
    string? output = null;

    Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
    Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
    for (int ctr = 0; ctr < dates.Length; ctr++)
    {
        Console.WriteLine(dates[ctr].ToString("f"));
        output += dates[ctr].ToUniversalTime().ToString("O", CultureInfo.InvariantCulture)
                  + (ctr != dates.Length - 1 ? "|" : "");
    }
    var sw = new StreamWriter(filenameTxt);
    sw.Write(output);
    sw.Close();
    Console.WriteLine("Saved dates...");
}

private static void RestoreDatesAsInvariantStrings()
{
    TimeZoneInfo.ClearCachedData();
    Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
    Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
    StreamReader sr = new StreamReader(filenameTxt);
    string[] inputValues = sr.ReadToEnd().Split(new char[] { '|' },
                                                StringSplitOptions.RemoveEmptyEntries);
    sr.Close();
    Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
    foreach (var inputValue in inputValues)
    {
        DateTime dateValue;
        if (DateTime.TryParseExact(inputValue, "O", CultureInfo.InvariantCulture,
                              DateTimeStyles.RoundtripKind, out dateValue))
        {
            Console.WriteLine($"'{inputValue}' --> {dateValue.ToLocalTime():f}");
        }
        else
        {
            Console.WriteLine($"Cannot parse '{inputValue}'");
        }
    }
    Console.WriteLine("Restored dates...");
}
// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       '2014-06-14T13:32:00.0000000Z' --> 14 June 2014 14:32
//       '2014-07-11T06:49:00.0000000Z' --> 11 July 2014 07:49
//       '2015-01-10T09:16:00.0000000Z' --> 10 January 2015 09:16
//       '2014-12-21T05:45:00.0000000Z' --> 21 December 2014 05:45
//       '2014-06-02T22:14:00.0000000Z' --> 02 June 2014 23:14
//       Restored dates...
let saveDatesAsInvariantStrings () =
    let dates = 
        [ DateTime(2014, 6, 14, 6, 32, 0)
          DateTime(2014, 7, 10, 23, 49, 0)
          DateTime(2015, 1, 10, 1, 16, 0)
          DateTime(2014, 12, 20, 21, 45, 0)
          DateTime(2014, 6, 2, 15, 14, 0) ]

    printfn $"Current Time Zone: {TimeZoneInfo.Local.DisplayName}"
    printfn $"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:"

    let output =
        [ for date in dates do
            printfn $"{date:f}"
            date.ToUniversalTime().ToString("O", CultureInfo.InvariantCulture) ]
        |> String.concat "|"

    use sw = new StreamWriter(filenameTxt)
    sw.Write output
    printfn "Saved dates..."

let restoreDatesAsInvariantStrings () =
    TimeZoneInfo.ClearCachedData()
    printfn $"Current Time Zone: {TimeZoneInfo.Local.DisplayName}"
    Thread.CurrentThread.CurrentCulture <- CultureInfo.CreateSpecificCulture "en-GB"
    
    use sr = new StreamReader(filenameTxt)
    let inputValues = 
        sr.ReadToEnd().Split('|', StringSplitOptions.RemoveEmptyEntries)

    printfn $"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:"

    for inputValue in inputValues do
        match DateTime.TryParseExact(inputValue, "O", CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind) with
        | true, dateValue ->
            printfn $"'{inputValue}' --> {dateValue.ToLocalTime():f}"
        | _ ->
            printfn $"Cannot parse '{inputValue}'"

    printfn "Restored dates..."

let persistAsInvariantStrings () =
    saveDatesAsInvariantStrings ()
    restoreDatesAsInvariantStrings ()

// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       '2014-06-14T13:32:00.0000000Z' --> 14 June 2014 14:32
//       '2014-07-11T06:49:00.0000000Z' --> 11 July 2014 07:49
//       '2015-01-10T09:16:00.0000000Z' --> 10 January 2015 09:16
//       '2014-12-21T05:45:00.0000000Z' --> 21 December 2014 05:45
//       '2014-06-02T22:14:00.0000000Z' --> 02 June 2014 23:14
//       Restored dates...

Utrwalanie wartości jako liczby całkowite

Możesz zapisać datę i godzinę jako wartość Int64, która reprezentuje liczbę tików. W takim przypadku nie trzeba brać pod uwagę kultury systemów, na DateTime których są utrwalane i przywracane wartości.

Aby utrwałyć DateTime wartość jako liczbę całkowitą:

  1. DateTime Jeśli wartości reprezentują pojedyncze chwile w czasie, przekonwertuj je na utc, wywołując metodę ToUniversalTime .
  2. Pobierz liczbę znaczników reprezentowaną przez wartość DateTime z właściwości Ticks.

Aby przywrócić wartość DateTime, która została zapisana jako liczba całkowita:

  1. Utwórz nowe wystąpienie obiektu DateTime, przekazując wartość Int64 do konstruktora DateTime(Int64).
  2. DateTime Jeśli wartość reprezentuje pojedynczą chwilę w czasie, przekonwertuj ją z czasu UTC na czas lokalny, wywołując metodę ToLocalTime .

W poniższym przykładzie tablica wartości DateTime jest utrwalana jako liczby całkowite w systemie w strefie czasowej Pacyfiku USA. Przywraca dane do systemu z ustawioną strefą czasową UTC. Plik zawierający liczby całkowite zawiera wartość Int32, która wskazuje całkowitą liczbę wartości Int64, które natychmiast po niej następują.

public static void PersistAsIntegers()
{
    SaveDatesAsInts();
    RestoreDatesAsInts();
}

private static void SaveDatesAsInts()
{
    DateTime[] dates = { new DateTime(2014, 6, 14, 6, 32, 0),
                   new DateTime(2014, 7, 10, 23, 49, 0),
                   new DateTime(2015, 1, 10, 1, 16, 0),
                   new DateTime(2014, 12, 20, 21, 45, 0),
                   new DateTime(2014, 6, 2, 15, 14, 0) };

    Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
    Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
    var ticks = new long[dates.Length];
    for (int ctr = 0; ctr < dates.Length; ctr++)
    {
        Console.WriteLine(dates[ctr].ToString("f"));
        ticks[ctr] = dates[ctr].ToUniversalTime().Ticks;
    }
    var fs = new FileStream(filenameInts, FileMode.Create);
    var bw = new BinaryWriter(fs);
    bw.Write(ticks.Length);
    foreach (var tick in ticks)
        bw.Write(tick);

    bw.Close();
    Console.WriteLine("Saved dates...");
}

private static void RestoreDatesAsInts()
{
    TimeZoneInfo.ClearCachedData();
    Console.WriteLine($"Current Time Zone: {TimeZoneInfo.Local.DisplayName}");
    Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
    FileStream fs = new FileStream(filenameInts, FileMode.Open);
    BinaryReader br = new BinaryReader(fs);
    int items;
    DateTime[] dates;

    try
    {
        items = br.ReadInt32();
        dates = new DateTime[items];

        for (int ctr = 0; ctr < items; ctr++)
        {
            long ticks = br.ReadInt64();
            dates[ctr] = new DateTime(ticks).ToLocalTime();
        }
    }
    catch (EndOfStreamException)
    {
        Console.WriteLine("File corruption detected. Unable to restore data...");
        return;
    }
    catch (IOException)
    {
        Console.WriteLine("Unspecified I/O error. Unable to restore data...");
        return;
    }
    // Thrown during array initialization.
    catch (OutOfMemoryException)
    {
        Console.WriteLine("File corruption detected. Unable to restore data...");
        return;
    }
    finally
    {
        br.Close();
    }

    Console.WriteLine($"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:");
    foreach (var value in dates)
        Console.WriteLine(value.ToString("f"));

    Console.WriteLine("Restored dates...");
}
// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       14 June 2014 14:32
//       11 July 2014 07:49
//       10 January 2015 09:16
//       21 December 2014 05:45
//       02 June 2014 23:14
//       Restored dates...
let saveDatesAsInts () =
    let dates = 
        [ DateTime(2014, 6, 14, 6, 32, 0)
          DateTime(2014, 7, 10, 23, 49, 0)
          DateTime(2015, 1, 10, 1, 16, 0)
          DateTime(2014, 12, 20, 21, 45, 0)
          DateTime(2014, 6, 2, 15, 14, 0) ]

    printfn $"Current Time Zone: {TimeZoneInfo.Local.DisplayName}"
    printfn $"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:"
    let ticks =
        [| for date in dates do
            printfn $"{date:f}"
            date.ToUniversalTime().Ticks |]
    use fs = new FileStream(filenameInts, FileMode.Create)
    use bw = new BinaryWriter(fs)
    bw.Write ticks.Length

    for tick in ticks do
        bw.Write tick

    printfn "Saved dates..."

let restoreDatesAsInts () =
    TimeZoneInfo.ClearCachedData()
    printfn $"Current Time Zone: {TimeZoneInfo.Local.DisplayName}"
    Thread.CurrentThread.CurrentCulture <- CultureInfo.CreateSpecificCulture "en-GB"
    use fs = new FileStream(filenameInts, FileMode.Open)
    use br = new BinaryReader(fs)

    try
        let items = br.ReadInt32()
        let dates =
            [| for _ in 0..items do
                let ticks = br.ReadInt64()
                DateTime(ticks).ToLocalTime() |]

        printfn $"The dates on an {Thread.CurrentThread.CurrentCulture.Name} system:"
        for value in dates do
            printfn $"{value:f}"
    with 
    | :? EndOfStreamException ->
        printfn "File corruption detected. Unable to restore data..."
    | :? IOException ->
        printfn "Unspecified I/O error. Unable to restore data..."
    // Thrown during array initialization.
    | :? OutOfMemoryException ->
        printfn"File corruption detected. Unable to restore data..."

    printfn "Restored dates..."

let persistAsIntegers () =
    saveDatesAsInts ()
    restoreDatesAsInts ()

// When saved on an en-US system, the example displays the following output:
//       Current Time Zone: (UTC-08:00) Pacific Time (US & Canada)
//       The dates on an en-US system:
//       Saturday, June 14, 2014 6:32 AM
//       Thursday, July 10, 2014 11:49 PM
//       Saturday, January 10, 2015 1:16 AM
//       Saturday, December 20, 2014 9:45 PM
//       Monday, June 02, 2014 3:14 PM
//       Saved dates...
//
// When restored on an en-GB system, the example displays the following output:
//       Current Time Zone: (UTC) Dublin, Edinburgh, Lisbon, London
//       The dates on an en-GB system:
//       14 June 2014 14:32
//       11 July 2014 07:49
//       10 January 2015 09:16
//       21 December 2014 05:45
//       02 June 2014 23:14
//       Restored dates...

Serializowanie wartości DateTime

Wartości można utrwalać za pomocą serializacji do strumienia lub pliku, a następnie przywrócić je za pomocą deserializacji. DateTime dane są serializowane w określonym formacie obiektu. Obiekty są przywracane podczas deserializacji. Formatator lub serializator, taki jak JsonSerializer lub XmlSerializer, obsługuje proces serializacji i deserializacji. Aby uzyskać więcej informacji na temat serializacji i typów serializacji obsługiwanych przez platformę .NET, zobacz Serializacja.

W poniższym przykładzie użyto XmlSerializer klasy do serializacji i deserializacji DateTime wartości. Wartości reprezentują wszystkie dni roku przestępnego w XXI wieku. Dane wyjściowe reprezentują wynik, jeśli przykład jest uruchamiany w systemie, którego bieżąca kultura to angielski (Wielka Brytania). Ponieważ zdeserializowałeś sam obiekt DateTime, kod nie musi obsługiwać różnic kulturowych w formatach daty i godziny.

public static void PersistAsXML()
{
    // Serialize the data.
    var leapYears = new List<DateTime>();
    for (int year = 2000; year <= 2100; year += 4)
    {
        if (DateTime.IsLeapYear(year))
            leapYears.Add(new DateTime(year, 2, 29));
    }
    DateTime[] dateArray = leapYears.ToArray();

    var serializer = new XmlSerializer(dateArray.GetType());
    TextWriter sw = new StreamWriter(filenameXml);

    try
    {
        serializer.Serialize(sw, dateArray);
    }
    catch (InvalidOperationException e)
    {
        Console.WriteLine(e.InnerException?.Message);
    }
    finally
    {
        if (sw != null) sw.Close();
    }

    // Deserialize the data.
    DateTime[]? deserializedDates;
    using (var fs = new FileStream(filenameXml, FileMode.Open))
    {
        deserializedDates = (DateTime[]?)serializer.Deserialize(fs);
    }

    // Display the dates.
    Console.WriteLine($"Leap year days from 2000-2100 on an {Thread.CurrentThread.CurrentCulture.Name} system:");
    int nItems = 0;
    if (deserializedDates is not null)
    {
        foreach (var dat in deserializedDates)
        {
            Console.Write($"   {dat:d}     ");
            nItems++;
            if (nItems % 5 == 0)
                Console.WriteLine();
        }
    }
}
// The example displays the following output:
//    Leap year days from 2000-2100 on an en-GB system:
//       29/02/2000       29/02/2004       29/02/2008       29/02/2012       29/02/2016
//       29/02/2020       29/02/2024       29/02/2028       29/02/2032       29/02/2036
//       29/02/2040       29/02/2044       29/02/2048       29/02/2052       29/02/2056
//       29/02/2060       29/02/2064       29/02/2068       29/02/2072       29/02/2076
//       29/02/2080       29/02/2084       29/02/2088       29/02/2092       29/02/2096
let persistAsXML () =
    // Serialize the data.
    let leapYears =
        [| for year in 2000..4..2100 do
            if DateTime.IsLeapYear year then
                DateTime(year, 2, 29) |]

    let serializer = XmlSerializer(leapYears.GetType())
    use sw = new StreamWriter(filenameXml)

    try
        serializer.Serialize(sw, leapYears)
    with :? InvalidOperationException as e ->
        printfn $"{e.InnerException.Message}"

    // Deserialize the data.
    use fs = new FileStream(filenameXml, FileMode.Open)
        
    let deserializedDates = serializer.Deserialize fs :?> DateTime []

    // Display the dates.
    printfn $"Leap year days from 2000-2100 on an {Thread.CurrentThread.CurrentCulture.Name} system:"
    
    let mutable nItems = 0
    for dat in deserializedDates do
        printf $"   {dat:d}     "
        nItems <- nItems + 1
        if nItems % 5 = 0 then
            printfn ""

// The example displays the following output:
//    Leap year days from 2000-2100 on an en-GB system:
//       29/02/2000       29/02/2004       29/02/2008       29/02/2012       29/02/2016
//       29/02/2020       29/02/2024       29/02/2028       29/02/2032       29/02/2036
//       29/02/2040       29/02/2044       29/02/2048       29/02/2052       29/02/2056
//       29/02/2060       29/02/2064       29/02/2068       29/02/2072       29/02/2076
//       29/02/2080       29/02/2084       29/02/2088       29/02/2092       29/02/2096

Poprzedni przykład nie zawiera informacji o czasie. DateTime Jeśli wartość reprezentuje moment w czasie i jest wyrażona jako czas lokalny, przekonwertuj ją z czasu lokalnego na UTC przed serializacji, wywołując metodę ToUniversalTime . Po deserializacji przekonwertuj ją z czasu UTC na czas lokalny, wywołując metodę ToLocalTime .

DateTime a TimeSpan

Typy DateTime wartości i TimeSpan różnią się tym, że DateTime reprezentuje moment w czasie, podczas gdy TimeSpan reprezentuje interwał czasu. Można odjąć jedno wystąpienie DateTime z innego, aby uzyskać TimeSpan obiekt reprezentujący przedział czasu między nimi. Możesz też dodać wynik dodatni TimeSpan do bieżącego DateTime , aby uzyskać DateTime wartość reprezentującą przyszłą datę.

Możesz dodać lub odjąć interwał czasu z DateTime obiektu. Przedziały czasu mogą być ujemne lub dodatnie i mogą być wyrażone w jednostkach, takich jak znaczniki, sekundy lub jako TimeSpan obiekt.

Porównaj pod kątem równości z uwzględnieniem tolerancji

Porównania równości wartości DateTime są dokładne. Aby uznać za równe, dwie wartości muszą być wyrażone jako ta sama liczba kleszczy. Ta precyzja jest często niepotrzebna lub nawet niepoprawna dla wielu aplikacji. Często chcesz sprawdzić, czy DateTime obiekty są w przybliżeniu równe.

W poniższym przykładzie pokazano, jak porównać mniej więcej równoważne DateTime wartości. Przyjmuje niewielki margines różnicy przy deklarowaniu ich jako równych.

public static bool RoughlyEquals(DateTime time, DateTime timeWithWindow, int windowInSeconds, int frequencyInSeconds)
{
    long delta = (long)((TimeSpan)(timeWithWindow - time)).TotalSeconds % frequencyInSeconds;
    delta = delta > windowInSeconds ? frequencyInSeconds - delta : delta;
    return Math.Abs(delta) < windowInSeconds;
}

public static void TestRoughlyEquals()
{
    int window = 10;
    int freq = 60 * 60 * 2; // 2 hours;

    DateTime d1 = DateTime.Now;

    DateTime d2 = d1.AddSeconds(2 * window);
    DateTime d3 = d1.AddSeconds(-2 * window);
    DateTime d4 = d1.AddSeconds(window / 2);
    DateTime d5 = d1.AddSeconds(-window / 2);

    DateTime d6 = (d1.AddHours(2)).AddSeconds(2 * window);
    DateTime d7 = (d1.AddHours(2)).AddSeconds(-2 * window);
    DateTime d8 = (d1.AddHours(2)).AddSeconds(window / 2);
    DateTime d9 = (d1.AddHours(2)).AddSeconds(-window / 2);

    Console.WriteLine($"d1 ({d1}) ~= d1 ({d1}): {RoughlyEquals(d1, d1, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d2 ({d2}): {RoughlyEquals(d1, d2, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d3 ({d3}): {RoughlyEquals(d1, d3, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d4 ({d4}): {RoughlyEquals(d1, d4, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d5 ({d5}): {RoughlyEquals(d1, d5, window, freq)}");

    Console.WriteLine($"d1 ({d1}) ~= d6 ({d6}): {RoughlyEquals(d1, d6, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d7 ({d7}): {RoughlyEquals(d1, d7, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d8 ({d8}): {RoughlyEquals(d1, d8, window, freq)}");
    Console.WriteLine($"d1 ({d1}) ~= d9 ({d9}): {RoughlyEquals(d1, d9, window, freq)}");
}
// The example displays output similar to the following:
//    d1 (1/28/2010 9:01:26 PM) ~= d1 (1/28/2010 9:01:26 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d2 (1/28/2010 9:01:46 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d3 (1/28/2010 9:01:06 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d4 (1/28/2010 9:01:31 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d5 (1/28/2010 9:01:21 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d6 (1/28/2010 11:01:46 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d7 (1/28/2010 11:01:06 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d8 (1/28/2010 11:01:31 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d9 (1/28/2010 11:01:21 PM): True
let roughlyEquals (time: DateTime) (timeWithWindow: DateTime) windowInSeconds frequencyInSeconds =
    let delta = 
        int64 (timeWithWindow - time).TotalSeconds % frequencyInSeconds
    
    let delta = if delta > windowInSeconds then frequencyInSeconds - delta else delta
    abs delta < windowInSeconds

let testRoughlyEquals () =
    let window = 10
    let window' = 10.
    let freq = 60 * 60 * 2 // 2 hours

    let d1 = DateTime.Now

    let d2 = d1.AddSeconds(2. * window')
    let d3 = d1.AddSeconds(-2. * window')
    let d4 = d1.AddSeconds(window' / 2.)
    let d5 = d1.AddSeconds(-window' / 2.)

    let d6 = (d1.AddHours 2).AddSeconds(2. * window')
    let d7 = (d1.AddHours 2).AddSeconds(-2. * window')
    let d8 = (d1.AddHours 2).AddSeconds(window' / 2.)
    let d9 = (d1.AddHours 2).AddSeconds(-window' / 2.)

    printfn $"d1 ({d1}) ~= d1 ({d1}): {roughlyEquals d1 d1 window freq}"
    printfn $"d1 ({d1}) ~= d2 ({d2}): {roughlyEquals d1 d2 window freq}"
    printfn $"d1 ({d1}) ~= d3 ({d3}): {roughlyEquals d1 d3 window freq}"
    printfn $"d1 ({d1}) ~= d4 ({d4}): {roughlyEquals d1 d4 window freq}"
    printfn $"d1 ({d1}) ~= d5 ({d5}): {roughlyEquals d1 d5 window freq}"

    printfn $"d1 ({d1}) ~= d6 ({d6}): {roughlyEquals d1 d6 window freq}"
    printfn $"d1 ({d1}) ~= d7 ({d7}): {roughlyEquals d1 d7 window freq}"
    printfn $"d1 ({d1}) ~= d8 ({d8}): {roughlyEquals d1 d8 window freq}"
    printfn $"d1 ({d1}) ~= d9 ({d9}): {roughlyEquals d1 d9 window freq}"

// The example displays output similar to the following:
//    d1 (1/28/2010 9:01:26 PM) ~= d1 (1/28/2010 9:01:26 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d2 (1/28/2010 9:01:46 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d3 (1/28/2010 9:01:06 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d4 (1/28/2010 9:01:31 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d5 (1/28/2010 9:01:21 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d6 (1/28/2010 11:01:46 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d7 (1/28/2010 11:01:06 PM): False
//    d1 (1/28/2010 9:01:26 PM) ~= d8 (1/28/2010 11:01:31 PM): True
//    d1 (1/28/2010 9:01:26 PM) ~= d9 (1/28/2010 11:01:21 PM): True
Public Shared Function RoughlyEquals(time As DateTime, timeWithWindow As DateTime,
                             windowInSeconds As Integer,
                             frequencyInSeconds As Integer) As Boolean
    Dim delta As Long = (timeWithWindow.Subtract(time)).TotalSeconds _
                                            Mod frequencyInSeconds

    If delta > windowInSeconds Then
        delta = frequencyInSeconds - delta
    End If

    Return Math.Abs(delta) < windowInSeconds
End Function

Public Shared Sub TestRoughlyEquals()
    Dim window As Integer = 10
    Dim freq As Integer = 60 * 60 * 2 ' 2 hours;
    Dim d1 As DateTime = DateTime.Now

    Dim d2 As DateTime = d1.AddSeconds(2 * window)
    Dim d3 As DateTime = d1.AddSeconds(-2 * window)
    Dim d4 As DateTime = d1.AddSeconds(window / 2)
    Dim d5 As DateTime = d1.AddSeconds(-window / 2)

    Dim d6 As DateTime = d1.AddHours(2).AddSeconds(2 * window)
    Dim d7 As DateTime = d1.AddHours(2).AddSeconds(-2 * window)
    Dim d8 As DateTime = d1.AddHours(2).AddSeconds(window / 2)
    Dim d9 As DateTime = d1.AddHours(2).AddSeconds(-window / 2)

    Console.WriteLine($"d1 ({d1}) ~= d1 ({d1}): {RoughlyEquals(d1, d1, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d2 ({d2}): {RoughlyEquals(d1, d2, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d3 ({d3}): {RoughlyEquals(d1, d3, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d4 ({d4}): {RoughlyEquals(d1, d4, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d5 ({d5}): {RoughlyEquals(d1, d5, window, freq)}")

    Console.WriteLine($"d1 ({d1}) ~= d6 ({d6}): {RoughlyEquals(d1, d6, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d7 ({d7}): {RoughlyEquals(d1, d7, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d8 ({d8}): {RoughlyEquals(d1, d8, window, freq)}")
    Console.WriteLine($"d1 ({d1}) ~= d9 ({d9}): {RoughlyEquals(d1, d9, window, freq)}")
End Sub
' The example displays output similar to the following:
'    d1 (1/28/2010 9:01:26 PM) ~= d1 (1/28/2010 9:01:26 PM): True
'    d1 (1/28/2010 9:01:26 PM) ~= d2 (1/28/2010 9:01:46 PM): False
'    d1 (1/28/2010 9:01:26 PM) ~= d3 (1/28/2010 9:01:06 PM): False
'    d1 (1/28/2010 9:01:26 PM) ~= d4 (1/28/2010 9:01:31 PM): True
'    d1 (1/28/2010 9:01:26 PM) ~= d5 (1/28/2010 9:01:21 PM): True
'    d1 (1/28/2010 9:01:26 PM) ~= d6 (1/28/2010 11:01:46 PM): False
'    d1 (1/28/2010 9:01:26 PM) ~= d7 (1/28/2010 11:01:06 PM): False
'    d1 (1/28/2010 9:01:26 PM) ~= d8 (1/28/2010 11:01:31 PM): True
'    d1 (1/28/2010 9:01:26 PM) ~= d9 (1/28/2010 11:01:21 PM): True

Zagadnienia dotyczące interoperacyjności modelu COM

Wartość DateTime, która jest przekazywana do aplikacji COM, a następnie przenoszona z powrotem do aplikacji zarządzanej, jest określana jako obiegowa. Jednak wartość DateTime określająca tylko czas nie pozwala na ponowne konwertowanie zgodnie z oczekiwaniami.

Jeśli określona jest tylko godzina, na przykład 13:00, ostateczna data i godzina to 30 grudnia 1899 n.e. o godzinie 13:00, zamiast 1 stycznia 0001 n.e. o godzinie 13:00. .NET i COM zakładają domyślną datę, gdy określona jest tylko godzina. Jednak system COM zakłada datę bazową 30 grudnia 1899 R., podczas gdy platforma .NET zakłada datę bazową 1 stycznia 0001 R.

Gdy tylko czas jest przekazywany z platformy .NET do modelu COM, wykonywane jest specjalne przetwarzanie, które konwertuje czas na format używany przez com. Gdy z modelu COM do platformy .NET przekazywany jest jedynie czas, nie jest wykonywane żadne specjalne przetwarzanie, ponieważ mogłoby to uszkodzić prawidłowe daty i godziny z dnia 30 grudnia 1899 r. lub wcześniejsze. Jeśli data rozpoczyna swoją podróż okrężną z COM, .NET i COM zachowują datę.

Zachowanie platformy .NET i modelu COM oznacza, że jeśli Twoja aplikacja przetwarza obiekt DateTime, który określa tylko godzinę, musi pamiętać o zmodyfikowaniu lub zignorowaniu błędnej daty w końcowym obiekcie DateTime.