2011-11-30 6 views
6

Esiste un modo elegante per trovare il giorno della settimana più vicino a una determinata data utilizzando JodaTime? Inizialmente ho pensato che fosse setCopy(), ma questo imposta il giorno per il giorno particolare nella stessa settimana. Pertanto, se ld è 2011-11-27 e day è "Lunedì", la seguente funzione restituisce 2011-11-21 e non 2011-11-28 come desidero.Come trovare il giorno della settimana più vicino per una data arbitraria?

// Note that "day" can be _any_ day of the week, not just weekdays. 
    LocalDate getNearestDayOfWeek(LocalDate ld, String day) { 
     return ld.dayOfWeek().setCopy(day); 
    } 

output desiderato per vari ingressi:

2011-12-04, Monday => 2011-12-05 
2011-12-04, Tuesday => 2011-12-06 
2011-12-04, Wednesday => 2011-12-07 
2011-12-04, Thursday => 2011-12-01 
2011-12-04, Friday => 2011-12-02 
2011-12-04, Saturday => 2011-12-03 
2011-12-04, Sunday => 2011-12-04 

2011-12-05, Monday => 2011-12-05 
2011-12-05, Tuesday => 2011-12-06 
2011-12-05, Wednesday => 2011-12-07 
2011-12-05, Thursday => 2011-12-08 
2011-12-05, Friday => 2011-12-02 
2011-12-05, Saturday => 2011-12-03 
2011-12-05, Sunday => 2011-12-04 

Qui di seguito è un work-around sono arrivato fino a che funziona per le particolari vincoli nella mia situazione attuale, ma mi piacerebbe avere aiutare a trovare una soluzione completamente generica che funziona sempre.

LocalDate getNearestDayOfWeek(LocalDate ld, String day) { 
     LocalDate target = ld.dayOfWeek().setCopy(day); 
     if (ld.getDayOfWeek() > DateTimeConstants.SATURDAY) { 
      target = target.plusWeeks(1); 
     } 
     return target; 
    } 
+0

possibile duplicato del [Joda-Time:? Come ottenere il prossimo venerdì] (http://stackoverflow.com/questions/1636038/joda-time- how-to-get-the-next-venerdì) –

+2

Io non la penso così. Quello trova il giorno _next_, ma mi piacerebbe trovare il giorno più difficile. –

+0

È necessario definire cosa si intende per "più vicino" e "giorno della settimana" per essere in grado di fornire la risposta corretta. Forse una tabella di input attesi da produrre? – JodaStephen

risposta

5

In Jodatime, questo genere di cose dovrebbe essere fattibile con tre o quattro linee:

/** Given a reference LocalDate and a day of week, eg DateTimeConstants.MONDAY 
     Returns the nearest date with that day of week */ 
    public static LocalDate getNearestDayOfWeek(LocalDate t0,int dow) { 
     LocalDate t1 = t0.withDayOfWeek(dow); 
     LocalDate t2 = t1.isBefore(t0) ? t1.plusWeeks(1) : t1.minusWeeks(1); 
     return Math.abs(Days.daysBetween(t1, t0).getDays()) < 
       Math.abs(Days.daysBetween(t2, t0).getDays()) ? t1 : t2; 
    } 

O più compatti ed efficienti:

public static LocalDate getNearestDayOfWeek(LocalDate t0, int dow) { 
    LocalDate t1 = t0.withDayOfWeek(dow); 
    if (t1.isBefore(t0.minusDays(3)))  return t1.plusWeeks(1); 
    else if (t1.isAfter(t0.plusDays(3))) return t1.minusWeeks(1); 
    else return t1; 
} 

E se si vuole passare il giorno della settimana come Stringa:

public static LocalDate getNearestDayOfWeek(LocalDate t0, String dow) { 
    return getNearestDayOfWeek(t0,t0.dayOfWeek().setCopy(dow).getDayOfWeek()); 
} 

Esempio:

// prints 2011-11-28 
    public static void main(String[] args) throws Exception { 
     LocalDate today = new LocalDate(2011,11,27); 
     int dow = DateTimeConstants.MONDAY; 
     System.out.println(getNearestDayOfWeek(today ,dow)); 
    } 
+0

Questo è buono. Le stringhe hanno senso nella mia situazione particolare. (Avevo a che fare con il nome delle stringhe del giorno da un file di configurazione.) Sono d'accordo che non è il migliore nel caso generale. –

1

Ecco un approccio al problema. So un po 'di JodaTime, ma non tutte le classi e i metodi. Suppongo che data una data, puoi ottenere il giorno della settimana e le date successive o precedenti.

Ci sono tre casi.

  1. Il DayoftheWeek per una data particolare è un giorno della settimana. Data di ritorno.
  2. giornoOfTheWeek è sabato. Sottrai 1 giorno dalla tua data. Restituire la data - 1 giorno.
  3. dayOfTheWeek è domenica. Aggiungi 1 giorno alla tua data. Restituisci la data + un giorno.

Se DayoftheWeek è un tipo enumerato, poi una dichiarazione caso sarebbe gestire l'attività in modo dritto in avanti.

+0

Penso che tu abbia frainteso la mia domanda. Il tuo algoritmo sembra trovare il giorno della settimana più vicino, che non è quello che voglio. Piuttosto, per ogni data in cui voglio essere in grado di chiedere "qual è il lunedì più vicino? Martedì? Sabato?" Ho modificato la mia domanda per chiarire questo punto. –

+0

@ stig-brautaset: Sì, l'ho fatto. Ho pensato che avrei potuto avere quando ho scritto la risposta, ma ho pensato che una risposta sbagliata potrebbe aiutare a ottenere quella giusta :-) Ci riproverò più tardi. –

1

Trova il giorno più vicino della settimana definendo un intervallo dei giorni più vicini della settimana. Joda definisce una settimana a partire da lunedì. Quindi se oggi è martedì e il giorno della settimana è impostato su Domenica, la data sarà la domenica successiva, non la precedente. Se il primo giorno della settimana viene ridefinito in domenica, la data restituita sarà la domenica precedente. Il seguente codice non è influenzato dalla definizione del primo giorno della settimana.

 
DateTime getNearestDayOfWeek(DateTime dateTime, String day) { 
    //Create an interval containing the nearest days of the week. 
    DateTime begin = dateTime.minusHours(DateTimeConstants.HOURS_PER_WEEK/2).dayOfWeek().roundHalfCeilingCopy(); 
    DateTime end = dateTime.plusHours(DateTimeConstants.HOURS_PER_WEEK/2).dayOfWeek().roundHalfCeilingCopy(); 
    Interval interval = new Interval(begin, end); 

    //Adjust nearest day to be within the interval. Doesn't depend on definition of first day of the week. 
    DateTime nearest = dateTime.dayOfWeek().setCopy(day); 
    if (interval.isAfter(nearest)) //nearest is before the interval 
    return nearest.plusWeeks(1); 
    else if (interval.isBefore(nearest)) //nearest is after the interval 
    return nearest.minusWeeks(1); 
    else 
    return nearest; 
} 
+0

Un interessante modo alternativo per farlo. –

2

Qualcosa come questo. Per il parametro dayOfWeek, utilizzare le costanti definite in org.joda.time.DateTimeConstants:

public LocalDate getNext(int dayOfWeek) { 
    LocalDate today = new LocalDate(); 
    return getNext(dateOfWeek, today); 
} 

public LocalDate getNext(int dayOfWeek, LocalDate fromDate) { 
    int dayOffset = DateTimeConstants.DAYS_PER_WEEK - dayOfWeek + 1; 
    LocalDate weekContainingDay = fromDate.plusDays(dayOffset); 

    return weekContainingDay.withDayOfWeek(dayOfWeek); 
} 

Usage:

LocalDate nextSunday = foo.getNext(DateTimeConstants.SUNDAY); 
Problemi correlati