Bagaimana cara mengulangi rentang Tanggal di Jawa?

145

Dalam skrip saya, saya perlu melakukan serangkaian tindakan melalui rentang tanggal, mengingat tanggal mulai dan berakhir.
Tolong beri saya panduan untuk mencapai ini menggunakan Java.

for ( currentDate = starDate; currentDate < endDate; currentDate++) {

}

Saya tahu kode di atas tidak mungkin, tetapi saya melakukannya untuk menunjukkan kepada Anda apa yang ingin saya capai.

Cache Staheli
sumber
Java 8 dan 9 pendekatan bersih: stackoverflow.com/a/51942109/1216775
akhil_mittal

Jawaban:

198

Nah, Anda bisa melakukan sesuatu seperti ini menggunakan time-API Java 8 , untuk masalah ini secara khusus java.time.LocalDate(atau kelas Joda Time yang setara untuk Java 7 dan yang lebih lama)

for (LocalDate date = startDate; date.isBefore(endDate); date = date.plusDays(1))
{
    ...
}

Saya benar - benar akan merekomendasikan menggunakan java.time(atau Joda Time) selama built-in Date/ Calendarkelas.

Jon Skeet
sumber
2
Untuk memperluas pada titik tentang Joda Time: mencoba untuk menerapkan ini dengan benar sendiri lebih sulit daripada yang mungkin dipikirkan karena kasus sudut di sekitar perubahan ke dan dari waktu musim panas.
Raedwald
+1 untuk Joda, saya harap suatu hari nanti akan mencapai tanahnya di API standar.
gyorgyabraham
4
@gyabraham: JSR-310 terlihat dalam kondisi yang cukup baik untuk Java 8.
Jon Skeet
4
Dapat mengkonfirmasi kode yang sama persis ini akan bekerja menggunakan Java 8's java.time.LocalDate, bukan Joda.
Es Molten
3
Proyek Joda-Time sekarang dalam mode pemeliharaan, dan merekomendasikan migrasi ke kelas java.time. Seperti disebutkan dalam komentar, kode Penjawab ini berfungsi seperti apa adanya di java.time, ubah saja importpernyataan Anda .
Basil Bourque
148

JodaTime bagus, namun, demi kelengkapan dan / atau jika Anda lebih suka fasilitas yang disediakan API, berikut adalah pendekatan API standar.

Saat memulai dengan java.util.Datecontoh seperti di bawah ini:

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date startDate = formatter.parse("2010-12-20");
Date endDate = formatter.parse("2010-12-26");

Inilah java.util.Calendarpendekatan lama jika Anda belum berada di Java8:

Calendar start = Calendar.getInstance();
start.setTime(startDate);
Calendar end = Calendar.getInstance();
end.setTime(endDate);

for (Date date = start.getTime(); start.before(end); start.add(Calendar.DATE, 1), date = start.getTime()) {
    // Do your job here with `date`.
    System.out.println(date);
}

Dan inilah java.time.LocalDatependekatan Java8 , pada dasarnya persis pendekatan JodaTime:

LocalDate start = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate end = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

for (LocalDate date = start; date.isBefore(end); date = date.plusDays(1)) {
    // Do your job here with `date`.
    System.out.println(date);
}

Jika Anda ingin mengulangi termasuk tanggal akhir, gunakan masing !start.after(end)- !date.isAfter(end)masing.

BalusC
sumber
75

Gaya Java 8 , menggunakan kelas java.time :

// Monday, February 29 is a leap day in 2016 (otherwise, February only has 28 days)
LocalDate start = LocalDate.parse("2016-02-28"),
          end   = LocalDate.parse("2016-03-02");

// 4 days between (end is inclusive in this example)
Stream.iterate(start, date -> date.plusDays(1))
        .limit(ChronoUnit.DAYS.between(start, end) + 1)
        .forEach(System.out::println);

Keluaran:

2016-02-28
2016-02-29
2016-03-01
2016-03-02

Alternatif:

LocalDate next = start.minusDays(1);
while ((next = next.plusDays(1)).isBefore(end.plusDays(1))) {
    System.out.println(next);
}

Java 9 menambahkan metode DateUntil () :

start.datesUntil(end.plusDays(1)).forEach(System.out::println);
Martin Andersson
sumber
1
dapatkah Anda menempatkan nilai beberapa? misalnya: hanya Senin atau Kamis atau keduanya
delive
26

Ini pada dasarnya adalah jawaban yang sama yang BalusC berikan, tetapi sedikit lebih mudah dibaca dengan loop sementara sebagai ganti loop

Calendar start = Calendar.getInstance();
start.setTime(startDate);

Calendar end = Calendar.getInstance();
end.setTime(endDate);

while( !start.after(end)){
    Date targetDay = start.getTime();
    // Do Work Here

    start.add(Calendar.DATE, 1);
}
Chris M.
sumber
3
Ini tidak akan berfungsi jika logikanya melibatkan pernyataan "melanjutkan", sedangkan versi for loop dari BalusC bekerja dengan pernyataan terus.
Sanjiv Jivan
6

Apache Commons

    for (Date dateIter = fromDate; !dateIter.after(toDate); dateIter = DateUtils.addDays(dateIter, 1)) {
        // ...
    }
Mike
sumber
+1, IMHO, ini adalah yang terbersih ketika Anda bekerja dengan kode lama. Hanya memasukkan impor statis ekstra untuk addDays(..)dan itu semakin pendek.
Priidu Neemre
4
private static void iterateBetweenDates(Date startDate, Date endDate) {
    Calendar startCalender = Calendar.getInstance();
    startCalender.setTime(startDate);
    Calendar endCalendar = Calendar.getInstance();
    endCalendar.setTime(endDate);

    for(; startCalender.compareTo(endCalendar)<=0;
          startCalender.add(Calendar.DATE, 1)) {
        // write your main logic here
    }

}
kushal agrawal
sumber
3
public static final void generateRange(final Date dateFrom, final Date dateTo)
{
    final Calendar current = Calendar.getInstance();
    current.setTime(dateFrom);

    while (!current.getTime().after(dateTo))
    {
        // TODO

        current.add(Calendar.DATE, 1);
    }
}
kayz1
sumber
3

Kita dapat melakukan migrasi logika ke berbagai metode untuk Java 7, Java 8 dan Java 9 :

public static List<Date> getDatesRangeJava7(Date startDate, Date endDate) {
    List<Date> datesInRange = new ArrayList<>();
    Calendar startCalendar = new GregorianCalendar();
    startCalendar.setTime(startDate);
    Calendar endCalendar = new GregorianCalendar();
    endCalendar.setTime(endDate);
    while (startCalendar.before(endCalendar)) {
        Date result = startCalendar.getTime();
        datesInRange.add(result);
        startCalendar.add(Calendar.DATE, 1);
    }
    return datesInRange;
}

public static List<LocalDate> getDatesRangeJava8(LocalDate startDate, LocalDate endDate) {
    int numOfDays = (int) ChronoUnit.DAYS.between(startDate, endDate);
    return IntStream.range(0, numOfDays)
            .mapToObj(startDate::plusDays)
            .collect(Collectors.toList());
}

public static List<LocalDate> getDatesRangeJava9(LocalDate startDate, LocalDate endDate) {
    return startDate.datesUntil(endDate).collect(Collectors.toList());
}

Kemudian kita dapat memanggil metode ini sebagai:

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date startDate = formatter.parse("2010-12-20");
Date endDate = formatter.parse("2010-12-26");
List<Date> dateRangeList = getDatesRangeJava7(startDate, endDate);
System.out.println(dateRangeList);

LocalDate startLocalDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate endLocalDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
List<LocalDate> dateRangeList8 = getDatesRangeJava8(startLocalDate, endLocalDate);
System.out.println(dateRangeList8);
List<LocalDate> dateRangeList9 = getDatesRangeJava8(startLocalDate, endLocalDate);
System.out.println(dateRangeList9);

Outputnya adalah:

[Sen, 20 Des 00:00:00 IST 2010, Selasa 21 Des 00:00:00 IST 2010, Rabu 22 Des 00:00:00 IST 2010, Kamis 23 Des 00:00:00 IST 2010, Jumat 24 Des 00: 00:00 IST 2010, Sabtu 25 Des 00:00:00 IST 2010]

[2010-12-20, 2010-12-21, 2010-12-22, 2010-12-23, 2010-12-24, 2010-12-25]

[2010-12-20, 2010-12-21, 2010-12-22, 2010-12-23, 2010-12-24, 2010-12-25]

akhil_mittal
sumber
1
Kelas-kelas yang mengerikan Datedan Calendardigantikan oleh kelas java.time tahun yang lalu. Secara khusus, diganti oleh Instantdan ZonedDateDate.
Basil Bourque
1
Saya suka cara Java 8 dan 9. Untuk Java 6 dan 7 saya sarankan menggunakan pustaka ThreeTen Backport dan kemudian dengan cara yang sama seperti di Java 8. Anda menunjukkan dengan baik bagaimana cara ini lebih jelas dan lebih ramah-programmer.
Ole VV
2

Berikut ini adalah kode Java 8. Saya pikir kode ini akan menyelesaikan masalah Anda. Selamat Coding

    LocalDate start = LocalDate.now();
    LocalDate end = LocalDate.of(2016, 9, 1);//JAVA 9 release date
    Long duration = start.until(end, ChronoUnit.DAYS);
    System.out.println(duration);
     // Do Any stuff Here there after
    IntStream.iterate(0, i -> i + 1)
             .limit(duration)
             .forEach((i) -> {});
     //old way of iteration
    for (int i = 0; i < duration; i++)
     System.out.print("" + i);// Do Any stuff Here
jatin Goyal
sumber
Ini adalah pendekatan terbaik dan mudah yang dapat Anda tindak lanjuti.
jatin Goyal
1

Mengapa tidak menggunakan zaman dan loop dengan mudah.

long startDateEpoch = new java.text.SimpleDateFormat("dd/MM/yyyy").parse(startDate).getTime() / 1000;

    long endDateEpoch = new java.text.SimpleDateFormat("dd/MM/yyyy").parse(endDate).getTime() / 1000;


    long i;
    for(i=startDateEpoch ; i<=endDateEpoch; i+=86400){

        System.out.println(i);

    }
mridul4c
sumber
1

Anda dapat menulis kelas seperti itu (mengimplementasikan antarmuka iterator) dan beralih di atasnya.

public class DateIterator implements Iterator<Date>, Iterable<Date>
{

 private Calendar end = Calendar.getInstance();
 private Calendar current = Calendar.getInstance();

 public DateIterator(Date start, Date end)
 {
     this.end.setTime(end);
     this.end.add(Calendar.DATE, -1);
     this.current.setTime(start);
     this.current.add(Calendar.DATE, -1);
 }

 @Override
 public boolean hasNext()
 {
     return !current.after(end);
 }

 @Override
 public Date next()
 {
     current.add(Calendar.DATE, 1);
     return current.getTime();
 }

 @Override
 public void remove()
 {
     throw new UnsupportedOperationException(
        "Cannot remove");
 }

 @Override
 public Iterator<Date> iterator()
 {
     return this;
 }
}

dan gunakan seperti:

Iterator<Date> dateIterator = new DateIterator(startDate, endDate);
while(dateIterator.hasNext()){
      Date selectedDate = dateIterator .next();

}
jdev
sumber
1

Anda dapat mencoba ini:

OffsetDateTime currentDateTime = OffsetDateTime.now();
for (OffsetDateTime date = currentDateTime; date.isAfter(currentDateTime.minusYears(YEARS)); date = date.minusWeeks(1))
{
    ...
}
Pankaj Singh
sumber
0

Ini akan membantu Anda memulai 30 hari secara berulang-ulang hingga tanggal hari ini. Anda dapat dengan mudah mengubah rentang tanggal dan arah.

private void iterateThroughDates() throws Exception {
    Calendar start = Calendar.getInstance();
    start.add(Calendar.DATE, -30);
    Calendar end = Calendar.getInstance();
    for (Calendar date = start; date.before(end); date.add(Calendar.DATE, 1))
        {
        System.out.println(date.getTime());
        }
}
Januka samaranyake
sumber