2015-03-25 15 views
5

Trong mã của tôi, tôi cần phải lặp giữa một loạt các số ngày sử dụng Joda, và tôi đã cố gắng này:Lặp giữa phạm vi hai ngày sử dụng Joda

for(LocalDate currentdate = startDate; currenDate.isBefore(endDate); currenDate= currenDate.plusDays(1)){ 
    System.out.println(currentdate); 
} 

Đoạn mã trên đang làm việc, nhưng lặp dừng lại khi currenDate đạt đến ngày trước endDate. Những gì tôi muốn đạt được là lặp lại dừng khi currentDate chính xác giống như endDate.

for(Date currentdate = startDate; currentdate <= endDate; currentdate++){ 
    System.out.println(currentdate); 
} 

Tôi biết mã ở trên là không thể, nhưng tôi làm điều đó để làm rõ những gì tôi muốn.

Trả lời

7

Trên thực tế có một cách đơn giản xung quanh để mã ban đầu của bạn, bạn đăng, thấy thi của tôi dưới đây, chỉ cần sửa đổi của bạn để thực hiện vòng lặp:

//test data 
    LocalDate startDate = LocalDate.now(); //get current date 
    LocalDate endDate = startDate.plusDays(5); //add 5 days to current date 

    System.out.println("startDate : " + startDate); 
    System.out.println("endDate : " + endDate); 

    for(LocalDate currentdate = startDate; 
      currentdate.isBefore(endDate) || currentdate.isEqual(endDate); 
      currentdate= currentdate.plusDays(1)){ 
     System.out.println(currentdate); 
    } 

dưới đây là Output (liên quan đến LOCALDATE của tôi):

NgàyBắtđầu: 2015/03/26
NgàyKếtthúc: 2015-03-31
2015-03-26
2015-03-27
2015-03-28
2015-03-29
2015 -03-30
2015-03-31

Hope this helps! Chúc mừng. :)

+0

'!currentDate.isAfter (endDate) 'ngắn hơn' currentdate.isBefore (endDate) || currentdate.isEqual (endDate) '. Nói cách khác, sử dụng “KHÔNG lớn hơn” như một phiên bản ngắn hơn “nhỏ hơn hoặc bằng”. Xem [Câu trả lời của tôi] (https://stackoverflow.com/a/44320192/642706) để có ví dụ hoàn chỉnh. Và bây giờ tôi thấy [câu trả lời này] (https://stackoverflow.com/a/44316083/642706) có cùng ý tưởng, nhưng trong vòng lặp 'for' so với vòng lặp' while' của tôi. –

1

Không chắc với Joda-type nhưng bạn có thể lặp lại ở khoảng thời gian (giây, phút, giờ, ngày, tháng, năm) với Calendar API, here & here là những ví dụ

4

Nếu bạn muốn vòng lặp của bạn để ngăn chặn khi ngày lặp của bạn giống như ngày hôm nay, bạn có thể sử dụng kiểm tra bình đẳng cho điều đó.

Có một cái nhìn tại .equals() vào LOCALDATE

Dưới đây là một ví dụ nhanh:

public class DateIterator { 

    public static void main(String[] args) { 

     LocalDate lastMonth = LocalDate.now().minusMonths(1); 
     LocalDate lastWeek = LocalDate.now().minusWeeks(1); 
     LocalDate yesterday = LocalDate.now().minusDays(1); 
     LocalDate today = LocalDate.now(); 
     LocalDate tomorrow = LocalDate.now().plusDays(1); 

     List<LocalDate> dates = Arrays.asList(lastMonth, lastWeek, yesterday, today, tomorrow); 

     for (LocalDate date : dates) { 
      if (date.isEqual(today)) { 
       System.out.println("Date is equal to todays date! Break out, or do something else here"); 
      } else if (date.isBefore(today)) { 
       System.out.println("The date " + date.toString() + " is in the past"); 
      } else { 
       System.out.println("The date " + date.toString() + " is in the future"); 
      } 
     } 
    } 
} 

Output là:

The date 2015-02-25 is in the past 
The date 2015-03-18 is in the past 
The date 2015-03-24 is in the past 
Date is equal to todays date! Break out, or do something else here 
The date 2015-03-26 is in the future 

Rõ ràng, nếu đó là kiểm tra bình đẳng trôi qua, bạn sẽ cần để thoát khỏi vòng lặp, v.v.

Có một số khác sử dụng một ngày cụ thể và từng bước 1 ngày tại một thời điểm, mà tôi nghĩ là một chút giống như những gì bạn muốn

public class DateIterator { 

    public static void main(String[] args) { 

     LocalDate specificDate = LocalDate.now().minusWeeks(1); 
     LocalDate today = LocalDate.now(); 

     boolean matchFound = false; 
     while (!matchFound) { 
      if (!specificDate.isEqual(today)) { 
       System.out.println(specificDate.toString() + " is in the past, incrementing day and checking again..."); 
       specificDate = specificDate.plusDays(1); 
      } else { 
       System.out.println("Date matches today!"); 
       matchFound = true; 
      } 
     } 
    } 
} 

Output:

2015-03-18 is in the past, incrementing day and checking again... 
2015-03-19 is in the past, incrementing day and checking again... 
2015-03-20 is in the past, incrementing day and checking again... 
2015-03-21 is in the past, incrementing day and checking again... 
2015-03-22 is in the past, incrementing day and checking again... 
2015-03-23 is in the past, incrementing day and checking again... 
2015-03-24 is in the past, incrementing day and checking again... 
Date matches today! 
+0

Rất tiếc, tôi không hiểu liệu bạn có đang lặp qua một loạt ngày hay có dữ liệu cố định và tăng thêm 1 ngày cùng một lúc hay không, nhưng tôi đã đưa ra ví dụ về cả hai. HTH – Jimmy

+0

cảm ơn bạn đã trả lời, ví dụ thứ hai của bạn đang hoạt động, cảm ơn: D –

2

Nếu bạn muốn vòng lặp bao gồm endDate, bạn có thể sử dụng !currentDate.isAfter(endDate). Điều này tương đương về mặt logic với currentDate.isBefore(endDate) || currentDate.equals(endDate).

Ví dụ sau sẽ in 6/1/2017 đến ngày 6/10/2017.

LocalDate startDate = new LocalDate(2017, 6, 1); 
LocalDate endDate = new LocalDate(2017, 6, 10); 
for (LocalDate currentDate = startDate; !currentDate.isAfter(endDate); currentDate = currentDate.plusDays(1)) 
{ 
    System.out.println(currentDate); 
} 
1

Sử dụng java.time

Dự án Joda-Time hiện đang ở maintenance mode, với đội ngũ tư vấn chuyển đổi sang các java.time lớp. Xem Tutorial by Oracle.

Lớp LocalDate đại diện cho giá trị chỉ có ngày không có thời gian trong ngày và không có múi giờ.

LocalDate start = LocalDate.of(2017 , Month.JANUARY , 23) ; 
LocalDate stop = LocalDate.of(2017 , Month.FEBRUARY , 2) ; 

Nhân tiện, bạn có thể muốn thêm kiểm tra tính xác thực để xác minh rằng kết thúc không phải trước khi bắt đầu.

Không sau

Tôi tin rằng logic bạn đang tìm kiếm, bao gồm ngày kết thúc, là "không sau". Lớp LocalDate bao gồm phương thức isAfter, mà bạn có thể thêm “NOT” (!) hợp lý.

Ngoài ra, vòng lặp while có vẻ thích hợp và tự giải thích trong trường hợp này hơn vòng lặp for.

LocalDate ld = start ; 
List<LocalDate> dates = new ArrayList<>() ; 
while (! ld.isAfter(stop)) { 
    dates.add(ld); // Collect this date. 
    ld = ld.plusDays(1) ; // Setup the next loop. 
} 

Xem code run live at IdeOne.com này.

ngày: [2017-01-23, 2017-01-24, 2017-01-25, 2017-01-26, 2017-01-27, 2017-01-28, 2017-01-29 , 2017/01/30, 2017/01/31, 2017/02/01, 2017/02/02]

nửa mở

lặp dừng lại khi currentDate đạt một ngày trước ENDDATE

Điều này thực sự mong muốn. Được gọi là Nửa mở, phương pháp phổ biến trong xử lý ngày giờ là xem xét sự bắt đầu là bao gồm trong khi kết thúc là độc quyền. Vì vậy, giờ nghỉ trưa bắt đầu lúc 12:00:00 (trưa) và chạy đến, nhưng không bao gồm, 13:00:00 (1 giờ chiều). Tháng 1 bắt đầu vào ngày 1 tháng 1 và chạy đến, nhưng không bao gồm, ngày 1 tháng Hai. Một tuần bắt đầu vào Thứ Hai và chạy đến, nhưng không bao gồm Thứ Hai sau. Theo cách hữu ích nhất, cách tiếp cận này tránh được vấn đề xác định lần tách thứ hai cuối cùng của một ngày mà một số hệ thống sử dụng mili giây (x.999), một số (x.999999), cùng nano giây (x.999999999) và một số khác sử dụng các biến thể như vậy như 5 chữ số thập phân (x.99999). Thay vào đó chúng tôi đi đến, nhưng không bao gồm, thời điểm đầu tiên của giờ hoặc ngày tiếp theo, v.v.

Tôi thấy rằng sử dụng phương pháp Half-Open một cách nhất quán trong suốt mã của tôi làm cho mã dễ đọc hơn, dễ hiểu hơn ít có khả năng dẫn đến lỗi off-by-one. Tôi đã bị bắt trong vô số vấn đề bí ẩn tài chính mà hóa ra là sự nhầm lẫn hoặc hiểu lầm về một báo cáo bao gồm ngày cho với ngày tháng độc quyền bao gồm. Vì vậy, nếu có thể, hãy đào tạo người dùng của bạn để nghĩ cách nửa mở một cách nhất quán. Nếu không khả thi, sau đó điều chỉnh mã của bạn để logic và vòng lặp của bạn đang sử dụng Half-Open trong nội bộ ít nhất.

Đây là mã tương tự như trên, nhưng sử dụng isBefore hơn NOT isAfter, sử dụng cách tiếp cận Half-Open. Kết thúc là ngày 3 tháng 2 thay vì ngày 2 tháng 2.

LocalDate start = LocalDate.of(2017 , Month.JANUARY , 23) ; 
LocalDate stop = LocalDate.of(2017 , Month.FEBRUARY , 3) ; // Third instead of the Second of February, to be half-open. 

LocalDate ld = start ; 
List<LocalDate> dates = new ArrayList<>() ; 
while (ld.isBefore(stop)) { // Using "isBefore" for Half-Open approach. 
    dates.add(ld); // Collect this date. 
    ld = ld.plusDays(1) ; // Setup the next loop. 
} 

Xem này code run live at IdeOne.com.

bắt đầu: 2017-01-23 | ngừng: 2017-02-03

ngày: [2017-01-23, 2017-01-24, 2017-01-25, 2017-01-26, 2017-01-27, 2017-01-28, 2017/01/29, 2017/01/30, 2017/01/31, 2017/02/01, 2017/02/02]


Về java.time

khung java.time được xây dựng trong Java 8 trở lên. Các lớp này thay thế các lớp học ngày giờ legacy phiền hà cũ như java.util.Date, Calendar, & SimpleDateFormat.

Dự án Joda-Time, hiện đang ở maintenance mode, khuyên di chuyển đến các lớp java.time.

Để tìm hiểu thêm, hãy xem Oracle Tutorial. Và tìm kiếm Stack Overflow cho nhiều ví dụ và giải thích. Đặc điểm kỹ thuật là JSR 310.

Nơi lấy các lớp java.time?

Dự án mở rộng ThreeTen-Extra java.time với các lớp bổ sung. Dự án này là một nền tảng chứng minh cho những bổ sung có thể có trong tương lai vào java.time. Bạn có thể tìm thấy một số lớp học hữu ích tại đây như Interval, YearWeek, YearQuartermore.

Các vấn đề liên quan