DateTime
实例之间的天数差异?“天数差异”是指如果开始时间是星期一,结束时间是星期二,则不管小时数/开始日期和结束日期的分钟/秒。
如果开始时间是晚上,早晨是结束时间,则
Days.daysBetween(start, end).getDays()
给我0。我也遇到了同样的问题与其他日期字段一起使用,因此我希望可以采用一种通用方法来“忽略”重要性较低的字段。
换句话说,2月至3月4日之间的月份也将为1,而14:45至15:12之间的时间也会为1。但是14:01和14:55之间的时差为0。
#1 楼
令人讨厌的是,withTimeAtStartOfDay答案是错误的,但只是偶尔出现。您要:Days.daysBetween(start.toLocalDate(), end.toLocalDate()).getDays()
事实证明,“午夜/一天的开始时间”有时表示凌晨1点(在某些地方以这种方式实现夏令时),而Days.daysBetween不会无法正确处理。
// 5am on the 20th to 1pm on the 21st, October 2013, Brazil
DateTimeZone BRAZIL = DateTimeZone.forID("America/Sao_Paulo");
DateTime start = new DateTime(2013, 10, 20, 5, 0, 0, BRAZIL);
DateTime end = new DateTime(2013, 10, 21, 13, 0, 0, BRAZIL);
System.out.println(daysBetween(start.withTimeAtStartOfDay(),
end.withTimeAtStartOfDay()).getDays());
// prints 0
System.out.println(daysBetween(start.toLocalDate(),
end.toLocalDate()).getDays());
// prints 1
通过
LocalDate
避开了整个问题。#2 楼
Days
类将
Days
类与withTimeAtStartOfDay
方法一起使用应该可以:Days.daysBetween(start.withTimeAtStartOfDay() , end.withTimeAtStartOfDay() ).getDays()
评论
谢谢!我试图用joda实现android.text.format.DateUtils.getRelativeTimeSpanString()的行为,这确实很有用。
– gosho_ot_pochivka
2013年6月27日10:28在
主席先生,关于此帖子,不建议使用DateTime类型的toDateMidnight()方法。
– Aniket Kulkarni
13-10-8在5:33
您现在应该使用.withTimeAtStartOfDay()而不是.toDateMidnight()
–bgolson
13-10-29在16:54
如果结束时间早于开始时间,会返回负数天怎么办?
– akhy
2015年2月4日,12:50
@akhyar:为什么不尝试呢?
–迈克尔·伯格沃德(Michael Borgwardt)
2015年2月4日,12:53
#3 楼
您可以使用LocalDate
:Days.daysBetween(new LocalDate(start), new LocalDate(end)).getDays()
评论
主席先生,关于此帖子,不建议使用DateTime类型的toDateMidnight()方法。
– Aniket Kulkarni
13年10月8日在5:34
为什么要在date.toLocalDate()上使用新的LocalDate(date)?
–SARose
17年1月28日在15:45
#4 楼
tl; drjava.time.temporal.ChronoUnit.DAYS.between(
earlier.toLocalDate(),
later.toLocalDate()
)
…或…
java.time.temporal.ChronoUnit.HOURS.between(
earlier.truncatedTo( ChronoUnit.HOURS ) ,
later.truncatedTo( ChronoUnit.HOURS )
)
java.time
FYI,Joda-Time项目现在处于维护模式,团队建议迁移到java.time类。
乔达时间
DateTime
的等效项是ZonedDateTime
。一天中的时间。例如,从午夜之前的一分钟开始,到午夜之后的一分钟结束,应该是一天。为此,请从您的LocalDate
中提取一个ZonedDateTime
。 LocalDate
类表示没有日期和时区的仅日期值。ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
使用
ChronoUnit
枚举来计算经过的天数或其他单位。 br /> LocalDate localDateStart = zdtStart.toLocalDate() ;
LocalDate localDateStop = zdtStop.toLocalDate() ;
截断
至于您询问一种更通用的计数方法,即您感兴趣的小时数增量为小时数请使用
truncatedTo
方法,而不是将整个小时数作为60分钟的时间跨度。这是您当天14:45到15:12的示例。
long days = ChronoUnit.DAYS.between( localDateStart , localDateStop ) ;
1
这几天都不起作用。在这种情况下,请使用toLocalDate()。关于java.time
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧的旧式日期时间类,例如
java.util.Date
,Calendar
和SimpleDateFormat
。 /> 要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规范是JSR310。
您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要
java.sql.*
类。从哪里获取java.time类?
Java SE 8,Java SE 9,Java SE 10和更高版本
内置。
具有捆绑实现的标准Java API的一部分。
Java 9增加了一些次要功能和修复。
Java SE 6和Java SE 7
java.time的许多功能在ThreeTen-Backport中都反向移植到Java 6和7。 Android
较新版本的java.time类的Android捆绑实现。请参见如何使用ThreeTenABP…。
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容打下了基础。您可能会在这里找到一些有用的类,例如
Interval
,YearWeek
,YearQuarter
等。ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容打下了基础。您可能会在这里找到一些有用的类,例如
Interval
,YearWeek
,YearQuarter
等。评论
您的TL; DR使用truncate的几天时间会成为接受的答案中详细说明的错误的牺牲品,即,当一天的凌晨1点时,它会被一对一关闭。我已更新它,以使用toLocalDate使用您进一步给出的正确答案。
–爱丽丝·珀塞尔(Alice Purcell)
19-09-27在10:28
#5 楼
可接受的答案将生成两个LocalDate
对象,如果您正在读取大量数据,这将非常昂贵。我使用此对象:
public static int getDaysBetween(DateTime earlier, DateTime later)
{
return (int) TimeUnit.MILLISECONDS.toDays(later.getMillis()- earlier.getMillis());
}
通过调用
getMillis()
,您可以使用已经存在的变量。 MILLISECONDS.toDays()
然后,使用简单的算术计算,不会创建任何对象。评论
仅当您对“天”的定义恰好是24小时长而没有考虑时区和日期时,此答案才有效。如果是这样,请使用此方法。如果不是,请查看针对时区的其他答案。
–罗勒·布尔克
16年6月21日在17:16
@BasilBourque,您是对的,不过,我还是会寻求一种基于算术计算的解决方案,而不是为每个方法调用构建昂贵的对象,如果您正在从网页中读取输入内容,则可以进行很多计算,也许还可以,但是如果您正在处理包含成千上万行的日志文件,这只会使其非常缓慢
– JBoy
16年6月21日在21:37
如果循环很热,Java将优化对象分配。请参阅docs.oracle.com/javase/7/docs/technotes/guides/vm/…
–爱丽丝·珀塞尔(Alice Purcell)
16年6月24日在8:20
#6 楼
java.time.Period
使用
java.time.Period
类对天数进行计数。由于Java 8使用
LocalDate
,LocalDateTime
来表示两个日期更加直观地计算了差异,所以> LocalDate now = LocalDate.now();
LocalDate inputDate = LocalDate.of(2018, 11, 28);
Period period = Period.between( inputDate, now);
int diff = period.getDays();
System.out.println("diff = " + diff);
#7 楼
DateTime dt = new DateTime(laterDate);
DateTime newDate = dt.minus( new DateTime ( previousDate ).getMillis());
System.out.println("No of days : " + newDate.getDayOfYear() - 1 );
#8 楼
public static int getDifferenceIndays(long timestamp1, long timestamp2) {
final int SECONDS = 60;
final int MINUTES = 60;
final int HOURS = 24;
final int MILLIES = 1000;
long temp;
if (timestamp1 < timestamp2) {
temp = timestamp1;
timestamp1 = timestamp2;
timestamp2 = temp;
}
Calendar startDate = Calendar.getInstance(TimeZone.getDefault());
Calendar endDate = Calendar.getInstance(TimeZone.getDefault());
endDate.setTimeInMillis(timestamp1);
startDate.setTimeInMillis(timestamp2);
if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) {
int day1 = endDate.get(Calendar.DAY_OF_MONTH);
int day2 = startDate.get(Calendar.DAY_OF_MONTH);
if (day1 == day2) {
return 0;
} else {
return 1;
}
}
int diffDays = 0;
startDate.add(Calendar.DAY_OF_MONTH, diffDays);
while (startDate.before(endDate)) {
startDate.add(Calendar.DAY_OF_MONTH, 1);
diffDays++;
}
return diffDays;
}
评论
问题特别是在寻找乔达时间。
– kapad
15年7月7日在11:01
评论
您是否可以提供一个示例案例,其中包含您认为Days.daysBetween不正确的特定数据?
–罗勒·布尔克
2014年12月25日上午9:33
当您说要使用Instant时,您不仅在谈论start.toInstant(),对吗?
–帕特里克M
2015年2月10日在21:44
@PatrickM是的,我是。关于反思,目前尚不清楚这是要施加什么约束,因此我将删除最后一句话。谢谢!
–爱丽丝·珀塞尔(Alice Purcell)
2015年2月11日在23:28
@chrispy daysBetween文档说它返回整个天数。在我的情况下,2天零1个小时应该让我3天。在您的示例中,它返回2天。有没有办法做到这一点?
– Sujit Joshi
16年6月18日在20:51
@SujitJoshi恐怕我不明白你的问题。我建议发布完整的Stack Overflow问题,并在此处为我粘贴一个链接:)
–爱丽丝·珀塞尔(Alice Purcell)
16年6月19日在21:55