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


433

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

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

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


10
なぜジョーダの時間への愛がないのですか?これは、Javaで日付を処理する場合に最適です。
ジョーンズ博士、

7
私のエレガントな2ライナーソリューションを確認してください。Jodaを使用せず、結果を任意のTimeUnitでstackoverflow.com/a/10650881/82609
Sebastien Lorber 2013

2
Jodaの

2
@ Zizouz212 Joda-Timeの推奨に関して、Javaにバンドルされている古い日時クラスは、悪い、本当の悪い、設計が不十分、混乱し、面倒です。Joda-Timeが後継製品として大成功を収めたほど、非常に悪いものでした。Sun / Oracleでさえあきらめて、Java 8以降の一部としてjava.timeパッケージを採用したほど悪い。java.timeクラスは、Joda-Timeに触発されています。Joda-Timeとjava.timeはどちらも同じ人物、Stephen Colbourneが率いています。私はこう言いますDateCalendar, and SimpleDateFormat”.
Basil Bourque

2
Joda Timeはおそらく質問されたときの良い答えでしたが、今日、Java 8を使用できるすべての人にとって最良の答えは、java.time.Periodまたはを使用することDurationです。下記のバジルブルクの回答を参照してください。
Ole VV

回答:


198

Date残念ながら、JDK APIはひどく壊れています。Joda Timeライブラリの使用をお勧めします

Joda Timeには時間間隔の概念があります。

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

EDIT:ところで、Jodaのは、二つの概念を持っている:Interval2つの時刻(午前8時と10時との間の時間を表す)、およびAとの間の時間間隔を表しますDuration、実際の時間境界のない時間の長さを表す(たとえば2時間を表す!)

時間の比較のみに関心がある場合、ほとんどのDate実装(JDKを含む)Comparableは、Comparable.compareTo()


ところで-そうではComparable.compareTo()ありませんComparable.compare()
スコットモリソン、

Joda-Timeには、時間間隔をさまざまな方法で表現するための3つのクラス(間隔、期間、および期間)があります。この正解は、この最初の2つについて説明しています。期間に関する情報については、私の回答を参照しください。
バジルブルク2014年

Java 8にはjodaのような新しい日時APIがあります。
tbodt 2014年

11
java.timeJava 8 の新しいパッケージはJoda-Timeに触発されたもので、ドロップインの代替品ではありません。それぞれに長所と短所があります。幸いなことに、それらを選択する必要はありません。自分のimport発言に注意を払っている限り、それぞれをその長所として使用してください。java.timeの例については、この別の回答を参照してください。
バジルブルク2014年

6
FYI、ジョダタイムプロジェクトは、今でメンテナンスモードへの移行を助言チームと、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);

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

TimeUnitjava.util.concurrent.TimeUnit、標準の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時間の経過時間の数を数えます:day + 1-day = 1 day = 24h

  • 夏時間を考慮して、経過時間の数をカウントします。day+ 1-day = 1 = 24h(ただし、午前0時と夏時間を使用すると、0日と23hになる場合があります)

  • の数をカウントしますday switches。これは、経過時間が2時間(夏時間がある場合は1時間)であっても、day + 1 1pm-day 11am = 1日を意味します:p)

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

JodaTimeを使用

JodaTimeを使用している場合は、次のコマンドで2つのインスタント(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()

うわー、あなたは本当に老犬に新しいトリックを教えることができます!これまで聞いたことがなく、日付の違いを意味のある文字列に変換するのに非常に役立ちます。
Jeremy Goodell 14

@SebastienLorber TimeUnitには、このように差を計算する方法がありますか?「アラームは3日後、4時間後、12分後に設定されます」。
likejudo 2014

素晴らしいものは本当に私の時間の多くを節約しました。あなたの助けに感謝。
Lyju I Edwinson 2014

私は、Java Datesを扱う私の人生の3日間を無駄にしました、そして、私はそれの多くを捨てて、これで置き換えました。ありがとうございました。
user1091524

これは私がstackoverflowに来て以来見た最高の答えです!:D:D:D
コールド

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

これはUTC日付で機能するため、現地の日付を見ると差が1日でなくなる場合があることに注意してください。また、現地の日付で正しく機能させるには、夏時間のため、まったく異なるアプローチが必要です。


6
これは実際にはAndroidでは正しく機能しません。丸め誤差があります。例5月19日から21日は1.99から1をキャストするため、1日と表示されます。intにキャストする前にラウンドを使用します。
Pratik Mandrekar 2013年

4
これが最良かつ最も簡単な答えです。2つの日付の差を計算するとき、ローカルタイムゾーンは互いに減算します。そのため、((double)(newer.getTime()-older.getTime())/ (86400.0 * 1000.0); ... doubleとして、HH:MM:ssに簡単に変換できる小数日もあります
。– scottb

8
@scottb:ローカル日付の問題は、夏時間を使用できることです。つまり、一部の日は23時間または25時間あり、結果を台無しにする可能性があります。
Michael Borgwardt 2013年

1
@Steve:この新しいDate(115、2、26)のように定義すると、28になります。(パラメータのAPIドキュメントに注意してください)。2015年3月26日が2015年の26か月目の3日目と解釈されるように、米国の日付形式と寛大なモードでそれらを解析している可能性はありますか?
Michael Borgwardt 2015

1
@Steve:ええと、なぜ以前に別の結果を得たのかはわかりませんが、今あなたのエラーを再現できます。あなたのコードの中かっこは私の答えとは異なり、最終的な結果の代わりに(endDate.getTime() - startDate.getTime())キャストされint、整数のオーバーフローが発生します。
Michael Borgwardt 2015

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

問題をより明確に定義する必要があります。たとえば、2つのオブジェクト間のミリ秒数を取得し、24時間のミリ秒数で除算することもできDateますが、たとえば次のようになります。

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

1
java.utilだと思った。Dateは、ローカル(デフォルト)タイムゾーンで解釈される、タイムミリ表現の小さなラッパーでした。日付を出力すると、ローカルのタイムゾーン表現が表示されます。ここで混乱していますか?
Adriaan Koster、2010

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は、時間のスパンの簡潔なテキスト表現を、年、月、日、時間などの数として定義します。標準では、そのようなスパンを持続時間と呼びます。形式はPnYnMnDTnHnMnSP「期間」を意味Tし、日付部分と時間部分を分離し、その間に数字の後に文字が続きます。

例:

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

java.time

java.timeのフレームワークは、Java 8に組み込まれており、後で面倒な古い取って代わるjava.util.Date/ java.util.Calendarクラスを。新しいクラスは非常に成功したJoda-Timeフレームワークに触発されたもので、後継として意図されており、概念は似ていますが再構築されています。JSR 310で定義されています。ThreeTen-Extraプロジェクトによって拡張されました。チュートリアルを見る

瞬間

このInstantクラスは、ナノ秒の分解能(小数点以下9桁まで)でUTCのタイムライン上の瞬間を表します。

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

Date/ などのレガシークラスを避けるのが最善Calendarです。ただし、java.timeにまだ更新されていない古いコードと相互運用する必要がある場合は、前後に変換してください。古いクラスに追加された新しい変換メソッドを呼び出します。a java.util.Dateからに移動するにはInstant、を呼び出します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 );

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

との両方ともPeriod、それらの値の文字列表現を生成するためにISO 8601標準をDuration使用します。

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

ジョダタイム今ではプロジェクト、メンテナンスモード、java.timeへの移行をアドバイスします。

詳細については、Oracleチュートリアルを参照してください。スタックオーバーフローで多くの例と説明を検索してください。仕様は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にバックポートされています。
  • アンドロイド
    • ThreeTenABPのプロジェクトは、適応ThreeTen、バックポートを、特にAndroidのための(上記の)。
    • 使い方…をご覧ください。

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時間単位でタイムスタンプを取得する方法ではなく、2つの日付間の差分を取得する方法です。それでおしまい。
バッファロー

@バッファローコメントが理解できません。私の回答には、、、およびの3つのクラスが含まれPeriod、その目的は、時点間のデルタを決定することです。私の「テキストの壁」のどの部分が無関係であるかを示してください。そして、質問は「日付間のデルタ」を要求したと言うのは正しくありません。質問は、そのクラスの不運な命名にもかかわらず、「日付」ではなく、日時の瞬間であるオブジェクト間のデルタを要求しました。DurationChronoUnitDate
バジルブルク

2つの既存のjava.util.Dateオブジェクトを処理するコメントはありません。コードでさまざまなスニペットを使用してみましたが、java.util.Dateオブジェクトを使用するものは何も見つかりませんでした。
バッファロー

@バッファローフェアは十分、良い批判。「tl; dr」セクションにa java.util.Dateからanに変換するコードを追加しましたInstant(を呼び出すだけです.toInstant)。そしてMoment、説明するセクションを追加しました。Dateオブジェクトのペアについて言及しましたが、実際には質問は既存のDateオブジェクトを1つだけ使用してから現在の瞬間をキャプチャしているので、同じことを行いました。フィードバックをお寄せいただきありがとうございます!ヒント:使用をあきらめるDate–これらのレガシークラスは本当にひどい惨めな混乱です。
バジルブルク2018年


23

もう少し簡単な方法:

System.currentTimeMillis() - oldDate.getTime()

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


22

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

たとえば、2つの日付03/24/2007と03/25/2007の差が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年である3番目の文を信用していただけますか
wchargin 2012年

少し効果がないのでは?
Gangnus 2013年

正常に動作しません。daysBetween(new GregorianCalendar(2014,03,01)、new GregorianCalendar(2014,04,02))); 31を返し、32を返します。timeanddate.com
date

5
@marcolopes-間違いです-暦月はゼロベースです。きっと3月/ 4月を意味していると思いますが、テストしているのは4月/ 6月の31です。安全のために-> new GregorianCalendar(2014、Calendar.MARCH、1)....
イロおじさん

@UncleIroh、あなたは正しい!その重要な事実を見逃しました(暦月はゼロベースです)。私はこの質問をもう一度見直しなければなりません。
marcolopes 14年

22

日付と時刻の違いを見つける方法はたくさんあります。私が知っている最も簡単な方法の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);

印刷ステートメントは一例にすぎません。好きなようにフォーマットできます。


5
@ manoj kumar bardhan:スタックオーバーフローへようこそ:ご覧のとおり、質問と回答は何年も前のものです。あなたの答えは、既存の質問/回答よりも質問/回答に追加する必要があります。
Jayan

3
DSTの移行のために23時間または25時間かかる日はどうですか?
ジョニ

19

ここでのすべての答えは正しいですが、レガシー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 );

9

ミリ秒単位の日付の減算は機能しますが(別の投稿で説明されています)、日付の時間部分をクリアするときは、HOURではなくHOUR_OF_DAYを使用する必要あります。

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
これは、標準ライブラリの外に出ることなく、2つのカレンダー日付の違いを判断するための最良の方法です。他のほとんどの回答では、1日を任意の24時間として扱います。うるう秒が加算されるのではなく差し引かれる場合、絶対差はMSPERDAYの倍数の整数よりわずかに小さくなる可能性があるため、切り捨てが原因で最終計算が1つずれる可能性があります。
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));

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

ただし、これは同じことdate1を前提としておりdate2、同じ時刻に設定されていることに注意してください。ジョンスキートが指摘したように、さまざまな時間帯について、最初に「日付の違い」の意味を定義する必要があります。


問題はdate1.getTime()vsにありdate2.getTime()ます。したがって、2016-03-03と2016-03-31を比較すると、27日が計算されますが、28日が必要です。
マラット

@malat:すみません、私はついていけません。私は試してみました-私のコードで2016-03-03と2016-03-31を比較すると28日間計算されます。それがあなたの例で何か他のものを計算するならば、それを別の質問として尋ねることを検討してください。
sleske 2018年

また、私の警告を読みましたか?「これはまだ、date1とdate2が同じ時刻に設定されていることを前提としています」。テストで1日のうちの異なる時間を使用しましたか?
sleske

ああそう!Math.round()「現実の世界」のカレンダーでは安全に思えるでトリックを逃しました。騒音でごめんなさい。
マラット

8

Joda Timeを見てください。これは、Java用の改良された日付/時刻APIであり、Scalaで正常に動作するはずです。


Java 8でjava.time(JSR-310)に置き換えられました
マラート

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行のコードしか必要ないのに、圧縮されたFileSizeが4.1 MBのライブラリをダウンロードしてプロジェクトに追加する必要があるのはなぜですか?
Ingo

1
Joda-Timeはポテトチップスのようなものです。1つだけを食べることはできません。どこでもJoda-Timeを使用します。そして、Joda-Timeは十分にテストされ、使い古されたコードであるためです。また、Joda-Timeはこれらの値のシリアル化またはレポートに便利な標準ISO 8601期間文字列を解析および生成するためです。また、Joda-Timeには、これらの値のローカライズされた表現を印刷するフォーマッターが含まれているためです。
バジルブルク2014

すべてのコードがテストされるわけではありません。std上記は未定義です。
バジルブルク14

@Basil Bourque:ヒントのThx。ソースを収集しました。このエラーは、英語への翻訳が原因です。
Ingo

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タイムゾーンを使用してカレンダーのインスタンスを取得し、カレンダークラスの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などのコンテキストでは良い答えです。ハックを使用してタイムゾーンをGMTに設定すると、コードは夏時間の影響を受けにくくなります。
Meno Hochschild、2016

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、

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。そのため、この比較は状況を考慮して達成できる最高のものです。
Bozho

1
OK、私たち両方が正しいと思います。それは、Dateインスタンスがどこから来たかに依存するのは事実です。それでも、言及する必要があるのはよくある間違いです。
sleske 2010

私があなたの解決策を使うとき、それは言います:型の不一致:longからintに変換できません。キャストも追加する必要があると思いますか、それとも何か不足していますか?
Ad Infininitum

3

やるべきことは

(Date1-Date2)/86 400 000 

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

ある日付と別の日付では、ミリ秒単位で差が出ます。

答えをdouble変数に収集します。


はい、なぜですか?質問のポイントがいくつかの点で理解できません:OPにはmsの違いがあります...そして、1日に一定のmsがあります(青い月に一度特定の天文学的調整でOKですが、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の日付タイプを維持しながら、Java 8の差分アプローチでより正確/標準になるようにするには、

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()メソッドのパラメーターで文字列を編集できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.