Javaで2つの日付間の日数を計算する


150

2つの日付の間の日数を計算するJavaプログラムが必要です。

  1. 最初の日付を入力(ドイツ語表記、空白文字: "dd mm yyyy")
  2. 2番目の日付を入力します。
  3. プログラムは、2つの日付の間の日数を計算する必要があります。

うるう年と夏時間を含めるにはどうすればよいですか?

私のコード:

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

public class NewDateDifference {

    public static void main(String[] args) {

        System.out.print("Insert first date: ");
        Scanner s = new Scanner(System.in);
        String[] eingabe1 = new String[3];

        while (s.hasNext()) {
            int i = 0;
            insert1[i] = s.next();
            if (!s.hasNext()) {
                s.close();
                break;
            }
            i++;
        }

        System.out.print("Insert second date: ");
        Scanner t = new Scanner(System.in);
        String[] insert2 = new String[3];

        while (t.hasNext()) {
            int i = 0;
            insert2[i] = t.next();
            if (!t.hasNext()) {
                t.close();
                break;
            }
            i++;
        }

        Calendar cal = Calendar.getInstance();

        cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(insert1[0]));
        cal.set(Calendar.MONTH, Integer.parseInt(insert1[1]));
        cal.set(Calendar.YEAR, Integer.parseInt(insert1[2]));
        Date firstDate = cal.getTime();

        cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(insert2[0]));
        cal.set(Calendar.MONTH, Integer.parseInt(insert2[1]));
        cal.set(Calendar.YEAR, Integer.parseInt(insert2[2]));
        Date secondDate = cal.getTime();


        long diff = secondDate.getTime() - firstDate.getTime();

        System.out.println ("Days: " + diff / 1000 / 60 / 60 / 24);
    }
}

何が機能しないのですか?クラッシュしていますか?それはあなたに間違った数字を与えていますか?
jens108 2013年

配列の宣言はどこですか:insert1?
Rhys

1
insert1 =ドイツ語のeingabe1 :)
peter.petrov 2013年

@ peter.petrovああ、なるほど!
Rhys

私は彼が問題を抱えていると思うmmし、MMP:
セージ

回答:


229

更新:一部のクラスが置き換えられたため、2013年の元の回答は古くなっています。これを行う新しい方法は、新しいjava.timeクラスを使用することです。

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd MM yyyy");
String inputString1 = "23 01 1997";
String inputString2 = "27 04 1997";

try {
    LocalDateTime date1 = LocalDate.parse(inputString1, dtf);
    LocalDateTime date2 = LocalDate.parse(inputString2, dtf);
    long daysBetween = Duration.between(date1, date2).toDays();
    System.out.println ("Days: " + daysBetween);
} catch (ParseException e) {
    e.printStackTrace();
}

このソリューションでは、カレンダーの日数ではなく、実際の24時間の日数が得られることに注意してください。後者の場合は、

long daysBetween = ChronoUnit.DAYS.between(date1, date2)

元の回答(Java 8の時点で古くなっています)

必要のない文字列を使用していくつかの変換を行っています。SimpleDateFormatそれのためのクラスがあります-これを試してください:

SimpleDateFormat myFormat = new SimpleDateFormat("dd MM yyyy");
String inputString1 = "23 01 1997";
String inputString2 = "27 04 1997";

try {
    Date date1 = myFormat.parse(inputString1);
    Date date2 = myFormat.parse(inputString2);
    long diff = date2.getTime() - date1.getTime();
    System.out.println ("Days: " + TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS));
} catch (ParseException e) {
    e.printStackTrace();
}

編集:このコードの正確さに関していくつかの議論があったので、それは確かにうるう年を処理します。ただし、TimeUnit.DAYS.convertミリ秒が日に変換されるため、関数の精度が低下します(詳細については、リンクされたドキュメントを参照してください)。これが問題の場合は、diff手動で変換することもできます。

float days = (diff / (1000*60*60*24));

これはfloat値であり、必ずしもではないことに注意してくださいint


40
これはうるう年を適切に考慮しない悪い実装です。
Groovy Ed

3
TimeUnit.DAYS.convert(diff、TimeUnit.MILLISECONDS)); <3
Guihgo 2016年

3
@GroovyEd私がテストしたものから、このコードはうるう年には問題がないようです。TimeUnit.Days.convert()は残りの単位を無視することに注意してください。たとえば、999ミリ秒を秒に変換すると0になります。これは、Dateオブジェクトの1つとしてnew Date()を使用すると、1日少なくなる可能性があるため注意してください
Klitos G. 2016

3
うるう年にも有効です。このString inputString1 = "28 2 2016"; String inputString2 = "1 3 2016";ansを確認してください:2
Rohit Gaikwad

10
これはうるう年では正しく機能すると思いますが、夏時間をめちゃくちゃにします。ロケールに夏時間がある場合、毎年、1日が23時間、1日が25時間です。このソリューションでは、毎日24時間であると誤って想定しています。したがって、夏時間以外の期間に始まり、夏時間の間に終了する期間については、誤った答えを出します。このソリューションを使用しないでください-より良い方法があります。
Dawood ibnカリーム2017

100

最も簡単な方法:

public static long getDifferenceDays(Date d1, Date d2) {
    long diff = d2.getTime() - d1.getTime();
    return TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
}

7
まあ、これは基本的に現在のベストアンサーと同じですが、このアンサーは関数として提供します。
Andrew T.

16
これは、2つの日付の時間間隔が24時間よりも長い場合にのみカウントされることに注意してください(コードからは明らかです)。したがって、getDifferenceDays(11PM, 4 AM nextday) == 0
ReDetection

1
この実装には、今日と同様に最終日がかかります。私は、D1 =今日、とd2 =昨日、戻っ0日でプログラムを実行した場合たとえば、..
karvoynistas

1
@Navは、6月に30日あるためです。
Dawood ibnカリーム2017

1
この答えは間違っています。夏時間を正しく処理しません。正しい結果が必要な場合は使用しないでください。
Dawood ibnカリーム2017

89

Java 8では、LocalDateおよびを使用してこれを実現できますDateTimeFormatter。のJavadocからLocalDate

LocalDateは、日付を表す不変の日時オブジェクトであり、年月日と見なされることがよくあります。

そして、パターンはを使用して構築できますDateTimeFormatter。ここでのJavadoc、そして私が使用し、関連するパターン文字は:

シンボル -意味- プレゼンテーション -例

Y -年の時代- - 2004; 04

M / L-年の月- 数/テキスト -7; 07; 7月; 7月; J

d-月の日- -10

次に例を示します。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;

public class Java8DateExample {
    public static void main(String[] args) throws IOException {
        final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MM yyyy");
        final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        final String firstInput = reader.readLine();
        final String secondInput = reader.readLine();
        final LocalDate firstDate = LocalDate.parse(firstInput, formatter);
        final LocalDate secondDate = LocalDate.parse(secondInput, formatter);
        final long days = ChronoUnit.DAYS.between(firstDate, secondDate);
        System.out.println("Days between: " + days);
    }
}

最新のラストを使用した入出力の例:

23 01 1997
27 04 1997
Days between: 94

より最近の最初:

27 04 1997
23 01 1997
Days between: -94

まあ、あなたはより簡単な方法でそれをメソッドとして行うことができます:

public static long betweenDates(Date firstDate, Date secondDate) throws IOException
{
    return ChronoUnit.DAYS.between(firstDate.toInstant(), secondDate.toInstant());
}

4
素晴らしい例です。これにより、うるう年が自動的に考慮されます。1991年と1992年(うるう年)をチェックすると、正しく計算されます。パーフェクト!
woahguy 2016年

標準ライブラリの活用。
dieresys 2017年

これは、現在受け入れられている答えです。うるう年と夏時間を考慮した標準ライブラリの使用と説明は問題になりません。
Pehmolelu 2017

3
これが現在/最新の回答です(他の回答は古くなっています)。また、夏時間(DST)も考慮します。Java 6またはJava 7で使用するには、ThreeTenバックポートを入手してください。新しいAndroidのThreeTenABPについて
Ole VV

夏時間は考慮されていません
Alex

63

夏時間になると、ほとんど/すべての回答が問題を引き起こしました。JodaTimeを使用せずに、すべての日付で使用できるソリューションを次に示します。カレンダーオブジェクトを利用します。

public static int daysBetween(Calendar day1, Calendar day2){
    Calendar dayOne = (Calendar) day1.clone(),
            dayTwo = (Calendar) day2.clone();

    if (dayOne.get(Calendar.YEAR) == dayTwo.get(Calendar.YEAR)) {
        return Math.abs(dayOne.get(Calendar.DAY_OF_YEAR) - dayTwo.get(Calendar.DAY_OF_YEAR));
    } else {
        if (dayTwo.get(Calendar.YEAR) > dayOne.get(Calendar.YEAR)) {
            //swap them
            Calendar temp = dayOne;
            dayOne = dayTwo;
            dayTwo = temp;
        }
        int extraDays = 0;

        int dayOneOriginalYearDays = dayOne.get(Calendar.DAY_OF_YEAR);

        while (dayOne.get(Calendar.YEAR) > dayTwo.get(Calendar.YEAR)) {
            dayOne.add(Calendar.YEAR, -1);
            // getActualMaximum() important for leap years
            extraDays += dayOne.getActualMaximum(Calendar.DAY_OF_YEAR);
        }

        return extraDays - dayTwo.get(Calendar.DAY_OF_YEAR) + dayOneOriginalYearDays ;
    }
}

夏時間の切り替えを
適切に

1
ただし、回答の+1は、Calendar dayOne = (Calendar) day1.clone(), dayTwo = (Calendar) day2.clone();元のカレンダーの値が上書きされないようにするため、行が必要であることを追加します。私はこれらの行を削除しました。これらの行は冗長であると考え、元のオブジェクトの値がこの関数内から上書きされていたという事実に1時間無駄にしました。
Rohan Kandwal 2015

2
カレンダークラスでは、月の値が0ベースであることを忘れないでください。calendar.set(2015、11、30、0、00、00); 実際には2015
Dmitry

20

最善の方法であり、ボーナスとして文字列に変換されます;)

protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    try {
        //Dates to compare
        String CurrentDate=  "09/24/2015";
        String FinalDate=  "09/26/2015";

        Date date1;
        Date date2;

        SimpleDateFormat dates = new SimpleDateFormat("MM/dd/yyyy");

        //Setting dates
        date1 = dates.parse(CurrentDate);
        date2 = dates.parse(FinalDate);

        //Comparing dates
        long difference = Math.abs(date1.getTime() - date2.getTime());
        long differenceDates = difference / (24 * 60 * 60 * 1000);

        //Convert long to String
        String dayDifference = Long.toString(differenceDates);

        Log.e("HERE","HERE: " + dayDifference);
    }
    catch (Exception exception) {
        Log.e("DIDN'T WORK", "exception " + exception);
    }
}

例外をスローする可能性は何ですか?
CoDe 2017年

これはうるう年では機能しないことに注意してください。たとえば、「2020年2月15日」から「2020年4月2日」までは47日です。このロジックは、46で出てくる
user1070304

11

使用する:

public int getDifferenceDays(Date d1, Date d2) {
    int daysdiff = 0;
    long diff = d2.getTime() - d1.getTime();
    long diffDays = diff / (24 * 60 * 60 * 1000) + 1;
    daysdiff = (int) diffDays;
    return daysdiff;
}

これはうるう年と夏時間の原因ですか?
Max Alexander Hanna

1
@MaxAlexanderHannaうるう年は正確に考慮されますが、夏時間は考慮されません。ある期間が夏時間以外の期間に始まり、夏時間の間に終了する場合にのみ、正しい答えが得られます。それ以外の場合はすべて、1つずれています。
Dawood ibnカリーム2017

1
@saidesh_kilaru「+ 1」とは何ですか?削除した方がいいと思います。
アリサ

INTにキャストすると4になり、floatにキャストすると4.9になるという問題がありました。たぶん、23:59のdate1と00:01のdate2のケースと、予想される結果が十分に説明されていない可能性があります。
EricG 2018年

10

Javaの日付ライブラリが壊れていることで有名です。ジョーダタイムを使うことをお勧めします。うるう年やタイムゾーンなどを管理してくれます。

最小限の作業例:

import java.util.Scanner;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class DateTestCase {

    public static void main(String[] args) {

        System.out.print("Insert first date: ");
        Scanner s = new Scanner(System.in);
        String firstdate = s.nextLine();
        System.out.print("Insert second date: ");
        String seconddate = s.nextLine();

        // Formatter
        DateTimeFormatter dateStringFormat = DateTimeFormat
                .forPattern("dd MM yyyy");
        DateTime firstTime = dateStringFormat.parseDateTime(firstdate);
        DateTime secondTime = dateStringFormat.parseDateTime(seconddate);
        int days = Days.daysBetween(new LocalDate(firstTime),
                                    new LocalDate(secondTime)).getDays();
        System.out.println("Days between the two dates " + days);
    }
}

4
この答えはいくつかの方法で改善できます。(a)JVMのデフォルトに依存するのではなく、タイムゾーンを指定します。そのため、そのDateTimeFormatterを作成するときに、への呼び出しを追加しますwithZone( DateTimeZone.forID( "Europe/Berlin" ) )。(b)は、なぜ、使用LocalDatedaysBetweenのコール?DateTimeオブジェクト(firstTime、secondTime)を渡すだけです。丸1日はまでお電話くださいwithTimeAtStartOfDays。(c)日付、時刻、および日時オブジェクト間のあいまいさを回避するためにfirstDateTime、変数名を使用しfirstTimeます。(d)予想されるフォーマットと一致しない不良データ入力を処理するために、いくつかのtry-catchを追加します。
バジルブルク2014年

5
String dateStart = "01/14/2015 08:29:58";
String dateStop = "01/15/2015 11:31:48";

//HH converts hour in 24 hours format (0-23), day calculation
SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");

Date d1 = null;
Date d2 = null;

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

//in milliseconds
long diff = d2.getTime() - d1.getTime();

long diffSeconds = diff / 1000 % 60;
long diffMinutes = diff / (60 * 1000) % 60;
long diffHours = diff / (60 * 60 * 1000) % 24;
long diffDays = diff / (24 * 60 * 60 * 1000);

System.out.print(diffDays + " days, ");
System.out.print(diffHours + " hours, ");
System.out.print(diffMinutes + " minutes, ");
System.out.print(diffSeconds + " seconds.");

1

プログラムを実行すると、2番目の日付を入力できるようになりません。

これは簡単で、エラーが発生しにくくなります。

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Test001 {

    public static void main(String[] args) throws Exception {

        BufferedReader br = null;

        br = new BufferedReader(new InputStreamReader(System.in));
        SimpleDateFormat sdf = new SimpleDateFormat("dd MM yyyy");

        System.out.println("Insert first date : ");
        Date dt1 = sdf.parse(br.readLine().trim());

        System.out.println("Insert second date : ");
        Date dt2 = sdf.parse(br.readLine().trim());

        long diff = dt2.getTime() - dt1.getTime();

        System.out.println("Days: " + diff / 1000L / 60L / 60L / 24L);

        if (br != null) {
            br.close();
        }
    }
}

1
// date format, it will be like "2015-01-01"
private static final String DATE_FORMAT = "yyyy-MM-dd";

// convert a string to java.util.Date
public static Date convertStringToJavaDate(String date)
        throws ParseException {
    DateFormat dataFormat = new SimpleDateFormat(DATE_FORMAT);
    return dataFormat.parse(date);
}

// plus days to a date
public static Date plusJavaDays(Date date, int days) {
    // convert to jata-time
    DateTime fromDate = new DateTime(date);
    DateTime toDate = fromDate.plusDays(days);
    // convert back to java.util.Date
    return toDate.toDate();
}

// return a list of dates between the fromDate and toDate
public static List<Date> getDatesBetween(Date fromDate, Date toDate) {
    List<Date> dates = new ArrayList<Date>(0);
    Date date = fromDate;
    while (date.before(toDate) || date.equals(toDate)) {
        dates.add(date);
        date = plusJavaDays(date, 1);
    }
    return dates;
}

0

LocalDateとChronoUnit Javaライブラリを利用できます。以下のコードは正常に動作しています。日付はyyyy-MM-ddの形式にする必要があります。

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.*;
class Solution {
    public int daysBetweenDates(String date1, String date2) {
        LocalDate dt1 = LocalDate.parse(date1);
        LocalDate dt2= LocalDate.parse(date2);

        long diffDays = ChronoUnit.DAYS.between(dt1, dt2);

        return Math.abs((int)diffDays);
    }
}

4
貢献していただきありがとうございます。この良い提案はすでにmkobitの回答で提示されていたと思います。
Ole VV
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.