В C#, как преобразовать тип данных TimeSpan в DateTime?

Я конвертирую небольшое приложение MSAccess в веб-приложение ASP.NET app, используя C# 3.5. Мне было интересно, как лучше всего работать с датами в C# при преобразовании некоторого кода VBA в 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 ответов


похоже, что ваш VB фактически возвращает промежуток времени, предположительно в днях. Вот ближайший прямой перевод:

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

Если вместо этого вы просто хотели количество дней, просто верните свойство TimeSpan дней:

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

не удается преобразовать null в System.DateTime, потому что это ненулевое значение типа" error

на DateTime тип тип значения, что означает, что он не может иметь значение null. Чтобы обойти это, вы можете сделать одну из двух вещей: либо вернуть DateTime.MinValue, и проверьте это, когда вы хотите использовать значение или изменить функцию для возврата DateTime? (обратите внимание на знак вопроса), который является nullable DateTime. Дату nullable можно использовать как это:

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

не удается неявно преобразовать систему.timepsan к системе.datetime

при вычитании DateTime С другой DateTime, результат -TimeSpan, представляющий количество времени между ними. The TimeSpan представляет собой не конкретный момент времени, а сам промежуток. Для того, чтобы получить дату, вы можете использовать Add способ или Subtract перегрузка метода DateTime объект, который принимает TimeSpan. Как именно это должно выглядеть, я не могу сказать, так как я не знаю, что представляют собой разные даты в вашем коде.

в последнем случае, вы можете просто использовать возвращаемое значение из метода AddDays, но с отрицательным значением (чтобы вычесть один день, вместо добавления одного):

return dateEffDateOne.AddDays(-1);

получить TimeSpan, а затем вычесть это из DateTime, чтобы получить нужную дату. Для вашего внутреннего утверждения IF это будет выглядеть так:

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

EDIT: вы также можете захотеть вернуть DateTime.MaxValue и проверить вызывающую функцию на максимальное значение вместо возврата null.


DateTime-это тип значения. Таким образом, Вы не можете назначить null DateTime. Но вы можете использовать специальное значение типа datetime.MinValue для указания того, что вы пытались указать null.

DateTime представляет собой дату (и время), например "22 июля 2009 года". Это означает, что вы не должны использовать этот тип для представления временного интервала, например, "9 дней". TimeSpan - Это тип, предназначенный для этого.

dateCurrentDate.Вычесть (dateEffDateOne) (или, что эквивалентно,dateCurrentDate-dateEffDateOne) - это разница между двумя датами, то есть временной интервал. Поэтому я предлагаю вам изменить тип возврата вашей функции на TimeSpan.

TimeSpan также является типом значения, поэтому вы можете использовать, например, TimeSpan.Вместо нуль нуль.


после некоторых отличных ответов (я проголосовал за вас, ребята), я, наконец, выковал то, что я думаю, это мой ответ. Оказывается, возвращение 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;
            }
        }
    }