在C#中,如何将TimeSpan数据类型转换为DateTime?

问题描述:

我正在使用C#3.5将小型MSAccess应用程序转换为基于Web的ASP.NET应用程序。我想知道在将某些VBA代码转换为C#时,处理C#中日期的最佳方式是什么。在C#中,如何将TimeSpan数据类型转换为DateTime?

下面是VBA代码的例子:

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

这里是我当前的C#代码看起来像在注释代码表示的错误:

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

它看起来像你的VB实际上返回一个时间跨度,大概是几天。这里是最接近的直接翻译:

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

相反,如果你只是想天的计数,只返回时间跨度的天属性:

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

和良好的措施,这是我会怎么收拾你最终版本:

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

获取时间跨度,然后从DateTime中减去以获得所需的日期。对于你内心的IF语句,它应该是这样的:

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

编辑:您可能还需要返回DateTime.MaxValue并有最大值调用功能检查,而不是返回null。

+0

您的代码将总是返回dateEffDateOne作为结果,而不是日期之间的差异。 我想,这不是@ program247365想要的。 – VladV 2009-07-21 21:42:15

+0

我不相信这是OP要求的。他需要DateTime,但是如果他需要存储时间段,那么他应该使用TimeSpan。 – 2009-07-21 21:46:26

不能转换为null为System.DateTime,因为它是一个非空值类型”错误

DateTime类型是值类型,这意味着它不能持有空值。要获得在这附近,您可以执行以下两项操作之一;要么返回DateTime.MinValue,要测试该值,或者更改函数返回DateTime?(注意问号),该值可以为空DateTime。可以为空的日期可以是像这样使用:

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

不能隐式转换system.timepsan为System.DateTime

当你减去从另一个DateTime一个DateTime,结果是TimeSpan,代表它们之间的时间量。 TimeSpan并不代表特定的时间点,而是跨度本身。为了获取日期,可以使用接受TimeSpanDateTime对象的Add方法或Subtract方法超载。具体如何看起来我不能说,因为我不知道你的代码中的不同日期代表了什么。

在最后一种情况下,你可以简单地使用来自AddDays方法的返回值,但负值(以扣除,而不是增加一个某一天,):

return dateEffDateOne.AddDays(-1); 
+0

> dateCurrentDate.Subtract(dateCurrentDate.Subtract(dateEffDateOne)) dateCurrentDate-(dateCurrentDate-dateEffDateOne)== dateEffDateOne 我想,这是不是有什么@ program247365希望。 – VladV 2009-07-21 21:47:54

+0

@VladV:我认为你是对的。由于我不知道原始代码示例中的各个日期如何相互关联,因此我无法弄清楚预期的结果,因此从我的答案中删除了该行。 – 2009-07-21 22:19:58

日期时间是value type。所以,你不能将null分配给DateTime。 但是,您可以使用一个特殊的值,如DateTime.MinValue来指示您试图通过null指示的任何值。

DateTime代表日期(和时间),如“2009年7月22日”。这意味着,您不应该使用此类型来表示时间间隔,如“9天”。 TimeSpan是为此设计的类型。

dateCurrentDate.Subtract(dateEffDateOne)(或,等价地,dateCurrentDate-dateEffDateOne)是两个日期之间的差,即,时间间隔。所以,我建议你将函数的返回类型改为TimeSpan。

TimeSpan也是一个值类型,因此您可以使用TimeSpan.Zero而不是null。

一些优秀的答案后(我上投你们),我终于敲定了什么,我觉得是我的答案。事实证明,在这种情况下,返回一个整数,就像天数一样。

谢谢大家,提供您真棒的答案。它帮助我走上了正确的轨道。

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