Joda-Time在周期计算中的奇怪行为

时间:2013-06-11 13:23:15

标签: java jodatime period date-arithmetic

关于2月份,有一个奇怪的行为,你可以在Joda-Time的错误结果中看到,你可以向下看:

DateTime date1 = new DateTime(2013, 4, 28, 0, 0, 0, 0);
DateTime date1PlusNineMonths = new DateTime(2014, 1, 28, 0, 0, 0, 0);
Period period1 = new Period(date1, date1PlusNineMonths);
//Correct result
System.out.print(date1.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date1.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period1.getYears() + "Years/" + period1.getMonths() + "Months/" + period1.getWeeks() + "Weeks/" + period1.getDays() + "Days");

DateTime date2 = new DateTime(2013, 4, 29, 0, 0, 0, 0);
DateTime date2PlusNineMonths = new DateTime(2014, 1, 28, 0, 0, 0, 0);
Period period2 = new Period(date2, date2PlusNineMonths);
//Correct result
System.out.print(date2.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date2.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period2.getYears() + "Years/" + period2.getMonths() + "Months/" + period2.getWeeks() + "Weeks/" + period2.getDays() + "Days");

DateTime date3 = new DateTime(2013, 5, 28, 0, 0, 0, 0);
DateTime date3PlusNineMonths = new DateTime(2014, 2, 28, 0, 0, 0, 0);
Period period3 = new Period(date3, date3PlusNineMonths);
//Correct result
System.out.print(date3.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date3.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period3.getYears() + "Years/" + period3.getMonths() + "Months/" + period3.getWeeks() + "Weeks/" + period3.getDays() + "Days");

DateTime date4 = new DateTime(2013, 5, 29, 0, 0, 0, 0);
DateTime date4PlusNineMonths = new DateTime(2014, 2, 28, 0, 0, 0, 0);
Period period4 = new Period(date4, date4PlusNineMonths);
//Incorrect result
System.out.print(date4.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date4.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period4.getYears() + "Years/" + period4.getMonths() + "Months/" + period4.getWeeks() + "Weeks/" + period4.getDays() + "Days");

DateTime date5 = new DateTime(2013, 5, 30, 0, 0, 0, 0);
DateTime date5PlusNineMonths = new DateTime(2014, 2, 28, 0, 0, 0, 0);
Period period5 = new Period(date5, date5PlusNineMonths);
//Incorrect result
System.out.print(date5.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date5.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period5.getYears() + "Years/" + period5.getMonths() + "Months/" + period5.getWeeks() + "Weeks/" + period5.getDays() + "Days");

DateTime date6 = new DateTime(2013, 5, 31, 0, 0, 0, 0);
DateTime date6PlusNineMonths = new DateTime(2014, 2, 28, 0, 0, 0, 0);
Period period6 = new Period(date6, date6PlusNineMonths);
//Incorrect result
System.out.print(date6.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date6.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period6.getYears() + "Years/" + period6.getMonths() + "Months/" + period6.getWeeks() + "Weeks/" + period6.getDays() + "Days");

DateTime date7 = new DateTime(2013, 6, 1, 0, 0, 0, 0);
DateTime date7PlusNineMonths = new DateTime(2014, 3, 1, 0, 0, 0, 0);
//Correct result
Period period7 = new Period(date7, date7PlusNineMonths);
System.out.print(date7.toString("dd/MM/YYYY") + ".plusMonths(9) = " + date7.plusMonths(9).toString("dd/MM/YYYY"));
System.out.print(period7.getYears() + "Years/" + period7.getMonths() + "Months/" + period7.getWeeks() + "Weeks/" + period7.getDays() + "Days");

通常在测试中(period4,period5,period6)我应该有几天改变而不是每次显示9个月和0天,这是正常的,也许我在使用joda框架时错了,输出变得正确我在.addMonth(9)上进行01/06/2013

输出:

28/04/2013.plusMonths(9) = 28/01/2014 //correct result

0Years/9Months/0Weeks/0Days //correct calculation

29/04/2013.plusMonths(9) = 29/01/2014 //correct result

0Years/8Months/4Weeks/2Days //correct calculation

28/05/2013.plusMonths(9) = 28/02/2014 //correct result

0Years/9Months/0Weeks/0Days //correct calculation

29/05/2013.plusMonths(9) = 28/02/2014 //incorrect result should be 29/02/2014

0Years/9Months/0Weeks/0Days //correct calculation

30/05/2013.plusMonths(9) = 28/02/2014 //incorrect result should be 01/03/2014

0Years/9Months/0Weeks/0Days //incorrect calculation, should be 0Years/8Months/4Weeks/2Days

31/05/2013.plusMonths(9) = 28/02/2014 //incorrect result should be 01/03/2014

0Years/9Months/0Weeks/0Days //incorrect calculation, should be 0Years/8Months/4Weeks/1Days

01/06/2013.plusMonths(9) = 01/03/2014 //correct result

0Years/9Months/0Weeks/0Days //correct calculation

3 个答案:

答案 0 :(得分:2)

为什么你认为这个结果不正确?
不是天数。 是抽象单位

所以月份的最后一天加上月份下个月的最后一天而不是下月的第一天

为什么你认为

  

30/05 / 2013.plusMonths(9)= 28/02/2014 //应该是错误的结果   2014年1月3日

为什么不02/03/2014

你的假设是对的。 Joda时间适用于您的示例

答案 1 :(得分:0)

我犯了一个错误因为我累了哈哈我不知道为什么我确定2014年是闰年,但事实上我更关注数月和日的计算 如果你看一下这里:

        DateTime date4 = new DateTime(2013, 5, 29, 0, 0, 0, 0);
        DateTime date4PlusNineMonths = new DateTime(2014, 2, 28, 0, 0, 0, 0);
        Period period4 = new Period(date4, date4PlusNineMonths);
        //Incorrect result
        System.out.print(date4.toString("dd/MM/YYYY")+".plusMonths(9) = "+ date4.plusMonths(9).toString("dd/MM/YYYY"));
        System.out.print(period4.getYears() +"Years/"+ period4.getMonths() +"Months/"+ period4.getWeeks() +"Weeks/"+ period4.getDays() +"Days");

输出:

0Years/9Months/0Weeks/0Days

这是一个不正确的计算应该是0年/ 8月/ 4周/ 2天是不是......?

如果它是正确的那么为什么当我增加两天(30和31)它总是给我相同的计算(0年/ 9个月/ 0周/ 0天)我们都同意日子正在减少或我在做梦...... ?

现在也许我在使用joda框架时出错了,因为在我开发的应用程序中,我每天都会检查一段时间,以便在两个日期(toDay和下一个日期)之间进行精确的月份分离,如果我有9个月和1天已经太晚了我需要在我的app中有9个月和0天= /

如果我错了怎么能达到这个目的呢?

答案 2 :(得分:0)

很抱歉,刚才没有解决方案。我想,由于向后兼容问题,joda架构师S. Colebourne甚至必须坚持他的周期计算方法。无论如何,他已经关闭the corresponding issue on joda-time/github作为非错误/不会修复。如果你按照那里给出的链接,他在joda javadoc的更新中说他的周期计算方法是正确的,因为

[2013-05-29] + P9M = [2014-02-28]

在我看来,这个论点相当薄弱,因为

也是如此

[2013-05-29] + P8M30D = [2014-02-28]

因此,仅基于加法算法,没有明确指示哪个周期是正确的。要明确指定期间计算的行为,如果存在类似以下规范的情况,那将是一个更好的解决方案:如果结束日期中的月份日期小于开始日期中的月份那么差异不应计为满月。简单易懂。我也不相信周数应该是周期计算的主要部分,因为LocalDate的状态仅基于年,月和日。因此,不是说P8M4W2D(与ISO-8601不兼容!),而是优先考虑解决方案P8M30D。