Wie erhalte ich bei einem DateTime-Objekt ein ISO 8601-Datum im Zeichenfolgenformat?

Wie erhalte ich bei einem DateTime-Objekt ein ISO 8601-Datum im Zeichenfolgenformat?

Gegeben:

DateTime.UtcNow

Wie erhalte ich eine Zeichenfolge, die denselben Wert in einem ISO 8601-kompatiblen Format darstellt?

Beachten Sie, dass ISO 8601 eine Reihe ähnlicher Formate definiert. Das spezifische Format, nach dem ich suche, ist:

yyyy-MM-ddTHH:mm:ssZ

DateTime.UtcNow.ToString("yyyy-MM-ddTHH\:mm\:ss.fffffffzzz");

Dadurch erhalten Sie ein Datum ähnlich 2008-09-22T13:57:31.2311892-04:00 .

Ein anderer Weg ist:

DateTime.UtcNow.ToString("o");

was Ihnen 2008-09-22T14:01:54.9571247Z gibt

Um das angegebene Format zu erhalten, können Sie Folgendes verwenden:

DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ")

DateTime-Formatierungsoptionen

DateTime.UtcNow.ToString("s", System.Globalization.CultureInfo.InvariantCulture) sollte Ihnen das geben, wonach Sie suchen, da der Formatbezeichner „s“ als sortierbares Datums-/Uhrzeitmuster beschrieben wird; entspricht ISO 8601.

BEARBEITEN: Um die zusätzliche Z zu erhalten Verwenden Sie am Ende, wie es das OP erfordert, "o" statt "s" .

DateTime.UtcNow.ToString("s")

Gibt so etwas wie 2008-04-10T06:30:00

zurück

UtcNow gibt offensichtlich eine UTC-Zeit zurück, also gibt es keinen Schaden in:

string.Concat(DateTime.UtcNow.ToString("s"), "Z")

Verwendung:

private void TimeFormats()
{
    DateTime localTime = DateTime.Now;
    DateTime utcTime = DateTime.UtcNow;
    DateTimeOffset localTimeAndOffset = new DateTimeOffset(localTime, TimeZoneInfo.Local.GetUtcOffset(localTime));

    //UTC
    string strUtcTime_o = utcTime.ToString("o");
    string strUtcTime_s = utcTime.ToString("s");
    string strUtcTime_custom = utcTime.ToString("yyyy-MM-ddTHH:mm:ssK");

    //Local
    string strLocalTimeAndOffset_o = localTimeAndOffset.ToString("o");
    string strLocalTimeAndOffset_s = localTimeAndOffset.ToString("s");
    string strLocalTimeAndOffset_custom = utcTime.ToString("yyyy-MM-ddTHH:mm:ssK");

    //Output
    Response.Write("<br/>UTC<br/>");
    Response.Write("strUtcTime_o: " + strUtcTime_o + "<br/>");
    Response.Write("strUtcTime_s: " + strUtcTime_s + "<br/>");
    Response.Write("strUtcTime_custom: " + strUtcTime_custom + "<br/>");

    Response.Write("<br/>Local Time<br/>");
    Response.Write("strLocalTimeAndOffset_o: " + strLocalTimeAndOffset_o + "<br/>");
    Response.Write("strLocalTimeAndOffset_s: " + strLocalTimeAndOffset_s + "<br/>");
    Response.Write("strLocalTimeAndOffset_custom: " + strLocalTimeAndOffset_custom + "<br/>");

}

AUSGABE

UTC
    strUtcTime_o: 2012-09-17T22:02:51.4021600Z
    strUtcTime_s: 2012-09-17T22:02:51
    strUtcTime_custom: 2012-09-17T22:02:51Z

Local Time
    strLocalTimeAndOffset_o: 2012-09-17T15:02:51.4021600-07:00
    strLocalTimeAndOffset_s: 2012-09-17T15:02:51
    strLocalTimeAndOffset_custom: 2012-09-17T22:02:51Z

Quellen:

  • Standardformatzeichenfolgen für Datum und Uhrzeit (MSDN)

  • Benutzerdefinierte Formatzeichenfolgen für Datum und Uhrzeit (MSDN)

System.DateTime.UtcNow.ToString("o")

=>

val it : string = "2013-10-13T13:03:50.2950037Z"

Sie haben einige Optionen, einschließlich des Formatbezeichners „Round-Trip („O“)“.

var date1 = new DateTime(2008, 3, 1, 7, 0, 0);
Console.WriteLine(date1.ToString("O"));
Console.WriteLine(date1.ToString("s", System.Globalization.CultureInfo.InvariantCulture));

Ausgabe

2008-03-01T07:00:00.0000000
2008-03-01T07:00:00

DateTime + TimeZone kann jedoch andere Probleme aufweisen, wie im Blog-Beitrag DateTime and DateTimeOffset in .NET:Good Practices and Common Tfalls beschrieben :

Überrascht, dass niemand es vorgeschlagen hat:

System.DateTime.UtcNow.ToString("u").Replace(' ','T')
# Using PowerShell Core to demo

# Lowercase "u" format
[System.DateTime]::UtcNow.ToString("u")
> 2020-02-06 01:00:32Z

# Lowercase "u" format with replacement
[System.DateTime]::UtcNow.ToString("u").Replace(' ','T')
> 2020-02-06T01:00:32Z

Das UniversalSortableDateTimePattern bringt Sie fast bis zu dem, was Sie wollen (was eher eine RFC 3339-Darstellung ist).

Hinzugefügt:
Ich habe mich entschieden, die Benchmarks in Antwort https://stackoverflow.com/a/43793679/653058 zu verwenden, um zu vergleichen, wie dies funktioniert.

tl:dr; es ist am teuren Ende, aber immer noch etwas mehr als eine halbe Millisekunde auf meinem beschissenen alten Laptop 🙂

Implementierung:

[Benchmark]
public string ReplaceU()
{
   var text = dateTime.ToUniversalTime().ToString("u").Replace(' ', 'T');
   return text;
}

Ergebnisse:

// * Summary *

BenchmarkDotNet=v0.11.5, OS=Windows 10.0.19002
Intel Xeon CPU E3-1245 v3 3.40GHz, 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=3.0.100
  [Host]     : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT
  DefaultJob : .NET Core 3.0.0 (CoreCLR 4.700.19.46205, CoreFX 4.700.19.46214), 64bit RyuJIT


|               Method |     Mean |     Error |    StdDev |
|--------------------- |---------:|----------:|----------:|
|           CustomDev1 | 562.4 ns | 11.135 ns | 10.936 ns |
|           CustomDev2 | 525.3 ns |  3.322 ns |  3.107 ns |
|     CustomDev2WithMS | 609.9 ns |  9.427 ns |  8.356 ns |
|              FormatO | 356.6 ns |  6.008 ns |  5.620 ns |
|              FormatS | 589.3 ns |  7.012 ns |  6.216 ns |
|       FormatS_Verify | 599.8 ns | 12.054 ns | 11.275 ns |
|        CustomFormatK | 549.3 ns |  4.911 ns |  4.594 ns |
| CustomFormatK_Verify | 539.9 ns |  2.917 ns |  2.436 ns |
|             ReplaceU | 615.5 ns | 12.313 ns | 11.517 ns |

// * Hints *
Outliers
  BenchmarkDateTimeFormat.CustomDev2WithMS: Default     -> 1 outlier  was  removed (668.16 ns)
  BenchmarkDateTimeFormat.FormatS: Default              -> 1 outlier  was  removed (621.28 ns)
  BenchmarkDateTimeFormat.CustomFormatK: Default        -> 1 outlier  was  detected (542.55 ns)
  BenchmarkDateTimeFormat.CustomFormatK_Verify: Default -> 2 outliers were removed (557.07 ns, 560.95 ns)

// * Legends *
  Mean   : Arithmetic mean of all measurements
  Error  : Half of 99.9% confidence interval
  StdDev : Standard deviation of all measurements
  1 ns   : 1 Nanosecond (0.000000001 sec)

// ***** BenchmarkRunner: End *****

Sie können das „Z“ (ISO 8601 UTC erhalten ) mit dem nächsten Code:

Dim tmpDate As DateTime = New DateTime(Now.Ticks, DateTimeKind.Utc)
Dim res as String = tmpDate.toString("o") '2009-06-15T13:45:30.0000000Z

Hier ist der Grund:

Die ISO 8601 hat einige unterschiedliche Formate:

DateTimeKind.Local

2009-06-15T13:45:30.0000000-07:00

DateTimeKind.Utc

2009-06-15T13:45:30.0000000Z

DateTimeKind.Unspecified

2009-06-15T13:45:30.0000000

.NET stellt uns eine Aufzählung mit diesen Optionen zur Verfügung:

'2009-06-15T13:45:30.0000000-07:00
Dim strTmp1 As String = New DateTime(Now.Ticks, DateTimeKind.Local).ToString("o")

'2009-06-15T13:45:30.0000000Z
Dim strTmp2 As String = New DateTime(Now.Ticks, DateTimeKind.Utc).ToString("o")

'2009-06-15T13:45:30.0000000
Dim strTmp3 As String = New DateTime(Now.Ticks, DateTimeKind.Unspecified).ToString("o")

Hinweis :Wenn Sie das „Überwachungsdienstprogramm“ von Visual Studio 2008 auf toString(„o“) anwenden Teils erhalten Sie möglicherweise andere Ergebnisse, ich weiß nicht, ob es sich um einen Fehler handelt, aber in diesem Fall erzielen Sie beim Debuggen bessere Ergebnisse, wenn Sie eine String-Variable verwenden.

Quelle:Standardformatzeichenfolgen für Datum und Uhrzeit (MSDN)

Die meisten dieser Antworten enthalten Millisekunden/Mikrosekunden, was eindeutig nicht von ISO 8601 unterstützt wird. Die richtige Antwort wäre:

System.DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ssK");
// or
System.DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssK");

Referenzen:

  • ISO 8601-Spezifikation
  • "K"-Spezifizierer

Ich würde einfach XmlConvert verwenden :

XmlConvert.ToString(DateTime.UtcNow, XmlDateTimeSerializationMode.RoundtripKind);

Die Zeitzone wird automatisch beibehalten.

DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss zzz");

DateTime.Now.ToString("O");

HINWEIS:Abhängig von der Konvertierung, die Sie an Ihrem Ende vornehmen, verwenden Sie die erste Zeile (am ähnlichsten) oder die zweite.

Stellen Sie sicher, dass das Format nur zur Ortszeit angewendet wird, da „zzz“ die Zeitzoneninformation für die UTC-Konvertierung ist.

– von MSDN

So konvertieren Sie DateTime.UtcNow in eine Zeichenfolgendarstellung von yyyy-MM-ddTHH:mm:ssZ , können Sie die ToString()-Methode der DateTime-Struktur mit einer benutzerdefinierten Formatierungszeichenfolge verwenden. Wenn Sie benutzerdefinierte Formatzeichenfolgen mit einer DateTime verwenden, ist es wichtig, daran zu denken, dass Sie Ihre Trennzeichen mit einfachen Anführungszeichen maskieren müssen.

Folgendes gibt die gewünschte Zeichenfolgendarstellung zurück:

DateTime.UtcNow.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'", DateTimeFormatInfo.InvariantInfo)

Es ist interessant, dass das benutzerdefinierte Format „yyyy-MM-ddTHH:mm:ssK“ (ohne ms) die schnellste Formatierungsmethode ist.

Es ist auch interessant, dass das „S“-Format auf Classic langsam und auf Core schnell ist…

Natürlich liegen die Zahlen sehr nahe beieinander, der Unterschied zwischen einigen Zeilen ist unbedeutend (Tests mit dem Suffix _Verify dieselben sind wie diejenigen ohne dieses Suffix, demonstriert die Wiederholbarkeit der Ergebnisse)

BenchmarkDotNet=v0.10.5, OS=Windows 10.0.14393
Processor=Intel Core i5-2500K CPU 3.30GHz (Sandy Bridge), ProcessorCount=4
Frequency=3233539 Hz, Resolution=309.2587 ns, Timer=TSC
  [Host] : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0
  Clr    : Clr 4.0.30319.42000, 64bit RyuJIT-v4.6.1637.0
  Core   : .NET Core 4.6.25009.03, 64bit RyuJIT


               Method |  Job | Runtime |       Mean |     Error |    StdDev |     Median |        Min |        Max | Rank |  Gen 0 | Allocated |
--------------------- |----- |-------- |-----------:|----------:|----------:|-----------:|-----------:|-----------:|-----:|-------:|----------:|
           CustomDev1 |  Clr |     Clr | 1,089.0 ns | 22.179 ns | 20.746 ns | 1,079.9 ns | 1,068.9 ns | 1,133.2 ns |    8 | 0.1086 |     424 B |
           CustomDev2 |  Clr |     Clr | 1,032.3 ns | 19.897 ns | 21.289 ns | 1,024.7 ns | 1,000.3 ns | 1,072.0 ns |    7 | 0.1165 |     424 B |
     CustomDev2WithMS |  Clr |     Clr | 1,168.2 ns | 16.543 ns | 15.474 ns | 1,168.5 ns | 1,149.3 ns | 1,189.2 ns |   10 | 0.1625 |     592 B |
              FormatO |  Clr |     Clr | 1,563.7 ns | 31.244 ns | 54.721 ns | 1,532.5 ns | 1,497.8 ns | 1,703.5 ns |   14 | 0.2897 |     976 B |
              FormatS |  Clr |     Clr | 1,243.5 ns | 24.615 ns | 31.130 ns | 1,229.3 ns | 1,200.6 ns | 1,324.2 ns |   13 | 0.2865 |     984 B |
       FormatS_Verify |  Clr |     Clr | 1,217.6 ns | 11.486 ns | 10.744 ns | 1,216.2 ns | 1,205.5 ns | 1,244.3 ns |   12 | 0.2885 |     984 B |
        CustomFormatK |  Clr |     Clr |   912.2 ns | 17.915 ns | 18.398 ns |   916.6 ns |   878.3 ns |   934.1 ns |    4 | 0.0629 |     240 B |
 CustomFormatK_Verify |  Clr |     Clr |   894.0 ns |  3.877 ns |  3.626 ns |   893.8 ns |   885.1 ns |   900.0 ns |    3 | 0.0636 |     240 B |
           CustomDev1 | Core |    Core |   989.1 ns | 12.550 ns | 11.739 ns |   983.8 ns |   976.8 ns | 1,015.5 ns |    6 | 0.1101 |     423 B |
           CustomDev2 | Core |    Core |   964.3 ns | 18.826 ns | 23.809 ns |   954.1 ns |   935.5 ns | 1,015.6 ns |    5 | 0.1267 |     423 B |
     CustomDev2WithMS | Core |    Core | 1,136.0 ns | 21.914 ns | 27.714 ns | 1,138.1 ns | 1,099.9 ns | 1,200.2 ns |    9 | 0.1752 |     590 B |
              FormatO | Core |    Core | 1,201.5 ns | 16.262 ns | 15.211 ns | 1,202.3 ns | 1,178.2 ns | 1,225.5 ns |   11 | 0.0656 |     271 B |
              FormatS | Core |    Core |   993.5 ns | 19.272 ns | 24.372 ns |   999.4 ns |   954.2 ns | 1,029.5 ns |    6 | 0.0633 |     279 B |
       FormatS_Verify | Core |    Core | 1,003.1 ns | 17.577 ns | 16.442 ns | 1,009.2 ns |   976.1 ns | 1,024.3 ns |    6 | 0.0674 |     279 B |
        CustomFormatK | Core |    Core |   878.2 ns | 17.017 ns | 20.898 ns |   877.7 ns |   851.4 ns |   928.1 ns |    2 | 0.0555 |     215 B |
 CustomFormatK_Verify | Core |    Core |   863.6 ns |  3.968 ns |  3.712 ns |   863.0 ns |   858.6 ns |   870.8 ns |    1 | 0.0550 |     215 B |

Code:

    public class BenchmarkDateTimeFormat
    {
        public static DateTime dateTime = DateTime.Now;

        [Benchmark]
        public string CustomDev1()
        {
            var d = dateTime.ToUniversalTime();
            var sb = new StringBuilder(20);

            sb.Append(d.Year).Append("-");
            if (d.Month <= 9)
                sb.Append("0");
            sb.Append(d.Month).Append("-");
            if (d.Day <= 9)
                sb.Append("0");
            sb.Append(d.Day).Append("T");
            if (d.Hour <= 9)
                sb.Append("0");
            sb.Append(d.Hour).Append(":");
            if (d.Minute <= 9)
                sb.Append("0");
            sb.Append(d.Minute).Append(":");
            if (d.Second <= 9)
                sb.Append("0");
            sb.Append(d.Second).Append("Z");
            var text = sb.ToString();
            return text;
        }

        [Benchmark]
        public string CustomDev2()
        {
            var u = dateTime.ToUniversalTime();
            var sb = new StringBuilder(20);
            var y = u.Year;
            var d = u.Day;
            var M = u.Month;
            var h = u.Hour;
            var m = u.Minute;
            var s = u.Second;
            sb.Append(y).Append("-");
            if (M <= 9)
                sb.Append("0");
            sb.Append(M).Append("-");
            if (d <= 9)
                sb.Append("0");
            sb.Append(d).Append("T");
            if (h <= 9)
                sb.Append("0");
            sb.Append(h).Append(":");
            if (m <= 9)
                sb.Append("0");
            sb.Append(m).Append(":");
            if (s <= 9)
                sb.Append("0");
            sb.Append(s).Append("Z");
            var text = sb.ToString();
            return text;
        }

        [Benchmark]
        public string CustomDev2WithMS()
        {
            var u  = dateTime.ToUniversalTime();
            var sb = new StringBuilder(23);
            var y  = u.Year;
            var d  = u.Day;
            var M  = u.Month;
            var h  = u.Hour;
            var m  = u.Minute;
            var s  = u.Second;
            var ms = u.Millisecond;
            sb.Append(y).Append("-");
            if (M <= 9)
                sb.Append("0");
            sb.Append(M).Append("-");
            if (d <= 9)
                sb.Append("0");
            sb.Append(d).Append("T");
            if (h <= 9)
                sb.Append("0");
            sb.Append(h).Append(":");
            if (m <= 9)
                sb.Append("0");
            sb.Append(m).Append(":");
            if (s <= 9)
                sb.Append("0");
            sb.Append(s).Append(".");
            sb.Append(ms).Append("Z");
            var text = sb.ToString();
            return text;
        }
        [Benchmark]
        public string FormatO()
        {
            var text = dateTime.ToUniversalTime().ToString("o");
            return text;
        }
        [Benchmark]
        public string FormatS()
        {
            var text = string.Concat(dateTime.ToUniversalTime().ToString("s"),"Z");
            return text;
        }

        [Benchmark]
        public string FormatS_Verify()
        {
            var text = string.Concat(dateTime.ToUniversalTime().ToString("s"), "Z");
            return text;
        }

        [Benchmark]
        public string CustomFormatK()
        {
            var text = dateTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssK");
            return text;
        }

        [Benchmark]
        public string CustomFormatK_Verify()
        {
            var text = dateTime.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssK");
            return text;
        }
    }

https://github.com/dotnet/BenchmarkDotNet wurde verwendet

Mit Newtonsoft.Json ist das möglich

JsonConvert.SerializeObject(DateTime.UtcNow)

Beispiel:https://dotnetfiddle.net/O2xFSl

Wenn Sie unter SharePoint 2010 oder höher entwickeln, können Sie

verwenden
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
...
string strISODate = SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now)

Zum Formatieren wie 2018-06-22T13:04:16 die in der URI einer API-Verwendung übergeben werden kann:

public static string FormatDateTime(DateTime dateTime)
{
    return dateTime.ToString("s", System.Globalization.CultureInfo.InvariantCulture);
}

Wie in der anderen Antwort erwähnt, DateTime hat konstruktionsbedingt Probleme.

NodaTime

Ich schlage vor, NodaTime zu verwenden, um Datums-/Uhrzeitwerte zu verwalten:

  • Ortszeit, Datum, DatumUhrzeit
  • Weltzeit
  • Zeit mit Zeitzone
  • Punkt
  • Dauer

Formatierung

Also, um ZonedDateTime zu erstellen und zu formatieren Sie können das folgende Code-Snippet verwenden:

var instant1 = Instant.FromUtc(2020, 06, 29, 10, 15, 22);

var utcZonedDateTime = new ZonedDateTime(instant1, DateTimeZone.Utc);
utcZonedDateTime.ToString("yyyy-MM-ddTHH:mm:ss'Z'", CultureInfo.InvariantCulture);
// 2020-06-29T10:15:22Z


var instant2 = Instant.FromDateTimeUtc(new DateTime(2020, 06, 29, 10, 15, 22, DateTimeKind.Utc));

var amsterdamZonedDateTime = new ZonedDateTime(instant2, DateTimeZoneProviders.Tzdb["Europe/Amsterdam"]);
amsterdamZonedDateTime.ToString("yyyy-MM-ddTHH:mm:ss'Z'", CultureInfo.InvariantCulture);
// 2020-06-29T12:15:22Z

Für mich NodaTime Code sieht ziemlich ausführlich aus. Aber Typen sind wirklich nützlich. Sie helfen bei der korrekten Handhabung von Datums-/Uhrzeitwerten.

Newtonsoft.Json

services
    .AddMvc()
    .AddJsonOptions(options =>
    {
        var settings=options.SerializerSettings;
        settings.DateParseHandling = DateParseHandling.None;
        settings.ConfigureForNodaTime(DateTimeZoneProviders.Tzdb);
    });