我需要从DB中提取日期字段并将其存储在VO中。如何比较两个日期的小时差异。
例如:
我们说date1 = 01-SEP-17 10:00:00
和date2 = 05-SEP-17 12:00:00
。我需要比较两个日期并执行一些操作,如:
if(hours>10){
//do something
}
if(hours<10){
//do something else
}
我只能将小时数(date2-date1)之间的差异计算为2但是在计算小时数之间的差异时如何考虑日期?
我现在的代码:
Date dateA = someVO.getDate();
long date = System.currentTimeMillis();
SimpleDateFormat df = new SimpleDateFormat("dd-MM-YY HH:mm:ss");
Date date1 = new Date(date);
Date date2 = df.parse(dateA.toString());
long date1Hours = date1.getHours();
long date2Hours = date2.getHours();
long dateDiff = date1Hours-date2Hours;
if(dateDiff>10){
//something
}
else if(dateDiff<10){
//something else
}
答案 0 :(得分:3)
使用Java 8中添加的新Java-Time API非常容易:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
.parseCaseInsensitive()
.appendPattern("dd-MMM-yy HH:mm:ss")
.toFormatter(Locale.US);
LocalDateTime date1 = LocalDateTime.parse("01-SEP-17 10:00:00", fmt);
LocalDateTime date2 = LocalDateTime.parse("05-SEP-17 12:00:00", fmt);
long hours = ChronoUnit.HOURS.between(date1, date2);
System.out.println(hours);
输出
98
答案 1 :(得分:2)
首先,您需要更改SimpleDateFormat
中使用的模式,并使用java.util.Locale
指定月份名称是英语(否则它使用系统默认语言环境,并且不保证永远是英语)。
然后,您获得每个Date
的对应millis值,计算它们之间的差异并使用java.util.concurrent.TimeUnit
将其转换为小时数:
SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yy HH:mm:ss", Locale.ENGLISH);
Date date1 = df.parse("01-SEP-17 10:00:00");
Date date2 = df.parse("05-SEP-17 12:00:00");
// get the difference in hours
long dateDiff = TimeUnit.MILLISECONDS.toHours(date2.getTime() - date1.getTime());
dateDiff
将为98
。
如果您想与当前日期进行比较,只需使用new Date()
。
这种方法存在一个问题。虽然它在一年中的大部分时间没有任何影响,但由于Daylight Saving Time更改可能会有所不同。
默认情况下,SimpleDateFormat
使用JVM默认时区。如果两个日期之间有夏令时转换(或只是偏移更改),结果可能会有所不同。
示例:在Africa/Windhoek
timezone中,在2017年9月3日 rd ,凌晨2点,时钟向前移动1小时,从凌晨2点到凌晨3点(偏移量从{{1到+01:00
)。这意味着,在当天,上午2点到凌晨2点59分之间的所有当地时间都不存在于此时区(就像他们在这个时间“跳过”一样)。
因此,如果JVM默认时区为+02:00
,则使用上述代码的差异将为97小时(而非98)。
即使您的JVM默认时区不是Africa/Windhoek
,这仍然会发生,具体取决于所涉及的时区和日期。
不仅如此,还有默认时区can be changed without notice, even at runtime。最好指定您正在使用的时区而不是仅仅依赖默认值。
您无法避免DST效果(除非您使用UTC),但至少您可以选择使用哪个时区而不是依赖系统默认值(可以更改,恕不另行通知)。
可以在格式化程序中设置时区,因此将考虑此时区来解析所有日期。在下面的示例中,我使用Africa/Windhoek
,但当然您可以更改为最适合您的情况:
Europe/London
现在所有解析的日期都将被认为是在伦敦时区(但提醒仍然会考虑DST效果 - 优点是您知道您正在使用的时区,并且JVM默认的任何更改都不会你的代码突然开始给出不同的意外结果。)
始终使用IANA timezones names(始终采用// set Europe/London timezone in the SimpleDateFormat
df.setTimeZone(TimeZone.getTimeZone("Europe/London"));
格式,例如Continent/City
或America/Sao_Paulo
。
避免使用3个字母的缩写(例如Europe/Berlin
或CST
),因为它们是ambiguous and not standard。
您可以使用PST
获取所有时区的列表 - 然后您可以选择最适合您情况的时区。
如果您不想考虑DST效果,可以使用TimeZone.getAvailableIDs()
- 因为UTC is a standard without DST changes。
旧类(TimeZone.getTimeZone("UTC")
,Date
和Calendar
)有lots of problems和design issues,它们将被新API取代。< / p>
如果您使用的是 Java 8 ,请考虑使用new java.time API。它更容易,less bugged and less error-prone than the old APIs。
如果您使用的是 Java&lt; = 7 ,则可以使用ThreeTen Backport,这是Java 8新日期/时间类的绝佳后端。对于 Android ,有ThreeTenABP(更多关于如何使用它here)。
以下代码适用于两者。
唯一的区别是包名称(在Java 8中为SimpleDateFormat
而在ThreeTen Backport(或Android的ThreeTenABP中)为java.time
),但类和方法名称是一样的。
首先,您需要解析输入(使用org.threeten.bp
)并指定它们的时区。由于日期也有时区,我使用的是DateTimeFormatter
,这是此案例的最佳选择。
然后,您可以使用ZonedDateTime
轻松计算小时数差异。在下面的例子中,我也使用伦敦时区作为例子:
ChronoUnit
如果您想使用UTC,只需将DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// case insensitive for month name in all caps
.parseCaseInsensitive()
// date/time pattern
.appendPattern("dd-MMM-yy HH:mm:ss")
// use English locale for month name
.toFormatter(Locale.ENGLISH)
// set a timezone
.withZone(ZoneId.of("Europe/London"));
// parse the dates
ZonedDateTime z1 = ZonedDateTime.parse("01-SEP-17 10:00:00", fmt);
ZonedDateTime z2 = ZonedDateTime.parse("05-SEP-17 12:00:00", fmt);
// calculate the difference in hours
long diffHours = ChronoUnit.HOURS.between(z1, z2);
更改为ZoneId
常量即可。如果您想与当前日期进行比较,只需使用:
ZoneOffset.UTC
如果您仍需要使用// use the same ZoneId used in the formatter if you want to consider DST effects
ZonedDateTime.now(ZoneId.of("Europe/London"));
,则可以从/转换为新API。在Java 8中,您可以使用本机方法,在Java&lt; = 7中,ThreeTen Backport具有java.util.Date
类。
将org.threeten.bp.DateTimeUtils
转换为新类:
Date
将Date date = // java.util.Date
// convert to zoneddatetime (java 8)
ZonedDateTime z = date.toInstant().atZone(ZoneId.of("Europe/London"));
// convert to zoneddatetime (java 7 ThreeTen Backport)
ZonedDateTime z = DateTimeUtils.toInstant(date).atZone(ZoneId.of("Europe/London"));
转换回日期:
ZonedDateTime
答案 2 :(得分:1)
你基本上已经有了几毫秒的时间。你总是可以直接比较毫秒。
{{1}}