В C # как конвертировать тип данных TimeSpan в DateTime? - PullRequest
7 голосов
/ 22 июля 2009

Я преобразую небольшое приложение MSAccess в веб-приложение ASP.NET, используя 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 ]

7 голосов
/ 22 июля 2009

не может преобразовать ноль в 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 представляет не конкретный момент времени, а сам интервал. Чтобы получить дату, вы можете использовать метод Add или перегрузку метода Subtract объекта DateTime, который принимает TimeSpan. Я не могу сказать, как именно это должно выглядеть, поскольку не знаю, что представляют разные даты в вашем коде.

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

return dateEffDateOne.AddDays(-1);
3 голосов
/ 22 июля 2009

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

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

Если вместо этого вам просто нужно количество дней, просто верните свойство TimeSpan's 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 голосов
/ 22 июля 2009

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

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

РЕДАКТИРОВАТЬ: Вы также можете захотеть вернуть DateTime.MaxValue и заставить вызывающую функцию проверять максимальное значение вместо возврата нуля.

2 голосов
/ 22 июля 2009

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

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

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

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

1 голос
/ 22 июля 2009

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