Necesito enviar una fecha de inicio y una fecha de finalización a una API en formato UTC, he intentado lo siguiente:

DateTime startDate = Convert.ToDateTime(start + "T00:00:00Z").ToUniversalTime();
DateTime endDate = Convert.ToDateTime(end + "T23:59:59Z").ToUniversalTime();

Pero parece que no se están convirtiendo a UTC, ¿cuál sería la forma correcta de tomar startDate y endDate y convertirlos a UTC?

Start es una cadena y es 2018-08-31 y la fecha de finalización también es una cadena y es 2018-08-31 Agregué las horas en el código anterior para cubrir la fecha completa.

0
user979331 7 sep. 2018 a las 22:57

3 respuestas

La mejor respuesta

Primero instale el siguiente paquete desde el administrador de paquetes NuGet y haga referencia a él en su proyecto:

Install-Package Newtonsoft.Json

Ahora puede usar fácilmente el método JsonConvert.SerializeObject(object value) para serializar cualquier objeto a Json.

Para convertir DateTime a UTC, use el método TimeZoneInfo.ConvertTimeToUtc(DateTime dateTime).

En su caso:

DateTime date = DateTime.Parse("2018-08-31");
DateTime dateTimeToUtc = TimeZoneInfo.ConvertTimeToUtc(date);
string dateInJson = JsonConvert.SerializeObject(dateTimeToUtc);

La variable dateInJson tendrá un valor como 2018-08-30T19:30:00Z.

1
Sajad Afaghiy 8 sep. 2018 a las 08:18

Quitar la Z

        string start = "2018-08-31";
        string end = "2018-08-31";

        DateTime startDate = Convert.ToDateTime(start + "T00:00:00");
        DateTime endDate = Convert.ToDateTime(end + "T23:59:59");

        Console.WriteLine(startDate);                   // 8/31/2018 12:00:00 (Local)
        Console.WriteLine(startDate.ToUniversalTime()); // 8/31/2018 5:00:00 (UTC)
        Console.WriteLine(endDate);                     // 8/31/2018 11:59:59 (Local)
        Console.WriteLine(endDate.ToUniversalTime());   // 9/1/2018 4:59:59 (UTC)
1
Todd Skelton 7 sep. 2018 a las 20:07

Suponiendo que desea que endDate represente el último momento posible en la fecha dada en UTC:

DateTime startDate = DateTime.ParseExact(start, "yyyy-MM-dd", CultureInfo.InvariantCulture,
                        DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);

DateTime endDate = DateTime.ParseExact(end, "yyyy-MM-dd", CultureInfo.InvariantCulture,
                        DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)
                        .AddDays(1).AddTicks(-1);

Algunas otras cosas:

  • ToUniversalTime se convierte a UTC desde la zona horaria local de la computadora (a menos que .Kind == DateTimeKind.Utc). En general, debe evitarlo a menos que la zona horaria local de la computadora sea relevante para su situación.

  • En el código anterior, necesita tanto AssumeUniversal para indicar que la fecha de entrada debe interpretarse como UTC, como AdjustToUniversal para indicar que desea que el valor de salida se mantenga en términos de UTC y no la zona horaria local de la computadora.

  • UTC no es un "formato". Las cadenas combinadas de fecha y hora estarían en formato extendido ISO 8601 (también compatible con RFC 3339).

  • En general, intente no usar Convert.ToDateTime. Es equivalente a DateTime.Parse con CultureInfo.CurrentCulture y no DateTimeStyles. Eso puede funcionar para algunos escenarios, pero generalmente es mejor ser más específico.

  • .AddDays(1).AddTicks(-1) está ahí para llevarlo a la última marca representable en esa fecha. Eso permite una comparación inclusiva entre el inicio y el final, sin embargo, tiene la desventaja de no poder restar los dos valores y obtener un total de 24 horas. Por lo tanto, generalmente es mejor hacer un seguimiento de 00:00 de un día a 00:00 del día siguiente, luego usar la comparación exclusiva en la fecha de finalización. (Solo se debe comparar la fecha de inicio inclusive).

    En otras palabras, en lugar de:

    2018-08-31T00:00:00.0000000Z <= someValueToTest <= 2018-08-31T23:59:59.9999999Z
    

    Haga esto:

    2018-08-31T00:00:00.0000000Z <= someValueToTest < 2018-09-01T00:00:00.0000000Z
    
3
Matt Johnson-Pint 7 sep. 2018 a las 20:20