从日期中减去时间跨度

发布于 2024-10-08 18:24:03 字数 1817 浏览 0 评论 0原文

我想使用 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 天的月份,而忽略闰年、不同的月份数等。我知道,这样做很奇怪。因此,我几乎在寻找“错误答案”,而不是托管类给出的确切答案。

I want to subtract a time-span from a date-time object using a 30-day month and ignoring leap years etc.

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)

I can use DateTime and TimeSpan objects to do this, after converting years and months of the time-span to days (assuming a 30 day month and a ~364 day year).

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

With this i get the result:

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

Above answer obviously doesn't ignore the factors i want ignored and gives me an accurate answer. But in this case that's not what i want so i wrote the below code.

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

Then i get:

1981/0/3-10:9:0

This is pretty close to what i'm after except i shouldn't get 0 for month and year should be 1980. Any kind of help is appreciated.


Just to make things clear again; in this context I have to use a 30-day month and ignore leap-years, different numbers of months, etc. Its a weird thing to do, i know. So I'm pretty much after a 'wrong answer' as opposed to the exact answer given by the managed classes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小情绪 2024-10-15 18:24:04

如果你用 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);

If you're estimating a month at 30 days, of course your math will be off. When you subtract 878 days from 5/1/1981, .Net is giving you the exact difference, not an estimate, and this difference accounts for leap years, if there are any. The error is not in the Subtract(...) method - it is in your own "manual" calculation.

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

These are the total ticks since the epoch. Do this math, then convert back into a datetime.


Also: correct your math. 878 days is 2 years and 148 days. 5/1/1981 is the 121st day of the year, so subtract 120 to get Jan 1, 1979. This leaves 28 days. Start counting backwards from the end of 1978, and you get very close to the .Net answer. Your own answer isn't anywhere close.

EDIT based on feedback

// 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);

Please note that you are still subtracting 878 days. The length of a month would be irrelevant in that case based on the Julian calendar. You will probably need to find the correct culture code for your particular calendar, then try this. However, with this calendar, I still arrive at the same answer above.

Beyond doing this, I am unsure how else to do the math. If you can provide a link to how you are doing it by hand, I can help code it for you.

EDIT 2

I understand now. Try this:

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);
回忆追雨的时光 2024-10-15 18:24:04

您不能假设每月有 30 天。您指定要减去 878 天。托管类(我假设您说本机时指的是托管)旨在考虑闰年、不同的月份数等。

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

You cannot assume a 30-day month. You are specifying that you want to subtract 878 days. The managed classes (I'm assuming you mean managed when you say native) are designed to factor in leap-years, different numbers of months, etc.

Using the managed classes will not give you a 0 for a month.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文