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);
    }
}
pengguna3025448
sumber
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.

jens108
sumber
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);
}
Bart
sumber
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());
}
mkobit
sumber
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 ;
    }
}
John Leehey
sumber
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);
    }
}
Soincincle
sumber
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;
}
saidesh kilaru
sumber
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);
    }
}
Julien
sumber
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.");
Gautam Viradiya
sumber
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();
        }
    }
}
peter.petrov
sumber
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;
}
Dayong
sumber
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);
    }
}
Abhijeet Upadhyay
sumber
4
Terima kasih telah mau berkontribusi. Saya percaya bahwa saran bagus ini sudah disajikan dalam jawaban oleh mkobit.
Ole VV