计算两个Java日期实例之间的差异


433

java.util.Date在Scala中使用Java的类,想比较一个Date对象和当前时间。我知道我可以使用getTime()计算增量:

(new java.util.Date()).getTime() - oldDate.getTime()

但是,这仅long代表我几毫秒。有没有更简单,更好的方法来获取时间增量?


10
为什么不爱乔达时间?如果要使用Java处理日期,这几乎是最好的选择。
2012年

7
请在不使用Joda的情况下检查我优雅的2衬板解决方案,并在stackoverflow.com/a/10650881/82609
塞巴斯蒂安·洛伯

2
对所有推荐Joda时间并且不推荐真正的Java答案的人都
感到羞耻

2
@ Zizouz212关于推荐Joda-Time,与Java捆绑在一起的旧的日期-时间类是不好的,非常糟糕的,设计不当的,令人困惑的和麻烦的。如此糟糕以至于乔达·时代(Joda-Time)成为他们的接班人,取得了巨大的成功。太糟糕了,甚至Sun / Oracle都放弃了它们,并采用java.time包作为Java 8和更高版本的一部分。java.time类是受Joda-Time启发的。Joda-Time和java.time都由同一个人Stephen Colbourne领导。我会说,“任何人的耻辱推荐使用的DateCalendarSimpleDateFormat”。
罗勒·布尔克

2
尽管在提出问题时Joda Time可能是一个很好的答案,但今天对于任何可以使用Java 8的人来说,最好的答案是使用java.time.Period和/或Duration。请参阅下面的Basil Bourque的答案
Ole VV

Answers:


198

Date不幸的是,JDK API严重损坏。我建议使用Joda时间库

Joda Time具有时间间隔的概念:

Interval interval = new Interval(oldTime, new Instant());

编辑:顺便说一句,乔达有两个概念:Interval代表两个时刻之间的时间间隔(代表8am到10am之间的时间),和Duration代表没有实际时间界限的时间长度(例如代表两个小时!)

如果您只关心时间比较,则大多数Date实现(包括JDK之一)都会实现Comparable接口,该接口可让您使用Comparable.compareTo()


顺便说一句-你的意思是Comparable.compareTo()不是Comparable.compare()
斯科特·莫里森

Joda-Time有三类以各种方式描绘时间跨度:“间隔”,“持续时间”和“周期”。这个正确答案讨论了前两个。请参阅我的答案以获取有关期间的信息。
罗勒·布尔克2014年

Java 8有一个新的日期和时间api,例如joda。
tbodt 2014年

11
java.timeJava 8中的新软件包受Joda-Time的启发,但不是替代产品。每个都有其优点和缺点。幸运的是,您不必在它们之间进行选择。只要谨慎对待import陈述,就可以发挥各自的优势。请参见此其他答案,例如java.time。
罗勒·布尔克2014年

6
仅供参考,Joda-Time项目现在处于维护模式,团队建议迁移到java.time类。请参见Oracle教程
罗勒·布尔克

550

简单的差异(没有lib)

/**
 * Get a diff between two dates
 * @param date1 the oldest date
 * @param date2 the newest date
 * @param timeUnit the unit in which you want the diff
 * @return the diff value, in the provided unit
 */
public static long getDateDiff(Date date1, Date date2, TimeUnit timeUnit) {
    long diffInMillies = date2.getTime() - date1.getTime();
    return timeUnit.convert(diffInMillies,TimeUnit.MILLISECONDS);
}

然后您可以致电:

getDateDiff(date1,date2,TimeUnit.MINUTES);

以分钟为单位获取两个日期的差异。

TimeUnitjava.util.concurrent.TimeUnit,一个标准的Java枚举,范围从nanos到数天。


可读的差异(无lib)

public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) {

    long diffInMillies = date2.getTime() - date1.getTime();

    //create the list
    List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class));
    Collections.reverse(units);

    //create the result map of TimeUnit and difference
    Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>();
    long milliesRest = diffInMillies;

    for ( TimeUnit unit : units ) {

        //calculate difference in millisecond 
        long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS);
        long diffInMilliesForUnit = unit.toMillis(diff);
        milliesRest = milliesRest - diffInMilliesForUnit;

        //put the result in the map
        result.put(unit,diff);
    }

    return result;
}

http://ideone.com/5dXeu6

输出类似于Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0},有序。

您只需要将该映射转换为用户友好的字符串即可。


警告

上面的代码片段计算了两个瞬间之间的简单差异。它可以在夏令开关过程中导致问题,就像在解释这个职位。这意味着,如果您没有时间计算日期之间的差异,则可能会缺少日期/小时。

我认为日期差异是主观的,尤其是在几天内。你可以:

  • 计算24小时经过的时间:天+1-天= 1天= 24小时

  • 计算经过的时间,注意夏令时:day + 1-day = 1 = 24h(但使用午夜时间和夏令时可能是0天和23h)

  • 计算的数量day switches,这意味着day + 1 1pm-day 11am = 1 day,即使经过的时间仅为2h(如果有夏令时,则为1h:p)

如果您对日期的日期差异的定义与第一种情况匹配,我的答案是有效的

与JodaTime

如果您使用的是JodaTime,则可以使用以下两个日期(以Millies为后盾的ReadableInstant)获取差异:

Interval interval = new Interval(oldInstant, new Instant());

但是您还可以获取本地日期/时间的差异:

// returns 4 because of the leap year of 366 days
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5), PeriodType.years()).getYears() 

// this time it returns 5
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5+1), PeriodType.years()).getYears() 

// And you can also use these static methods
Years.yearsBetween(LocalDate.now(), LocalDate.now().plusDays(365*5)).getYears()

哇,您真的可以教老狗新花样!以前从未听说过,对于将日期差异转换为有意义的字符串非常有用。
杰里米·古德尔2014年

@SebastienLorber TimeUnit中是否有办法计算差异?“从现在起,警报设置为3天4小时12分钟”。
likejudo 2014年

出色的东西确实节省了我很多时间。感谢你的帮助。
Lyju I Edwinson,2014年

我花了3天的时间来处理Java Date,我只是将其中的很多东西扔掉了,取而代之的是。谢谢。
user1091524

自从我进入stackoverflow以来,这是我看到的最好的答案!:D:D:D
2015年

153
int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime()) 
                 / (1000 * 60 * 60 * 24) )

请注意,这适用于UTC日期,因此,如果您查看本地日期,则可能会相差一天。而由于夏令时的原因,使其与本地日期一起正常使用需要完全不同的方法。


6
实际上,这在Android中无法正常工作。存在舍入错误。示例5月19日至21日表示1天,因为它将1.99转换为1。在将整数转换为int之前使用round。
Pratik Mandrekar,

4
这是最好和最简单的答案。当计算两个日期之间的差时,本地时区彼此相减...以便通过((double)(newer.getTime()-old.getTime())/ (86400.0 * 1000.0); ...作为双倍,您也可以轻松将小数日转换为HH:MM:ss
斯科特(Scottb)2013年

8
@scottb:本地日期的问题是您可以节省夏令时,这意味着有些日子有23或25个小时,可能会弄乱结果。
Michael Borgwardt

1
@Steve:像这样的新Date(115,2,26)定义它们时是28岁;(请注意参数的API文档)。您是否有可能使用美国日期格式并以宽松模式来解析它们,以便将26/03/2015解释为2015年第26个月的第3天?
Michael Borgwardt 2015年

1
@Steve:嗯,不知道为什么以前我得到不一样的结果,但是现在我可以重现您的错误了。您的代码中的花括号与我的答案中的花括号不同,后者导致(endDate.getTime() - startDate.getTime())强制转换int而不是最终结果,并且您得到整数溢出。
Michael Borgwardt

54

使用Java 8+中内置的java.time框架:

ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10);
Duration duration = Duration.between(oldDate, now);
System.out.println("ISO-8601: " + duration);
System.out.println("Minutes: " + duration.toMinutes());

输出:

ISO-8601:PT24H10M

分钟:1450

有关更多信息,请参见Oracle教程ISO 8601标准。


5
或使用Period代替Duration日期。
Aphex

53

您需要更清楚地定义问题。您可以只取两个Date对象之间的毫秒数,然后除以24小时内的毫秒数,例如...但是:

  • 这不会考虑时区- Date始终采用UTC
  • 这不会考虑夏令时(例如,可能只有23小时长的日期)
  • 即使在UTC内,从8月16日晚上11点到8月18日凌晨2点有多少天?只有27个小时,那意味着一天吗?还是应该因为涵盖三个日期才是三天?

1
我以为java.util。Date只是一个围绕时毫秒表示的小包装,以本地(默认)时区解释。打印出日期可以显示本地时区。我在这里困惑吗?
Adriaan Koster

46

tl; dr

将过时的java.util.Date对象转换为它们的替换java.time.Instant。然后将经过时间计算为Duration

Duration d = 
    Duration.between(                   // Calculate the span of time between two moments as a number of hours, minutes, and seconds.
        myJavaUtilDate.toInstant() ,    // Convert legacy class to modern class by calling new method added to the old class.
        Instant.now()                   // Capture the current moment in UTC. About two and a half hours later in this example.
    )
;

d.toString():PT2H34M56S

d.toMinutes():154

d.toMinutesPart():34

ISO 8601格式: PnYnMnDTnHnMnS

明智的标准ISO 8601定义了跨度的简洁文本表示形式,以年,月,日,小时等表示。该跨度称为持续时间。格式是PnYnMnDTnHnMnS其中P装置“周期”,则T分开的时间部分的时间部分,并且在是数字后跟一个字母之间。

例子:

  • P3Y6M4DT12H30M5S
    三年零六个月四天十二小时三十分钟五秒
  • PT4H30M
    四个半小时

java.time

java.time内置到Java 8及更高版本的框架取代了麻烦老java.util.Date/ java.util.Calendar班。新课程的灵感取自于成功的Joda-Time框架,该框架旨在作为其继任者,其概念相似但经过重新架构。由JSR 310定义。由ThreeTen-Extra项目扩展。请参阅教程

时刻

Instant级表示时间轴上的时刻UTC,分辨率为纳秒(最多小数的9个位数)。

Instant instant = Instant.now() ;  // Capture current moment in UTC.

最好避免使用Date/ 等旧类Calendar。但是,如果您必须与尚未更新为java.time的旧代码进行互操作,请来回转换。调用添加到旧类中的新转换方法。要从a java.util.Date移到an Instant,请致电Date::toInstant

Instant instant = myJavaUtilDate.toInstant() ;  // Convert from legacy `java.util.Date` class to modern `java.time.Instant` class.

时间跨度

java.time类将这种表示时间跨度的想法分为两半:年,月,日,小时,分钟,秒:

  • Period 数年,数月,数天
  • Duration 持续几天,几小时,几分钟,几秒钟

这是一个例子。

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
ZonedDateTime future = now.plusMinutes ( 63 );
Duration duration = Duration.between ( now , future );

转储到控制台。

二者PeriodDurationISO 8601标准,用于产生其值的字符串表示。

System.out.println ( "now: " + now + " to future: " + now + " = " + duration );

现在:2015-11-26T00:46:48.016-05:00 [美国/蒙特利尔]至未来:2015-11-26T00:46:48.016-05:00 [美国/蒙特利尔] = PT1H3M

Java 9添加了一些方法来Duration获取天数,小时数,分钟数和秒数。

您可以获取整个“持续时间”中的天数或小时数,分钟数或秒数或毫秒或纳秒数的总数。

long totalHours = duration.toHours();

在Java 9中,Duration该类获得了用于返回天,小时,分钟,秒,毫秒/纳秒各个部分的新方法。调用to…Part方法:toDaysPart()toHoursPart()等等。

ChronoUnit

如果您只关心更简单的较大时间粒度,例如“经过的天数”,请使用ChronoUnit枚举。

long daysElapsed = ChronoUnit.DAYS.between( earlier , later );

另一个例子。

Instant now = Instant.now();
Instant later = now.plus( Duration.ofHours( 2 ) );

long minutesElapsed = ChronoUnit.MINUTES.between( now , later );

120


关于java.time

java.time框架是建立在Java 8和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar,和SimpleDateFormat

现在处于维护模式Joda-Time项目建议迁移到java.time。

要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

在哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多


乔达时代

更新:Joda-Time项目现在处于维护模式,团队建议迁移到java.time类。我保留此部分的历史记录。

Joda-Time库使用ISO 8601作为其默认值。它的Period类解析并生成这些PnYnMnDTnHnMnS字符串。

DateTime now = DateTime.now(); // Caveat: Ignoring the important issue of time zones.
Period period = new Period( now, now.plusHours( 4 ).plusMinutes( 30));
System.out.println( "period: " + period );

渲染:

period: PT4H30M

有趣的是,您使用“ tl; dr”开始了一个无关紧要的文字墙。问题不是关于如何从X以前或X时间单位中获取时间戳,而是如何获取两个日期之间的差异。而已。
布法罗

@布法罗我不明白你的评论。我的答案涉及PeriodDuration和的ChronoUnit三个类,其目的是确定时间点之间的差异。请指出我的“文字墙”中哪些部分无关。您说这个问题要求“日期之间的差异”是不正确的:Date尽管该类的命名很不幸,但该问题要求的是对象之间的差异,它们是日期时间,而不是“日期”。
罗勒·布尔克

您的注释中没有任何东西可以处理两个现有的java.util.Date对象。我尝试在代码中使用各种代码段,但未发现使用java.util.Date对象的任何代码。
Buffalo

@布法罗公平,很好的批评。我在“ tl; dr”部分中添加了从a java.util.Date到a 的代码Instant(只需调用.toInstant)。我添加了这一Moment节来说明。您提到了一对Date对象,但实际上Question仅使用一个现有Date对象,然后捕获了当前时刻,所以我也做同样的事情。感谢您的反馈!提示:放弃使用Date–这些旧类确实是一个可怕的烂摊子。
罗勒·布尔克


23

一个更简单的选择:

System.currentTimeMillis() - oldDate.getTime()

至于“ nicer”:那么,您到底需要什么?将持续时间表示为小时数和天数等问题是由于日期的复杂性(例如,由于夏令时,几天可能有23或25个小时)可能导致不准确和错误的期望。


22

使用毫秒方法可能会在某些区域中引起问题。

例如,让我们将2007年3月24日和2007年3月25日这两个日期之间的差值设为1天;

但是,如果使用毫秒级的路线,那么在英国运行,您将获得0天!

/** Manual Method - YIELDS INCORRECT RESULTS - DO NOT USE**/  
/* This method is used to find the no of days between the given dates */  
public long calculateDays(Date dateEarly, Date dateLater) {  
   return (dateLater.getTime() - dateEarly.getTime()) / (24 * 60 * 60 * 1000);  
} 

更好的方法是使用java.util.Calendar

/** Using Calendar - THE CORRECT WAY**/  
public static long daysBetween(Calendar startDate, Calendar endDate) {  
  Calendar date = (Calendar) startDate.clone();  
  long daysBetween = 0;  
  while (date.before(endDate)) {  
    date.add(Calendar.DAY_OF_MONTH, 1);  
    daysBetween++;  
  }  
  return daysBetween;  
}  

19
您能否将此代码的原始作者和第三句话(其博客条目可以追溯到2007年)归功于此?
wchargin 2012年

是不是有点无效?
Gangnus

它不能正常工作。daysBetween(new GregorianCalendar(2014,03,01),new GregorianCalendar(2014,04,02))); :返回31,它应该返回32 timeanddate.com/date/...
marcolopes

5
@marcolopes-您错了-因为日历月从零开始。我确定您的意思是三月/四月,但您要测试的是四月/六月,即31。为了安全起见,请像这样-> new GregorianCalendar(2014,Calendar.MARCH,1)...
Iroh叔叔

@UncleIroh,你是对的!我错过了这个重要事实(日历月份是从零开始的)。我必须重新审查这个问题。
marcolopes 2014年

22

您可以通过多种方式查找日期和时间之间的差异。我知道的最简单的方法之一是:

      Calendar calendar1 = Calendar.getInstance();
      Calendar calendar2 = Calendar.getInstance();
      calendar1.set(2012, 04, 02);
      calendar2.set(2012, 04, 04);
      long milsecs1= calendar1.getTimeInMillis();
      long milsecs2 = calendar2.getTimeInMillis();
      long diff = milsecs2 - milsecs1;
      long dsecs = diff / 1000;
      long dminutes = diff / (60 * 1000);
      long dhours = diff / (60 * 60 * 1000);
      long ddays = diff / (24 * 60 * 60 * 1000);

      System.out.println("Your Day Difference="+ddays);

打印语句只是一个示例-您可以按照自己喜欢的方式对其进行格式化。


5
// @ manoj kumar bardhan:欢迎堆栈溢出:您所看到的问题和答案已经有岁了。您的答案应该比现有答案/问题更多。
Jayan 2012年

3
由于DST转换而需要23或25个小时的日子呢?
乔尼2012年

19

由于这里的所有答案都是正确的,但是使用了遗留的Java或第3方库(例如joda或类似的库),因此我将放弃使用Java 8及更高版本中新的java.time类的另一种方式。请参阅Oracle教程

使用LocalDateChronoUnit

LocalDate d1 = LocalDate.of(2017, 5, 1);
LocalDate d2 = LocalDate.of(2017, 5, 18);

long days = ChronoUnit.DAYS.between(d1, d2);
System.out.println( days );

9

用毫秒减去日期是可行的(如另一篇文章中所述),但是在清除日期的时间部分时,您必须使用HOUR_OF_DAY而不是HOUR:

public static final long MSPERDAY = 60 * 60 * 24 * 1000;
...
final Calendar dateStartCal = Calendar.getInstance();
dateStartCal.setTime(dateStart);
dateStartCal.set(Calendar.HOUR_OF_DAY, 0); // Crucial.
dateStartCal.set(Calendar.MINUTE, 0);
dateStartCal.set(Calendar.SECOND, 0);
dateStartCal.set(Calendar.MILLISECOND, 0);
final Calendar dateEndCal = Calendar.getInstance();
dateEndCal.setTime(dateEnd);
dateEndCal.set(Calendar.HOUR_OF_DAY, 0); // Crucial.
dateEndCal.set(Calendar.MINUTE, 0);
dateEndCal.set(Calendar.SECOND, 0);
dateEndCal.set(Calendar.MILLISECOND, 0);
final long dateDifferenceInDays = ( dateStartCal.getTimeInMillis()
                                  - dateEndCal.getTimeInMillis()
                                  ) / MSPERDAY;
if (dateDifferenceInDays > 15) {
    // Do something if difference > 15 days
}

1
这是确定两个日历日期之间差异的最佳方法,而无需超出标准库。其他大多数答案将一天视为任意24小时周期。如果要减去而不是加上leap秒,则由于截断,最终计算可能会减一,因为绝对差可能会略小于MSPERDAY的整数倍。
JulianSymes 2014年

8

如果您不想使用JodaTime或类似的东西,最好的解决方案可能是:

final static long MILLIS_PER_DAY = 24 * 3600 * 1000;
long msDiff= date1.getTime() - date2.getTime();
long daysDiff = Math.round(msDiff / ((double)MILLIS_PER_DAY));

每天的毫秒数并不总是相同的(由于夏令时和and秒),但是它非常接近,至少由于夏令时而导致的偏差会在更长的时间内抵消。因此,除以四舍五入将得到正确的结果(至少只要使用的本地日历不包含DST和leap秒以外的怪异时间跳转)。

请注意,这仍然假设date1并且date2设置为一天中的同一时间。正如乔恩·斯凯特(Jon Skeet)所指出的,对于一天中的不同时间,您首先必须定义“日期差异”的含义。


问题在date1.getTime()vs中date2.getTime()。因此,将2016-03-03与2016-03-31进行比较将计算27天,而您需要28天。
malat

@malat:对不起,我无法理解。我刚刚尝试过-将我的代码与2016-03-03到2016-03-31相差28天。如果它在您的示例中计算出其他内容,请考虑将其作为一个单独的问题进行询问。
sleske

另外,你读过我的警告吗?“这仍然假设date1和date2设置为一天中的同一时间”。您是否在测试中使用一天中的不同时间?
sleske

对啊!我错过了的技巧Math.round(),在“现实世界”日历中似乎很安全。对不起,噪音。
malat

8

看一下Joda Time,它是Java的改进的Date / Time API,应该可以与Scala一起正常工作。


在Java 8中由java.time(JSR-310)取代
Malat

5

让我展示一下Joda Interval和Days之间的区别:

DateTime start = new DateTime(2012, 2, 6, 10, 44, 51, 0);
DateTime end = new DateTime(2012, 2, 6, 11, 39, 47, 1);
Interval interval = new Interval(start, end);
Period period = interval.toPeriod();
System.out.println(period.getYears() + " years, " + period.getMonths() + " months, " + period.getWeeks() + " weeks, " + period.getDays() + " days");
System.out.println(period.getHours() + " hours, " + period.getMinutes() + " minutes, " + period.getSeconds() + " seconds ");
//Result is:
//0 years, 0 months, *1 weeks, 1 days*
//0 hours, 54 minutes, 56 seconds 

//Period can set PeriodType,such as PeriodType.yearMonthDay(),PeriodType.yearDayTime()...
Period p = new Period(start, end, PeriodType.yearMonthDayTime());
System.out.println(p.getYears() + " years, " + p.getMonths() + " months, " + p.getWeeks() + " weeks, " + p.getDays() + "days");
System.out.println(p.getHours() + " hours, " + p.getMinutes() + " minutes, " + p.getSeconds() + " seconds ");
//Result is:
//0 years, 0 months, *0 weeks, 8 days*
//0 hours, 54 minutes, 56 seconds 

5

如果您需要格式化的返回字符串,例如“ 2 Days 03h 42m 07s”,请尝试以下操作:

public String fill2(int value)
{
    String ret = String.valueOf(value);

    if (ret.length() < 2)
        ret = "0" + ret;            
    return ret;
}

public String get_duration(Date date1, Date date2)
{                   
    TimeUnit timeUnit = TimeUnit.SECONDS;

    long diffInMilli = date2.getTime() - date1.getTime();
    long s = timeUnit.convert(diffInMilli, TimeUnit.MILLISECONDS);

    long days = s / (24 * 60 * 60);
    long rest = s - (days * 24 * 60 * 60);
    long hrs = rest / (60 * 60);
    long rest1 = rest - (hrs * 60 * 60);
    long min = rest1 / 60;      
    long sec = s % 60;

    String dates = "";
    if (days > 0) dates = days + " Days ";

    dates += fill2((int) hrs) + "h ";
    dates += fill2((int) min) + "m ";
    dates += fill2((int) sec) + "s ";

    return dates;
}

2
哇,当Joda-Time提供已经编写和调试的Period类时,为什么要自己动手?
罗勒·布尔克2014年

8
当我只需要32行代码时,为什么要下载压缩文件大小为4.1 MB的库并将其添加到我的项目中?
Ingo 2014年

1
因为Joda-Time就像薯片:您不能只吃一个。您将在各处使用Joda-Time。并且因为Joda-Time是经过充分测试和完善的代码。而且由于Joda-Time会解析并生成标准的ISO 8601持续时间字符串,因此对于序列化或报告这些值可能很方便。并且因为Joda-Time包含格式化程序以打印这些值的本地化表示形式。
罗勒·布尔克

并非所有代码都经过测试。std上面是不确定的。
罗勒·布尔克

@Basil Bourque:提示。我已整理好来源。此错误来自翻译成英语。
Ingo 2014年

5

注意:startDate和endDates是-> java.util.Date

import org.joda.time.Duration;
import org.joda.time.Interval;
// Use .getTime() unless it is a joda DateTime object
Interval interval = new Interval(startDate.getTime(), endDate.getTime());
Duration period = interval.toDuration();
//gives the number of days elapsed between start 
period.getStandardDays();

和结束日期

类似于几天,您还可以获取小时,分钟和秒

period.getStandardHours();
period.getStandardMinutes();
period.getStandardSeconds();

4

在此处查看示例http://www.roseindia.net/java/beginners/DateDifferent.shtml 此示例为您提供了以天,小时,分钟,秒和毫秒为单位的差异:)。

import java.util.Calendar;
import java.util.Date;

public class DateDifferent {
    public static void main(String[] args) {
        Date date1 = new Date(2009, 01, 10);
        Date date2 = new Date(2009, 07, 01);
        Calendar calendar1 = Calendar.getInstance();
        Calendar calendar2 = Calendar.getInstance();
        calendar1.setTime(date1);
        calendar2.setTime(date2);
        long milliseconds1 = calendar1.getTimeInMillis();
        long milliseconds2 = calendar2.getTimeInMillis();
        long diff = milliseconds2 - milliseconds1;
        long diffSeconds = diff / 1000;
        long diffMinutes = diff / (60 * 1000);
        long diffHours = diff / (60 * 60 * 1000);
        long diffDays = diff / (24 * 60 * 60 * 1000);
        System.out.println("\nThe Date Different Example");
        System.out.println("Time in milliseconds: " + diff + " milliseconds.");
        System.out.println("Time in seconds: " + diffSeconds + " seconds.");
        System.out.println("Time in minutes: " + diffMinutes + " minutes.");
        System.out.println("Time in hours: " + diffHours + " hours.");
        System.out.println("Time in days: " + diffDays + " days.");
    }
}

3
-1这是错误的,除非Date实例是从UTC时间派生的。请参阅Jon Skeet的答案。
sleske,2010年

4

使用GMT时区获取Calendar的实例,使用Calendar类的set方法设置时间。GMT时区的偏移量为0(不是很重要),夏时制标志设置为false。

    final Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));

    cal.set(Calendar.YEAR, 2011);
    cal.set(Calendar.MONTH, 9);
    cal.set(Calendar.DAY_OF_MONTH, 29);
    cal.set(Calendar.HOUR, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    final Date startDate = cal.getTime();

    cal.set(Calendar.YEAR, 2011);
    cal.set(Calendar.MONTH, 12);
    cal.set(Calendar.DAY_OF_MONTH, 21);
    cal.set(Calendar.HOUR, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    final Date endDate = cal.getTime();

    System.out.println((endDate.getTime() - startDate.getTime()) % (1000l * 60l * 60l * 24l));

不要忘记将毫秒部分设置为零,否则在旧类java.util.Date等情况下这是一个很好的答案。使用hack将时区设置为GMT会使代码对夏令时不敏感。
Meno Hochschild

4

以下代码可以为您提供所需的输出:

String startDate = "Jan 01 2015";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd yyyy");
LocalDate date = LocalDate.parse(startDate, formatter);

String currentDate = "Feb 11 2015";
LocalDate date1 = LocalDate.parse(currentDate, formatter);

System.out.println(date1.toEpochDay() - date.toEpochDay());

3
您能确切说明您的代码做什么吗?这个问题似乎在询问时间增量,乍一看,您的代码似乎返回了一天增量?
GHC 2015年

4
public static String getDifferenceBtwTime(Date dateTime) {

    long timeDifferenceMilliseconds = new Date().getTime() - dateTime.getTime();
    long diffSeconds = timeDifferenceMilliseconds / 1000;
    long diffMinutes = timeDifferenceMilliseconds / (60 * 1000);
    long diffHours = timeDifferenceMilliseconds / (60 * 60 * 1000);
    long diffDays = timeDifferenceMilliseconds / (60 * 60 * 1000 * 24);
    long diffWeeks = timeDifferenceMilliseconds / (60 * 60 * 1000 * 24 * 7);
    long diffMonths = (long) (timeDifferenceMilliseconds / (60 * 60 * 1000 * 24 * 30.41666666));
    long diffYears = (long)(timeDifferenceMilliseconds / (1000 * 60 * 60 * 24 * 365));

    if (diffSeconds < 1) {
        return "one sec ago";
    } else if (diffMinutes < 1) {
        return diffSeconds + " seconds ago";
    } else if (diffHours < 1) {
        return diffMinutes + " minutes ago";
    } else if (diffDays < 1) {
        return diffHours + " hours ago";
    } else if (diffWeeks < 1) {
        return diffDays + " days ago";
    } else if (diffMonths < 1) {
        return diffWeeks + " weeks ago";
    } else if (diffYears < 12) {
        return diffMonths + " months ago";
    } else {
        return diffYears + " years ago";
    }
}   

3
int daysDiff = (date1.getTime() - date2.getTime()) / MILLIS_PER_DAY;

5
-1这是错误的,除非Date实例是从UTC时间派生的。请参阅Jon Skeet的答案。
sleske,2010年

5
@sleske你说的不对。他已经通过使用丢失了时区信息Date,因此这种比较是在特定情况下可以实现的最佳效果。
博若

1
好吧,猜猜我们都是对的。确实,这取决于Date实例的来源。尽管如此,这是一个普遍的错误,值得一提。
sleske,2010年

当我使用您的解决方案时,它说:类型不匹配:无法从long转换为int。我认为您还应该添加演员表,或者我缺少什么?
Ad Infinitum

3

最好的事情是

(Date1-Date2)/86 400 000 

该数字是一天中的毫秒数。

一个日期-另一个日期为您提供以毫秒为单位的差异。

将答案收集在一个变量中。


是的,为什么不?我在某些方面不明白问题的重点:OP的毫秒数有所不同...而且一天中有一定数量的ms(好的,一次天蓝色的天文学调整一次,但是OP却没有)并不是说它必须与天文学家所需要的一样精确……)
麦克·罗丹

3

这是O(1)中没有任何依赖关系的正确Java 7解决方案。

public static int countDaysBetween(Date date1, Date date2) {

    Calendar c1 = removeTime(from(date1));
    Calendar c2 = removeTime(from(date2));

    if (c1.get(YEAR) == c2.get(YEAR)) {

        return Math.abs(c1.get(DAY_OF_YEAR) - c2.get(DAY_OF_YEAR)) + 1;
    }
    // ensure c1 <= c2
    if (c1.get(YEAR) > c2.get(YEAR)) {
        Calendar c = c1;
        c1 = c2;
        c2 = c;
    }
    int y1 = c1.get(YEAR);
    int y2 = c2.get(YEAR);
    int d1 = c1.get(DAY_OF_YEAR);
    int d2 = c2.get(DAY_OF_YEAR);

    return d2 + ((y2 - y1) * 365) - d1 + countLeapYearsBetween(y1, y2) + 1;
}

private static int countLeapYearsBetween(int y1, int y2) {

    if (y1 < 1 || y2 < 1) {
        throw new IllegalArgumentException("Year must be > 0.");
    }
    // ensure y1 <= y2
    if (y1 > y2) {
        int i = y1;
        y1 = y2;
        y2 = i;
    }

    int diff = 0;

    int firstDivisibleBy4 = y1;
    if (firstDivisibleBy4 % 4 != 0) {
        firstDivisibleBy4 += 4 - (y1 % 4);
    }
    diff = y2 - firstDivisibleBy4 - 1;
    int divisibleBy4 = diff < 0 ? 0 : diff / 4 + 1;

    int firstDivisibleBy100 = y1;
    if (firstDivisibleBy100 % 100 != 0) {
        firstDivisibleBy100 += 100 - (firstDivisibleBy100 % 100);
    }
    diff = y2 - firstDivisibleBy100 - 1;
    int divisibleBy100 = diff < 0 ? 0 : diff / 100 + 1;

    int firstDivisibleBy400 = y1;
    if (firstDivisibleBy400 % 400 != 0) {
        firstDivisibleBy400 += 400 - (y1 % 400);
    }
    diff = y2 - firstDivisibleBy400 - 1;
    int divisibleBy400 = diff < 0 ? 0 : diff / 400 + 1;

    return divisibleBy4 - divisibleBy100 + divisibleBy400;
}


public static Calendar from(Date date) {

    Calendar c = Calendar.getInstance();
    c.setTime(date);

    return c;
}


public static Calendar removeTime(Calendar c) {

    c.set(HOUR_OF_DAY, 0);
    c.set(MINUTE, 0);
    c.set(SECOND, 0);
    c.set(MILLISECOND, 0);

    return c;
}

2

那可能是最简单的方法-也许是因为我已经使用Java进行了一段时间的编码(它的日期和时间库很笨拙),但是对我来说,这段代码看起来“简单而好”!

您对以毫秒为单位返回结果感到满意,还是您希望以某种其他格式返回结果呢?


2

不使用标准API,否。您可以滚动自己执行以下操作:

class Duration {
    private final TimeUnit unit;
    private final long length;
    // ...
}

或者您可以使用Joda

DateTime a = ..., b = ...;
Duration d = new Duration(a, b);

2

只是为了回答最初的问题:

将以下代码放入Long getAge(){}之类的函数中

Date dahora = new Date();
long MillisToYearsByDiv = 1000l *60l * 60l * 24l * 365l;
long javaOffsetInMillis = 1990l * MillisToYearsByDiv;
long realNowInMillis = dahora.getTime() + javaOffsetInMillis;
long realBirthDayInMillis = this.getFechaNac().getTime() + javaOffsetInMillis;
long ageInMillis = realNowInMillis - realBirthDayInMillis;

return ageInMillis / MillisToYearsByDiv;

这里最重要的是在相乘和相除时要处理长整数。当然,Java在其日期演算中应用的偏移量。

:)


2

由于问题是用Scala标记的,

import scala.concurrent.duration._
val diff = (System.currentTimeMillis() - oldDate.getTime).milliseconds
val diffSeconds = diff.toSeconds
val diffMinutes = diff.toMinutes
val diffHours = diff.toHours
val diffDays = diff.toDays

2

在仔细研究了所有其他答案之后,要保留Java 7 Date类型,但要使Java 8 diff方法更加精确/标准,

public static long daysBetweenDates(Date d1, Date d2) {
    Instant instant1 = d1.toInstant();
    Instant instant2 = d2.toInstant();
    long diff = ChronoUnit.DAYS.between(instant1, instant2);
    return diff;
}

1

尝试这个:

int epoch = (int) (new java.text.SimpleDateFormat("MM/dd/yyyy HH:mm:ss").parse("01/01/1970  00:00:00").getTime() / 1000);

您可以在parse()方法参数中编辑字符串。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.