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

时间:2009-07-21 21:16:43

标签: c# .net vba type-conversion access-vba

我正在使用C#3.5将一个小型MSAccess应用程序转换为基于Web的ASP.NET应用程序。当我将一些VBA代码转换为C#时,我想知道在C#中处理日期的最佳方法是什么。

以下是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
            }
        }
    }

5 个答案:

答案 0 :(得分:7)

无法将null转换为System.DateTime,因为它是一个不可为空的值类型“error

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并不代表特定的时间点,而是跨度本身。要获取日期,您可以使用接受DateTime的{​​{1}}对象的Add方法或Subtract方法重载。究竟应该怎么看我不能说,因为我不知道代码中的不同日期代表什么。

在最后一种情况下,您可以简单地使用AddDays方法的返回值,但使用负值(为了减去一天,而不是添加一个):

TimeSpan

答案 1 :(得分:3)

获取TimeSpan,然后从DateTime中减去它以获得所需的日期。对于你的内部IF语句,它看起来像这样:

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

编辑:您可能还想返回DateTime.MaxValue并让调用函数检查最大值,而不是返回null。

答案 2 :(得分:3)

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

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

如果您想要计算天数,只需返回TimeSpan的Days属性:

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

答案 3 :(得分:2)

DateTime是value type。因此,您不能将null分配给DateTime。 但是你可以使用像DateTime.MinValue这样的特殊值来表示你想要用null表示的任何内容。

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

dateCurrentDate.Subtract(dateEffDateOne)(或等效地, dateCurrentDate-dateEffDateOne )是两个日期之间的差异,即时间间隔。因此,我建议您将函数的返回类型更改为TimeSpan。

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

答案 4 :(得分:1)

经过一些优秀的答案(我已经投票给你了),我终于敲定了我认为我的答案。事实证明,在这种情况下,返回一个int作为天数对我有用。

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

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