Menghitung hari antara dua tanggal dengan Java


150

Saya ingin program Java yang menghitung hari antara dua tanggal.

  1. Ketik tanggal pertama (notasi Jerman; dengan spasi putih: "dd mm yyyy")
  2. Ketikkan tanggal kedua.
  3. Program harus menghitung jumlah hari antara dua tanggal.

Bagaimana saya bisa memasukkan tahun kabisat dan musim panas?

Kode saya:

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

Apa yang tidak berhasil? Apakah itu menabrak? Apakah itu memberi Anda nomor yang salah?
jens108

Di mana deklarasi array: insert1?
Rhys

1
insert1 = eingabe1 dalam bahasa Jerman :)
peter.petrov

@ peter.petrov Ah, saya mengerti!
Rhys

Saya pikir dia memiliki masalah dengan mmdan MM: P
Sage

Jawaban:


229

UPDATE: Jawaban asli dari 2013 sekarang sudah usang karena beberapa kelas telah diganti. Cara baru untuk melakukan ini adalah menggunakan java.timekelas - kelas baru .

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

Perhatikan bahwa solusi ini akan memberikan jumlah aktual 24 jam sehari, bukan jumlah hari kalender. Untuk yang terakhir, gunakan

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

Jawaban asli (kedaluwarsa pada Java 8)

Anda membuat beberapa konversi dengan String Anda yang tidak perlu. Ada SimpleDateFormatkelas untuk itu - coba ini:

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

EDIT: Karena telah ada beberapa diskusi mengenai kebenaran kode ini: itu memang menangani tahun kabisat. Namun, TimeUnit.DAYS.convertfungsi kehilangan presisi karena milidetik dikonversi menjadi hari (lihat dokumen terkait untuk info lebih lanjut). Jika ini masalah, diffbisa juga dikonversi dengan tangan:

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

Perhatikan bahwa ini adalah floatnilai, tidak harus berupa int.


40
Ini adalah implementasi buruk yang tidak memperhitungkan tahun kabisat dengan benar.
Groovy Ed

3
TimeUnit.DAYS.convert (beda, TimeUnit.MILLISECONDS)); <3
Guihgo

3
@GovovyEd Dari apa yang saya uji tampaknya kode ini tidak memiliki masalah dengan tahun kabisat. Harap perhatikan bahwa TimeUnit.Days.convert () akan mengabaikan unit yang tersisa, misalnya, mengubah 999 milidetik menjadi detik menghasilkan 0. Ini berarti bahwa jika Anda menggunakan Date baru () sebagai salah satu objek Date, Anda mungkin mendapatkan satu hari lebih sedikit sehingga berhati-hatilah
Klitos G.

3
Ini juga berfungsi untuk tahun kabisat. periksa ini String inputString1 = "28 2 2016"; String inputString2 = "1 3 2016";: 2
Rohit Gaikwad

10
Saya percaya ini berfungsi dengan benar untuk tahun kabisat, tapi itu mengacaukan waktu musim panas. Jika lokal Anda memiliki waktu musim panas, maka setiap tahun, ada satu hari yang memiliki 23 jam dan satu hari yang memiliki 25 jam. Solusi ini salah mengasumsikan bahwa setiap hari memiliki 24 jam. Oleh karena itu, ini memberikan jawaban yang salah untuk periode apa pun yang dimulai selama tabungan di siang hari dan berakhir di siang hari. JANGAN GUNAKAN SOLUSI INI - ada cara yang lebih baik.
Dawood ibn Kareem

100

Cara termudah:

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

7
Yah, pada dasarnya ini sama dengan jawaban terbaik saat ini , meskipun jawaban ini menyediakannya sebagai fungsi.
Andrew T.

16
Perhatikan, bahwa ini hanya dihitung ketika interval waktu antara dua tanggal lebih besar dari 24 jam (cukup jelas dari kode), dengan demikiangetDifferenceDays(11PM, 4 AM nextday) == 0
ReDetection

1
implementasi ini membutuhkan hari terakhir seperti hari ini. Misalnya, jika saya menjalankan program dengan d1 = hari ini, dan d2 = kemarin, mengembalikan 0 hari ..
karvoynistas

1
@Nav itu karena ada 30 hari di bulan Juni.
Dawood ibn Kareem

1
Jawaban ini salah. Itu tidak berurusan dengan penghematan waktu siang hari dengan benar. Jangan menggunakannya jika Anda ingin hasil yang benar.
Dawood ibn Kareem

89

Di Java 8, Anda bisa melakukannya dengan menggunakan LocalDatedan DateTimeFormatter. Dari Javadoc dari LocalDate:

LocalDate adalah objek tanggal-waktu yang tidak dapat berubah yang mewakili tanggal, sering dianggap sebagai tahun-bulan-hari.

Dan polanya dapat dibangun menggunakan DateTimeFormatter. Inilah Javadoc , dan karakter pola yang relevan yang saya gunakan:

Simbol - Makna - Presentasi - Contoh

y - tahun-dari-era - tahun - 2004; 04

M / L - bulan-tahun - angka / teks - 7; 07; Jul; Juli; J

d - hari-bulan - nomor - 10

Berikut ini contohnya:

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

Contoh input / output dengan yang terbaru terbaru:

23 01 1997
27 04 1997
Days between: 94

Dengan yang lebih baru dulu:

27 04 1997
23 01 1997
Days between: -94

Nah, Anda bisa melakukannya sebagai metode dengan cara yang lebih sederhana:

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

4
Contoh yang bagus. Ini secara otomatis menyumbang tahun kabisat. Jika Anda memeriksa tahun 1991 dan 1992 (tahun kabisat) itu menghitung dengan benar. Sempurna!
woahguy

Penggunaan perpustakaan standar yang bagus.
dieresys

Ini harus menjadi jawaban yang diterima saat ini. Penggunaan dan akun perpustakaan standar untuk tahun kabisat dan penghematan siang hari tidak akan menjadi masalah.
Pehmolelu

3
Ini adalah jawaban saat ini / modern (yang lain sudah usang). Ini juga menyumbang waktu musim panas (DST). Untuk menggunakan di Java 6 atau 7, dapatkan ThreeTen Backport . Di Android ThreeTenABP yang bukan baru .
Ole VV

tidak memperhitungkan penghematan waktu siang hari
Alex

63

Sebagian besar / semua jawaban menyebabkan masalah bagi kami ketika waktu musim panas tiba. Inilah solusi kerja kami untuk semua tanggal, tanpa menggunakan JodaTime. Ini menggunakan objek kalender:

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

menangani sakelar waktu hemat siang hari dengan baik
Ravi Sanwal

1
+1 untuk jawabannya, ingin menambahkan bahwa kami memerlukan Calendar dayOne = (Calendar) day1.clone(), dayTwo = (Calendar) day2.clone();garis karena mereka memastikan bahwa nilai kalender asli tidak diganti. Saya menghapus garis-garis ini menganggapnya berlebihan dan menghabiskan satu jam karena fakta bahwa nilai-nilai objek asli saya ditimpa dari dalam fungsi ini.
Rohan Kandwal

2
Jangan lupa bahwa nilai Bulan berbasis di 0 di Kalender Kelas. calendar.set (2015, 11, 30, 0, 00, 00); sebenarnya berarti 30/12/2015
Dmitry

20

Cara terbaik, dan itu dikonversi ke String sebagai bonus;)

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

apa kemungkinan melempar pengecualian?
CoDe

Perhatikan bahwa ini tidak berfungsi dalam tahun kabisat. Misalnya, dari "02/15/2020" hingga "04/02/2020" adalah 47 hari. Logika ini akan muncul dengan 46.
user1070304

11

Menggunakan:

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

Apakah akun ini untuk tahun kabisat dan penghematan siang hari?
Max Alexander Hanna

1
@ MaxAlexanderHanna menyumbang tahun kabisat dengan benar, tetapi bukan penghematan siang hari. Ini hanya memberikan jawaban yang benar setiap kali periode dimulai selama waktu tabungan non-siang hari tetapi berakhir pada siang hari. Dalam semua kasus lain, tidak aktif satu per satu.
Dawood ibn Kareem

1
@saidesh_kilaru Apa itu "+ 1"? Saya pikir Anda harus menghapusnya.
Alisa

Saya punya masalah yang casting ke INT menghasilkan 4 dan casting ke float menghasilkan 4,9, jadi itu tidak benar-benar apa yang saya inginkan; Mungkin tidak cukup jelas menggambarkan kasus untuk date1 pada 23:59 dan date2 pada 00:01 dan apa hasil yang diharapkan.
EricG

10

Pustaka tanggal Java terkenal rusak. Saya akan menyarankan untuk menggunakan Joda Time . Ini akan menangani tahun kabisat, zona waktu dan sebagainya untuk Anda.

Contoh kerja minimal:

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
Jawaban ini dapat ditingkatkan dalam beberapa cara. (a) Tentukan zona waktu daripada bergantung pada standar JVM. Jadi saat membuat DateTimeFormatter itu, tambahkan panggilan ke withZone( DateTimeZone.forID( "Europe/Berlin" ) ). (B) Mengapa digunakan LocalDatedalam daysBetweenpanggilan? Cukup lewati objek DateTime (firstTime, secondTime). Untuk hari penuh, teleponlah withTimeAtStartOfDays. (C) Saya akan menggunakan nama variabel firstDateTimedaripada firstTimeuntuk menghindari ambiguitas antara objek tanggal, waktu, dan tanggal-waktu. (d) Tambahkan beberapa try-catch untuk menangani input data buruk yang tidak sesuai dengan format yang kami harapkan.
Basil Bourque

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

Ketika saya menjalankan program Anda, itu bahkan tidak sampai ke titik di mana saya dapat memasukkan tanggal kedua.

Ini lebih sederhana dan lebih rentan kesalahan.

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

Kita dapat menggunakan perpustakaan java LocalDate dan ChronoUnit, kode di bawah ini berfungsi dengan baik. Tanggal harus dalam format 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
Terima kasih telah mau berkontribusi. Saya percaya bahwa saran bagus ini sudah disajikan dalam jawaban oleh mkobit.
Ole VV
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.