2014-10-16 8 views
9

Desidero controllare se un periodo di date contiene il 29 febbraio.Java 8 DateTime verifica se il periodo contiene giorno specifico

private static final MonthDay LEAP = MonthDay.of(Month.FEBRUARY, 29); 

Ho provato:

if (LEAP.isAfter(beginDate) && LEAP.isBefore(maturity)) { 

    } 

ma beginDate e maturity provengono dal tipo LocalDate così metodi .isAfter e .isBefore non possono essere utilizzati.

Esempio

beginDate è 15.01.2012
maturity è 20.01.2013

durante questo periodo il 29 febbraio esiste

Soluzione

ho finalmente trovato una soluzione:

for (int i = beginDate.getYear(); i <= maturity.getYear(); i++) { 
    final Year year = Year.of(i); 
    if (year.isLeap()) { 
     if (beginDate.compareTo(LEAP.atYear(i)) <= 0 || maturity.compareTo(LEAP.atYear(i)) >= 0) { 
      minMaturity.plusDays(1); 
     } 
    } 
    return false; 
} 
+0

Basta controllare l'ultimo giorno del mese febbraio – Roshan

+0

E 'un momento joda o Java 8 question time api? La risposta potrebbe essere diversa ... – assylias

+0

@assylias Java 8. Grazie :-) – YvesHendseth

risposta

1

Hai provato la conversione del LocalDate e MonthDay-DateTime utilizzando rispettivamente toDateTimeAtStartOfDay e toDateTime?

È necessario verificare se ciò si tradurrebbe in vero quando l'anno non è un anno bisestile. Potrebbe.

1

Come creare un intervallo e controllarlo? Qualcosa di simile:

LocalDate beginDate, maturity; 
    final Interval interval = new Interval(beginDate.toDateTimeAtStartOfDay(), maturity.toDateTimeAtStartOfDay()); 
    if (interval.contains(new DateTime(beginDate.getYear(), Month.FEBRUARY, 29, 0, 1)) || 
     interval.contains(new DateTime(maturity.getYear(), Month.FEBRUARY, 29, 0, 1))) { 
     // It does 
    } 
+2

fallirà quando il 29 febbraio è in scadenza l'anno – YvesHendseth

+0

Vero, e per controllare entrambi è brutto. : -/ –

3

Un modo potrebbe essere quello di creare un TemporalAdjuster che restituisce il prossimo 29 febbraio e verificare se maturity è prima o dopo tale data. Esempio (non testato):

public static TemporalAdjuster nextOrSame29Feb() { 
    return temporal -> { 
    LocalDate input = LocalDate.from(temporal); 
    if (input.isLeapYear()) { 
     LocalDate feb29 = input.with(MonthDay.of(FEBRUARY, 29)); 
     if (!input.isAfter(feb29)) return feb29; 
    } 
    for (int year = input.getYear() + 1; ; year++) { 
     if (Year.isLeap(year)) return LocalDate.of(year, FEBRUARY, 29); 
    } 
    }; 
} 

e il codice la:

boolean contains29Feb = !maturity.isBefore(beginDate.with(nextOrSame29Feb())); 
+0

Grazie! Lo proverò domani :-) – YvesHendseth

1

Mi piace pensare in termini di casi di test. Quali valori per beginDate e endDate causeranno un tale metodo per restituire vero o falso?

Ad esempio, cosa succede se si trovano nello stesso anno? Forse entrambi i valori sono dalla stessa parte del 29 febbraio o lo comprendono.

E se fossero in anni diversi? Cosa succede se quegli anni sono adiacenti, o se ci sono altri anni in mezzo? Forse nessuno degli anni che intercorrono è nemmeno un anno bisestile.

Quello che puoi fare in questo tipo di scenario è mettere insieme esempi di questi casi e poi scrivere un metodo, regolandolo fino a che passino tutti gli asseriti.

Di seguito è riportato un approccio che è possibile adottare. È possibile aggiungere casi in cui lo beginDate e/o lo maturity atterrano in un giorno bisestile.

public class Q26403911 { 
    @Test 
    public void testContainsLeapYear() throws Exception { 
     Assert.assertTrue(isContainsLeapYear(LocalDate.of(1984, 2, 28), LocalDate.of(1984, 3, 1))); 
     Assert.assertFalse(isContainsLeapYear(LocalDate.of(1985, 2, 28), LocalDate.of(1985, 3, 1))); 
     Assert.assertFalse(isContainsLeapYear(LocalDate.of(1984, 2, 27), LocalDate.of(1984, 2, 28))); 
     Assert.assertFalse(isContainsLeapYear(LocalDate.of(1984, 3, 1), LocalDate.of(1984, 3, 2))); 
     Assert.assertTrue(isContainsLeapYear(LocalDate.of(1984, 2, 28), LocalDate.of(1985, 3, 1))); 
     Assert.assertTrue(isContainsLeapYear(LocalDate.of(1983, 3, 1), LocalDate.of(1984, 3, 1))); 
     Assert.assertFalse(isContainsLeapYear(LocalDate.of(1984, 3, 1), LocalDate.of(1985, 3, 1))); 
     Assert.assertFalse(isContainsLeapYear(LocalDate.of(1983, 2, 28), LocalDate.of(1984, 2, 28))); 
     Assert.assertTrue(isContainsLeapYear(LocalDate.of(1983, 3, 1), LocalDate.of(1985, 2, 28))); 
     Assert.assertFalse(isContainsLeapYear(LocalDate.of(1985, 3, 1), LocalDate.of(1987, 2, 28))); 
    } 

    public boolean isContainsLeapYear(LocalDate beginDate, LocalDate maturity) { 
     if (beginDate.getYear() == maturity.getYear()) 
     { 
      if (!Year.isLeap(beginDate.getYear())) 
      { 
       return false; 
      } 

      if (maturity.isBefore(LocalDate.of(beginDate.getYear(), Month.FEBRUARY, 29))) 
      { 
       return false; 
      } 

      if (beginDate.isAfter(LocalDate.of(maturity.getYear(), Month.FEBRUARY, 29))) 
      { 
       return false; 
      } 

      return true; 
     } 
     else if (Year.isLeap(beginDate.getYear()) 
         && !beginDate.isAfter(LocalDate.of(beginDate.getYear(), Month.FEBRUARY, 29))) 
     { 
      return true; 
     } 
     else if (Year.isLeap(maturity.getYear()) 
         && !maturity.isBefore(LocalDate.of(maturity.getYear(), Month.FEBRUARY, 29))) 
     { 
      return true; 
     } 
     else 
     { 
      for (int year = beginDate.getYear() + 1; year < maturity.getYear(); year++) 
      { 
       if (Year.isLeap(year)) 
       { 
        return true; 
       } 
      } 
     } 
     return false; 
    } 
} 
0

posso proporre soluzione successiva, witout MonthDay

static int LEAP = 31 + 29; 

    public static boolean conatins29Feb(LocalDate dateFrom, LocalDate dateTo) 
    { 
     final int yearFrom = dateFrom.getYear(), 
       yearTo = dateTo.getYear(), 
       dayOfYearFrom = dateFrom.getDayOfYear(), 
       dayOfYearTo = dateTo.getDayOfYear(), 
       nearestLeapYear = (yearTo/4) * 4; // nearest to `dateTo` 

     return (yearFrom <= nearestLeapYear && yearTo >= nearestLeapYear) 
       && (yearFrom < nearestLeapYear || dayOfYearFrom <= LEAP) 
        && (yearTo > nearestLeapYear || dayOfYearTo >= LEAP); 
    } 
+0

Sei sicuro su: 'nearestLeapYear = (yearTo/4) * 4;'? Per esempio, il 1900 non è stato un anno bisestile ... Usare i metodi integrati è probabilmente una scelta migliore rispetto a farlo manualmente ... – assylias