2009-07-21 14 views
6

Konwertuję małą aplikację MSAccess do internetowej aplikacji ASP.NET, używając C# 3.5. Zastanawiam się, jaki jest najlepszy sposób pracy z datami w C#, przy konwersji niektórych z tego kodu VBA na C#.W języku C#, jak przekonwertować typ danych TimeSpan na DateTime?

Oto przykład kodu VBA:

Coverage1=IIf(IsNull([EffDate1]),0,IIf([CurrDate]<=[EndDate1],[CurrDate]-[EffDate1],[EndDate1]-[EffDate1]+1)) 

Oto co mój aktualny kod C# wygląda z błędów oznaczonych w komentowanym kodu:

public DateTime CalculateCoverageOne(DateTime dateEffDateOne, DateTime dateCurrentDate, DateTime dateEndDateOne) 
    { 
     if (dateCurrentDate.Date <= dateEndDateOne.Date) 
     { 
      return null; //Get "cannot convert null to System.DateTime because it is a non-nullable value type" error 
     } 
     else 
     { 
      if (dateCurrentDate.Date <= dateEndDateOne) 
      { 
       return dateCurrentDate.Subtract(dateEffDateOne); //Gets error "cannot implicitly convert system.timepsan to system.datetime 
      } 
      else 
      { 
       return dateEndDateOne.Subtract(dateEffDateOne.AddDays(1)); //Gets error "cannot implicitly convert system.timepsan to system.datetime 
      } 
     } 
    } 

Odpowiedz

2

Wygląda na to, że Twój VB rzeczywiście zwraca czas, prawdopodobnie w dniach. Poniżej znajduje się najbliżej bezpośrednie tłumaczenie:

public TimeSpan CalculateCoverageOne(DateTime EffDate1, DateTime CurrDate, DateTime? EndDate1) 
{ 
    return (EndDate1 == null) ? TimeSpan.Zero : 
      (CurrDate < EndDate1) ? (CurrDate - EffDate1) : 
      (EndDate1.AddDays(1) - EffDate1); 
} 

Jeśli zamiast tego po prostu chcieliśmy liczbę dni, po prostu zwrócić Okres rekreacyjnego dni:

public int CalculateCoverageOne(DateTime EffDate1, DateTime CurrDate, DateTime? EndDate1) 
{ 
    return ((EndDate1 == null) ? TimeSpan.Zero : 
      (CurrDate < EndDate1) ? (CurrDate - EffDate1) : 
      (EndDate1.AddDays(1) - EffDate1)).Days; 
} 

A na dokładkę, to jak bym oczyścić ostateczna wersja:

public int CalculateCoverageOne(DateTime dateCurrentDate, DateTime dateEffectiveDate, DateTime dateEffDateOne, DateTime dateEndDateOne) 
{ 
    TimeSpan ts; 
    if (dateEffDateOne == DateTime.MinValue) 
    { 
     ts = TimeSpan.Zero; 
    } 
    else if (dateEffectiveDate <= dateEndDateOne) 
    { 
     ts = dateCurrentDate - dateEffDateOne; 
    } 
    else 
    { 
     ts = (dateEndDateOne - dateEffDateOne) + new TimeSpan(1, 0, 0, 0); 
    } 
    return ts.Days; 
} 
+0

Najbardziej doskonały. Dziękuję Ci bardzo! – program247365

2

Pobierz Okres, po czym odejmij to od DateTime, aby uzyskać żądaną datę. Dla Państwa wewnętrzna if, to będzie wyglądać następująco:

TimeSpan estSpan = dateCurrentDate.Subtract(dateEffDateOne); 
return dateCurrentDate.Subtract(estSpan); 

EDIT: Można też wrócić parametr DateTime.MaxValue i mieć kontrolę działania wzywający do maksymalnej wartości, zamiast zwracania wartości null.

+0

Twój kod zawsze zwróci datęEffDateOne jako wynik, a nie różnicę między datami. Chyba nie jest to, czego chce @ program247365. – VladV

+0

Nie wierzę w to, o co prosił PO. On potrzebuje DateTime, ale jeśli potrzebuje do przechowywania okresów, to powinien używać TimeSpan. –

6

nie można przekonwertować null System.DateTime ponieważ jest to typ wartości nie pustych”Błąd

Typ DateTime jest rodzajem wartość, co oznacza, że ​​nie może posiadać wartość null. Aby uzyskać wokół tego możesz zrobić jedną z dwóch rzeczy, albo zwróć DateTime.MinValue, i przetestuj to, gdy chcesz użyć wartości, lub zmień funkcję, aby zwrócić DateTime? (uwaga na znak zapytania), który jest zerowalny DateTime. Null można należy używać w następujący sposób:

DateTime? nullable = DateTime.Now; 
if (nullable.HasValue) 
{ 
    // do something with nullable.Value 
} 

nie można niejawnie przekonwertować system.timepsan do System.DateTime

Jeśli odjąć od innej DateTimeDateTime, wynik jest TimeSpan, reprezentujący czas między nimi. TimeSpan nie reprezentuje określonego punktu w czasie, ale sam zakres. Aby uzyskać datę, można użyć metody Add lub przeciążenia metody Subtract obiektu, który akceptuje obiekt TimeSpan. Dokładnie, jak to powinno wyglądać, nie mogę powiedzieć, ponieważ nie wiem, co reprezentują różne daty w twoim kodzie.

W ostatnim przypadku można po prostu użyć wartości zwracanej z metody AddDays, ale z wartością ujemną (aby odjąć jeden dzień, zamiast dodawania jeden):

return dateEffDateOne.AddDays(-1); 
+0

> dateCurrentDate.Subtract (dateCurrentDate.Subtract (dateEffDateOne)) dateCurrentDate- (dateCurrentDate-dateEffDateOne) == dateEffDateOne Myślę, że nie jest to, co @ program247365 chce. – VladV

+0

@VladV: Myślę, że masz rację. Ponieważ nie mam pojęcia, w jaki sposób różne daty w oryginalnej próbce kodu odnoszą się do siebie, nie jestem w stanie określić, jaki wynik jest oczekiwany, więc usunąłem tę linię z mojej odpowiedzi. –

1

DateTime jest value type. Tak więc nie można przypisać wartości null do DateTime. Ale można użyć specjalnej wartości, takiej jak DateTime.MinValue, aby wskazać, co próbujesz wskazać jako wartość zerową.

DateTime oznacza datę (i godzinę), np. "22 lipca 2009". Oznacza to, że nie należy używać tego typu do reprezentowania przedziału czasu, np. "9 dni". TimeSpan jest typem przeznaczonym do tego.

dateCurrentDate.Subtract (dateEffDateOne) (lub równoważnie dateCurrentDate-dateEffDateOne) jest to różnica pomiędzy dwiema datami, to znaczy przedział czasu. Proponuję więc zmienić typ zwrotu funkcji na TimeSpan.

TimeSpan jest również typem wartości, więc można użyć na przykład TimeSpan.Zero zamiast null.

0

Po kilku doskonałych odpowiedzi (mam up-głosowało wy), mam w końcu wypracowane co myślę jest moja odpowiedź. Okazuje się, że zwracanie int, jak liczba dni, jest dla mnie skuteczne w tej sytuacji.

Dziękuję wszystkim, za dostarczanie wspaniałych odpowiedzi. Pomogło mi to przejść na właściwą drogę.

public int CalculateCoverageOne(DateTime dateCurrentDate, DateTime dateEffectiveDate, DateTime dateEffDateOne, DateTime dateEndDateOne) 
    { 
     //Coverage1= 
     //IIf(IsNull([EffDate1]),0, 
      //IIf([CurrDate]<=[EndDate1], 
       //[CurrDate]-[EffDate1], 
        //[EndDate1]-[EffDate1]+1)) 

     if (dateEffDateOne.Equals(TimeSpan.Zero)) 
     { 
      return (TimeSpan.Zero).Days; 
     } 
     else 
     { 
      if (dateEffectiveDate <= dateEndDateOne) 
      { 
       return (dateCurrentDate - dateEffDateOne).Days; 
      } 
      else 
      { 
       return (dateEndDateOne - dateEffDateOne).Add(new TimeSpan(1, 0, 0, 0)).Days; 
      } 
     } 
    } 
+0

Prawdopodobnie masz na myśli dateEffDateOne.Equals (DateTime.MinValue) zamiast TimeSpan.Zero. W praktyce są to te same rzeczy (przechowywane jako 0L), ale nie powinieneś polegać na tym zbiegu okoliczności. – dahlbyk

+0

Gotcha. Dziękuję za komentarz. – program247365

Powiązane problemy