【问题标题】:End of month calculations月末计算
【发布时间】:2010-11-02 00:18:19
【问题描述】:

只是想知道是否有人知道以下优雅的解决方案。

如果我有 2009 年 6 月 30 日并且我添加了一个月,我希望它转到 2009 年 7 月 31 日,而不是 2009 年 7 月 30 日。

这个逻辑是基于这样一个事实,即 2009 年 6 月 30 日是 6 月的月底,当我添加一个月时,我想去下个月的月底。

但如果我有 2009 年 6 月 29 日并且我添加一个月,它应该是 2009 年 7 月 29 日。

请注意,我需要能够添加任意月数,并且需要考虑闰年。

我也知道这里的逻辑是有问题的,但这是一项业务需求,适用于未来一个月的月底合同。

我已经想到了几种解决方案,但没有一个非常优雅。因此,我认为有人可能有更好的方法。

干杯 安东尼

【问题讨论】:

  • 你自相矛盾。 “如果我有 2009 年 6 月 30 日并且我添加了一个月,我不希望它去到 2009 年 7 月 31 日......当我添加一个月时,我想去到下个月的月底。”。你的意思是说你希望它到月底?
  • 是的,我只是注意到我自己... :)
  • 你有什么不优雅的解决方案?

标签: c# .net datetime date logic


【解决方案1】:

要检查某个日期是否是月底,请检查下一天是否是某个月的第一天。然后你的算法应该是“如果一天不是月底,加 1 个月。如果是月底,加一天,加一个月,减一天。”

    bool IsEndOfMonth(DateTime date) {
        return date.AddDays(1).Day == 1;
    }
    DateTime AddMonthSpecial(DateTime date) {
        if (IsEndOfMonth(date))
            return date.AddDays(1).AddMonths(1).AddDays(-1);
        else
            return date.AddMonths(1);
    }

【讨论】:

  • 对不起,我把“加一天,加一个月,减一个月”的解释弄错了,应该是“加一天,加一个月,减一天”。我修正了最后一句话。
  • 您的示例仍然有效,因为您将 2 个月添加到 2010 年 1 月 1 日,得到 2010 年 3 月 1 日,然后减去 1 天得到“下个月前 1 天”,相当于“最后一天”月”
【解决方案2】:
DateTime exampleDate = DateTime.Parse("12/31/2009");
bool isLastDayOfMonth = (exampleDate.AddDays(1).Month != exampleDate.Month);

if (isLastDayOfMonth)
    Console.WriteLine(exampleDate.AddDays(1).AddMonths(1).AddDays(-1));
else
    Console.WriteLine(new DateTime(exampleDate.Year, exampleDate.Month, 1).AddMonths(2).AddDays(-1));

编辑:我再次阅读了您的问题。您需要检查一下是否是该月的最后一天。

对不起,我希望我已经清楚地阅读了需要什么的问题。
希望这足以让您了解需要什么。

【讨论】:

    【解决方案3】:

    您可以从上个月的第一天开始并返回一天吗?

    【讨论】:

      【解决方案4】:
      1. 测试旧日期是否为“月末”。
        1. 在日期上加一天,看看月数是否变化。
      2. 添加一个月
      3. 如果旧日期是“月末”
        1. 将日期设置为 1
        2. 再增加一个月
        3. 减去一天

      【讨论】:

      • public int Day { get; } ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/fxref_mscorlib/html/899d9772-e792-052a-2c0b-8a28aea0d5b9.htm
      【解决方案5】:

      我解决这个问题的方法是从确定给定日期是否是一个月的最后一天的例程开始(当然要考虑闰年的二月!)

      您还需要一个例程,在该月的某一天为您提供一个月的最后一天。

      然后,如果您遇到的一天是最后一天,则添加一天,然后使用第二个例程获取该月的最后一天。使用循环数月。

      【讨论】:

        【解决方案6】:

        您可以实现 EndOfMonth() 和 isEndOfMonth()。

        所以你的代码或多或少会是,

        if isEndOfMonth( this.Date() )
          endDate = (startmonth + addedMonths).EndOfMonth()
        else
          endDate = startDate + addedMonths
        

        有点简单,但你明白了。

        EndOFMonth和isEndOfMonth的逻辑这里当然有很多思路

        【讨论】:

          【解决方案7】:

          这是一个简单的 .NET C# 解决方案,适用于闰年等:

          static DateTime ContractDue(DateTime start, int months)
          {
               if (start.Month == start.AddDays(1).Month)
               { // Same month, just add the months
                      return start.AddMonths(months);
               }
               // Last day of month... add a day, add the months, then go back one day
               return start.AddDays(1).AddMonths(months).AddDays(-1);
          }
          

          【讨论】:

            【解决方案8】:

            您可以使用 DateTime.DaysInMonth() 方法,如下所示:

            DateTime workingMonth = new DateTime(2009, 06, 30).AddDays(1);
            int nextMonthDays = DateTime.DaysInMonth(workingMonth.Year, workingMonth.Month);
            DateTime newMonth = new DateTime(workingMonth.Year, workingMonth.Month, nextMonthDays);
            

            【讨论】:

              【解决方案9】:

              如果我在月初,这会是补函数吗? DateTime.Now.AddDays(-1).Month == DateTime.Now.AddMonths(-1).Month

              【讨论】:

                【解决方案10】:

                如果您只需要 EndOfMonth 或简单的 AddNMonth,那么您已经得到了答案。

                否则,要获得完整的通用解决方案,您需要实现循环模式,正如您在Outlook Meeting interface 的 UI 中看到的那样。虽然我不建议您使用 Outlook 实现,但应该有一些您可以购买的 .NET 组件。或者自己实现它,但不要低估它并对其进行单元测试 - 这是一个非常难以实现的组件。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2019-01-09
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多