2012-03-28 9 views
9

Poniższe wywala kod i oparzenia, a ja nie rozumiem dlaczego:Dodawanie Seconds to DateTime z poprawnym podwójnymi Wyniki w ArgumentOutOfRangeException

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

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

Czy ktoś może mi powiedzieć, co się dzieje? Ja po prostu nie wydają się być w stanie dowiedzieć się dlaczego ...

EDIT

Wartość ta wraca z API REST i Salesforce z tego co rozumiem to Unix czas epoka znaczek. "Czas emisji tokena, reprezentowany jako liczba sekund od epoki Uniksa (00:00:00 UTC w dniu 1 stycznia 1970 r.)."

ROZWIĄZANIE

Salesforce REST API jest w rzeczywistości wysyłającego milisekund z powrotem na polu issued_at podczas wykonywania żądania OAuth, gdy mówią, że wysyłają sekund ...

+0

Jaki jest błąd/wyjątek można dostać? – Mathieu

+0

Ta podwójna wartość może spowodować, że spróbujesz dodać '1332958778172.00000000000004' sekund (ze względu na sposób obsługi podwójnej), co spowoduje wyjątek poza zakresem. To również mija liczba lat, którą może obsłużyć DT. – jzworkman

Odpowiedz

13

Jak powiedzieli inni, problemem jest to, że wartość jest zbyt duża.

Po spojrzał na nią, uważam, że reprezentuje milisekund od epoki Uniksa, nie sekund więc chcesz:

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)); 

Albo to, albo podzielić przez 1000 przed wywołaniem AddSeconds - ale oczywiście, że straci dane.

+0

Być może masz rację, ale API Salesforce twierdzi, że to * sekundy *. http://wiki.developerforce.com/page/Digging_Deeper_into_OAuth_2.0_on_Force.com – Gup3rSuR4c

+0

Tak, właśnie sprawdziłem, to jest w milisekundach. Tak bardzo nienawidzę Salesforce, każdego dnia sprawia mi to trudność. – Gup3rSuR4c

+1

@Hupperware: Nie tylko "gdzieś w 2012", ale "dzisiaj", co wydaje się być całkiem przekonującym punktem danych :) –

7

wartość, którą dodają wyniki w terminie wykraczającym poza prawidłowy zakres dat obsługiwanych przez program DateTime.

Usługa DateTime obsługuje 01/01/0001 00:00:00 do 31.12.9999 23:59:59.

Proste obliczenie 1332958778172/3600/24/365 daje 42267 lat.

+0

Masz rację 42k lat jest daleko poza zasięgiem – Mathieu

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

Tyle że ...

1332958778172/60/60/24/365 = 42,267 lat ... co DateTime może tylko wzrosnąć do 23: 59: 59.9999999, 31 grudnia 9999

3

Myślę, że podwójna wartość jest naprawdę zbyt duża. To niewiele ponad 42 267 lat (jeśli moja matematyka jest poprawna), a DateTime.MaxValue to 23: 59: 59.9999999, 31 grudnia, 9999

1

Miałem podobny problem, kiedy musiałem dodać konfigurowalny przedział czasowy do datetime. Jeśli konfiguracja nie jest poprawna, muszę przyjąć "najgorszy scenariusz": MaxValue.

Rozwiązałem go poprzez wdrożenie rozszerzenie DateTime (wciąż w fazie testów):

/// <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; 
    } 
Powiązane problemy