2009-05-11 2 views
6

Estoy buscando una clase de Java donde puedo especificar un conjunto de reglas de fecha, como "cada tercer domingo" y "la primera aparición de un lunes por segundo mes". Quiero ser capaz de obtener algo así como un iterador infinito (.next() devolvería la próxima fecha que coincida con el conjunto de reglas).Java fecha iterador de fábrica, con reglas que especifican cómo calcular los intervalos

Creo que podría construirlo yo mismo, pero los calendarios son una molestia, y parece que ya debería existir algo similar. Odio ser el que reinventa una rueda de crappier.

¿Alguien es consciente de algo como esto? He estado buscando en JODA, y parece sentar las bases para ello, pero no parece dar la funcionalidad completa que quiero ..

Respuesta

7

No creo que haya iteradores fácilmente hechos para joda-time o Java API de calendario para el caso, sin embargo, con joda es tan fácil que debería ir con él. Por ejemplo, después de volver a familiarizarme con joda después de unos pocos meses de pausa que hice esto en unos 10 minutos:

public class InstantIterator implements Iterator<Instant>, 
             Iterable<Instant> { 

    private Instant current; 
    private final Instant original; 
    private Duration skip; 
    private List<Instant> skipThese; 

    public InstantIterator(Instant startFrom, Duration skip) { 
     this.current = original = startFrom; 
     this.skip = skip; 
     skipThese = new Vector<Instant>(); 
    } 

    public boolean hasNext() { 
     return true; 
    } 

    public Instant next() { 
     Instant currentNext = current.toInstant(); 
     current = current.plus(skip); 
     while (skipThese.contains(currentNext)) { 
      currentNext = current.toInstant(); 
      current = current.plus(skip); 
     } 
     return currentNext; 
    } 

    public void remove() { 
     skipThese.add(current.toInstant()); 
    } 

    public Iterator<Instant> iterator() { 
     return this; 
    } 

    public void rewind() { 
     current = original.toInstant(); 
    } 

    public void resetRemoved() { 
     skipThese.clear(); 
    } 

    public void resetIterator() { 
     rewind(); 
     resetRemoved(); 
    } 
} 

Joda El tiempo es impresionante :-)

+0

Me sacudiste la tarde, gracias amigo! –

+0

Aunque no es importante en absoluto, solo quiero decir que este es el segundo iterador que he creado y que admite remove(); por lo general, he encontrado que es demasiado engorroso para admitirlo. – Esko

0

Puede echar un vistazo a Quartz que está diseñado para la programación de trabajos.

0

tl; dr

Fácil, con java.time.

Por tercera Jueves:

LocalDate.now().with(           // Get today's date, then adjust. 
    TemporalAdjusters.dayOfWeekInMonth(3 , DayOfWeek.THURSDAY) // Define adjuster to move to third Thursday of same month. 
)                 // Instantiates another `LocalDate` object (java.time uses immutable objects). 

java.time

Las clases de fecha y hora viejas problemáticas que vienen con las primeras versiones de Java son ahora obsoletos, suplantado por las clases java.time.

La clase LocalDate representa un valor de fecha solamente sin hora del día y sin zona horaria.

LocalDate ld = LocalDate.of(2018 , Month.FEBRUARY , 17) ; 

Para cualquier LocalDate, puede ajustar en la ocurrencia ordinal de un día de la semana dentro del mismo mes (por ejemplo: tercer jueves 2 martes, etc.). Especifique el día de la semana con DayOfWeek enum.

Para realizar el ajuste, utilice una implementación TemporalAdjuster que se encuentra en la clase TemporalAdjusters.

TemporalAdjuster thirdThursdayAdjuster = TemporalAdjusters.dayOfWeekInMonth​(3 , DayOfWeek.THURSDAY) ; // Third-Thursday. 

aplicar ese ajuste para cualquier LocalDate, produciendo otro objeto LocalDate.

LocalDate thirdThursday = ld.with(thirdThursdayAdjuster) ; 

algo así como un iterador infinita fuera de él (.Next() devolvería la próxima fecha a juego

Basta con pasar de una a otra LocalDate. Se le podría llamar LocalDate::addMonths.O si se trata de un mes a la vez, use la clase YearMonth.

TemporalAdjuster thirdThursdayAdjuster = TemporalAdjusters.dayOfWeekInMonth​(3 , DayOfWeek.THURSDAY) ; // Third-Thursday. 
List<LocalDate> dozenThirdThursdays = new ArrayList<>(12) ; 
YearMonth start = YearMonth.of(2018 , Month.MARCH) ; 
for(int i = 1 ; i <= 12 ; i ++) { 
    YearMonth ym = start.plusMonths(i) ; 
    LocalDate firstOfMonth = ym.atDay(1) ; 
    LocalDate thirdThursday = firstOfMonth.with(thirdThursdayAdjuster) ; 
    dozenThirdThursdays.add(thirdThursday) ; 
} 

Sobre java.time

El marco java.time está incorporado en Java 8 y versiones posteriores. Estas clases suplantan a las viejas y problemáticas clases de fecha y hora de legacy, como java.util.Date, Calendar, & SimpleDateFormat.

El proyecto Joda-Time, ahora en maintenance mode, recomienda la migración a las clases java.time.

Para obtener más información, consulte el Oracle Tutorial. Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310.

¿Dónde obtener las clases java.time?

  • Java SE 8, Java SE 9, y más tarde
    • incorporado.
    • Parte de la API estándar de Java con una implementación integrada.
    • Java 9 agrega algunas características menores y correcciones.
  • Java SE 6 y Java SE 7
    • Gran parte de la funcionalidad de back-java.time está portado a Java 6 & 7 en ThreeTen-Backport.
  • Android
    • Las versiones posteriores de las implementaciones de haces de Android de las clases java.time.
    • Para Android anterior, el proyecto ThreeTenABP se adapta a ThreeTen-Backport (mencionado anteriormente). Ver How to use ThreeTenABP….

El proyecto se extiende ThreeTen-Extra java.time con clases adicionales. Este proyecto es un terreno de prueba para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí, como Interval, YearWeek, YearQuarter y more.

Cuestiones relacionadas