我在Scala中使用Java的java.util.Date
类,想要比较一个Date
对象和当前时间。我知道可以通过使用getTime()
计算时间差:
(new java.util.Date()).getTime() - oldDate.getTime()
然而,这只给我留下了一个表示毫秒的long
。是否有更简单、更好的方法来获得时间差?
我在Scala中使用Java的java.util.Date
类,想要比较一个Date
对象和当前时间。我知道可以通过使用getTime()
计算时间差:
(new java.util.Date()).getTime() - oldDate.getTime()
然而,这只给我留下了一个表示毫秒的long
。是否有更简单、更好的方法来获得时间差?
我曾经喜欢 TimeUnit-based 的方法,直到发现它只适用于数量上的特殊情况,即一个 TimeUnit 包含多少个下一级单位的数量固定。当你想知道两个时间单位之间有多少个月、年等时,这种方法就会失效。
这里有一种计数方法,虽然不如其他一些方法高效,但对我来说似乎很管用,并且还考虑了夏令时的影响。
public static String getOffsetAsString( Calendar cNow, Calendar cThen) {
Calendar cBefore;
Calendar cAfter;
if ( cNow.getTimeInMillis() < cThen.getTimeInMillis()) {
cBefore = ( Calendar) cNow.clone();
cAfter = cThen;
} else {
cBefore = ( Calendar) cThen.clone();
cAfter = cNow;
}
// compute diff
Map<Integer, Long> diffMap = new HashMap<Integer, Long>();
int[] calFields = { Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND};
for ( int i = 0; i < calFields.length; i++) {
int field = calFields[ i];
long d = computeDist( cAfter, cBefore, field);
diffMap.put( field, d);
}
final String result = String.format( "%dY %02dM %dT %02d:%02d:%02d.%03d",
diffMap.get( Calendar.YEAR), diffMap.get( Calendar.MONTH), diffMap.get( Calendar.DAY_OF_MONTH), diffMap.get( Calendar.HOUR_OF_DAY), diffMap.get( Calendar.MINUTE), diffMap.get( Calendar.SECOND), diffMap.get( Calendar.MILLISECOND));
return result;
}
private static int computeDist( Calendar cAfter, Calendar cBefore, int field) {
cBefore.setLenient( true);
System.out.print( "D " + new Date( cBefore.getTimeInMillis()) + " --- " + new Date( cAfter.getTimeInMillis()) + ": ");
int count = 0;
if ( cAfter.getTimeInMillis() > cBefore.getTimeInMillis()) {
int fVal = cBefore.get( field);
while ( cAfter.getTimeInMillis() >= cBefore.getTimeInMillis()) {
count++;
fVal = cBefore.get( field);
cBefore.set( field, fVal + 1);
System.out.print( count + "/" + ( fVal + 1) + ": " + new Date( cBefore.getTimeInMillis()) + " ] ");
}
int result = count - 1;
cBefore.set( field, fVal);
System.out.println( "" + result + " at: " + field + " cb = " + new Date( cBefore.getTimeInMillis()));
return result;
}
return 0;
}
另一种纯Java变体:
public boolean isWithin30Days(Calendar queryCalendar) {
// 1. Take the date you are checking, and roll it back N days
Calendar queryCalMinus30Days = Calendar.getInstance();
queryCalMinus30Days.setTime(queryCalendar.getTime());
queryCalMinus30Days.add(Calendar.DATE, -30); // subtract 30 days from the calendar
// 2. Get respective milliseconds for the two Calendars: now & queryCal minus N days
long nowL = Calendar.getInstance().getTimeInMillis();
long queryCalMinus30DaysL = queryCalMinus30Days.getTimeInMillis();
// 3. if nowL is still less than the queryCalMinus30DaysL, it means queryCalendar is more than 30 days into future
boolean isWithin30Days = nowL >= queryCalMinus30DaysL;
return isWithin30Days;
}
由于日期可以包含小时和分钟,最终结果会被向下取整,导致值不正确。例如,你计算今天晚上 10 点和后天凌晨 12 点之间的差异,那么最终的结果将是1,因为实际上它的差异是1.08或者其他东西,然后在调用TimeUnit.MILLISECONDS.toDays(..)
时被向下取整。这就是为什么你需要考虑到这一点,所以在我的解决方案中,我从一天的毫秒数中减去毫秒的余数。此外,如果你想计算结束日期,你需要+1。
import java.util.Date;
import java.util.concurrent.TimeUnit;
public static long getDaysBetween(Date date1, Date date2, boolean includeEndDate) {
long millisInDay = 60 * 60 * 24 * 1000;
long difference = Math.abs(date1.getTime() - date2.getTime());
long add = millisInDay - (difference % millisInDay);//is used to calculate true number of days, because by default hours, minutes are also counted
return TimeUnit.MILLISECONDS.toDays(difference + add) + (includeEndDate ? 1 : 0);
}
测试:
Date date1 = new Date(121, Calendar.NOVEMBER, 27); //2021 Nov 27
Date date2 = new Date(121, Calendar.DECEMBER, 29); //2021 Dec 29
System.out.println( getDaysBetween(date1, date2, false) ); //32 days difference
System.out.println( getDaysBetween(date1, date2, true) ); //33 days difference
Date
和Calendar
了。 - Ole V.V.这将与joda api完美配合使用。
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import org.joda.time.DateTime;
import org.joda.time.Months;
import org.joda.time.Weeks;
import org.joda.time.Years;
import java.util.LinkedHashMap;
public Map<String,Integer> Datedifference(String fromDate,String toDate) throws ParseException {
Map<String,Integer> dateUtilMap = new LinkedHashMap<String, Integer>();
Date date1=new SimpleDateFormat("dd-MM-yyyy").parse(fromDate);
Date date2=new SimpleDateFormat("dd-MM-yyyy").parse(toDate);
Calendar fromDay = new GregorianCalendar();
fromDay.setTime(date1);
Calendar toDay = new GregorianCalendar();
toDay.setTime(date2);
int days = (int) (1+(toDay.getTimeInMillis() -fromDay.getTimeInMillis()) / 1000 / 60 / 60 / 24);
if(days >1) {
DateTime dateTime1 = new DateTime(fromDay);
DateTime dateTime2 = new DateTime(toDay);
int weeks = Weeks.weeksBetween(dateTime1.dayOfWeek().withMinimumValue().minusDays(1),
dateTime2.dayOfWeek().withMaximumValue().plusDays(1)).getWeeks();
int months = Months.monthsBetween(dateTime1.dayOfMonth().withMinimumValue().minusDays(1),
dateTime2.dayOfMonth().withMaximumValue().plusDays(1)).getMonths();
int years =1+Years.yearsBetween(dateTime1, dateTime2).getYears();
dateUtilMap.put("days", days);
dateUtilMap.put("weeks", weeks);
dateUtilMap.put("months", months);
dateUtilMap.put("years", years);
System.out.println(dateUtilMap);
return dateUtilMap;
} else {
System.out.println("From Date Must be samller than to Date");
return null;
}
}
SimpleDateFormat
和设计不佳、笨重的Date
和Calendar
类。您的代码比必要的代码长得多,复杂得多,可读性差得多。而且没有正确缩进。您回答的是另一个问题。问题是关于两个Date
对象(而不是两个字符串)。 - Ole V.V.Datedifference("10-05-2023", "11-05-2023")
(从今天到明天)得到了 {days=2, weeks=1, months=1, years=1}
。我有点惊讶,但好吧,我想每个人都有自己对“完美”的定义。然后我尝试了 Datedifference("26-03-2023", "27-03-2023")
,结果是——null
?!怎么回事?我必须说,你的代码在任何定义下都是不正确的。 - Ole V.V.int days1 = d1.getTime()/(60*60*24*1000);//find the number of days since the epoch.
int days2 = d2.getTime()/(60*60*24*1000);
那就说吧
days2-days1
或者其他什么
Date
、Calendar
和SimpleDateFormat
就太不应该了”。 - Basil Bourquejava.time.Period
和/或Duration
。请查看下面的Basil Bourque的答案。 - Ole V.V.