Sự khác biệt về ngày giữa hai ngày trong Java?


81

Tôi cần tìm số ngày giữa hai ngày : một là từ báo cáo và một là ngày hiện tại. Đoạn mã của tôi:

  int age=calculateDifference(agingDate, today);

Đây calculateDifferencelà một phương pháp riêng tư agingDatetodayDatecác đối tượng, chỉ để bạn làm rõ. Tôi đã theo dõi hai bài viết từ một diễn đàn Java, Chủ đề 1 / Chủ đề 2 .

Nó hoạt động tốt trong một chương trình độc lập mặc dù khi tôi đưa điều này vào logic của mình để đọc từ báo cáo, tôi nhận được sự khác biệt bất thường về giá trị.

Tại sao nó lại xảy ra và làm thế nào tôi có thể sửa chữa nó?

BIÊN TẬP :

Tôi đang nhận được số ngày lớn hơn so với số ngày thực tế.

public static int calculateDifference(Date a, Date b)
{
    int tempDifference = 0;
    int difference = 0;
    Calendar earlier = Calendar.getInstance();
    Calendar later = Calendar.getInstance();

    if (a.compareTo(b) < 0)
    {
        earlier.setTime(a);
        later.setTime(b);
    }
    else
    {
        earlier.setTime(b);
        later.setTime(a);
    }

    while (earlier.get(Calendar.YEAR) != later.get(Calendar.YEAR))
    {
        tempDifference = 365 * (later.get(Calendar.YEAR) - earlier.get(Calendar.YEAR));
        difference += tempDifference;

        earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    if (earlier.get(Calendar.DAY_OF_YEAR) != later.get(Calendar.DAY_OF_YEAR))
    {
        tempDifference = later.get(Calendar.DAY_OF_YEAR) - earlier.get(Calendar.DAY_OF_YEAR);
        difference += tempDifference;

        earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    return difference;
}

Ghi chú :

Thật không may, không có câu trả lời nào giúp tôi giải quyết vấn đề. Tôi đã giải quyết được vấn đề này với sự trợ giúp của thư viện Joda-time .


3
Ý bạn là gì bởi các giá trị khác biệt bất thường? Bạn có thể nói rõ hơn hoặc cho một ví dụ về một số loại?
Marcel Gheorghita

1
Bạn có thể đăng mã cho phương pháp tính toán
Eugene Ryzhikov

FYI, người già lớp ngày thời gian phiền hà như java.util.Date, java.util.Calendarjava.text.SimpleDateFormatbây giờ là di sản , thay thế bởi sự java.time lớp. Xem Hướng dẫn của Oracle . Tương tự như vậy, dự án Joda-Time hiện đang ở chế độ bảo trì , với nhóm tư vấn di chuyển sang các lớp java.time.
Basil Bourque

Câu trả lời:


149

Tôi khuyên bạn nên sử dụng thư viện Joda Time tuyệt vời thay vì java.util.Date còn thiếu sót và các bạn. Bạn chỉ có thể viết

import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.Days;

Date past = new Date(110, 5, 20); // June 20th, 2010
Date today = new Date(110, 6, 24); // July 24th 
int days = Days.daysBetween(new DateTime(past), new DateTime(today)).getDays(); // => 34

3
joda-time.sourceforge.net/faq.html#datediff - Tôi sắp đề xuất điều tương tự.
Nebril,

2
jodaInstance = new DateTime (jdkDate); Về chuyển đổi giữa thời gian Joda và java.util.Date và bạn bè, xem joda-time.sourceforge.net/userguide.html#JDK_Interoperability
Adam Schmideg

2
@ven coder - Tôi nghĩ bạn có thể đăng nó dưới dạng một câu hỏi riêng về việc sử dụng joda time. Bạn cũng có thể cung cấp một đoạn mã cho kết quả dường như sai.
Adam Schmideg

2
@ven coder - Tôi đã cập nhật mã mẫu, nó phù hợp với tôi. Tôi thấy câu hỏi này đã được trả lời. Hiển thị mã không phù hợp với bạn, tại đây hoặc trong một câu hỏi riêng.
Adam Schmideg

1
FYI, dự án Joda-Time hiện đang ở chế độ bảo trì , với nhóm tư vấn di chuyển sang các lớp java.time . Xem Hướng dẫn của Oracle .
Basil Bourque

48

Tôi có thể đã quá muộn để tham gia trò chơi nhưng cái quái gì vậy? :)

Bạn có nghĩ rằng đây là một vấn đề phân luồng? Ví dụ, bạn đang sử dụng đầu ra của phương pháp này như thế nào? HOẶC LÀ

Chúng tôi có thể thay đổi mã của bạn để làm điều gì đó đơn giản như:

Calendar calendar1 = Calendar.getInstance();
    Calendar calendar2 = Calendar.getInstance();
    calendar1.set(<your earlier date>);
    calendar2.set(<your current date>);
    long milliseconds1 = calendar1.getTimeInMillis();
    long milliseconds2 = calendar2.getTimeInMillis();
    long diff = milliseconds2 - milliseconds1;
    long diffSeconds = diff / 1000;
    long diffMinutes = diff / (60 * 1000);
    long diffHours = diff / (60 * 60 * 1000);
    long diffDays = diff / (24 * 60 * 60 * 1000);
    System.out.println("\nThe Date Different Example");
    System.out.println("Time in milliseconds: " + diff
 + " milliseconds.");
    System.out.println("Time in seconds: " + diffSeconds
 + " seconds.");
    System.out.println("Time in minutes: " + diffMinutes 
+ " minutes.");
    System.out.println("Time in hours: " + diffHours 
+ " hours.");
    System.out.println("Time in days: " + diffDays 
+ " days.");
  }

18
Mã này không chú ý đến thời gian tiết kiệm ánh sáng ban ngày, vì vậy kết quả của sự khác biệt về ngày có thể không chính xác.
Johanna

@Johanna Mặc dù đã khá muộn, bạn có thể vui lòng cho một ví dụ khi điều này không thành công. Tôi đã thử rất nhiều nhưng không thể tìm thấy bất kỳ phạm vi ngày nào không thành công. Cảm ơn bạn.
abhilash

4
Lỗi này chỉ xảy ra nếu bạn đang ở trong múi giờ (cài đặt múi giờ địa phương của bạn) sử dụng giờ tiết kiệm ánh sáng ban ngày, ví dụ: Giờ Trung Âu, Berlin, Paris hoặc Amsterdam. Ngày bắt đầu và kết thúc của thời gian tiết kiệm ánh sáng ban ngày không có 24 giờ, ví dụ: ngày 30 tháng 3 năm 2014 chỉ có 23 giờ trong khi ngày 26 tháng 10 năm 2014 sẽ có 25 giờ. Nếu ngày trước đó là trước 2:00 ngày 30 tháng 3 và ngày muộn hơn là sau 3:00 ngày 30 tháng 3 thì phép tính không thành công.
Johanna

23

Khác biệt / (24 * v.v.) không tính đến Múi giờ, vì vậy nếu múi giờ mặc định của bạn có DST trong đó, nó có thể loại bỏ tính toán.

Đây liên kết có một chút thực hiện tốt đẹp.

Đây là nguồn của liên kết trên trong trường hợp liên kết bị lỗi:

/** Using Calendar - THE CORRECT WAY**/  
public static long daysBetween(Calendar startDate, Calendar endDate) {  
  //assert: startDate must be before endDate  
  Calendar date = (Calendar) startDate.clone();  
  long daysBetween = 0;  
  while (date.before(endDate)) {  
    date.add(Calendar.DAY_OF_MONTH, 1);  
    daysBetween++;  
  }  
  return daysBetween;  
}  

/** Using Calendar - THE CORRECT (& Faster) WAY**/  
public static long daysBetween(final Calendar startDate, final Calendar endDate)
{
  //assert: startDate must be before endDate  
  int MILLIS_IN_DAY = 1000 * 60 * 60 * 24;  
  long endInstant = endDate.getTimeInMillis();  
  int presumedDays = 
    (int) ((endInstant - startDate.getTimeInMillis()) / MILLIS_IN_DAY);  
  Calendar cursor = (Calendar) startDate.clone();  
  cursor.add(Calendar.DAY_OF_YEAR, presumedDays);  
  long instant = cursor.getTimeInMillis();  
  if (instant == endInstant)  
    return presumedDays;

  final int step = instant < endInstant ? 1 : -1;  
  do {  
    cursor.add(Calendar.DAY_OF_MONTH, step);  
    presumedDays += step;  
  } while (cursor.getTimeInMillis() != endInstant);  
  return presumedDays;  
}

4
Phương pháp thứ hai là sai, cuối cùng whilenên được. while (cursor.getTimeInMillis() <= endInstant); Nếu không, bạn sẽ nhận được một vòng lặp vô hạn nếu chưa đầy một ngày.
Chris.Jenkins

Từ nhận xét trong liên kết "Bạn nên biết rằng thuật toán đưa ra có thể cho 'thêm một ngày' so với bạn mong đợi. Nó cho 1 là số ngày từ 2009-02-28 19:00:00 đến 2009-02-28 19:00:01. "
Zyoo

16

java.time

Trong Java 8 trở lên, hãy sử dụng khuôn khổ java.time ( Hướng dẫn ).

Duration

Các Durationlớp đại diện cho một khoảng thời gian như một số giây cộng thêm một giây phân đoạn. Nó có thể đếm ngày, giờ, phút và giây.

ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10);
Duration duration = Duration.between(oldDate, now);
System.out.println(duration.toDays());

ChronoUnit

Nếu tất cả những gì bạn cần là số ngày, bạn có thể sử dụng enum . Lưu ý rằng các phương thức tính toán trả về một thay vì .ChronoUnit longint

long days = ChronoUnit.DAYS.between( then, now );

cũng hãy chắc chắn chuyển ngày cho ChronoUnit.DAYS. giữa các ngày theo đúng thứ tự, nếu không nó sẽ trả về kết quả -ve
RRR_J

13
import java.util.Calendar;
import java.util.Date;

public class Main {
    public static long calculateDays(String startDate, String endDate)
    {
        Date sDate = new Date(startDate);
        Date eDate = new Date(endDate);
        Calendar cal3 = Calendar.getInstance();
        cal3.setTime(sDate);
        Calendar cal4 = Calendar.getInstance();
        cal4.setTime(eDate);
        return daysBetween(cal3, cal4);
    }

    public static void main(String[] args) {
        System.out.println(calculateDays("2012/03/31", "2012/06/17"));

    }

    /** Using Calendar - THE CORRECT WAY**/
    public static long daysBetween(Calendar startDate, Calendar endDate) {
        Calendar date = (Calendar) startDate.clone();
        long daysBetween = 0;
        while (date.before(endDate)) {
            date.add(Calendar.DAY_OF_MONTH, 1);
            daysBetween++;
        }
        return daysBetween;
    }
}

1
Vòng lặp không phải là ý tưởng xuất sắc. Làm thế nào về hiệu suất khi có nhiều tùy chọn đơn giản hơn để làm tương tự?
angelcervera

1
Cải thiện hiệu suất sẽ là tăng theo lũy thừa của 2 và sau đó khi ngày điều kiện. có thể sẽ thực hiện 30 lần lặp lại thay vì một tỷ. Bạn cũng có thể cải thiện hiệu suất bằng cách phỏng đoán bằng cách kiểm tra mili giây, nhưng điều đó có lẽ sẽ kém thanh lịch hơn.
Muhd

12

Nó phụ thuộc vào những gì bạn xác định là sự khác biệt. Để so sánh hai ngày vào lúc nửa đêm, bạn có thể làm.

long day1 = ...; // in milliseconds.
long day2 = ...; // in milliseconds.
long days = (day2 - day1) / 86400000;

9
Mã này không chú ý đến thời gian tiết kiệm ánh sáng ban ngày, vì vậy kết quả có thể không chính xác.
Johanna

@Johanna Giải pháp này hoạt động với DST. Khi vòng được áp dụng sau khi chia, sự khác biệt này được bỏ qua và kết quả là ổn.
angelcervera

1
@angelcervera Hầu hết thời gian nó sẽ chính xác, nhưng nếu nó gần kề, thời gian thêm có thể làm cho độ chính xác giảm +/- 1 ngày (tức là nó sẽ làm tròn sai cách).
Muhd

3
@Muhd Đúng, Bạn nói đúng. Dòng thứ ba phải là: long days = Math.round ((day2 - day1) / 86400000D); Điều rất quan trọng là số chia phải là một giá trị kép.
angelcervera

3
Lấy làm tiếc. Sáng nay tôi đã quên cắm đầu vào mô-đun toán lớp một của mình. Tôi đã nghĩ rằng trừ đi một số âm sẽ loại bỏ phép tính. Chúng tôi sẽ có thể từ chối bình luận.
Snekse

9

Giải pháp sử dụng sự khác biệt giữa thời gian mili giây, với cách làm tròn chính xác cho ngày DST:

public static long daysDiff(Date from, Date to) {
    return daysDiff(from.getTime(), to.getTime());
}

public static long daysDiff(long from, long to) {
    return Math.round( (to - from) / 86400000D ); // 1000 * 60 * 60 * 24
}

Một lưu ý: Tất nhiên, ngày tháng phải nằm trong một số múi giờ.

Mã quan trọng:

Math.round( (to - from) / 86400000D )

Nếu bạn không muốn làm tròn, bạn có thể sử dụng ngày UTC,


1
@marcolopes Không, trả về 32. System.out.println (daysDiff (new Date (2014, 2, 1), new Date (2014, 3, 2))); Hãy cẩn thận, bởi vì tháng Giêng là 0.
angelcervera

4

Hình minh họa sự cố: (Mã của tôi là tính toán delta tính theo tuần, nhưng vấn đề tương tự cũng áp dụng với delta tính theo ngày)

Đây là một triển khai trông rất hợp lý:

public static final long MILLIS_PER_WEEK = 7L * 24L * 60L * 60L * 1000L;

static public int getDeltaInWeeks(Date latterDate, Date earlierDate) {
    long deltaInMillis = latterDate.getTime() - earlierDate.getTime();
    int deltaInWeeks = (int)(deltaInMillis / MILLIS_PER_WEEK);
    return deltaInWeeks; 
}

Nhưng thử nghiệm này sẽ thất bại:

public void testGetDeltaInWeeks() {
    delta = AggregatedData.getDeltaInWeeks(dateMar09, dateFeb23);
    assertEquals("weeks between Feb23 and Mar09", 2, delta);
}

Lý do là:

Thứ Hai tháng 3 09 00:00:00 EDT 2009 = 1.236.571.200.000
Thứ Hai 23 tháng 2 00:00:00 EST 2009 = 1.235.365.200.000
MillisPerWeek = 604.800.000
Như vậy,
( 09 tháng 3 - 23 tháng 2 ) / MillisPerWeek =
1.206.000.000 / 604.800.000 = 1.994 ...

nhưng bất cứ ai nhìn vào lịch sẽ đồng ý rằng câu trả lời là 2.


1
Chú ý EDTEST . Bạn đang tìm kiếm thời gian tiết kiệm ánh sáng ban ngày. 168 giờ trong một tuần (+1 cho "tăng" một giờ vào mùa xuân) * hai tuần, cộng thêm giờ DST và bạn có: 335/168 = 1.9940476190.
jpswain

3

Tôi sử dụng chức năng này:

DATEDIFF("31/01/2016", "01/03/2016") // me return 30 days

chức năng của tôi:

import java.util.Date;

public long DATEDIFF(String date1, String date2) {
        long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000;
        long days = 0l;
        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy"); // "dd/MM/yyyy HH:mm:ss");

        Date dateIni = null;
        Date dateFin = null;        
        try {       
            dateIni = (Date) format.parse(date1);
            dateFin = (Date) format.parse(date2);
            days = (dateFin.getTime() - dateIni.getTime())/MILLISECS_PER_DAY;                        
        } catch (Exception e) {  e.printStackTrace();  }   

        return days; 
     }


2

Dựa trên câu trả lời của @ Mad_Troll, tôi đã phát triển phương pháp này.

Tôi đã chạy khoảng 30 trường hợp thử nghiệm chống lại nó, là phương pháp duy nhất xử lý các phân đoạn thời gian phụ một cách chính xác.

Ví dụ: Nếu bạn vượt qua ngay bây giờ và bây giờ + 1 mili giây vẫn trong cùng một ngày. Làm 1-1-13 23:59:59.098để 1-1-13 23:59:59.099trả về 0 ngày, một cách chính xác; tất cả các phương pháp khác được đăng ở đây sẽ không làm điều này một cách chính xác.

Đáng chú ý là nó không quan tâm đến cách bạn đặt chúng vào, Nếu ngày kết thúc của bạn trước ngày bắt đầu của bạn, nó sẽ tính ngược lại.

/**
 * This is not quick but if only doing a few days backwards/forwards then it is very accurate.
 *
 * @param startDate from
 * @param endDate   to
 * @return day count between the two dates, this can be negative if startDate is after endDate
 */
public static long daysBetween(@NotNull final Calendar startDate, @NotNull final Calendar endDate) {

    //Forwards or backwards?
    final boolean forward = startDate.before(endDate);
    // Which direction are we going
    final int multiplier = forward ? 1 : -1;

    // The date we are going to move.
    final Calendar date = (Calendar) startDate.clone();

    // Result
    long daysBetween = 0;

    // Start at millis (then bump up until we go back a day)
    int fieldAccuracy = 4;
    int field;
    int dayBefore, dayAfter;
    while (forward && date.before(endDate) || !forward && endDate.before(date)) {
        // We start moving slowly if no change then we decrease accuracy.
        switch (fieldAccuracy) {
            case 4:
                field = Calendar.MILLISECOND;
                break;
            case 3:
                field = Calendar.SECOND;
                break;
            case 2:
                field = Calendar.MINUTE;
                break;
            case 1:
                field = Calendar.HOUR_OF_DAY;
                break;
            default:
            case 0:
                field = Calendar.DAY_OF_MONTH;
                break;
        }
        // Get the day before we move the time, Change, then get the day after.
        dayBefore = date.get(Calendar.DAY_OF_MONTH);
        date.add(field, multiplier);
        dayAfter = date.get(Calendar.DAY_OF_MONTH);

        // This shifts lining up the dates, one field at a time.
        if (dayBefore == dayAfter && date.get(field) == endDate.get(field))
            fieldAccuracy--;
        // If day has changed after moving at any accuracy level we bump the day counter.
        if (dayBefore != dayAfter) {
            daysBetween += multiplier;
        }
    }
    return daysBetween;
}

Bạn có thể xóa các @NotNullchú thích, những chú thích này được Intellij sử dụng để phân tích mã một cách nhanh chóng


Tôi tính đến Millis, máy tính đó thì không, tôi giả sử nó làm tròn các số xuống 0. Như tôi đã nêu ở đầu câu trả lời. Làm phẳng số giờ / phút / giây / mili của bạn và bạn sẽ thấy rằng nó sẽ được đếm chính xác.
Chris.Jenkins

1

Bạn nói rằng nó "hoạt động tốt trong một chương trình độc lập", nhưng bạn nhận được "giá trị khác biệt bất thường" khi bạn "đưa điều này vào logic của tôi để đọc từ báo cáo". Điều đó cho thấy rằng báo cáo của bạn có một số giá trị mà nó không hoạt động chính xác và chương trình độc lập của bạn không có những giá trị đó. Thay vì một chương trình độc lập, tôi đề xuất một trường hợp thử nghiệm. Viết một trường hợp thử nghiệm giống như bạn làm với một chương trình độc lập, phân lớp từ lớp TestCase của JUnit. Bây giờ bạn có thể chạy một ví dụ rất cụ thể, biết bạn mong đợi giá trị nào (và không đưa nó ngay hôm nay cho giá trị thử nghiệm, vì ngày nay thay đổi theo thời gian). Nếu bạn đặt các giá trị mà bạn đã sử dụng trong chương trình độc lập, các bài kiểm tra của bạn có thể sẽ vượt qua. Điều đó thật tuyệt - bạn muốn những trường hợp đó tiếp tục hoạt động. Bây giờ, hãy thêm một giá trị từ báo cáo của bạn, một giá trị không t làm việc đúng. Bài kiểm tra mới của bạn có thể sẽ thất bại. Tìm ra lý do tại sao nó không thành công, sửa nó và chuyển sang màu xanh lá cây (tất cả các bài kiểm tra đều vượt qua). Chạy báo cáo của bạn. Xem những gì vẫn còn bị hỏng; viết bài kiểm tra; làm cho nó trôi qua. Bạn sẽ sớm thấy báo cáo của mình đang hoạt động.


1

Hàng trăm dòng mã cho chức năng cơ bản này ???

Chỉ là một phương pháp đơn giản:

protected static int calculateDayDifference(Date dateAfter, Date dateBefore){
    return (int)(dateAfter.getTime()-dateBefore.getTime())/(1000 * 60 * 60 * 24); 
    // MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
}

5
Bỏ qua múi giờ. Bỏ qua Giờ tiết kiệm ánh sáng ban ngày và các hiện tượng bất thường khác. Bỏ qua việc làm tròn số ngày.
Basil Bourque

1
public static int getDifferenceIndays(long timestamp1, long timestamp2) {
    final int SECONDS = 60;
    final int MINUTES = 60;
    final int HOURS = 24;
    final int MILLIES = 1000;
    long temp;
    if (timestamp1 < timestamp2) {
        temp = timestamp1;
        timestamp1 = timestamp2;
        timestamp2 = temp;
    }
    Calendar startDate = Calendar.getInstance(TimeZone.getDefault());
    Calendar endDate = Calendar.getInstance(TimeZone.getDefault());
    endDate.setTimeInMillis(timestamp1);
    startDate.setTimeInMillis(timestamp2);
    if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) {
        int day1 = endDate.get(Calendar.DAY_OF_MONTH);
        int day2 = startDate.get(Calendar.DAY_OF_MONTH);
        if (day1 == day2) {
            return 0;
        } else {
            return 1;
        }
    }
    int diffDays = 0;
    startDate.add(Calendar.DAY_OF_MONTH, diffDays);
    while (startDate.before(endDate)) {
        startDate.add(Calendar.DAY_OF_MONTH, 1);
        diffDays++;
    }
    return diffDays;
}

1

ThreeTen-Extra

Câu trả lời của Vitalii Fedorenko là đúng, mô tả cách thực hiện phép tính này theo cách hiện đại với các lớp java.time ( Duration& ChronoUnit) được tích hợp trong Java 8 trở lên (và được chuyển ngược sang Java 6 & 7Android ).

Days

Nếu bạn đang sử dụng một số ngày thường xuyên trong mã của mình, bạn có thể thay thế các số nguyên đơn thuần bằng việc sử dụng một lớp. Các Dayslớp có thể được tìm thấy trong ThreeTen-Extra dự án, một phần mở rộng của java.time và chứng minh đất cho bổ sung trong tương lai có thể java.time. Các Dayslớp học cung cấp một cách kiểu an đại diện cho một số ngày trong ứng dụng của bạn. Lớp này bao gồm các hằng số thuận tiện cho ZEROONE.

Với các java.util.Dateđối tượng cũ đã lỗi thời trong Câu hỏi, trước tiên hãy chuyển đổi chúng thành các java.time.Instantđối tượng hiện đại . Các lớp date-time cũ có các phương thức mới được thêm vào để tạo điều kiện chuyển đổi sang java.time, chẳng hạn java.util.Date::toInstant.

Instant start = utilDateStart.toInstant(); // Inclusive.
Instant stop = utilDateStop.toInstant();  // Exclusive.

Chuyển cả hai Instantđối tượng sang phương thức gốc choorg.threeten.extra.Days .

Trong triển khai hiện tại (2016-06) đây là một trình bao bọc đang gọi java.time.temporal.ChronoUnit.DAYS.between, hãy đọc ChronoUnittài liệu lớp để biết chi tiết. Để rõ ràng: tất cả các chữ hoa DAYSđều nằm trong enum ChronoUnittrong khi ban đầu Dayslà một lớp từ ThreeTen-Extra.

Days days = Days.between( start , stop );

Bạn có thể chuyển các Daysđối tượng này xung quanh mã của riêng bạn. Bạn có thể tuần tự hóa thành một Chuỗi ở định dạng tiêu chuẩn ISO 8601 bằng cách gọi toString. Định dạng này PnDsử dụng a Pđể đánh dấu sự bắt đầu và Dcó nghĩa là "ngày", với một số ngày ở giữa. Cả hai lớp java.time và ThreeTen-Extra đều sử dụng các định dạng chuẩn này theo mặc định khi tạo và phân tích cú pháp các Chuỗi đại diện cho các giá trị ngày-giờ.

String output = days.toString();

P3D

Days days = Days.parse( "P3D" );  

0

Mã này tính toán các ngày giữa 2 Chuỗi ngày:

    static final long MILLI_SECONDS_IN_A_DAY = 1000 * 60 * 60 * 24;
    static final String DATE_FORMAT = "dd-MM-yyyy";
    public long daysBetween(String fromDateStr, String toDateStr) throws ParseException {
    SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
    Date fromDate;
    Date toDate;
    fromDate = format.parse(fromDateStr);
    toDate = format.parse(toDateStr);
    return (toDate.getTime() - fromDate.getTime()) / MILLI_SECONDS_IN_A_DAY;
}

0

Nếu bạn đang tìm kiếm một giải pháp trả về số hoặc ngày thích hợp giữa ví dụ 11/30/2014 23:5912/01/2014 00:01đây là giải pháp sử dụng Joda Time.

private int getDayDifference(long past, long current) {
    DateTime currentDate = new DateTime(current);
    DateTime pastDate = new DateTime(past);
    return currentDate.getDayOfYear() - pastDate.getDayOfYear();
} 

Việc triển khai này sẽ trở lại 1như một sự khác biệt trong ngày. Hầu hết các giải pháp được đăng ở đây đều tính toán chênh lệch tính bằng mili giây giữa hai ngày. Nó có nghĩa là 0sẽ được trả lại vì chỉ có 2 phút chênh lệch giữa hai ngày này.


0

Bạn nên sử dụng thư viện Joda Time vì Java Util Date đôi khi trả về giá trị sai.

Ngày Joda vs Java Util

Ví dụ các ngày từ hôm qua (dd-mm-yyyy, 12-07-2016) đến ngày đầu tiên của năm 1957 (dd-mm-yyyy, 01-01-1957):

public class Main {

public static void main(String[] args) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date date = null;
    try {
        date = format.parse("12-07-2016");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    //Try with Joda - prints 21742
    System.out.println("This is correct: " + getDaysBetweenDatesWithJodaFromYear1957(date));
    //Try with Java util - prints 21741
    System.out.println("This is not correct: " + getDaysBetweenDatesWithJavaUtilFromYear1957(date));    
}


private static int getDaysBetweenDatesWithJodaFromYear1957(Date date) {
    DateTime jodaDateTime = new DateTime(date);
    DateTimeFormatter formatter = DateTimeFormat.forPattern("dd-MM-yyyy");
    DateTime y1957 = formatter.parseDateTime("01-01-1957");

    return Days.daysBetween(y1957 , jodaDateTime).getDays();
}

private static long getDaysBetweenDatesWithJavaUtilFromYear1957(Date date) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date y1957 = null;
    try {
        y1957 = format.parse("01-01-1957");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return TimeUnit.DAYS.convert(date.getTime() - y1957.getTime(), TimeUnit.MILLISECONDS);
}

Vì vậy, tôi thực sự khuyên bạn nên sử dụng thư viện Joda Time.


1
FYI, trong khi Joda-Time vẫn được hỗ trợ tích cực, nhóm phát triển của nó khuyên bạn nên chuyển sang java.time . Trích dẫn từ trang chủ của họ: “Joda-Time là thư viện ngày và giờ chuẩn trên thực tế dành cho Java trước Java SE 8. Người dùng hiện được yêu cầu chuyển sang java.time (JSR-310).”
Basil Bourque vào

-6

Tôi đã làm theo cách này. dễ thôi :)

Date d1 = jDateChooserFrom.getDate();
Date d2 = jDateChooserTo.getDate();

Calendar day1 = Calendar.getInstance();
day1.setTime(d1);

Calendar day2 = Calendar.getInstance();
day2.setTime(d2);

int from = day1.get(Calendar.DAY_OF_YEAR);
int to = day2.get(Calendar.DAY_OF_YEAR);

int difference = to-from;

4
Thực hiện một số thử nghiệm về điều này, Bạn sẽ rất nhanh chóng nhận ra điều này sẽ không hoạt động. Làm từ ngày 31 tháng 12 năm 2013 đến ngày 1 tháng 1 năm 2014, đó là một ngày chênh lệch phải không? Tính toán của bạn sẽ là, 1 - 365 = -364. Mà chắc chắn nhất là không đúng.
Chris.Jenkins
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.