web-dev-qa-db-ja.com

2つのJava日付インスタンス間の差を計算する

私はScalaでJavaのJava.util.Dateクラスを使っていて、Dateオブジェクトと現在の時刻を比較したいのです。 getTime()を使用してデルタを計算することができます。

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

しかし、これは私にミリ秒を表すlongを残すだけです。タイムデルタを取得するための、より簡単で優れた方法はありますか。

388
pr1001

JDKのDateAPIは残念ながらひどく壊れています。 Joda Time library の使用をお勧めします。

Joda Timeは時間の概念を持っています 間隔

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

編集:ところで、Jodaには2つの概念があります。2つの時刻の間の時間間隔を表すIntervalname__(午前8時から10時の間の時間を表す)と実際の時間境界のない時間の長さを表すDurationname__(例:2時間) !)

時間の比較だけが気になる場合は、ほとんどのDatename__の実装(JDKを含む)は Comparable.compareTo() を使用できるComparablename__インターフェースを実装します。

181
notnoop

単純な差分(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);

2つの日付の差分を分単位で取得します。

TimeUnitJava.util.concurrent.TimeUnitで、nanosから何日も続く標準のJava列挙型です。


人間が読める差分(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}のようなもので、単位は順序付けされています。

そのマップをユーザーフレンドリーな文字列に変換するだけです。


警告

上記のコードスニペットは、2つの時点間の単純な差分を計算します。 この記事 で説明されているように、夏時間の切り替え中に問題が発生する可能性があります。これは、時間なしで日付間の差分を計算すると、欠けている日/時がある可能性があることを意味します。

私の意見では、日付の差分は主観的なもので、特に日々です。してもいいです:

  • 24時間経過時間の数を数える:日+ 1 - 日= 1日= 24時間

  • 夏時間を考慮して経過時間の数を数えます。day + 1 - day = 1 = 24h(ただし、真夜中の時間と夏時間を使用すると0日と23時間になる可能性があります)

  • day switchesの数を数えます。これは、経過時間がちょうど2時間(夏時間がある場合は1時間)であっても、日+ 1 1 pm - 日11am = 1日を意味します

私の答えは、日数に対する日付差分の定義が最初のケースと一致する場合に有効です

JodaTimeとは

JodaTimeを使用している場合は、次のようにして2つの瞬間(ReadyInstantを基にしたミリ秒)の日付の差分を取得できます。

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()
496
int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime()) 
                 / (1000 * 60 * 60 * 24) )

これはUTCの日付で機能することに注意してください。そのため、現地の日付を見ると違いは休日かもしれません。現地の日付で正しく機能するようにするには、夏時間のためにまったく異なるアプローチが必要です。

148

問題をより明確に定義する必要があります。 2つのDateオブジェクトの間のミリ秒数をし、24時間のミリ秒数で除算すればいいのですが、例えば…

  • これはタイムゾーンを考慮に入れません - Dateは常にUTCです
  • これは夏時間を考慮に入れません(たとえば、23時間しかない日がある場合など)。
  • UTC内でも、8月16日の午後11時から8月18日の午前2時までに何日ありますか。たった27時間なので、1日ということでしょうか。それとも3つの日付をカバーするのでそれは3日であるべきですか?
53
Jon Skeet

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 Tutorial および ISO 8601 standardを参照してください。

47

tl; dr

廃止されたJava.util.Dateオブジェクトをそれらの置き換え物であるJava.time.Instantに変換します。その後、経過時間をDurationname__として計算します。

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フォーマット:PnYnMnDTnHnMnSname__

賢明な規格 ISO 8601 は、年数、月数、日数、時間数などの期間の簡潔なテキスト表現を定義しています。規格はそのような期間を duration と呼んでいます。形式はPnYnMnDTnHnMnSname__で、Pname__は「ピリオド」を意味し、Tname__は日付部分と時間部分を区切り、その間には数字の後に文字が続きます。

例:

  • P3Y6M4DT12H30M5S
    3年6ヶ月4日12時間30分5秒
  • PT4H30M
    4時間半

Java.time

Java 8以降に組み込まれた Java.time フレームワークは、面倒な古いJava.util.DateJava.util.Calendarクラスに取って代わるものです。新しいクラスは、成功した_/Joda-Time フレームワークにインスパイアされています。これは後継として作られたもので、概念は似ていますが再設計されています。 JSR 310 によって定義されています。 ThreeTen-Extra プロジェクトによって拡張されています。 Tutorial を参照してください。

瞬間

InstantNAME_ クラスは、 UTC 内のタイムライン上のモーメントを nanoseconds の分解能で表します(小数点以下9桁まで)。

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

Datename _ CalendarNAME__などの従来のクラスを避けるために最善です。しかし、まだJAVA.TIMEに更新されていない古いコードと相互運用する必要がある場合は、前後に変換してください。古いクラスに追加された新しい変換メソッドを呼び出します。 _/Java.util.Date から InstantNAME_ に移動するには、 Date::toInstant を呼び出します。

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

一定の期間

Java.timeクラスは、期間を年、月、日、時、分、秒の数で表すというこの考え方を2つに分けました。

これが一例です。

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

コンソールにダンプします。

Periodname__とDurationname__の両方とも、それらの値の文字列表現を生成するために ISO 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では、Durationname__にメソッドが追加され、日数、時間数、分数、秒数が取得されます。

期間全体の合計の日数、時間数、分数、秒数、ミリ秒数、またはナノ秒数を取得できます。

long totalHours = duration.toHours();

Java 9では、 Durationname__クラスは、日、時、分、秒、ミリ秒/ナノ秒のさまざまな部分を返すための新しいメソッド を取得します。 to…Partメソッド(toDaysPart()toHoursPart()など)を呼び出します。

ChronoUnitname__

「経過日数」のように、もっと単純な、より大きな粒度だけを気にする場合は、 ChronoUnitNAME_ 列挙型を使用します。

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.DateCalendarNAME_ 、& SimpleDateFormatNAME_ などの厄介な古い legacy 日時クラスに代わるものです。

Joda-Time プロジェクトは現在 maintenanceモード になっており、Java.timeへの移行を推奨します。

詳細については、 Oracleチュートリアル を参照してください。そして多くの例と説明についてはStack Overflowを検索してください。仕様は JSR 310 です。

Java.timeクラスはどこで入手できますか?

  • Java SE 8 および SE 9 以降
    • ビルトイン。
    • バンドル実装の標準Java APIの一部。
    • Java 9では、いくつかのマイナーな機能と修正が追加されています。
  • Java SE 6 および SE 7
    • Java.time機能の多くは ThreeTen-Backport でJava 6と7にバックポートされています。
  • Android
    • ThreeTenABP プロジェクトは、Android用にThreeTen-Backportに適応しています。
    • 使用方法… を参照してください。

ThreeTen-Extra プロジェクトは、追加クラスでJava.timeを拡張します。このプロジェクトは、Java.timeに将来追加される可能性があることを証明するものです。 IntervalNAME_YearWeekNAME_YearQuarterNAME_ 、および more など、便利なクラスがいくつかあります。


ジョダタイム

更新: Joda-Time プロジェクトは現在 maintenanceモード になっており、チームは Java.time クラスへの移行を推奨しています。このセクションは歴史のためにそのまま残しておきます。

Joda-TimeライブラリはデフォルトでISO 8601を使用しています。そのPeriodname__クラスは、これらの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
39
Basil Bourque
Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();

https://www.joda.org/joda-time/faq.html#datediff

34
Adriano Bacha

もう少し簡単な方法:

System.currentTimeMillis() - oldDate.getTime()

"より良い"に関しては:まあ、あなたは正確に何が必要ですか?期間を時間数や日数などで表すことの問題は、日付の複雑さのために不正確さや誤った予想につながる可能性があることです(たとえば、夏時間のために日数が23または25時間になることがあります)。

24

ミリ秒アプローチを使用すると、一部のロケールで問題が発生する可能性があります。

たとえば、2007年3月24日と2007年3月25日の2つの日付の差は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;  
}  
22
zasadnyy

日付と時刻の違いを見つける方法はたくさんあります。私が知っている最も簡単な方法の1つは次のとおりです。

      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ステートメントはほんの一例です - あなたは好きなようにそれをフォーマットすることができます。

21
xxxxxxxx d

ここでの答えはすべて正解ですが、従来のJavaまたはjodaなどのサードパーティ製のライブラリを使用するので、Java 8以降では新しい Java.time クラスを使用して別の方法を使用します。 Oracleチュートリアル を参照してください。

LocalDate および ChronoUnit を使用します。

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 );

ミリ秒単位での日付の減算はうまくいきます(別の記事で説明します)が、日付の時間部分をクリアするときにHOURではなくHOUR_OF_DAYを使用するにはhaveを使用します。

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
}
9

Joda Time を見てください。これはJava用の改良されたDate/Time APIであり、Scalaでもうまく動作するはずです。

8
Rob H

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));

1日当たりのミリ秒数は(サマータイムとうるう秒のせいで)常に同じというわけではありませんが、非常に近い値であり、少なくともサマータイムによる偏差は長期間にわたって相殺されます。したがって、分割してから四捨五入すると正しい結果が得られます(少なくとも使用されるローカルカレンダにDSTとうるう秒以外の奇妙な時間のジャンプが含まれていない限り)。

これはまだdate1date2が同じ時刻に設定されていると仮定していることに注意してください。 Jon Skeetが指摘したように、異なる時間帯では、まず「日付の違い」が何を意味するのかを定義する必要があります。

8
sleske

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
user674158

「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;
}
5
Ingo
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";
    }
}   
4
Parth Solanki

ここで例を確認してください 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.");
    }
}
4
YoK

コードの後に​​は、あなたに所望の出力を与えることができます:

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());
4
Vishal Ganjare

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));
4
Michal
int daysDiff = (date1.getTime() - date2.getTime()) / MILLIS_PER_DAY;
3
Bozho

注:startDateとendDatesは - > Java.util.Dateです。

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

日と同様に、時間、分、秒も取得できます。

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

一番やることは

(Date1-Date2)/86 400 000 

その数は、1日の ミリ秒 の数です。

ある日付と他の日付との差はミリ秒単位です。

答えを double 変数にまとめます。

3
Revanth Kumar

最初の質問に答えるだけです:

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

他のすべての答えを調べて、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;
}
2
gene b.

質問は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
VasiliNovikov

標準のAPIを使用していません。あなたはこのようなことをしてあなた自身を転がすことができます:

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

または Joda :を使用できます。

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

これはおそらくそれを行うための最も直接的な方法です - おそらく私はJavaでコーディングしてきたので(明らかにぎこちない日付と時刻のライブラリで)、そのコードは私には "シンプルでいい"と思われます!

結果がミリ秒単位で返されることに満足していますか、それとも他の形式で返されることを希望するという質問の一部ですか?

2
Andrzej Doyle

これは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
suxumuxu

この質問に対する多くの答えとコメントを読んだ後、私は人がJoda時間を使うか、あるいは夏時間などの特殊性を考慮に入れなければならないという印象を残しました。これらのことから、日付や時間に関連するJavaクラスを使用せずに2つの日付の差を計算するためのコードを数行書くことになりました。

以下のコードでは、年、月、日の数字は実際のものと同じです。たとえば、2015年12月24日の場合、年は2015、月は12、日は24です。

他の誰かがそれを使用したい場合に備えて、私はこのコードを共有したいと思います。 3つの方法があります:1)与えられた年がうるう年かどうかを調べる方法2)与えられた年の1月1日に関連して与えられた日の数を計算する方法3)方法2を使用して任意の2つの日付の間の日数(終了日の数から開始日の数を引いた数)。

方法は次のとおりです。

1)

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)

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)

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

以前のバージョンのJavaを試すことができます。

 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+"";
    }
1
Kumar Abhishek

Scalaを使っているので、とても良いScalaライブラリ Lamma があります。 Lammaでは-演算子を使って日付を直接マイナスにすることができます

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
1
Max

これを試して:

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

parse()メソッドのパラメータで文字列を編集できます。

1
sabbibJAVA

ただ2つのDateオブジェクトでbelowメソッドを使用してください。現在の日付を渡したい場合は、現在の時刻で初期化されるので、new Date()を2番目のパラメータとして渡します。

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";
     }
}

また、日数とは別に、他のパラメータの違いも必要な場合は、以下のスニペットを使用してください。

int year = delta / 365;
int rest = delta % 365;
int month = rest / 30;
rest = rest % 30;
int weeks = rest / 7;
int days = rest % 7;

P.Sコードは完全にSO回答から取られています。

1
Shubham A.

Javaでこれを行う簡単な方法があります

//ユーティリティメソッドを作成します

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

このメソッドは、2つの日付の間の日数を返します。デフォルトのJava日付フォーマットを使用することも、任意の日付フォーマットから簡単に変換することもできます。

0
Vishal Kumar

我々がこれを達成することができる多くの方法があるので、以下は一つの解決策です:

  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));
0
kundan bora

これは別のサンプルです。これは基本的にユーザー定義のパターンに対して機能します。

   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;        
   }
0
The N..

TimeUnitベースのアプローチは、1つのタイムユニットの次の上位ユニットに含まれるユニットの数が決まっているという些細なケースだけをカバーすることがわかったまでは気に入らなかった。何ヶ月、何年などの間にあるかを知りたいときには、これはバラバラになります。

これは、数え切れないほどのアプローチで、他の人ほど効率的ではありませんが、私にとってはうまくいくようで、DSTも考慮に入れています。

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;
}
0
Ralf H

fix にしたい日付範囲の問題が 夏時間と夏時間の境界を交差させる の場合(例:夏時間と冬時間) 日数の差

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);
}
0
Fabi
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();
    }

}

これは同じ日の日付差分も与えます

0
spysr

もう1つの純粋な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;
}

こちらのスターターコードのおかげで: https://stackoverflow.com/a/30207726/2162226

0
Gene Bo

@ Michael Borgwardtの答えは、Androidでは実際には正しく機能しません。丸め誤差があります。例5月19日から21日は、1.99から1をキャストするため、1日と表示されます。intにキャストする前にroundを使用します。

修正する

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

これはUTCの日付で機能することに注意してください。そのため、現地の日付を見ると違いは休日かもしれません。現地の日付で正しく機能するようにするには、夏時間のためにまったく異なるアプローチが必要です。

0