将小数年添加到日期时间

问题描述 投票:0回答:3

当我遇到这个问题时,我认为这将是一个涉及 TimeSpans 和基本 DateTime 算法的微不足道的挑战。除非我错过了一些非常明显的错误......

如何将“13.245”年添加到“3/22/2023 5:25:00 AM”?

我得到的最接近的是这个片段:

    long ticks = (long)((365.0M - 4) * (decimal)TimeSpan.TicksPerDay * 13.245M); 
            
    DateTime futureDate= new DateTime(2023, 3, 22, 5, 25, 0).AddTicks(ticks);
    Console.WriteLine(futureDate.ToString());

这给了我“4/23/2036 4:05:48 PM”的输出,我对此并不完全有信心。另外,请注意我不得不手动处理闰年的方式:

    365.0M - 4
c# datetime decimal timespan
3个回答
0
投票

你的做法几乎是正确的,但有几个问题需要考虑:

闰年:正如你提到的,你需要考虑闰年,因为他们有额外的一天。一种方法是计算两个日期之间的天数,然后加上与该期间闰年数相对应的一天的分数。

Precision:“13.245”年的值不准确,因为一年不正好是365天。它更接近 365.2425 天。这对于小的时间间隔可能无关紧要,但对于较长的时间间隔,它可能会产生重大影响。

时区:您提供的代码假设输入日期是在当地时区,这可能不是您想要的。如果你想使用 UTC 日期,你应该使用 DateTimeOffset 结构而不是 DateTime。

这是考虑到这些问题的代码的修改版本:

decimal yearsToAdd = 13.245M;
DateTime inputDate = new DateTime(2023, 3, 22, 5, 25, 0);
int inputYear = inputDate.Year;

// Calculate the number of leap years between the input year and the future year
int futureYear = inputYear + (int)yearsToAdd;
int numLeapYears = Enumerable.Range(inputYear, futureYear - inputYear)
    .Count(y => DateTime.IsLeapYear(y));

// Calculate the number of days to add, including leap years
TimeSpan daysToAdd = TimeSpan.FromDays(yearsToAdd * 365.2425M + numLeapYears);

// Add the days to the input date
DateTime futureDate = inputDate.Add(daysToAdd);

Console.WriteLine(futureDate.ToString());

此代码使用 LINQ 的 Enumerable.Range 方法计算输入年份和未来年份之间的闰年数。然后计算要添加的总天数,包括与部分年份和闰年对应的一天的分数。最后,它将生成的 TimeSpan 添加到输入日期以获得未来日期。


0
投票

我会这样做:

private static DateTime AddYears(DateTime date, double years)
{
    date = date.AddYears((int)years);
    double remainder = years - (int)years;

    double yearSeconds = (new DateTime(date.Year + 1, 1, 1) - new DateTime(date.Year, 1, 1)).TotalSeconds;

    return date.AddSeconds(yearSeconds * remainder);
}

下降到第二个的好处是可以接受最后加法的两倍,并允许更高的精度。

但是,仍然存在出错的可能性,因为剩余的部分可能会使我们进入一个长度不同的新的一年:闰年或其他因素(如奇数闰秒)可能发生变化。例如,假设开始日期是

2023-12-31 23:23:59
,加法是
0.99
。上面的代码假定年份长度基于当前的 365 天年份(添加 0 整年),但几乎所有最终的小数加法都发生在明年,它有 366 天。 你最终会比预期的时间短 16 1/2 小时。

要真正准确,你需要把小数部分加到年底,然后根据新的年份重新计算剩下的部分。

知道 Jon Skeet 正在看这个问题,如果 Noda Time 使这更容易,我不会感到惊讶,但现在我将把最后的小数部分作为 OP 的练习。

我确定还有其他可能的错误,但我觉得这会让你在大多数情况下足够接近。


-1
投票

就我个人而言,我会先添加整个年份 (13),然后添加整个月份 (0.245 * 12 = 2.94 = 2),最后一步是检查下个月有多少天和(例如 30)并添加相应的天(0.94 * 30 = 28.2)。 像这样的东西:

private static DateTime AddYears(DateTime date, double years)
{
    date = date.AddYears((int)years);
    double remainingYearsToAdd = years - (int)years;

    double monthsToAdd = remainingYearsToAdd * 12;
    date = date.AddMonths((int)monthsToAdd);
    double remainingMonthsToAdd = monthsToAdd - (int)monthsToAdd;

    int daysInThisMonth = DateTime.DaysInMonth(date.Year, date.Month);
    double elapsedPercentageThisMonth = 1d / daysInThisMonth * (date.Day + (date.Hour + (date.Minute + (date.Second + date.Millisecond / 1000d) / 60d) / 60d) / 24d);
    if (elapsedPercentageThisMonth + remainingMonthsToAdd <= 1)
    {
        return date.AddDays(remainingMonthsToAdd * daysInThisMonth);
    }
    else
    {
        remainingMonthsToAdd -= elapsedPercentageThisMonth;
        date = new DateTime(date.Year, date.Month+1, 1);
        int daysInNextMonth = DateTime.DaysInMonth(date.Year, date.Month);
        return date.AddDays(daysInNextMonth * remainingMonthsToAdd);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.