Java 8:複数の単位での2つのLocalDateTimeの違い


266

2つの差を計算しようとしていますLocalDateTime

出力は次の形式である必要がありますy years m months d days h hours m minutes s seconds。これが私が書いたものです:

import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.ZoneId;

public class Main {

    static final int MINUTES_PER_HOUR = 60;
    static final int SECONDS_PER_MINUTE = 60;
    static final int SECONDS_PER_HOUR = SECONDS_PER_MINUTE * MINUTES_PER_HOUR;

    public static void main(String[] args) {
        LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 9, 19, 46, 45);
        LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);

        Period period = getPeriod(fromDateTime, toDateTime);
        long time[] = getTime(fromDateTime, toDateTime);

        System.out.println(period.getYears() + " years " + 
                period.getMonths() + " months " + 
                period.getDays() + " days " +
                time[0] + " hours " +
                time[1] + " minutes " +
                time[2] + " seconds.");


    }

    private static Period getPeriod(LocalDateTime dob, LocalDateTime now) {
        return Period.between(dob.toLocalDate(), now.toLocalDate());
    }

    private static long[] getTime(LocalDateTime dob, LocalDateTime now) {
        LocalDateTime today = LocalDateTime.of(now.getYear(),
                now.getMonthValue(), now.getDayOfMonth(), dob.getHour(), dob.getMinute(), dob.getSecond());
        Duration duration = Duration.between(today, now);

        long seconds = duration.getSeconds();

        long hours = seconds / SECONDS_PER_HOUR;
        long minutes = ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
        long secs = (seconds % SECONDS_PER_MINUTE);

        return new long[]{hours, minutes, secs};
    }
}

私が得ている出力は29 years 8 months 24 days 12 hours 0 minutes 50 secondsです。このWebサイトからの結果を確認しました(値12/16/1984 07:45:55とを使用09/09/2014 19:46:45)。次のスクリーンショットは出力を示しています。

エポックコンバーター

私は、月の値の後のフィールドが私のコードから間違っていることをかなり確信しています。どんな提案も非常に役に立ちます。

更新

別のウェブサイトから結果をテストしましたが、得られた結果は異なります。ここにある:2つの日付の間の計算期間(29年、8ヶ月、24日、12時間、0分50秒の結果)。

更新

2つの異なるサイトから2つの異なる結果を得たので、私の計算のアルゴリズムが正当かどうか疑問に思っています。次の2つのLocalDateTimeオブジェクトを使用する場合:

LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 40, 45);
LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);

次に、出力が来ています: 29 years 8 months 25 days -1 hours -5 minutes -10 seconds.

このリンクからそれはあるはずです29 years 8 months 24 days 22 hours, 54 minutes and 50 seconds。したがって、アルゴリズムは負の数も処理する必要があります。

問題は、どのサイトからどのような結果が得られたのかではなく、正しいアルゴリズムを知り、正しい結果を得る必要があることに注意してください。


単なる推測ですが、Period.between()いくつかの丸めを適用する可能性がありますか?
Thomas

3
コードをもう一度見たところ、ウェブサイトが間違っているようです(自分で計算してみてください)。年、月、日の違いなど、日付を省略すると、開始時刻7:45:55と終了時刻19:46:45(または7:46:45PM)が表示されます。したがって、これら2つの時間の差は12時間0分50秒であり、 23時間34分12秒になることはありません。したがって、少なくとも時間の部分では、計算の実際は正しいようです。
トーマス

1
そのWebサイトの興味深い現象:開始日に10年を追加すると、時間の差が23から8に変わります-確かにバグの兆候です。
トーマス

8
LocalDateTimeはタイムゾーンがないため、一意の答えがない可能性があることに注意してください。開始と終了のタイムゾーンが同じであると想定した場合でも、2014-09-09のような特定のゾーンの日付は夏時間または夏時間になり、他の日付はそうなりません。これにより、1時間遅れることがあります。したがって、2番目の差を計算しても、これを解決しない限り意味がありません。
スチュアートマークス

2
LocalDateTimeこのクラスは意図的にタイムゾーンやUTCからのオフセットの概念を欠いているため、使用すると非現実的な結果が得られることを理解していますか?現実的な値を得るには、を使用してタイムゾーンを割り当てZoneIdますZonedDateTime
バジルブルク2017年

回答:


163

残念ながら、時間にまたがる期間クラスはないようなので、計算は自分で行う必要があるかもしれません。

幸い、日付と時刻のクラスには、それをある程度簡略化するユーティリティメソッドがたくさんあります。違いを計算する方法は次のとおりですが、必ずしも最速とは限りません。

LocalDateTime fromDateTime = LocalDateTime.of(1984, 12, 16, 7, 45, 55);
LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 40, 45);

LocalDateTime tempDateTime = LocalDateTime.from( fromDateTime );

long years = tempDateTime.until( toDateTime, ChronoUnit.YEARS );
tempDateTime = tempDateTime.plusYears( years );

long months = tempDateTime.until( toDateTime, ChronoUnit.MONTHS );
tempDateTime = tempDateTime.plusMonths( months );

long days = tempDateTime.until( toDateTime, ChronoUnit.DAYS );
tempDateTime = tempDateTime.plusDays( days );


long hours = tempDateTime.until( toDateTime, ChronoUnit.HOURS );
tempDateTime = tempDateTime.plusHours( hours );

long minutes = tempDateTime.until( toDateTime, ChronoUnit.MINUTES );
tempDateTime = tempDateTime.plusMinutes( minutes );

long seconds = tempDateTime.until( toDateTime, ChronoUnit.SECONDS );

System.out.println( years + " years " + 
        months + " months " + 
        days + " days " +
        hours + " hours " +
        minutes + " minutes " +
        seconds + " seconds.");

//prints: 29 years 8 months 24 days 22 hours 54 minutes 50 seconds.

基本的な考え方は次のとおりです。一時的な開始日を作成し、完全な年を最後まで取得します。次に、その日付を年数で調整して、開始日が終了日から1年未満になるようにします。時間単位ごとに降順で繰り返します。

最後に免責事項:私は異なるタイムゾーンを考慮に入れていません(両方の日付が同じタイムゾーンでなければなりません)。また、夏時間やカレンダーの他の変更(Samoaのタイムゾーンの変更など)のテストや確認もしていません。この計算に影響します。慎重に使用してください。


1
あなたは同じ基本的な考え方を持っているので、私の賛成票ですが、同じ入力を使用してみてください。そうしないと、異なる結果が混乱します。
Meno Hochschild、2014

@MenoHochschildこれ同じ入力であり、OPに負の時間に関する問題がある更新から取得したものです。;)
Thomas

1
アルゴリズムは適切ですが、型が間違っています(Thomasの免責事項を参照)。計算を行う前に、たとえばデフォルトのタイムゾーン(または必要な任意のタイムゾーン)を使用してLocalDateTime変数をZonedDateTimeに変換する必要があります。ZonedDateTime fromZonedDateTime = fromDateTime.atZone(ZoneId.systemDefault());
トリスタン

2
@Thomasあなたの例はJava 8も使用しています-質問はjava-8としてタグ付けされています。実際、あなたの例ではChronoUnit:) を使用していますが、「手作業」で仕事をしています。
Eugene Beresovsky

3
@EugeneBeresovskyああそうです、あなたは正しいです。完全にそれを逃しました;)-それ以外に、たとえばlong minutes = ChronoUnit.MINUTES.between(fromDate, toDate);、少なくとも1時間の間隔で59より大きい数値を返すため、間隔からより大きな単位を減算する必要があります。これはOPが望んでいることではありません。それを考慮に入れると、6回の呼び出しをChronoUnit#between()行って完了できません。
Thomas

503

これを行う最善の方法は、ChronoUnitを使用することです。

long minutes = ChronoUnit.MINUTES.between(fromDate, toDate);
long hours = ChronoUnit.HOURS.between(fromDate, toDate);

追加のドキュメントはこちら:https : //docs.oracle.com/javase/tutorial/datetime/iso/period.html


8
実際の改善は見られません。単に置き換えるあなた受け入れトーマスの答えと比較しtempDateTime.until( toDateTime, ChronoUnit.YEARS)ChronoUnit.YEARS.between(fromDate, toDate)。しかし、その他の重要な追加行tempDateTime.plusYears( years )は回答に完全に含まれていないため、OPには役立ちません。完全なアルゴリズムが重要です!
Meno Hochschild、2015年

9
より簡潔で、読みやすくなるので、私はこれが好きです。これは、2つの日付の違いを見つける最良の方法です。
Somaiah Kumbera 2016年

7
@SomaiahKumbera重要なポイントを完全に逃してはいけません。OPは1つのユニットだけではなく複数のユニット期間を必要としないため、この回答は実際の回答ではありません。OPの懸念には対処していません。質問をもう一度読んでください。(多くの賛成者が質問を誤解しているようです)。
Meno Hochschild、2016年

125
@MenoHochschild、私はあなたが実際に重要なポイントを逃している人だと思います。OPは1年以上前に回答を得ました。この質問を閲覧している36千人は、OPの特定の質問を気にしません。彼らはここでグーグルによってリードされ、私の答えは彼らが探していたものを提供しました-2つの日付の違いを取得するためのクリーンでシンプルな解決策。
satnam

10
2つの日付時刻の秒差が必要で、独自のソリューションの実装を開始しました。まもなくそれは複雑に思われ、私はグーグルを引き受けました。satnam answerはOPの質問には答えないかもしれませんが、確かに私を大いに助け、私は私のような他の多くの人に賭けます。
ジュリアン、

43

以下は、DurationとTimeUnitを使用して「hh:mm:ss」形式を取得する1つの例です。

Duration dur = Duration.between(localDateTimeIni, localDateTimeEnd);
long millis = dur.toMillis();

String.format("%02d:%02d:%02d", 
        TimeUnit.MILLISECONDS.toHours(millis),
        TimeUnit.MILLISECONDS.toMinutes(millis) - 
        TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)),
        TimeUnit.MILLISECONDS.toSeconds(millis) - 
        TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis)));

2
実際には次のようにすることができますString.format("%02d:%02d:%02d",dur.toHoursPart(), dur.toMinutesPart(), dur.toSecondsPart());。partメソッドは、文字列を作成するための適切な数値を提供します。もっと読みやすいと思います。
Daantie

以前のコメントの補足:パーツメソッドはJDK 9以降でのみ使用できます。
Daantie

40

それはもっと簡単なはずです!

Duration.between(startLocalDateTime, endLocalDateTime).toMillis();

1
これは実際にはJava 8以降の意味的に正しいソリューションだと思います。そのバージョンの前は、JodaTimeでも同じことが行われています。
Vrakfall

9

TL; DR

Duration duration = Duration.between(start, end);
duration = duration.minusDays(duration.toDaysPart()); // essentially "duration (mod 1 day)"
Period period = Period.between(start.toLocalDate(), end.toLocalDate());

その後、メソッドを使用してperiod.getYears()period.getMonths()period.getDays()duration.toHoursPart()duration.toMinutesPart()duration.toSecondsPart()


拡大された答え

元の質問に答えます。つまりLocalDateTimes、年、月、日、時、分の2つの時間差を取得して、異なる単位のすべての値の「合計」(下記の注を参照)が合計と等しくなるようにします。時間差、及び各ユニットの値は大きく次ユニット-IEよりも小さくなるようにminutes < 60hours < 24など。

2つとを指定するLocalDateTimes startend、たとえば

LocalDateTime start = LocalDateTime.of(2019, 11, 29, 17, 15);
LocalDateTime end = LocalDateTime.of(2020, 11, 30, 18, 44);

我々は2つの間の絶対タイムスパンを表すことができDuration-perhapsを使用しますDuration.between(start, end)。ただし、抽出できる最大の単位Durationは日数です(24時間に相当する時間単位として)。説明については、下記の注を参照してください。より大きな単位(月、年)を使用するには、これDurationを(PeriodDuration)のペアで表すことができます。ここで、Periodメジャーは差を日数の精度まで測定し、Durationは残りを表します。

Duration duration = Duration.between(start, end);
duration = duration.minusDays(duration.toDaysPart()); // essentially "duration (mod 1 day)"
Period period = Period.between(start.toLocalDate(), end.toLocalDate());

今、私たちは、単純に定義されたメソッドを使用することができますPeriodし、Duration個々のユニットを抽出します:

System.out.printf("%d years, %d months, %d days, %d hours, %d minutes, %d seconds",
        period.getYears(), period.getMonths(), period.getDays(), duration.toHoursPart(),
        duration.toMinutesPart(), duration.toSecondsPart());
1 years, 0 months, 1 days, 1 hours, 29 minutes, 0 seconds

または、デフォルトのフォーマットを使用します:

System.out.println(period + " + " + duration);
P1Y1D + PT1H29M

年、月、日に関する注記

java.timeの概念では、次の例に示すように、「月」や「年」などの「単位」は固定の絶対時間値を表すのではなく、日付とカレンダーに依存することに注意してください。

LocalDateTime
        start1 = LocalDateTime.of(2020, 1, 1, 0, 0),
        end1 = LocalDateTime.of(2021, 1, 1, 0, 0),
        start2 = LocalDateTime.of(2021, 1, 1, 0, 0),
        end2 = LocalDateTime.of(2022, 1, 1, 0, 0);
System.out.println(Period.between(start1.toLocalDate(), end1.toLocalDate()));
System.out.println(Duration.between(start1, end1).toDays());
System.out.println(Period.between(start2.toLocalDate(), end2.toLocalDate()));
System.out.println(Duration.between(start2, end2).toDays());
P1Y
366
P1Y
365

5

Tapas BoseコードとThomasコードにはいくつかの問題があります。時間差が負の場合、配列は負の値を取得します。たとえば

LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 46, 45);
LocalDateTime fromDateTime = LocalDateTime.of(2014, 9, 9, 7, 46, 45);

0年0月1日-1時間0分0秒を返します。

私は正しい出力は次のとおりだと思います:0年0ヶ月0日23時間0分0秒。

LocalDateインスタンスとLocalTimeインスタンスでLocalDateTimeインスタンスを分離することを提案します。その後、Java 8 PeriodおよびDurationインスタンスを取得できます。Durationインスタンスは、日数と終日の時間値(<24時間)で区切られ、その後に期間値が修正されます。2番目のLocalTime値がfirstLocalTime値の前にある場合、1日の期間を短縮する必要があります。

LocalDateTimeの差を計算する私の方法は次のとおりです。

private void getChronoUnitForSecondAfterFirst(LocalDateTime firstLocalDateTime, LocalDateTime secondLocalDateTime, long[] chronoUnits) {
    /*Separate LocaldateTime on LocalDate and LocalTime*/
    LocalDate firstLocalDate = firstLocalDateTime.toLocalDate();
    LocalTime firstLocalTime = firstLocalDateTime.toLocalTime();

    LocalDate secondLocalDate = secondLocalDateTime.toLocalDate();
    LocalTime secondLocalTime = secondLocalDateTime.toLocalTime();

    /*Calculate the time difference*/
    Duration duration = Duration.between(firstLocalDateTime, secondLocalDateTime);
    long durationDays = duration.toDays();
    Duration throughoutTheDayDuration = duration.minusDays(durationDays);
    Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO,
            "Duration is: " + duration + " this is " + durationDays
            + " days and " + throughoutTheDayDuration + " time.");

    Period period = Period.between(firstLocalDate, secondLocalDate);

    /*Correct the date difference*/
    if (secondLocalTime.isBefore(firstLocalTime)) {
        period = period.minusDays(1);
        Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO,
                "minus 1 day");
    }

    Logger.getLogger(PeriodDuration.class.getName()).log(Level.INFO,
            "Period between " + firstLocalDateTime + " and "
            + secondLocalDateTime + " is: " + period + " and duration is: "
            + throughoutTheDayDuration
            + "\n-----------------------------------------------------------------");

    /*Calculate chrono unit values and  write it in array*/
    chronoUnits[0] = period.getYears();
    chronoUnits[1] = period.getMonths();
    chronoUnits[2] = period.getDays();
    chronoUnits[3] = throughoutTheDayDuration.toHours();
    chronoUnits[4] = throughoutTheDayDuration.toMinutes() % 60;
    chronoUnits[5] = throughoutTheDayDuration.getSeconds() % 60;
}

上記の方法を使用して、ローカルの日付と時刻の値の差を計算できます。次に例を示します。

public long[] getChronoUnits(String firstLocalDateTimeString, String secondLocalDateTimeString) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    LocalDateTime firstLocalDateTime = LocalDateTime.parse(firstLocalDateTimeString, formatter);
    LocalDateTime secondLocalDateTime = LocalDateTime.parse(secondLocalDateTimeString, formatter);

    long[] chronoUnits = new long[6];
    if (secondLocalDateTime.isAfter(firstLocalDateTime)) {
        getChronoUnitForSecondAfterFirst(firstLocalDateTime, secondLocalDateTime, chronoUnits);
    } else {
        getChronoUnitForSecondAfterFirst(secondLocalDateTime, firstLocalDateTime, chronoUnits);
    }
    return chronoUnits;
}

上記のメソッドのユニットテストを作成すると便利です(どちらもPeriodDurationクラスメンバーです)。これがコードです:

@RunWith(Parameterized.class)
public class PeriodDurationTest {

private final String firstLocalDateTimeString;
private final String secondLocalDateTimeString;
private final long[] chronoUnits;

public PeriodDurationTest(String firstLocalDateTimeString, String secondLocalDateTimeString, long[] chronoUnits) {
    this.firstLocalDateTimeString = firstLocalDateTimeString;
    this.secondLocalDateTimeString = secondLocalDateTimeString;
    this.chronoUnits = chronoUnits;
}

@Parameters
public static Collection<Object[]> periodValues() {
    long[] chronoUnits0 = {0, 0, 0, 0, 0, 0};
    long[] chronoUnits1 = {0, 0, 0, 1, 0, 0};
    long[] chronoUnits2 = {0, 0, 0, 23, 0, 0};
    long[] chronoUnits3 = {0, 0, 0, 1, 0, 0};
    long[] chronoUnits4 = {0, 0, 0, 23, 0, 0};
    long[] chronoUnits5 = {0, 0, 1, 23, 0, 0};
    long[] chronoUnits6 = {29, 8, 24, 12, 0, 50};
    long[] chronoUnits7 = {29, 8, 24, 12, 0, 50};
    return Arrays.asList(new Object[][]{
        {"2015-09-09 21:46:44", "2015-09-09 21:46:44", chronoUnits0},
        {"2015-09-09 21:46:44", "2015-09-09 22:46:44", chronoUnits1},
        {"2015-09-09 21:46:44", "2015-09-10 20:46:44", chronoUnits2},
        {"2015-09-09 21:46:44", "2015-09-09 20:46:44", chronoUnits3},
        {"2015-09-10 20:46:44", "2015-09-09 21:46:44", chronoUnits4},
        {"2015-09-11 20:46:44", "2015-09-09 21:46:44", chronoUnits5},
        {"1984-12-16 07:45:55", "2014-09-09 19:46:45", chronoUnits6},
        {"2014-09-09 19:46:45", "1984-12-16 07:45:55", chronoUnits6}
    });
}

@Test
public void testGetChronoUnits() {
    PeriodDuration instance = new PeriodDuration();
    long[] expResult = this.chronoUnits;
    long[] result = instance.getChronoUnits(this.firstLocalDateTimeString, this.secondLocalDateTimeString);
    assertArrayEquals(expResult, result);
}

}

最初のLocalDateTimeの値がLocalTime値の前であるかどうかに関係なく、すべてのテストが成功します。


上記の入力を使用したThomasコードは混合符号を生成するというあなたの声明を再現できません。私の出力は、「0年0ヶ月0日23時間0分0秒」です。そして、私はたった今テストしました。
Meno Hochschild、2015年

コメントありがとうございます。Thomasコードを徹底的にテストしました。実際、正しく機能しています!マジックは、クロノユニットを修正するメソッドまでLocalDateTimeによって行われます。最初のDateTimeが2番目よりも遅い場合、Thomasコードの負の値が表示されます。しかし、たとえば上記のコードで行ったように、これは簡単に修正できます。再度、感謝します。
Gennady Kolomoets

さて、トーマスコードと私のライブラリTime4Jは、期間の計算に同じアルゴリズムを使用して負の符号を生成できますが、期間全体に対してのみです。それが決定的なポイントです!符号は期間全体に関係するため、開始が終了より遅く、単一の期間コンポーネントに決して関係しないかどうかを示します。ここでは混合標識は不可能であり、終了に対するこのような開始の解釈を妨げます(カウンターの例はJoda-Time-periodであるかjava.time.Period、または内部設計が異なるためにユーザーがこのような混合標識を実施/生成できる場所です)。
Meno Hochschild、2015年

5

また、Groovyでの@Thomasのバージョンは、値をハードコーディングする代わりに、リスト内の必要な単位を取ります。この実装(Javaに簡単に移植できる-関数宣言を明示的にした)により、Thomasのアプローチがより再利用可能になります。

def fromDateTime = LocalDateTime.of(1968, 6, 14, 0, 13, 0)
def toDateTime = LocalDateTime.now()
def listOfUnits = [
    ChronoUnit.YEARS, ChronoUnit.MONTHS, ChronoUnit.DAYS,
    ChronoUnit.HOURS, ChronoUnit.MINUTES, ChronoUnit.SECONDS,
    ChronoUnit.MILLIS]

println calcDurationInTextualForm(listOfUnits, fromDateTime, toDateTime)    

String calcDurationInTextualForm(List<ChronoUnit> listOfUnits, LocalDateTime ts, LocalDateTime to)
{
    def result = []

    listOfUnits.each { chronoUnit ->
        long amount = ts.until(to, chronoUnit)
        ts = ts.plus(amount, chronoUnit)

        if (amount) {
            result << "$amount ${chronoUnit.toString()}"
        }
    }

    result.join(', ')
}

この記事の執筆時点では、上記のコードはを返します47 Years, 8 Months, 9 Days, 22 Hours, 52 Minutes, 7 Seconds, 140 Millis。また、@ Gennady Kolomoets入力の場合、コードはを返します23 Hours

ユニットのリストを提供するときは、ユニットのサイズ(最大のものが最初)でソートする必要があります。

def listOfUnits = [ChronoUnit.WEEKS, ChronoUnit.DAYS, ChronoUnit.HOURS]
// returns 2495 Weeks, 3 Days, 8 Hours

4

ここにあなたの質問に対する非常に簡単な答えがあります。できます。

import java.time.*;
import java.util.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

public class MyClass {
public static void main(String args[]) {
    DateTimeFormatter T = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
    Scanner h = new Scanner(System.in);

    System.out.print("Enter date of birth[dd/mm/yyyy hh:mm]: ");
    String b = h.nextLine();

    LocalDateTime bd = LocalDateTime.parse(b,T);
    LocalDateTime cd = LocalDateTime.now();

    long minutes = ChronoUnit.MINUTES.between(bd, cd);
    long hours = ChronoUnit.HOURS.between(bd, cd);

    System.out.print("Age is: "+hours+ " hours, or " +minutes+ " minutes old");
}
}

1
これは正確ではありません。これで試してください。それは1分の違いを言います。LocalDateTime bd = LocalDateTime.of(2019、11、26、15、03、55); LocalDateTime cd = LocalDateTime.of(2019、11、26、15、04、45);
Mark Amabile

私は昨日の時間を入力してもらいましたAge is: 0 years,0 months, 1 days, -10 hours, -48 minutes old。これが望まれていたことではないと思います。
Ole VV

@ OleV.V。その問題を修正
SavedBeau

1

ジョーダタイム

回答の多くはAPI 26サポートを必要とし、私の最小APIは23だったので、以下のコードで解決しました:

import org.joda.time.Days

LocalDate startDate = Something
LocalDate endDate = Something
// The difference would be exclusive of both dates, 
// so in most of use cases we may need to increment it by 1
Days.daysBetween(startDate, endDate).days

1
ジョダタイムプロジェクトはメンテナンスモードになっている、その作成者スティーブンColebourneが作成する上で行ったjava.timeのほとんどのJSR 310で定義されているクラスをjava.timeの機能がでJava 6&7にバックポートされThreeTen-バックポートプロジェクト。ThreeTenABPプロジェクトの初期のAndroidにさらに適合。
バジルブルク

1

5年以上後、私は私の質問に答えます。負の期間の問題は簡単な修正で解決できると思います:

LocalDateTime fromDateTime = LocalDateTime.of(2014, 9, 9, 7, 46, 45);
LocalDateTime toDateTime = LocalDateTime.of(2014, 9, 10, 6, 46, 45);

Period period = Period.between(fromDateTime.toLocalDate(), toDateTime.toLocalDate());
Duration duration = Duration.between(fromDateTime.toLocalTime(), toDateTime.toLocalTime());

if (duration.isNegative()) {
    period = period.minusDays(1);
    duration = duration.plusDays(1);
}
long seconds = duration.getSeconds();
long hours = seconds / SECONDS_PER_HOUR;
long minutes = ((seconds % SECONDS_PER_HOUR) / SECONDS_PER_MINUTE);
long secs = (seconds % SECONDS_PER_MINUTE);
long time[] = {hours, minutes, secs};
System.out.println(period.getYears() + " years "
            + period.getMonths() + " months "
            + period.getDays() + " days "
            + time[0] + " hours "
            + time[1] + " minutes "
            + time[2] + " seconds.");

注:サイトhttps://www.epochconverter.com/date-differenceで、時差が正しく計算されるようになりました。

皆さんの議論と提案に感謝します。


答えてくれてありがとう。時間と小さいために、あなたが恩恵を受けることができるtoHourstoMinutestoSecondsの方法Duration。Java 9以降、toMinutesPart()およびからtoSecondsPart()。また、時間、分、秒を配列にラップして、それらを再び取り出すだけの意味はありません。しかし、一般的には良い答えです。
Ole VV

5年以上後、私は私の質問に答えます。別の名前、タイトル、場所のアカウントから質問が投稿されましたが、よく似ていないようです。それは重要ではない、ただ疑問に思います。
Ole VV

「5年以上経ってから私の質問に答えます」私はOPだったと思います:)
Tapas Bose
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.