2012-03-28 9 views
9

Los siguientes códigos accidentes y quemaduras y yo no entiendo por qué:Adición de segundos a DateTime con unos resultados válidos de dobles en ArgumentOutOfRangeException

DateTime dt = new DateTime(1970,1,1,0,0,0,0, DateTimeKind.Utc); 
double d = double.Parse("1332958778172"); 

Console.Write(dt.AddSeconds(d)); 

¿Puede alguien decirme lo que está pasando? Me parece que no puede ser capaz de averiguar por qué ...

EDITAR

Este valor se vuelve de la API REST y Salesforce por lo que entiendo que es una marca de tiempo Unix época. "La hora del problema del token, representada como el número de segundos desde la época de Unix (00:00:00 UTC del 1 de enero de 1970)."

SOLUCIÓN

Salesforce REST API es en el envío de milisegundos vuelta para el campo issued_at al realizar la solicitud de OAuth cuando dicen que están enviando segundo hecho ...

+0

¿Cuál es el error/excepción se obtiene? – Mathieu

+0

Ese doble valor puede ocasionar que intentes agregar '1332958778172.00000000000004' segundos (debido a la forma en que se manejan los dobles), esto causaría una excepción fuera de rango. También esto pasa la cantidad de años que un DT puede manejar. – jzworkman

Respuesta

13

Como han dicho otros, el problema es que el valor es demasiado grande.

han consultado sobre ella, creo que representa milisegundos desde la época Unix, no segundos por lo que desea:

DateTime dt = new DateTime(1970,1,1,0,0,0,0, DateTimeKind.Utc); 
double d = double.Parse("1332958778172"); // Or avoid parsing if possible :) 
Console.Write(dt.AddMilliseconds(d)); 

O eso, o dividir por 1000 antes de llamar AddSeconds - pero obviamente eso perderá datos.

+0

Y es posible que tenga razón, pero la API de Salesforce indica que es * segundos *. http://wiki.developerforce.com/page/Digging_Deeper_into_OAuth_2.0_on_Force.com – Gup3rSuR4c

+0

Sí, acabo de comprobarlo, está en milisegundos. Odio tanto a Salesforce que me dificulta la vida todos los días. – Gup3rSuR4c

+1

@Hupperware: no solo "en algún lugar en 2012" sino "hoy", que parece ser un punto de datos bastante convincente :) –

7

El valor que están agregando resultados en una fecha fuera del rango válido de fechas que admite DateTime.

DateTime admite 01/01/0001 00:00:00 a 31/12/9999 23:59:59.

Un simple cálculo de 1332958778172/3600/24/365 da 42267 años.

+0

Tiene razón 42k años está fuera del rango – Mathieu

2
DateTime dt = new DateTime(1970,1,1,0,0,0,0, DateTimeKind.Utc);  
Console.Write(dt.AddSeconds(1332958778172D)); 

Excepto que ...

1332958778172/60/60/24/365 = 42,267 años ... lo que DateTime sólo puede ir hasta 23: 59: 59.9999999, 31 de diciembre de 9999

3

Creo que el doble valor es realmente demasiado grande. Representa algo más de 42,267 años (si mis cálculos son correctos), y DateTime.MaxValue es 23: 59: 59,999999, 31 de diciembre de 9999

1

Tuve un problema similar cuando se me requirió agregar un intervalo de tiempo configurable a una fecha y hora. Si la configuración no es correcta, tengo que asumir el "peor escenario": MaxValue.

Lo resuelto mediante la implementación de una extensión a DateTime (todavía en fase de prueba):

/// <summary> 
    /// Removes a timespan from a date, returning MinValue or MaxValue instead of throwing exception when if the resulting date 
    /// is behind the Min/Max values 
    /// </summary> 
    /// <returns></returns> 
    public static DateTime SafeAdd(this DateTime source, TimeSpan value) 
    { 
     // Add or remove ? 
     if (value.Ticks > 0) 
     { 
      // add 
      var maxTicksToAdd = DateTime.MaxValue - source; 
      if (value.Ticks > maxTicksToAdd.Ticks) 
       return DateTime.MaxValue; 
     } 
     else 
     { 
      var maxTicksToRemove = source - DateTime.MinValue; 

      // get the value to remove in unsigned representation. 
      // negating MinValues is impossible because it would result in a value bigger than MaxValue : (-32768 .. 0 .. 32767) 
      var absValue = value == TimeSpan.MinValue ? TimeSpan.MaxValue : -value; 

      if (absValue.Ticks > maxTicksToRemove.Ticks) 
       return DateTime.MinValue; 
     } 
     return source + value; 
    } 
Cuestiones relacionadas