Java ile iki tarih arasındaki günleri hesaplama


150

İki tarih arasındaki günleri hesaplayan bir Java programı istiyorum.

  1. İlk tarihi yazın (Almanca gösterim; boşluklarla: "gg mm yyyy")
  2. İkinci tarihi yazın.
  3. Program iki tarih arasındaki gün sayısını hesaplamalıdır.

Artık yılları ve yazları nasıl ekleyebilirim?

Kodum:

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

Ne çalışmıyor? Çöküyor mu? Size yanlış numaralar veriyor mu?
jens108

Dizinin bildirimi nerede: insert1?
Rhys

1
insert1 = Almanca eingabe1 :)
peter.petrov

@ peter.petrov Ah, anlıyorum!
Rhys

Onun sorunu yaşıyor düşünüyorum mmve MMP:
Adaçayı

Yanıtlar:


230

GÜNCELLEME: Bazı sınıflar değiştirildiği için 2013'teki orijinal cevap artık güncel değil. Bunu yapmanın yeni yolu yeni java.timesınıfları kullanmaktır.

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

Bu çözümün takvim günü sayısını değil, gerçek 24 saatlik gün sayısını vereceğini unutmayın. İkincisi için,

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

Orijinal cevap (Java 8'den eski)

Dizelerinizle gerekli olmayan bazı dönüşümler yapıyorsunuz. Bunun için bir SimpleDateFormatsınıf var - şunu deneyin:

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: Bu kodun doğruluğu hakkında bazı tartışmalar yapıldığı için: gerçekten artık yıllar ilgileniyor. Ancak, TimeUnit.DAYS.convertmilisaniye güne dönüştürüldüğünden işlev hassasiyeti kaybeder (daha fazla bilgi için bağlantılı dokümana bakın). Bu bir sorunsa, diffelle de dönüştürülebilir:

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

Bunun bir floatdeğer olduğunu, mutlaka bir değer olmadığını unutmayın int.


40
Bu, artık yılları düzgün bir şekilde hesaba katmayan kötü bir uygulamadır.
Groovy Ed

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

3
@GroovyEd Ne test ettik bu kod artık yıllar ile hiçbir sorun var gibi görünüyor. TimeUnit.Days.convert () yönteminin kalan birimleri yok sayacağına dikkat edin, örneğin 999 milisaniyeyi saniyeye çevirmek 0 sonucunu verir.
Klitos G.

3
Artık yıllar boyunca çalışıyor. Bunu denetlemek String inputString1 = "28 2 2016"; String inputString2 = "1 3 2016";2: ans
Rohit Gaikwad

10
Bunun artık yıllar boyunca doğru çalıştığına inanıyorum, ancak gün ışığından yararlanma süresini berbat ediyor. Yerel ayarınız gün ışığından yararlanma saati içeriyorsa, her yıl bir gün 23 saat ve bir gün 25 saat vardır. Bu çözüm yanlış her gün 24 saat olduğunu varsayar. Bu nedenle, gün ışığından yararlanmayan tasarruf sırasında başlayan ve gün ışığından yararlanma sırasında biten herhangi bir dönem için yanlış cevap verir. BU ÇÖZÜMÜ KULLANMAYIN - daha iyi yollar var.
Dawood ibn Kareem

100

En basit yol:

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

7
Temel olarak bu mevcut en iyi cevapla aynıdır , ancak bu cevap bir işlev olarak sağlar.
Andrew T.

16
Bu, yalnızca iki tarih arasındaki zaman aralığı 24 saatten (koddan oldukça açık) daha büyük olduğunda getDifferenceDays(11PM, 4 AM nextday) == 0
sayılır

1
bu uygulama bugün olduğu gibi son günü almaktadır. Örneğin, programı d1 = bugün ve d2 = dün ile çalıştırırsam 0 gün döndürür ..
karvoynistas

1
@Nav, Haziran ayında 30 gün olduğu için.
Dawood ibn Kareem

1
Bu cevap yanlış. Yaz saati uygulamasıyla doğru bir şekilde ilgilenmez. Doğru sonuçlar istiyorsanız bunu kullanmayın.
Dawood ibn Kareem

89

Java 8'de bunu LocalDateve ile yapabilirsiniz DateTimeFormatter. Gönderen Javadoc ait LocalDate:

LocalDate, genellikle yıl-ay-gün olarak görülen bir tarihi temsil eden değişmez bir tarih-saat nesnesidir.

Ve desen kullanılarak inşa edilebilir DateTimeFormatter. İşte Javadoc ve kullandığım ilgili desen karakterleri:

Sembol - Anlamı - Sunum - Örnekler

y - dönem yılı - 2004; 04

M / L - yılın ayı - sayı / metin - 7; 07; Temmuz; Temmuz; J

d - ayın günü - sayı - 10

İşte örnek:

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

Son kullanılan örnek giriş / çıkış:

23 01 1997
27 04 1997
Days between: 94

Öncelikle daha yenisiyle:

27 04 1997
23 01 1997
Days between: -94

Bunu bir yöntem olarak daha basit bir şekilde yapabilirsiniz:

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

4
Mükemmel bir örnek. Bu otomatik olarak artık yılı açıklar. 1991 ve 1992'yi (artık yıl) kontrol ettiyseniz, doğru bir şekilde hesaplar. Mükemmel!
woahguy

Standart kütüphanenin büyük kullanımı.
dieresys

Bu geçerli kabul edilen cevap olmalıdır. Standart kütüphane kullanımı ve artık yıllar ve gün ışığından yararlanma hesapları sorun oluşturmaz.
Pehmolelu

3
Bu mevcut / modern cevaptır (diğerleri modası geçmiş). Aynı zamanda yaz saati (DST) için de geçerlidir. Java 6 veya 7'de kullanmak için ThreeTen Backport'u edinin . Yeni olmayan Android ThreeTenABP'de .
Ole VV

yaz saati uygulamasını dikkate almaz
Alex

63

Çoğu / tüm cevaplar gün ışığından yararlanma saati geldiğinde bizim için sorunlara neden oldu. JodaTime kullanmadan tüm tarihler için çalışma çözümümüz. Takvim nesnelerini kullanır:

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

Yaz saati uygulamalarını iyi idare eder
Ravi Sanwal

1
Ancak yanıt için +1 Calendar dayOne = (Calendar) day1.clone(), dayTwo = (Calendar) day2.clone();, orijinal takvim değerlerinin geçersiz kılınmamasını sağladığından satırlara ihtiyacımız olduğunu eklemek istiyor . Onları gereksiz düşünerek bu satırları sildim ve orijinal nesnemin değerlerinin bu fonksiyonun üzerine yazıldığından bir saat harcadım.
Rohan Kandwal

2
Calendar Class'ta Month değerinin 0 tabanlı olduğunu unutmayın. takvim.set (2015, 11, 30, 0, 00, 00); aslında 30/12/2015 anlamına gelir
Dmitry

20

En iyi yol ve bonus olarak bir String'e dönüştürür;)

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

istisna fırlatma olasılığı nedir?
CoDe

Bunun artık yıllarda çalışmadığını unutmayın. Örneğin, "02/15/2020" ile "04/02/2020" arası 47 gündür. Bu mantık 46 ile gelecek.
user1070304

11

kullanın:

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

Bu artık yıllar ve gün ışığından yararlanıyor mu?
Max Alexander Hanna

1
@MaxAlexanderHanna artık yılları doğru bir şekilde açıklar, ancak gün ışığından tasarruf etmez. Yalnızca gün ışığından yararlanma saati sırasında bir dönem başladığında, ancak gün ışığından yararlanma sırasında sona erdiğinde doğru yanıtı verir. Diğer tüm durumlarda, birer birer kapalıdır.
Dawood ibn Kareem

1
@saidesh_kilaru "+ 1" nedir? Bence onu kaldırmalısın.
Alisa

INT için döküm 4 sonuçlandı ve float için döküm 4.9 sonuçlandı bir sorun vardı, bu yüzden gerçekten istediğim bu değil; Belki de tarih 1 23:59 ve tarih 2 00:01 saatlerini ve beklenen sonucun ne olacağını yeterince açıklamamıştır.
EricG

10

Java tarih kitaplıkları herkesin bildiği gibi bozuldu. Joda Time'ı kullanmanızı tavsiye ederim . Artık yıl, zaman dilimi vb.Ile ilgilenecektir.

Minimum çalışma örneği:

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
Bu cevap birkaç şekilde geliştirilebilir. (a) JVM'nin varsayılan ayarına bağlı kalmak yerine saat dilimini belirtin. Bu DateTimeFormatter'ı oluştururken bir çağrı ekleyin withZone( DateTimeZone.forID( "Europe/Berlin" ) ). (b) neden kullanılmalı LocalDateiçinde daysBetweençağrı? DateTime nesnelerini (firstTime, secondTime) iletmeniz yeterlidir. Tam gün boyunca arayın withTimeAtStartOfDays. Ben değişken isimleri kullanmak istiyorsunuz (c) firstDateTimeziyade firstTimetarih, saat ve tarih-saat nesneler arasındaki karışıklıkları önlemek. (d) Beklenen biçimimizle uyuşmayan hatalı veri girişini işlemek için bir miktar yakalama ekleyin.
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

Programınızı çalıştırdığımda, beni ikinci tarihe girebileceğim noktaya bile getirmiyor.

Bu daha basit ve daha az hataya açıktır.

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 ve ChronoUnit java kütüphanesini kullanabiliriz, Aşağıdaki kod iyi çalışıyor. Tarih yyyy-AA-gg biçiminde olmalıdır.

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
Katkıda bulunmak istediğiniz için teşekkür ederiz. Bu iyi önerinin zaten mkobit tarafından cevapta sunulduğuna inanıyorum.
Ole VV
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.