从日期减去TimeSpan

时间:2010-12-24 07:41:10

标签: c# .net datetime timespan

我想使用30天的月份从日期时间对象中减去时间跨度,忽略闰年等。

Date is 1983/5/1 13:0:0 (y/m/d-h:m:s)
Time span is 2/4/28-2:51:0 (y/m/d-h:m:s)

我可以使用DateTime和TimeSpan对象将时间跨度的年份和月份转换为天数(假设每月30天,每年约364天)。

new DateTime(1981,5,1,13,0,0).Subtract(new TimeSpan(878,13,51,0));

有了这个,我得到了结果:

{12/4/1978 11:09:00 PM}

上面的答案显然不会忽略我想忽略的因素,并给我一个准确的答案。但在这种情况下,这不是我想要的,所以我写了下面的代码。

public static CustomDateTime operator -(CustomDateTime DT1,CustomDateTime DT2)
{
    CustomDateTime retVal = new CustomDateTime();
    try
    {
        const int daysPerYear = 364.25;
        const int monthsPerYear = 12;
        const int daysPerMonth = 30;
        const int hoursPerDay = 24;
        const int minutesPerHour = 60;

        retVal.Minute = DT1.Minute - DT2.Minute;
        if (retVal.Minute < 0)
        {
            retVal.Minute += minutesPerHour;
            DT1.Hour -= 1;
        }
        retVal.Hour = DT1.Hour - DT2.Hour;
        if (retVal.Hour < 0)
        {
            retVal.Hour += hoursPerDay;
            DT1.Day -= 1;
        }
        retVal.Day = DT1.Day - DT2.Day;
        if (retVal.Day < 0)
        {
            retVal.Day += daysPerMonth;
            DT1.Month -= 1;
        }
        retVal.Month = DT1.Month - DT2.Month;
        if (retVal.Month < 0)
        {
            retVal.Month += monthsPerYear;
            DT1.Year -= 1;
        }
        retVal.Year = DT1.Year - DT2.Year;                
    }
    catch (Exception ex) { }
    return retVal;
}

然后我得到:

1981/0/3-10:9:0

这非常接近我所追求的,除了我不应该每月0和年应该是1980年。任何形式的帮助都表示赞赏。


只是为了让事情再次清楚;在这种情况下,我必须使用一个30天的月份,忽略闰年,不同的月份等。我知道这是一件奇怪的事情。所以我几乎都是在“错误答案”之后,而不是托管类给出的确切答案。

2 个答案:

答案 0 :(得分:2)

如果您估计30个月的一个月,当然您的数学将会被取消。当您从1981年5月1日减去878天时,.Net正在为您提供完全差异,而非估计值,并且这个差异占闰年,如果有的话。该错误不在Subtract(...)方法中 - 它在您自己的“手动”计算中。

DateTime dt = new DateTime(1981, 5, 1, 13, 0, 0);
TimeSpan t = new TimeSpan(878, 13, 51, 0);

dt.Ticks
    624931668000000000

t.Ticks
    759090600000000

dt.Ticks - t.Ticks
    624172577400000000

new DateTime(dt2)
    {12/4/1978 11:09:00 PM}
    Date: {12/4/1978 12:00:00 AM}
    Day: 4
    DayOfWeek: Monday
    DayOfYear: 338
    Hour: 23
    Kind: Unspecified
    Millisecond: 0
    Minute: 9
    Month: 12
    Second: 0
    Ticks: 624172577400000000
    TimeOfDay: {23:09:00}
    Year: 1978

这些是自纪元以来的总刻度。做这个数学运算,然后转换回日期时间。

<击> 另外:纠正你的数学。 878天是2年148天。 1981年5月1日是一年中的第121天,因此减去120到1979年1月1日。这将留下28天。从1978年底开始向后计数,你非常接近.Net的答案。你自己的答案并不是很接近。

根据反馈进行编辑

// zh-Hans is a chinese culture
CultureInfo ci = CultureInfo.GetCultureInfo("zh-Hans");
DateTime dt = new DateTime(1981, 5, 1, 13, 0, 0, ci.Calendar);
TimeSpan t = new TimeSpan(878, 13, 51, 0);

请注意,您仍然减去878天。在这种情况下,基于朱利安历法,一个月的长度将无关紧要。您可能需要为特定日历找到正确的文化代码,然后尝试这样做。 然而,使用此日历,我仍然会得到相同的答案。

除此之外,我不确定如何进行数学运算。如果您可以手动提供链接,我可以帮助您编写代码。

编辑2

我现在明白了。试试这个:

DateTime dt = new DateTime(1981, 5, 1, 13, 0, 0, ci.Calendar);

int years = 878 / 365;
int remainingDays = 878 % 365;
int months = remainingDays / 30;
remainingDays = remainingDays % 30;
TimeSpan t = new TimeSpan(years * 365 + months * 30 + remainingDays);
DateTime newdate = dt.Subtract(t);

答案 1 :(得分:1)

你不能假设一个30天的月份。您指定要减去878天。托管类(我假设你的意思是当你说本地时管理的)被设计成考虑闰年,不同的月数等。

使用托管类不会给你一个月的0。