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

Calculating the difference between two Java date instances

我在斯卡拉使用Java的EDCOX1×0类,并希望将EDCOX1与1的对象和当前时间进行比较。我知道我可以用getTime()计算delta:

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

然而,这只留下了一个表示毫秒的long。有没有更简单,更好的方法来获得时间差?


简单diff(不带lib)

1
2
3
4
5
6
7
8
9
10
11
/**
 * 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);
}

然后你能打电话给:

1
getDateDiff(date1,date2,TimeUnit.MINUTES);

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

TimeUnitjava.util.concurrent.TimeUnit,一个标准的Java枚举从Nano到天。

人可读差异(无lib)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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小时运行时间:day+1-day=1 day=24小时

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

  • 计算day switches的个数,即day+1 1pm-day 11am=1天,即使经过的时间仅为2小时(如果有日光节约,则为1小时:p)。

如果您对日期差异的定义与第一个案例相匹配,我的回答是有效的。

与约旦

如果您使用的是jodatime,则可以获得2个瞬间的diff(毫秒支持readableinstant)日期,其中:

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

但您也可以获得本地日期/时间的差异:

1
2
3
4
5
6
7
8
// 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()


不幸的是,JDK DateAPI被严重破坏。我建议使用Joda时间库。

Joda Time有时间间隔的概念:

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

编辑:顺便说一下,joda有两个概念:Interval表示两个时间瞬间之间的时间间隔(表示上午8点到上午10点之间的时间),Duration表示没有实际时间界限的时间长度(例如表示两个小时!)

如果您只关心时间比较,大多数Date实现(包括jdk)实现Comparable接口,允许您使用Comparable.compareTo()接口。


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

请注意,这适用于UTC日期,因此如果您查看本地日期,差异可能是休息日。要使它与当地日期正确工作,需要一个完全不同的方法,因为夏令时。


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

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


使用Java 8 +中构建的JavaTimeFramework:

1
2
3
4
5
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

Minutes: 1450

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


DR

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

1
2
3
4
5
6
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

Ok.

d.toMinutes(): 154

Ok.

d.toMinutesPart(): 34

Ok.

ISO 8601格式:PnYnMnDTnHnMnS

明智的标准ISO 8601将时间跨度的简明文本表示定义为若干年、月、日、小时等。标准将这种跨度称为持续时间。格式为PnYnMnDTnHnMnS,其中P表示"句点",T将日期部分与时间部分分开,中间是数字,后面是字母。好的。

实例:好的。

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

Java.时间

JavaTimeFramework内置到Java 8中,并随后取代了麻烦的旧EDCOX1、0、EDCX1、10个类。这些新的类是受到非常成功的Joda时间框架的启发,这个框架的目的是作为它的继承者,在概念上类似,但重新架构了。由JSR 310定义。由三个额外的项目扩展。请参见教程。好的。力矩

Instant类表示UTC时间轴上的一个时刻,分辨率为纳秒(小数点后九(9)位)。好的。

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

最好避免遗留类,如Date/Calendar。但是,如果您必须与尚未更新到java.time的旧代码进行交互操作,请来回转换。调用添加到旧类中的新转换方法。从一个java.util.Date移动到一个Instant时,叫Date::toInstant。好的。

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

时间跨度

java.time类将时间跨度表示为年、月、天、小时、分钟、秒的概念分成了两部分:好的。

  • 年、月、日
  • Duration用于天、小时、分钟、秒

下面是一个例子。好的。

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

转储到控制台。好的。

PeriodDuration都使用ISO 8601标准生成其值的字符串表示。好的。

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

now: 2015-11-26T00:46:48.016-05:00[America/Montreal] to future: 2015-11-26T00:46:48.016-05:00[America/Montreal] = PT1H3M

Ok.

Java 9向EDCOX1(2)添加方法以获得日期部分、小时部分、分钟部分和秒部分。好的。

您可以获取整个持续时间内的总天数、小时数、分钟数、秒数、毫秒数或纳秒数。好的。

1
long totalHours = duration.toHours();

在Java 9中,EDCOX1×2类获得了返回日期、小时、分钟、秒、毫秒/毫微秒的各个部分的新方法。调用to…Part方法:toDaysPart()toHoursPart()等。好的。ChronoUnit

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

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

另一个例子。好的。

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

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

120

Ok.

关于java.time

该框架是一个Java内置的java.time 8及以后。这类遗产的老supplant troublesome日期时间类,如java.util.DateCalendar&;SimpleDateFormat

现在的项目是完全搞砸了时,在维护模式,advises java.time迁移。

学习更多,看Oracle教程。堆栈溢出是搜索和讲许多实例。JSR规范是310。

在获得的java.time班吗?

  • Java SE 8和9和后
    • 内置的。
    • 标准的Java API的一部分,以捆绑的实现。
    • java的一些很酷的功能和增加小9。
  • Java SE 6和7
    • 多功能的java.time后台是Java 6 ported &;threeten - 7在维护。
  • Android
    • 该项目adapts threetenabp threeten -维护(上述)特别是Android。
    • 国有企业如何使用……

在额外的项目java.time threeten延伸与额外的类。这个项目是一个试验场java.time additions到地面可能的未来。你可以在这里找到一些有用的类,如IntervalYearWeekYearQuarter,和更多。

时间是完全搞砸了

更新:现在的时间是完全搞砸了项目是在维护模式下,与团队advising迁移到java.time类。我把这段历史是完整的。

该库是完全搞砸了时使用ISO 8601在其默认值。它的两个竞争的剖析器和产生这些pnynmndtnhnmns Period类的字符串。

1
2
3
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 );

renders:

1
period: PT4H30M

好的。


1
2
Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();

https://www.joda.org/joda time/faq.html日期差异


一个稍微简单的选择:

1
System.currentTimeMillis() - oldDate.getTime()

至于"更好":那么,你到底需要什么?将持续时间表示为若干小时和天数等的问题是,由于日期的复杂性,它可能导致不准确和错误的预期(例如,由于夏令时,天数可以有23或25小时)。


使用毫秒方法可能会在某些地方造成问题。

举个例子,2007年3月24日和2007年3月25日之间的差额应该是1天;

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

1
2
3
4
5
/** 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

1
2
3
4
5
6
7
8
9
10
/** 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;  
}


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

1
2
3
4
5
6
7
8
9
10
11
12
13
      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);

print语句只是一个例子-您可以按照自己喜欢的方式格式化它。


由于所有的答案都是正确的,但在这里,使用传统的Java类或第三方库或是类似的,我会用另一个方式是把新的Java类java.time 8和以后。在Oracle教程。

使用LocalDateChronoUnit

1
2
3
4
5
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 );


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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
}


如果您不想使用jodatime或类似工具,最好的解决方案可能是:

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

每天的毫秒数并不总是相同的(因为夏令时和闰秒),但它非常接近,至少由于夏令时的偏差会在更长的时间内取消。因此,分割然后舍入将得到正确的结果(至少只要使用的本地日历不包含DST和闰秒以外的奇怪时间跳跃)。

请注意,这仍然假定date1date2设置为当天的同一时间。对于一天中的不同时间,你首先必须定义"日期差异"的含义,如乔恩·斯基特所指出的。


看看JoDaTime,它是Java的一个改进的日期/时间API,应该和斯卡拉一起工作。


如果需要类似"2天03h 42m 07s",尝试以下操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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;
}


让我展示一下Joda间隔和天之间的区别:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
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";
    }
}

使用GMT时区获取日历实例,使用日历类的set方法设置时间。GMT时区的偏移量为0(不太重要),夏令时标志设置为假。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    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));


请查看以下示例:http://www.roseindia.net/java/初学者/datendifferent.shtml这个例子给出了以天、小时、分钟、秒和毫秒为单位的差异:)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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("
The 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.");
    }
}


下面的代码会给你的desired输出:

1
2
3
4
5
6
7
8
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());


最好的办法是

1
(Date1-Date2)/86 400 000

这个数字是一天中的毫秒数。

一个日期和另一个日期的毫秒数不同。

用双变量收集答案。


注:"起始日期"和enddates是java.util.date >

1
2
3
4
5
import org.joda.time.Duration;
import org.joda.time.Interval;
Interval interval = new Interval(startDate.getTime(), endDate.getTime);
Duration period = interval.toDuration();
period.getStandardDays() //gives the number of days elapsed between start and end date

相似的两天,你也能得到小时、分钟和秒

1
2
3
period.getStandardHours();
period.getStandardMinutes();
period.getStandardSeconds();

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


这里的正确的Java 7的溶液在O(1)"没有任何dependencies。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
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;
}


这可能是最直接的方法——也许是因为我已经用Java编码了(用它公认的笨拙的日期和时间库)一段时间,但是代码对我来说"简单而美好"。

您对以毫秒为单位返回的结果满意吗,还是希望以其他格式返回结果是问题的一部分?


不使用标准API,不。您可以自己进行如下操作:

1
2
3
4
5
class Duration {
    private final TimeUnit unit;
    private final long length;
    // ...
}

或者你可以使用Joda:

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

在所有其他wading通两个答案,保持Java 7的约会,但更确切的类型/ 8与Java标准差异的方法

1
2
3
4
5
6
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;
}


"问题是,自认为与Scala

1
2
3
4
5
6
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

我不能回答的问题:初始

把下面的代码在一个功能大类getage(){ }

1
2
3
4
5
6
7
8
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;

最重要的是,我的工作与长数当multiplying dividing鸭。和当然,Java的偏移,在其applies微积分的日期。

:)


之前版本的Java,你可以试试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 public static String daysBetween(Date createdDate, Date expiryDate) {

        Calendar createdDateCal = Calendar.getInstance();
        createdDateCal.clear();
        createdDateCal.setTime(createdDate);

        Calendar expiryDateCal = Calendar.getInstance();
        expiryDateCal.clear();
        expiryDateCal.setTime(expiryDate);


        long daysBetween = 0;
        while (createdDateCal.before(expiryDateCal)) {
            createdDateCal.add(Calendar.DAY_OF_MONTH, 1);
            daysBetween++;
        }
        return daysBetween+"";
    }

产品具有多读和回答这两个问题的评论,是与"左一个印象,无论使用的是有两个小时或采取其他一些peculiarities为客户节省时间与daylight等。因为我不想让它这样做,在结束的IP少写一行代码的两个calculate双差分之间没有约会使用任何日期或时间相关的Java类。

下面的代码的数年、月和日的是相同的作为在现实生活的。例如,在2015年12月24日,在2015年=,= 12个月和24节)。

我想在这两个案例代码共享别人想使用它。有三个方法:(1)两种方法找到一个给定的一年是否是一个飞跃的一年(2)两种方法calculate号天一个给定的一个给定的1年(3)方法的两个calculate数天之间的任何两次使用的方法2(number of the比日期减去number of the start date)。

这里的方法是:

1)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public static boolean isLeapYear (int year) {
    //Every 4. year is a leap year, except if the year is divisible by 100 and not by 400
    //For example 1900 is not a leap year but 2000 is

    boolean result = false;

    if (year % 4 == 0) {
        result = true;
    }
    if (year % 100 == 0) {
        result = false;
    }
    if (year % 400 == 0) {
        result = true;
    }

    return result;

}

2)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public static int daysGoneSince (int yearZero, int year, int month, int day) {
    //Calculates the day number of the given date; day 1 = January 1st in the yearZero

    //Validate the input
    if (year < yearZero || month < 1 || month > 12 || day < 1 || day > 31) {
        //Throw an exception
        throw new IllegalArgumentException("Too many or too few days in month or months in year or the year is smaller than year zero");
    }
    else if (month == 4 || month == 6 || month == 9 || month == 11) {//Months with 30 days
        if (day == 31) {
            //Throw an exception
            throw new IllegalArgumentException("Too many days in month");
        }
    }
    else if (month == 2) {//February 28 or 29
        if (isLeapYear(year)) {
            if (day > 29) {
                //Throw an exception
                throw new IllegalArgumentException("Too many days in month");
            }
        }
        else if (day > 28) {
            //Throw an exception
            throw new IllegalArgumentException("Too many days in month");
        }
    }

    //Start counting days
    int days = 0;

    //Days in the target month until the target day
    days = days + day;

    //Days in the earlier months in the target year
    for (int i = 1; i < month; i++) {
        switch (i) {
            case 1: case 3: case 5:
            case 7: case 8: case 10:
            case 12:
                days = days + 31;
                break;
            case 2:
                days = days + 28;
                if (isLeapYear(year)) {
                    days = days + 1;
                }
                break;
            case 4: case 6: case 9: case 11:
                days = days + 30;
                break;
        }
    }

    //Days in the earlier years
    for (int i = yearZero; i < year; i++) {
        days = days + 365;
        if (isLeapYear(i)) {
            days = days + 1;
        }
    }

    return days;

}

3)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static int dateDiff (int startYear, int startMonth, int startDay, int endYear, int endMonth, int endDay) {

    int yearZero;

    //daysGoneSince presupposes that the first argument be smaller or equal to the second argument
    if (10000 * startYear + 100 * startMonth + startDay > 10000 * endYear + 100 * endMonth + endDay) {//If the end date is earlier than the start date
        yearZero = endYear;
    }
    else {
        yearZero = startYear;
    }

    return daysGoneSince(yearZero, endYear, endMonth, endDay) - daysGoneSince(yearZero, startYear, startMonth, startDay);

}

试试这个:

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

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


我使用下面的方法与双Date对象。如果你想要两个通流通new Date()约会,只是作为一个二次参数作为它的冰流与initialised小时。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public String getDateDiffString(Date dateOne, Date dateTwo)
{
    long timeOne = dateOne.getTime();
    long timeTwo = dateTwo.getTime();
    long oneDay = 1000 * 60 * 60 * 24;
    long delta = (timeTwo - timeOne) / oneDay;

    if (delta > 0) {
        return"dateTwo is" + delta +" days after dateOne";
    }
    else {
        delta *= -1;
        return"dateTwo is" + delta +" days before dateOne";
     }
}

也从分开的,从数天,如果你想要的其他参数太差,使用下面的代码段

1
2
3
4
5
6
int year = delta / 365;
int rest = delta % 365;
int month = rest / 30;
rest = rest % 30;
int weeks = rest / 7;
int days = rest % 7;

P码。说由冰从安猪回答。


由于您使用scala,所以有一个非常好的scala库lamma。使用lamma,您可以直接使用-运算符减去日期。

1
2
3
4
5
scala> Date(2015, 5, 5) - 2     // minus days by int
res1: io.lamma.Date = Date(2015,5,3)

scala> Date(2015, 5, 15) - Date(2015, 5, 8)   // minus two days => difference between two days
res2: Int = 7


有个简单的方式这样做在Java

/ /的create方法的效用

1
2
3
public long getDaysBetweenDates(Date d1, Date d2){
return TimeUnit.MILLISECONDS.toDays(d1.getTime() - d2.getTime());
}

这个方法将返回的数天之间的2次。或者你可以使用Java的默认日期格式可以很容易convert或从任何的日期格式。


@迈克尔·博格华特的答案在安卓系统中实际上并不正确。存在舍入错误。例如,5月19日至21日为1天,因为它的时间是1.99:1。在铸造前使用圆。

固定

1
2
int diffInDays = (int)Math.round(( (newerDate.getTime() - olderDate.getTime())
                 / (1000 * 60 * 60 * 24) ))

请注意,这适用于UTC日期,因此如果您查看本地日期,差异可能是休息日。要使它与当地日期正确工作,需要一个完全不同的方法,因为夏令时。


如果你想解决的问题,数据ranges跨边界daylight储蓄时(例如在一个夏天的约会时间和其他冬季一个小时),你可以用这把分差在两天。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static long calculateDifferenceInDays(Date start, Date end, Locale locale) {
    Calendar cal = Calendar.getInstance(locale);

    cal.setTime(start);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    long startTime = cal.getTimeInMillis();

    cal.setTime(end);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);
    long endTime = cal.getTimeInMillis();

    // calculate the offset if one of the dates is in summer time and the other one in winter time
    TimeZone timezone = cal.getTimeZone();
    int offsetStart = timezone.getOffset(startTime);
    int offsetEnd = timezone.getOffset(endTime);
    int offset = offsetEnd - offsetStart;

    return TimeUnit.MILLISECONDS.toDays(endTime - startTime + offset);
}

另一个纯Java的变化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
}

谢谢,这两个启动代码:http:/ / / / stackoverflow.com 30207726 / 2162226


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public static void main(String[] args) {

    String dateStart ="01/14/2012 09:29:58";
    String dateStop ="01/14/2012 10:31:48";

    SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");

    Date d1 = null;
    Date d2 = null;

    try {
        d1 = format.parse(dateStart);
        d2 = format.parse(dateStop);

        DateTime date11 = new DateTime(d1);
        DateTime date22 = new DateTime(d2);
        int days = Days.daysBetween(date11.withTimeAtStartOfDay(), date22.withTimeAtStartOfDay()).getDays();
        int hours = Hours.hoursBetween(date11, date22).getHours() % 24;
        int minutes = Minutes.minutesBetween(date11, date22).getMinutes() % 60;
        int seconds = Seconds.secondsBetween(date11, date22).getSeconds() % 60;
        if (hours > 0 || minutes > 0 || seconds > 0) {
            days = days + 1;
        }

        System.out.println(days);

    } catch (Exception e) {
        e.printStackTrace();
    }

}

这将给出同一天的日期差异


我喜欢基于时间单位的方法,直到我发现它只涉及一些小情况,即一个时间单位中有多少个单位在下一个更高的单位中是固定的。当你想知道中间有多少个月、多少年等的时候,这个问题就被打破了。

这里有一个计数方法,没有其他方法那么有效,但它似乎对我有用,而且也考虑到了DST。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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;
}

这是另一个样品。这basically厂为用户定义的模式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   public static LinkedHashMap<String, Object> checkDateDiff(DateTimeFormatter dtfObj, String startDate, String endDate)
   {
          Map<String, Object> dateDiffMap = new HashMap<String, Object>();
          DateTime start = DateTime.parse(startDate,dtfObj);
          DateTime end = DateTime.parse(endDate,dtfObj);
          Interval interval = new Interval(start, end);
          Period period = interval.toPeriod();

          dateDiffMap.put("ISO-8601_PERIOD_FORMAT", period);
          dateDiffMap.put("YEAR", period.getYears());
          dateDiffMap.put("MONTH", period.getMonths());
          dateDiffMap.put("WEEK", period.getWeeks());
          dateDiffMap.put("DAY", period.getWeeks());            
          dateDiffMap.put("HOUR", period.getHours());
          dateDiffMap.put("MINUTE", period.getMinutes());
          dateDiffMap.put("SECOND", period.getSeconds());

          return dateDiffMap;        
   }


以下是一个解决方案,因为我们有许多方法可以实现这一点:

1
2
3
4
5
6
7
8
9
10
  import java.util.*;
   int syear = 2000;
   int eyear = 2000;
   int smonth = 2;//Feb
   int emonth = 3;//Mar
   int sday = 27;
   int eday = 1;
   Date startDate = new Date(syear-1900,smonth-1,sday);
   Date endDate = new Date(eyear-1900,emonth-1,eday);
   int difInDays = (int) ((endDate.getTime() - startDate.getTime())/(1000*60*60*24));

好消息给你。

有一个生命如何在日历天之间的差分双约会,没有使用第三方工具。这个,你只需要用两个圆的日期一天的日历使用的Java类。然后,我们简单的双差分caclculate日期之间的鸿沟milliseconds和它在城市的一天(在milliseconds)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public int getDiffernceInDays(long timeAfter, long timeBefore) {
    Calendar calendarAfter = Calendar.getInstance();
    calendarAfter.setTime(new Date(timeAfter));

    Calendar calendarNewAfter = Calendar.getInstance();
    calendarNewAfter.set(calendarAfter.get(Calendar.YEAR), calendarAfter.get(Calendar.MONTH), calendarAfter.get(Calendar.DAY_OF_MONTH));

    Calendar calendarBefore = Calendar.getInstance();
    calendarBefore.setTime(new Date(timeBefore));

    Calendar calendarNewBefore = Calendar.getInstance();
    calendarNewBefore.set(calendarBefore.get(Calendar.YEAR), calendarBefore.get(Calendar.MONTH), calendarBefore.get(Calendar.DAY_OF_MONTH));

    return (int) ((calendarNewAfter.getTime().getTime() - calendarNewBefore.getTime().getTime()) / (24 * 60 * 60 * 1000));
}


如果您的日期是d1和d2,最好的解决方案可能是:

1
2
int days1 = d1.getTime()/(60*60*24*1000);//find the number of days since the epoch.
int days2 = d2.getTime()/(60*60*24*1000);

然后说

1
days2-days1

或者什么


只需对每个函数调用gettime,取其差,然后除以一天中的毫秒数。