2009-07-21 8 views
6

Je convertis une petite application MSAccess en application Web ASP.NET, en utilisant C# 3.5. Je me demandais quelle est la meilleure façon de travailler avec des dates en C#, en convertissant une partie de ce code VBA en C#.En C#, comment convertir le type de données TimeSpan en DateTime?

Voici un exemple du code VBA:

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

Voici ce que mon code actuel C# ressemble avec les erreurs notées dans le code commenté:

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 
      } 
     } 
    } 

Répondre

2

Il semble que votre VB soit en train de revenir dans le temps, vraisemblablement en quelques jours. Voici la traduction la plus directe:

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

Si au contraire vous vouliez juste un nombre de jours, il suffit de retourner la propriété Jours du TimeSpan:

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

Et pour faire bonne mesure, voici comment je nettoyer votre version finale:

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

Le plus excellent. Merci beaucoup! – program247365

2

Obtenez le TimeSpan, puis soustrayez cela de DateTime pour obtenir la date que vous voulez. Pour votre déclaration intérieure IF, il ressemblerait à ceci:

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

EDIT: Vous pouvez également revenir DateTime.MaxValue et avoir le contrôle de la fonction d'appel pour la valeur maximale, au lieu de retourner null.

+0

Votre code retournera toujours dateEffDateOne en conséquence, pas une différence entre les dates. Je suppose que ce n'est pas ce que veut @ program247365. – VladV

+0

Je ne crois pas que c'est ce que le PO a demandé. Il a besoin de DateTime, mais s'il a besoin de stocker des périodes, il devrait utiliser TimeSpan. –

6

ne peut pas convertir null à System.DateTime, car il est un type de valeur non nulle » erreur

Le type DateTime est un type de valeur , ce qui signifie qu'il ne peut pas contenir une valeur nulle. Pour Autour de cela, vous pouvez faire l'une des deux choses, soit retourner DateTime.MinValue, et tester pour cela lorsque vous voulez utiliser la valeur, ou changer la fonction pour retourner DateTime? (notez le point d'interrogation), qui est un DateTime nullable. s'utilise comme ceci:

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

ne peut pas convertir implicitement system.timepsan à System.DateTime

Lorsque vous soustrayez un DateTime d'un autre DateTime, le résultat est un TimeSpan, ce qui représente la quantité de temps entre eux. Le TimeSpan ne représente pas un point précis dans le temps, mais l'étendue elle-même. Pour obtenir la date, vous pouvez utiliser la méthode Add ou la surcharge de méthode Subtract d'un objet DateTime qui accepte un TimeSpan. Exactement comment cela devrait ressembler je ne peux pas dire, puisque je ne sais pas ce que les différentes dates dans votre code représentent.

Dans le dernier cas, vous pouvez simplement utiliser la valeur de retour de la méthode AddDays, mais avec une valeur négative (pour soustraire un jour, au lieu d'ajouter un):

return dateEffDateOne.AddDays(-1); 
+0

> dateCurrentDate.Subtract (dateCurrentDate.Subtract (dateEffDateOne)) dateCurrentDate- (dateCurrentDate-dateEffDateOne) == dateEffDateOne Je suppose que, ce n'est pas ce que @ program247365 veut. – VladV

+0

@VladV: Je pense que vous avez raison. Comme je n'ai aucune idée de la façon dont les différentes dates de l'exemple de code original se rapportent les unes aux autres, je ne peux pas vraiment comprendre quel résultat est attendu, donc j'ai supprimé cette ligne de ma réponse. –

1

DateTime est un value type. Donc, vous ne pouvez pas affecter de null à DateTime. Mais vous pouvez utiliser une valeur spéciale comme DateTime.MinValue pour indiquer tout ce que vous essayiez d'indiquer par null.

DateHeure représente une date (et une heure), comme "22 juillet 2009". Cela signifie que vous ne devez pas utiliser ce type pour représenter un intervalle de temps, par exemple "9 jours". TimeSpan est le type prévu pour cela.

dateCurrentDate.Subtract (dateEffDateOne) (ou, de manière équivalente, dateCurrentDate-dateEffDateOne) est une différence entre deux dates, soit l'intervalle de temps. Donc, je vous suggère de changer le type de retour de votre fonction à TimeSpan.

TimeSpan est également un type de valeur, vous pouvez donc utiliser, par exemple, TimeSpan.Zero au lieu de null.

0

Après quelques excellentes réponses (je vous ai mis voté les gars), je l'ai enfin martelé ce que je pense est ma réponse. Il s'avère que retourner un int, comme le nombre de jours, est ce qui a fonctionné pour moi dans cette situation.

Merci à tous pour vos réponses géniales. Cela m'a aidé à me mettre sur la bonne voie.

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

Vous voulez probablement dire dateEffDateOne.Equals (DateTime.MinValue) plutôt que TimeSpan.Zero. En pratique, ils sont la même chose (stocké sous 0L), mais vous ne devriez pas compter sur cette coïncidence. – dahlbyk

+0

Gotcha. Merci pour le commentaire. – program247365

Questions connexes