Dela via


System.DateTime-struktur

Anmärkning

Den här artikeln innehåller ytterligare kommentarer till referensdokumentationen för det här API:et.

Viktigt!

Epoker i de japanska kalendrarna baseras på kejsarens regeringstid och förväntas därför förändras. Den 1 maj 2019 markerade till exempel början av Reiwa-eran i JapaneseCalendar och JapaneseLunisolarCalendar. En sådan ändring av era påverkar alla program som använder dessa kalendrar. Mer information och för att avgöra om dina program påverkas finns i Hantera en ny era i den japanska kalendern i .NET. Information om hur du testar dina program i Windows-system för att säkerställa att de är redo för tidsändringen finns i Förbereda ditt program för ändringen av den japanska eran. Funktioner i .NET som stöder kalendrar med flera epoker och bästa praxis när du arbetar med kalendrar som stöder flera epoker finns i Arbeta med epoker.

Översikt

Värdetypen DateTime representerar datum och tider med värden från 00:00:00 (midnatt), 1 januari 0001 Anno Domini (Common Era) till 11:59:59, 31 december 9999 e.D. (C.E.) i den gregorianska kalendern.

Tidsvärden mäts i 100 nanosekunder som kallas ticks. Ett visst datum är antalet tidsenheter sedan 12:00 midnatt, 1 januari 0001 e.Kr. (C.E.) i GregorianCalendar-kalendern. Talet exkluderar fästingar som skulle läggas till med skottsekunder. Ett tickvärde på 31241376000000000L representerar till exempel datumet fredag 01 januari 0100 12:00:00 midnatt. Ett DateTime värde uttrycks alltid i kontexten för en explicit kalender eller standardkalender.

Anmärkning

Om du arbetar med ett tickvärde som du vill konvertera till ett annat tidsintervall, till exempel minuter eller sekunder, bör du använda konstanten TimeSpan.TicksPerDay, TimeSpan.TicksPerHour, TimeSpan.TicksPerMinuteTimeSpan.TicksPerSecond, eller TimeSpan.TicksPerMillisecond för att utföra konverteringen. Om du till exempel vill lägga till antalet sekunder som representeras av ett angivet antal tidsenheter till Second-komponenten i ett DateTime-värde kan du använda uttrycket dateValue.Second + nTicks/Timespan.TicksPerSecond.

Anmärkning

Ett alternativ till strukturen för att DateTime arbeta med datum- och tidsvärden i vissa tidszoner är DateTimeOffset strukturen. Strukturen DateTimeOffset lagrar datum- och tidsinformation i ett privat DateTime fält och antalet minuter med vilket datum och tid skiljer sig från UTC i ett privat Int16 fält. Detta gör det möjligt för ett DateTimeOffset värde att återspegla tiden i en viss tidszon, medan ett DateTime värde otvetydigt endast kan återspegla UTC och den lokala tidszonens tid. En diskussion om när du ska använda strukturen eller DateTime strukturen när du arbetar med datum- och tidsvärden finns i DateTimeOffset.

Den här artikeln innehåller flera exempel som använder typen DateTime :

Initieringsexempel

Formatera DateTime objekt som strängexempel

Parsa strängar som DateTime objektexempel

DateTime upplösningsexempel

Exempel på kultur och kalendrar

Exempel på beständighet

Initiera ett DateTime-objekt

Du kan tilldela ett initialt värde till ett nytt DateTime värde på många olika sätt:

  • Anropa en konstruktor, antingen en där du anger argument för värden, eller använd den implicita parameterlösa konstruktorn.
  • Tilldela ett DateTime till returvärdet för en egenskap eller metod.
  • Parsa ett DateTime värde från dess strängrepresentation.
  • Använda Visual Basic-specifika språkfunktioner för att instansiera en DateTime.

Följande kodfragment visar exempel på var och en.

Anropa konstruktorer

Du anropar någon av överlagringarna för DateTime konstruktorn som anger element i datum- och tidsvärdet (till exempel år, månad och dag eller antalet fästingar). Följande kod skapar ett specifikt datum med konstruktorn DateTime som anger år, månad, dag, timme, minut och 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}"

Du anropar DateTime strukturens implicita parameterlösa konstruktor när du vill att standardvärdet DateTime ska initieras. (Mer information om den implicita parameterlösa konstruktorn för en värdetyp finns i Värdetyper.) Vissa kompilatorer stöder också att deklarera ett DateTime värde utan att uttryckligen tilldela ett värde till det. Att skapa ett värde utan en explicit initiering resulterar också i standardvärdet. I följande exempel visas den DateTime implicita parameterlösa konstruktorn i C# och Visual Basic, samt en DateTime deklaration utan tilldelning i 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}"

Tilldela ett beräknat värde

Du kan tilldela DateTime objektet ett datum- och tidsvärde som returneras av en egenskap eller metod. I följande exempel tilldelas aktuellt datum och tid, aktuellt datum och tid för koordinerad universell tid (UTC) och aktuellt datum till tre nya DateTime variabler.

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

Parsa en sträng som representerar en DateTime

Metoderna Parse, ParseExact, TryParseoch TryParseExact konverterar alla en sträng till motsvarande datum- och tidsvärde. I följande exempel används Parse metoderna och ParseExact för att parsa en sträng och konvertera den till ett DateTime värde. Det andra formatet använder ett formulär som stöds av ISO 8601-standarden för ett datum och en tid i strängformat. Den här standardrepresentationen används ofta för att överföra datuminformation i webbtjänster.

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)

Metoderna TryParse och TryParseExact anger om en sträng är en giltig representation av ett DateTime värde och, om den är det, utför konverteringen.

Språkspecifik syntax för Visual Basic

Följande Visual Basic-instruktion initierar ett nytt DateTime värde.

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

DateTime-värden och deras strängrepresentationer

Alla DateTime värden representeras internt som antalet tidsenheter (antalet 100-nanosekunders intervaller) som har förflutit sedan 00:00:00 vid midnatt, den 1 januari år 0001. Det faktiska DateTime värdet är oberoende av hur värdet visas när det visas. Utseendet på ett DateTime värde är resultatet av en formateringsåtgärd som konverterar ett värde till dess strängrepresentation.

Utseendet på datum- och tidsvärden är beroende av kultur, internationella standarder, programkrav och personliga preferenser. Strukturen DateTime ger flexibilitet när det gäller att formatera datum- och tidsvärden genom överlagringar av ToString. DateTime.ToString() Standardmetoden returnerar strängrepresentationen av ett datum- och tidsvärde med hjälp av den aktuella kulturens mönster för kort datum och lång tid. I följande exempel används standardmetoden DateTime.ToString() . Den visar datum och tid med hjälp av mönstret för kort datum och lång tid för den aktuella kulturen. Kulturen en-US är den nuvarande kulturen på datorn där exemplet kördes.

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

Du kan behöva formatera datum i en specifik kultur för att stödja webbscenarier där servern kan finnas i en annan kultur än klienten. Du anger kulturen med hjälp av DateTime.ToString(IFormatProvider) metoden för att skapa en kort datum- och långtidsrepresentation i en specifik kultur. I följande exempel används DateTime.ToString(IFormatProvider) metoden för att visa datum och tid med hjälp av det korta datum- och långtidsmönstret för fr-FR kultur.

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

Andra program kan kräva olika strängrepresentationer av ett datum. Metoden DateTime.ToString(String) returnerar strängrepresentationen som definieras av en standard- eller anpassad formatspecificerare med hjälp av formateringskonventionerna i den aktuella kulturen. I följande exempel används DateTime.ToString(String) metoden för att visa det fullständiga datum- och tidsmönstret för den en-US kulturen, den aktuella kulturen på den dator där exemplet kördes.

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

Slutligen kan du ange både kulturen och formatet med hjälp av DateTime.ToString(String, IFormatProvider) metoden . I följande exempel används DateTime.ToString(String, IFormatProvider) metoden för att visa det fullständiga datum- och tidsmönstret för fr-FR kultur.

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

Överlagringen DateTime.ToString(String) kan också användas med en anpassad formatsträng för att ange andra format. I följande exempel visas hur du formaterar en sträng med standardformatet ISO 8601 som ofta används för webbtjänster. Iso 8601-formatet har ingen motsvarande standardformatsträng.

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

Mer information om formateringsvärden DateTime finns i Formatsträngar för standarddatum och tid och anpassade datum- och tidsformatsträngar.

Parsa DateTime-värden från strängar

Parsning konverterar strängrepresentationen av ett datum och en tid till ett DateTime värde. Vanligtvis har datum- och tidssträngar två olika användningar i program:

  • Ett datum och tid tar olika former och återspeglar konventionerna för antingen den aktuella kulturen eller en specifik kultur. Ett program tillåter till exempel en användare vars aktuella kultur är en-US att ange ett datumvärde som "12/15/2013" eller "15 december 2013". Det gör det möjligt för en användare vars aktuella kultur en-gb att ange ett datumvärde som "15/12/2013" eller "15 december 2013".

  • Ett datum och en tid representeras i ett fördefinierat format. Ett program serialiserar till exempel ett datum som "20130103" oberoende av kulturen där appen körs. Ett program kan kräva att datum anges i den aktuella kulturens korta datumformat.

Du använder Parse metoden eller TryParse för att konvertera en sträng från ett av de vanliga datum- och tidsformat som används av en kultur till ett DateTime värde. I följande exempel visas hur du kan använda TryParse för att konvertera datumsträngar i olika kulturspecifika format till ett DateTime värde. Den ändrar den aktuella kulturen till engelska (Storbritannien) och anropar GetDateTimeFormats() metoden för att generera en matris med datum- och tidssträngar. Sedan skickas varje element i matrisen till TryParse -metoden. Utdata från exemplet visar att parsningsmetoden kunde konvertera var och en av de kulturspecifika datum- och tidssträngarna.

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

Du använder ParseExact och TryParseExact metoder för att konvertera en sträng som måste matcha ett särskilt format eller flera till ett DateTime värde. Du anger en eller flera datum- och tidsformatsträngar som en parameter till parsningsmetoden. I följande exempel används TryParseExact(String, String[], IFormatProvider, DateTimeStyles, DateTime) metoden för att konvertera strängar som antingen måste ha formatet "yyyyMMdd" eller ett "HHmmss"-format till DateTime värden.

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

En vanlig användning för ParseExact är att konvertera en strängrepresentation från en webbtjänst, vanligtvis i standardformatet ISO 8601 . Följande kod visar rätt formatsträng att använda:

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}")

Om en sträng inte kan parsas utlöser Parse metoderna och ParseExact ett undantag. Metoderna TryParse och TryParseExact returnerar ett Boolean värde som anger om konverteringen lyckades eller misslyckades. Du bör använda TryParse metoderna eller TryParseExact i scenarier där prestanda är viktigt. Parsningsåtgärden för datum- och tidssträngar tenderar att ha en hög felfrekvens och undantagshantering är dyr. Använd dessa metoder om strängar är indata från användare eller kommer från en okänd källa.

Mer information om parsning av datum- och tidsvärden finns i Parsa datum- och tidssträngar.

DateTime-värden

Beskrivningar av tidsvärden i DateTime typen uttrycks ofta med utc-standarden (Coordinated Universal Time). Coordinated Universal Time är det internationellt erkända namnet för Greenwich Mean Time (GMT). Samordnad universell tid är den tid som mäts vid noll grader longitud, UTC-ursprungspunkten. Sommartid gäller inte för UTC.

Lokal tid är relativ till en viss tidszon. En tidszon är associerad med en tidszonsförskjutning. En tidszonsförskjutning är förskjutningen av tidszonen mätt i timmar från UTC-ursprungspunkten. Dessutom påverkas lokal tid eventuellt av sommartid, vilket lägger till eller subtraherar en tidsintervalljustering. Lokal tid beräknas genom att tidszonsförskjutningen läggs till i UTC och justeras för sommartid om det behövs. Tidszonsförskjutningen vid UTC-ursprungspunkten är noll.

UTC-tid är lämplig för beräkningar, jämförelser och lagring av datum och tid i filer. Lokal tid är lämplig för visning i användargränssnitt för skrivbordsprogram. Tidszonsmedvetna program (till exempel många webbprogram) måste också fungera med ett antal andra tidszoner.

Om egenskapen för Kind ett DateTime objekt är DateTimeKind.Unspecifiedär det ospecificerat om den aktuella tiden är lokal tid, UTC-tid eller en tid i någon annan tidszon.

DateTime-upplösning

Anmärkning

Som ett alternativ till att utföra datum- och tidsaritmetik på DateTime värden för att mäta förfluten Stopwatch tid kan du använda klassen.

Egenskapen Ticks uttrycker datum- och tidsvärden i enheter på en tio miljonerdels sekund. Egenskapen Millisecond returnerar tusendelarna av en sekund i ett datum- och tidsvärde. Att använda upprepade anrop till DateTime.Now egenskapen för att mäta förfluten tid beror på systemklockan. Systemklockan på Windows 7- och Windows 8-system har en upplösning på cirka 15 millisekunder. Den här lösningen påverkar små tidsintervall som är mindre än 100 millisekunder.

I följande exempel visas beroendet av aktuella datum- och tidsvärden på systemklockans upplösning. I exemplet upprepas en yttre slinga 20 gånger, och en inre slinga fördröjer den yttre slingan. Om värdet för den yttre loopräknaren är 10 medför ett anrop till Thread.Sleep metoden en fördröjning på fem millisekunder. I följande exempel visas antalet millisekunder som returneras av egenskapen DateTime.Now.Milliseconds och ändras först efter anropet till 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

DateTime-åtgärder

En beräkning med hjälp av en DateTime struktur, till exempel Add eller Subtract, ändrar inte strukturens värde. I stället returnerar beräkningen en ny DateTime struktur vars värde är resultatet av beräkningen.

Konverteringsåtgärder mellan tidszoner (till exempel mellan UTC och lokal tid eller mellan en tidszon och en annan) tar hänsyn till sommartid, men aritmetiska åtgärder och jämförelseåtgärder gör det inte.

Själva DateTime strukturen har begränsat stöd för konvertering från en tidszon till en annan. Du kan använda ToLocalTime metoden för att konvertera UTC till lokal tid, eller så kan du använda ToUniversalTime metoden för att konvertera från lokal tid till UTC. Det finns dock en fullständig uppsättning metoder för tidszonskonvertering i TimeZoneInfo klassen. Du konverterar tiden i någon av världens tidszoner till tiden i någon annan tidszon med hjälp av dessa metoder.

Beräkningar och jämförelser av DateTime objekt är bara meningsfulla om objekten representerar tider i samma tidszon. Du kan använda ett TimeZoneInfo objekt för att representera ett DateTime värdes tidszon, även om de två är löst kopplade. Ett DateTime objekt har ingen egenskap som returnerar ett objekt som representerar det datum- och tidsvärdets tidszon. Egenskapen Kind anger om en DateTime representerar UTC, lokal tid eller är ospecificerad. I ett tidszonsmedvetent program måste du förlita dig på någon extern mekanism för att fastställa tidszonen där ett DateTime objekt skapades. Du kan använda en struktur som omsluter både DateTime värdet och objektet TimeZoneInfo som representerar DateTime värdets tidszon. Mer information om hur du använder UTC i beräkningar och jämförelser med DateTime värden finns i Utföra aritmetiska åtgärder med datum och tider.

Varje DateTime medlem använder implicit den gregorianska kalendern för att utföra sin åtgärd. Undantag är metoder som implicit anger en kalender. Dessa inkluderar konstruktorer som anger en kalender och metoder med en parameter som härleds från IFormatProvider, till exempel System.Globalization.DateTimeFormatInfo.

Åtgärder av medlemmar av typen DateTime tar hänsyn till information som skottår och antalet dagar i en månad.

DateTime-värden och kalendrar

.NET-klassbiblioteket innehåller ett antal kalenderklasser, som alla härleds från Calendar klassen. De är:

Viktigt!

Epoker i de japanska kalendrarna baseras på kejsarens regeringstid och förväntas därför förändras. Den 1 maj 2019 markerade till exempel början av Reiwa-eran i JapaneseCalendar och JapaneseLunisolarCalendar. En sådan ändring av era påverkar alla program som använder dessa kalendrar. Mer information och för att avgöra om dina program påverkas finns i Hantera en ny era i den japanska kalendern i .NET. Information om hur du testar dina program i Windows-system för att säkerställa att de är redo för tidsändringen finns i Förbereda ditt program för ändringen av den japanska eran. Funktioner i .NET som stöder kalendrar med flera epoker och bästa praxis när du arbetar med kalendrar som stöder flera epoker finns i Arbeta med epoker.

Varje kultur använder en standardkalender som definieras av dess skrivskyddade CultureInfo.Calendar egenskap. Varje kultur kan ha stöd för en eller flera kalendrar som definierats av dess skrivskyddade CultureInfo.OptionalCalendars egenskap. Kalendern som för närvarande används av ett specifikt CultureInfo objekt definieras av dess DateTimeFormatInfo.Calendar egenskap. Det måste vara en av kalendrarna som finns i matrisen CultureInfo.OptionalCalendars .

En kulturs aktuella kalender används i alla formateringsåtgärder för den kulturen. Till exempel är standardkalendern för den thailändska buddistiska kulturen kalendern thai buddhistisk era, som representeras av ThaiBuddhistCalendar klassen. När ett CultureInfo objekt som representerar den thailändska buddistiska kulturen används i en datum- och tidsformateringsåtgärd används kalendern för thailändsk buddistisk era som standard. Den gregorianska kalendern används endast om kulturens DateTimeFormatInfo.Calendar egenskap ändras, vilket visas i följande exempel:

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

En kulturs aktuella kalender används också i alla parsningsåtgärder för den kulturen, vilket visas i följande exempel.

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

Du instansierar ett DateTime värde med hjälp av datum- och tidselementen (antal år, månad och dag) i en specifik kalender genom att anropa en DateTime-konstruktor som innehåller en calendar parameter och skicka ett Calendar objekt som representerar den kalendern. I följande exempel används datum- och tidselementen ThaiBuddhistCalendar från kalendern.

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 konstruktorer som inte innehåller en calendar parameter förutsätter att datum- och tidselementen uttrycks som enheter i den gregorianska kalendern.

Alla andra DateTime egenskaper och metoder använder den gregorianska kalendern. Egenskapen returnerar till exempel DateTime.Year året i den gregorianska kalendern, och DateTime.IsLeapYear(Int32) metoden förutsätter att parametern year är ett år i den gregorianska kalendern. Varje DateTime medlem som använder den gregorianska kalendern har en motsvarande medlem i klassen Calendar som använder en specifik kalender. Metoden returnerar till exempel Calendar.GetYear året i en specifik kalender och Calendar.IsLeapYear metoden tolkar parametern year som ett årsnummer i en specifik kalender. I följande exempel används både DateTime och motsvarande medlemmar i ThaiBuddhistCalendar klassen.

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

Strukturen DateTime innehåller en DayOfWeek egenskap som returnerar veckodagen i den gregorianska kalendern. Den innehåller inte en medlem som gör att du kan hämta årets veckonummer. Om du vill hämta veckan på året anropar du den enskilda kalenderns Calendar.GetWeekOfYear metod. I följande exempel visas en bild.

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

Mer information om datum och kalendrar finns i Arbeta med kalendrar.

Spara DateTime-värden

Du kan spara DateTime värden på följande sätt:

Du måste se till att rutinen DateTime som återställer värdena inte förlorar data eller utlöser ett undantag oavsett vilken teknik du väljer. DateTime värden bör tur och retur. Det vill sa att det ursprungliga värdet och det återställde värdet ska vara samma. Och om det ursprungliga DateTime värdet representerar en enda tidpunkt bör det identifiera samma tidpunkt när det återställs.

Spara värden som strängar

Om du vill återställa DateTime värden som sparas som strängar följer du dessa regler:

  • Gör samma antaganden om kulturspecifik formatering när du återställer strängen som när du bevarade den. För att säkerställa att en sträng kan återställas i ett system vars nuvarande kultur skiljer sig från kulturen i systemet som den sparades på, anropar du överlagringen ToString för att spara strängen med hjälp av konventionerna i den invarianta kulturen. Anropa Parse(String, IFormatProvider, DateTimeStyles) eller TryParse(String, IFormatProvider, DateTimeStyles, DateTime) överlagringen för att återställa strängen med hjälp av konventionerna i den neutrala kulturen. Använd aldrig överlagringarna ToString(), Parse(String)eller TryParse(String, DateTime) som använder den aktuella kulturens konventioner.

  • Om datumet representerar ett enda ögonblick kontrollerar du att det representerar samma tidpunkt när det återställs, även i en annan tidszon. Konvertera värdet DateTime till Coordinated Universal Time (UTC) innan du sparar det eller använder DateTimeOffset.

Det vanligaste felet som uppstår när DateTime värden bevaras som strängar är att förlita sig på formateringskonventionerna i standardkulturen eller den aktuella kulturen. Problem uppstår om den aktuella kulturen skiljer sig när strängarna sparas och återställs. I följande exempel visas dessa problem. Det sparar fem datum med formateringskonventionerna för den aktuella kulturen, som i det här fallet är engelska (USA). Den återställer datumen med formateringskonventionerna för en annan kultur, som i det här fallet är engelska (Storbritannien). Eftersom formateringskonventionerna för de två kulturerna skiljer sig åt kan två av datumen inte återställas och de återstående tre datumen tolkas felaktigt. Om de ursprungliga datum- och tidsvärdena representerar enstaka ögonblick i tiden är de återställda tiderna också felaktiga eftersom tidszonsinformationen går förlorad.

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...

Följ dessa steg för att lyckas med att återställa DateTime-värden:

  1. Om värdena representerar enstaka tidpunkter konverterar du dem från den lokala tiden till UTC genom att anropa ToUniversalTime metoden.
  2. Konvertera datumen till deras strängrepresentationer genom att anropa ToString(String, IFormatProvider)- eller String.Format(IFormatProvider, String, Object[])-överlagringen. Använd formateringskonventionerna för den invarianta kulturen genom att ange CultureInfo.InvariantCulture som provider argument. Ange att värdet ska avrundas med standardformatsträngen "O" eller "R".

Följ dessa steg för att återställa de bevarade DateTime värdena utan dataförlust:

  1. Parsa data genom att anropa ParseExact eller TryParseExact överlagring. Ange CultureInfo.InvariantCulture som provider argument och använd samma standardformatsträng som du använde för argumentet under konverteringen format . Inkludera värdet DateTimeStyles.RoundtripKind i styles argumentet.
  2. DateTime Om värdena representerar enstaka ögonblick i tiden anropar du ToLocalTime metoden för att konvertera det parsade datumet från UTC till lokal tid.

I följande exempel används den invarianta kulturen och standardformatsträngen "O" för att säkerställa att värden som DateTime sparas och återställs representerar samma tidpunkt oavsett system, kultur eller tidszon för käll- och målsystemen.

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...

Spara värden som heltal

Du kan spara ett datum och en tid som ett Int64 värde som representerar ett antal tick. I det här fallet behöver du inte tänka på kulturen i de system som DateTime värdena sparas och återställs på.

Så här bevarar du ett DateTime värde som ett heltal:

  1. DateTime Om värdena representerar enstaka ögonblick i tiden konverterar du dem till UTC genom att anropa ToUniversalTime metoden.
  2. Hämta antalet fästingar som representeras av DateTime värdet från dess Ticks egenskap.

Så här återställer du ett DateTime värde som har sparats som ett heltal:

  1. Instansiera ett nytt DateTime objekt genom att skicka Int64 värdet till DateTime(Int64) konstruktorn.
  2. Om värdet DateTime representerar ett enda ögonblick i tiden konverterar du det från UTC till den lokala tiden genom att anropa ToLocalTime metoden.

I följande exempel bevaras en matris med DateTime värden som heltal i ett system i tidszonen usa stillahavsområdet. Den återställer den på ett system i UTC-zonen. Filen som innehåller heltal innehåller ett Int32 värde som anger det totala antalet Int64 värden som omedelbart följer den.

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...

Serialisera DateTime-värden

Du kan spara DateTime värden genom serialisering till en dataström eller fil och sedan återställa dem genom deserialisering. DateTime data serialiseras i något angivet objektformat. Objekten återställs när de deserialiseras. En formaterare eller serialiserare, till exempel JsonSerializer eller XmlSerializer, hanterar serialiserings- och deserialiseringsprocessen. Mer information om serialisering och de typer av serialisering som stöds av .NET finns i Serialisering.

I följande exempel används XmlSerializer klassen för att serialisera och deserialisera DateTime värden. Värdena representerar alla skottårsdagar under 2000-talet. Utdata representerar resultatet om exemplet körs på ett system vars aktuella kultur är engelska (Storbritannien). Eftersom du har deserialiserat DateTime själva objektet behöver koden inte hantera kulturella skillnader i datum- och tidsformat.

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

I föregående exempel ingår inte tidsinformation. Om ett DateTime värde representerar ett ögonblick i tiden och uttrycks som en lokal tid konverterar du det från lokal tid till UTC innan du serialiserar det genom att anropa ToUniversalTime metoden. När du har deserialiserat den konverterar du den från UTC till lokal tid genom att anropa metoden ToLocalTime.

DateTime jämfört med TimeSpan

Värdetyperna DateTime och TimeSpan skiljer sig åt eftersom en DateTime representerar ett ögonblick i tiden medan ett TimeSpan representerar ett tidsintervall. Du kan subtrahera en instans av DateTime från en annan för att hämta ett TimeSpan objekt som representerar tidsintervallet mellan dem. Eller så kan du lägga till ett positivt TimeSpan till den nuvarande DateTime för att få ett DateTime-värde som representerar ett framtida datum.

Du kan lägga till eller subtrahera ett tidsintervall från ett DateTime objekt. Tidsintervall kan vara negativa eller positiva, och de kan uttryckas i enheter som ticks, sekunder eller som ett TimeSpan-objekt.

Jämför för likhet inom tolerans

Likhetsjämförelser för DateTime värden är exakta. För att betraktas som lika måste två värden uttryckas som samma antal fästingar. Den precisionen är ofta onödig eller till och med felaktig för många program. Ofta vill du testa om DateTime objekten är ungefär lika.

I följande exempel visas hur du jämför ungefär motsvarande DateTime värden. Den accepterar en liten skillnadsmarginal när de deklareras lika.

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

COM-interopöverväganden

Ett DateTime värde som överförs till ett COM-program och sedan överförs tillbaka till ett hanterat program, kallas för en rundtur. Ett värde som endast anger en tid går dock DateTime inte tur och retur som du kan förvänta dig.

Om du bara reser en gång, till exempel 15:00, är det sista datumet och tiden den 30 december 1899 C.E. kl. 15:00, istället för januari, 1, 0001 C.E. kl. 15:00. NET och COM förutsätter ett standarddatum när endast en tid har angetts. COM-systemet förutsätter dock ett basdatum den 30 december 1899, medan .NET antar ett basdatum den 1 januari 0001.

När endast en tid skickas från .NET till COM utförs särskild bearbetning som konverterar tiden till det format som används av COM. När endast en tid skickas från COM till .NET utförs ingen särskild bearbetning eftersom det skulle skada legitima datum och tider den 30 december 1899. Om ett datum startar sin tur-och-retur-resa från COM bevarar .NET och COM datumet.

Beteendet för .NET och COM innebär att om ditt program rundresor en DateTime som bara anger en tid, måste ditt program komma ihåg att ändra eller ignorera det felaktiga datumet från det slutliga DateTime objektet.