java months between,关于java:Joda时间 – 两个日期之间的月份差异

博客讨论了使用JodaTime库在Java中计算两个日期之间月份差异时遇到的问题。当日期中包含时间部分时,Months.monthsBetween()方法可能会返回不期望的结果。解决方案是使用LocalDate而非DateTime,并确保没有时间部分。文章还提醒注意负值和使用Math.abs来获取正确的月数差异。
摘要由CSDN通过智能技术生成

本问题已经有最佳答案,请猛点这里访问。

我需要得到两个日期之间的月差异,我使用的是Joda Time,问题是:

DateTime date1 = new DateTime().withDate(2015, 2, 1);

DateTime date2 = new DateTime().withDate(2015, 1, 1);

Months m = Months.monthsBetween(date1, date2);

int monthDif = m.getMonths();//this return 0

它返回0是因为这两个日期中间没有月份,所以我需要返回月份之间的差额而不是几个月之间的差额,如果日期相同,则添加1会有问题。

虽然上面的问题是关于天的,但和你的问题非常相似,解决方法也是一样的,叫DateTime#toLocalDate()把LocalDate传给Months#monthsBetween而不是DateTime。

你为什么一开始使用new Datetime().withDate()?它创建当前时刻的日期时间实例,然后更改它(保留时间字段不变)。如果您只想创建一个没有时间的新的特定日期,那么只需使用localdate,然后Months.monthsBetween(date1, date2)就可以了。

将第一个日期更改为2015-02-02,Joda正确返回1个月:

DateTime date1 = new DateTime().withDate(2015, 2, 2);

DateTime date2 = new DateTime().withDate(2015, 1, 1);

System.out.println(Months.monthsBetween(date2, date1).getMonths());

// Returns 1.

所以我的猜测是,由于你没有提供时间部分,Joda无法准确地确定2015-01-01 date2所指的时间点。你可能已经提到了23:59:59,在这种情况下,从技术上讲,一个完整的月还不会过去。

如果显式地提供零时间部分,它将按您最初预期的方式工作:

DateTime date1 = new DateTime().withDate(2015, 2, 1).withTime(0, 0, 0, 0);

DateTime date2 = new DateTime().withDate(2015, 1, 1).withTime(0, 0, 0, 0);

System.out.println(Months.monthsBetween(date2, date1).getMonths());

// Returns 1.

因此,我建议您在每个日期中明确指定00:00:00时间部分。

只是一个细节,datetime具有timeAtStartOfDay()方法

虽然其他答案是正确的,但它们仍然掩盖了真正的问题。

it returns 0 because there is no month in the middle of the two dates

不。它返回0,因为datetime对象有时间部分。创建两个时间间隔的DateTime,用当前时间(小时、分钟、秒和毫秒)填充,然后修改日期部分。如果你只想比较两个日期,就没有理由这么做。改为使用localdate。

LocalDate date1 = new LocalDate(2015, 2, 1);

LocalDate date2 = new LocalDate(2015, 1, 1);

Months m = Months.monthsBetween(date1, date2);

int monthDif = Math.abs(m.getMonths());//this return 1

还需要注意一个事实,即尽管几个月的文档对此一无所知,但如果第一个日期在第二个日期之后,Month可以包含负值。所以我们需要用Math.abs来计算两个日期之间的月数。

博士说:

Creates a Months representing the number of whole months between the two specified partial datetimes.

但事实并非如此。它真的计算了几个月的差额。不是月数。

是的,是我的错。实际返回-1,因为date1在date2之后。Months.monthsBetween文件从不说月份的周期可以是负数。:)但对于问题和接受的答案也是如此,不会改变任何东西。我把答案编辑成使用Math.abs。

我想最好向op(在答案中)解释为什么它用当前代码返回-1,并使用Months.monthsBetween(date2, date1);。它就像调用X.compareTo(Y)和Y.compareTo(X)一样,结果也会颠倒:d。

计算方法取决于要使用的业务逻辑。每个月的长度各不相同。一种选择是,在monthsBetween()函数中,获取date1和date2的月初,并进行比较。

类似:

DateTime firstOfMonthDate1 = new DateTime(date1.getYear(), date1.getMonthOfYear(), 1, 0, 0);

DateTime firstOfMonthDate2 = new DateTime(date2.getYear(), date2.getMonthOfYear(), 1, 0, 0);

Months m = Months.monthsBetween(firstOfMonthDate1, firstOfMonthDate2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值