【问题标题】:Subtracting TimeSpan from date从日期中减去 TimeSpan
【发布时间】:2010-12-24 07:41:09
【问题描述】:

我想使用 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 天的月份并忽略闰年、不同的月份等。我知道这是一件很奇怪的事情。因此,我非常喜欢“错误答案”,而不是托管类给出的确切答案。

【问题讨论】:

  • “如果我手动执行此操作”是什么意思?
  • 我相信它的意思是“手工,在纸上”。而且我不知道他所说的“原生类”是什么意思。
  • 是的。从分钟(m2)中减去分钟(m1)。如果 m1
  • “假设一个月有 30 天”?你怎么能这样假设?
  • @yodaj007 我的意思是 .Net 框架中的 DateTime 对象。如果我的描述在技术上不正确,请见谅。

标签: c# .net datetime timespan


【解决方案1】:

如果您估计一个月为 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);

【讨论】:

  • 如果我“必须”估计一个月的 30 天该怎么办。我该怎么做呢?
  • 你为什么要得到一个(不正确的)估计而不是准确的答案?
  • 因为我在东方占星术的背景下使用它。有一个特殊的计算方法使用 30 天的月份。
  • 我明白了。我正在更新我的答案。给我一点时间。
  • @yodaj007 878 days 并不是我在这里输入的内容。我只需要从给定日期中减去 2 年 4 个月、28 天等。 878 是我粗略计算 2 年 4 个月 28 天到几天的方法,因为时间跨度课程不需要几年和几个月。我还包含了我的“手动”代码。
【解决方案2】:

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

使用托管课程不会给你一个月的分数。

【讨论】:

    猜你喜欢
    • 2011-06-23
    • 2017-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    • 2012-10-07
    • 2016-12-01
    • 1970-01-01
    相关资源
    最近更新 更多