Dado un objeto DateTime, ¿cómo obtengo una fecha ISO 8601 en formato de cadena?

Dado:

DateTime.UtcNow 

¿Cómo obtengo una cadena que representa el mismo valor en un formato compatible con ISO 8601 ?

Tenga en cuenta que ISO 8601 define una cantidad de formatos similares. El formato específico que estoy buscando es:

 yyyy-MM-ddTHH:mm:ssZ 

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

Esto le da una fecha similar a 2008-09-22T13: 57: 31.2311892-04: 00 .

Otra forma es:

 DateTime.UtcNow.ToString("o"); 

que te da 2008-09-22T14: 01: 54.9571247Z

Para obtener el formato especificado, puede usar:

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

Opciones de formateo de DateTime

DateTime.UtcNow.ToString("s", System.Globalization.CultureInfo.InvariantCulture) debería darle lo que está buscando, ya que el especificador de formato “s” se describe como un patrón de fecha / hora ordenable; cumple con ISO 8601.

 DateTime.UtcNow.ToString("s") 

Devuelve algo como 2008-04-10T06: 30: 00

UtcNow obviamente devuelve una hora UTC por lo que no hay daño en:

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

Utilizar:

 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("
UTC
"); Response.Write("strUtcTime_o: " + strUtcTime_o + "
"); Response.Write("strUtcTime_s: " + strUtcTime_s + "
"); Response.Write("strUtcTime_custom: " + strUtcTime_custom + "
"); Response.Write("
Local Time
"); Response.Write("strLocalTimeAndOffset_o: " + strLocalTimeAndOffset_o + "
"); Response.Write("strLocalTimeAndOffset_s: " + strLocalTimeAndOffset_s + "
"); Response.Write("strLocalTimeAndOffset_custom: " + strLocalTimeAndOffset_custom + "
"); }

SALIDA

 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 

Fuentes:

  • Cadenas estándar de formato de fecha y hora (MSDN)

  • Cadenas de formato de fecha y hora personalizadas (MSDN)

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

=>

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

Puede obtener la “Z” ( ISO 8601 UTC ) con el siguiente código:

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

Aquí es por qué:

El ISO 8601 tiene algunos formatos diferentes:

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 nos proporciona una enumeración con esas opciones:

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

Nota : Si aplica Visual Studio 2008 “watch utility” a la parte toString (“o”) puede obtener resultados diferentes, no sé si es un error, pero en este caso tiene mejores resultados usando una variable String si estás depurando

Origen: cadenas de formato de fecha y hora estándar (MSDN)

Si debe usar DateTime en ISO 8601, ToString (“o”) debería dar lo que está buscando. Por ejemplo,

 2015-07-06T12:08:27 

Sin embargo, DateTime + TimeZone puede presentar otros problemas como se describe en la publicación del blog DateTime y DateTimeOffset en .NET: buenas prácticas y riesgos comunes :

DateTime tiene innumerables trampas que están diseñadas para dar los errores de código:

1.- Los valores de DateTime con DateTimeKind.Unspecified son malas noticias.

2.- DateTime no se preocupa por UTC / Local al hacer comparaciones.

3.- Los valores DateTime no conocen cadenas de formato estándar.

4.- Analizar una cadena que tiene un marcador UTC con DateTime no garantiza un tiempo UTC.

Yo solo usaría XmlConvert :

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

Preservará automáticamente la zona horaria.

La mayoría de estas respuestas tienen milisegundos / microsegundos, lo que claramente no es compatible con ISO 8601. La respuesta correcta sería:

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

Referencias

  • Especificación ISO 8601
  • Especificador “K”

Para convertir DateTime.UtcNow en una representación de cadena de aaaa-MM-ddTHH: mm: ssZ , puede usar el método ToString () de la estructura DateTime con una cadena de formato personalizada. Al usar cadenas de formato personalizadas con DateTime, es importante recordar que debe escapar de sus separadores utilizando comillas simples.

Lo siguiente devolverá la representación de cadena que deseaba:

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

El especificador de formato estándar "s" representa una cadena de formato de fecha y hora personalizada que está definida por la propiedad DateTimeFormatInfo.SortableDateTimePattern . El patrón refleja un estándar definido ( ISO 8601 ) y la propiedad es de solo lectura. Por lo tanto, siempre es igual, independientemente de la cultura utilizada o del proveedor de formato suministrado. La cadena de formato personalizado es "yyyy'-'MM'-'dd'T'HH':'mm':'ss" .

Cuando se utiliza este especificador de formato estándar, la operación de formateo o análisis utiliza siempre la cultura invariable.

– de MSDN

Es interesante que el formato personalizado “aaaa-MM-ddTHH: mm: ssK” (sin ms) sea el método de formato más rápido.

También es interesante que el formato “S” sea lento en Classic y rápido en Core …

Por supuesto, los números son muy cercanos, entre algunas filas, la diferencia es insignificante (las pruebas con el sufijo _Verify son las mismas que las que no tienen ese sufijo, demuestran la repetibilidad de los resultados)

 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 | 

Código:

  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 fue utilizado

Si está desarrollando en SharePoint 2010 o superior, puede usar

 using Microsoft.SharePoint; using Microsoft.SharePoint.Utilities; ... string strISODate = SPUtility.CreateISO8601DateTimeFromSystemDateTime(DateTime.Now) 
 DateTime.Now.ToString("yyyy-MM-dd'T'HH:mm:ss zzz"); DateTime.Now.ToString("O"); 

NOTA: Dependiendo de la conversión que esté haciendo en su extremo, usará la primera línea (más parecida) o la segunda.

Asegúrese de aplicar el formato solo a la hora local, ya que “zzz” es la información de la zona horaria para la conversión UTC.

imagen

Para formatear como 2018-06-22T13: 04: 16 que se puede pasar en el URI de un uso de API:

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