2016-06-23 32 views
6

Dire che voglio che la settimana inizi il martedì e che il giorno inizi alle 5:30.Java8 java.time: come modificare il giorno della settimana e l'ora di inizio della giornata?

Ciò significa, codice come questo dovrebbe funzionare:

// LocalDateTimes created with the "standard" ISO time 
LocalDateTime tuesday_4_30 = LocalDateTime.now() 
           .with(TemporalAdjusters.next(DayOfWeek.TUESDAY)) 
           .withHour(4).withMinute(30); 

LocalDateTime tuesday_6_30 = tuesday_4_30.withHour(6).withMinute(30); 
LocalDateTime previous_monday = tuesday_4_30.minusDays(1); 

// eventual adjustment using TemporalAdjusters here? like this? 
// tuesday_4_30 = tuesday_4_30.with(new MyTemporalAdjuster(DayOfWeek.TUESDAY, 5, 30)); 
// <do the same for 6_30 and previous monday> 
// or possibly change some global parameter like Chronology, Locale, or such.. 

Assert.assertEquals(tuesday_4_30.getDayOfWeek(), DayOfWeek.MONDAY); 

Assert.assertEquals(tuesday_6_30.getDayOfWeek(), DayOfWeek.TUESDAY); 

// there is 1 week between the previous monday and the next tuesday 6:30 
Assert.assertEquals(ChronoUnit.WEEKS.between(previous_monday,tuesday_6_30), 1); 

// there is 0 week between the previous monday and the next tuesday 4:30 
Assert.assertEquals(ChronoUnit.WEEKS.between(previous_monday,tuesday_4_30), 0); 

// 1 day between tuesday_4_30 and tuesday_6_30 
Assert.assertEquals(ChronoUnit.DAYS.between(tuesday_4_30,tuesday_6_30), 1); 

// 0 day between previous_monday and tuesday_4_30 
Assert.assertEquals(ChronoUnit.DAYS.between(previous_monday,tuesday_4_30), 1); 

Sono tentato di utilizzare regolatori temporali qui, e sono abbastanza sicuro che avrei potuto compensare le ore e minuti in modo che la giornata inizia alle 5: 30, ma non riesco a capire come modificare l'inizio della settimana.

Nota che ho controllato WeekFields ma non riesco a farlo funzionare con ChronoUnit.XXX.between(), quindi non sono andato troppo lontano. Sembra che dovrei codificare la mia cronologia, che sembrava troppo acuta.

Potete aiutarmi?

risposta

3

Nota: ChronoUnit.WEEKS.between conta il numero di intere settimane (un periodo di 7 giorni) tra due date. Nel tuo caso, c'è solo un giorno tra il lunedì e il martedì, quindi ritornerà 0. Probabilmente hai intenzione di confrontare i campi della settimana dell'anno.

A meno che non si vuole scrivere il proprio cronologia (che sta per essere un dolore), si potrebbe "falso" il vostro calendario:

  • convertire avanti e indietro tra UTC e GMT + 5: 30 a rappresentare il tempo di cut-off/o semplicemente sottrarre 05:30 dalle date
  • l'aggiunta di un po 'di semplice logica per i calcoli settimana

vedere di seguito un esempio di massima in base al codice, che rende tutti i test passano - si potrebbe voler estrarre la logica in una classe separata ecc. Questo è un po ' hacky ma potrebbe essere sufficiente per il tuo caso d'uso.

@Test 
public void test() { 
    LocalDateTime tuesday_4_30 = LocalDateTime.now() 
          .with(TemporalAdjusters.next(DayOfWeek.TUESDAY)) 
          .withHour(4).withMinute(30); 

    LocalDateTime tuesday_6_30 = tuesday_4_30.withHour(6).withMinute(30); 
    LocalDateTime previous_monday = tuesday_4_30.minusDays(1); 

    // eventual adjustment using TemporalAdjusters here? like this? 
    // tuesday_4_30 = tuesday_4_30.with(new MyTemporalAdjuster(DayOfWeek.TUESDAY, 5, 30)); 
    // <do the same for 6_30 and previous monday> 
    // or possibly change some global parameter like Chronology, Locale, or such.. 
    assertEquals(dayOfWeek(tuesday_4_30), DayOfWeek.MONDAY); 

    assertEquals(dayOfWeek(tuesday_6_30), DayOfWeek.TUESDAY); 

    // there is 1 week between the previous monday and the next tuesday 6:30 
    assertEquals(weekBetween(previous_monday, tuesday_6_30), 1); 

    // there is 0 week between the previous monday and the next tuesday 4:30 
    assertEquals(weekBetween(previous_monday, tuesday_4_30), 0); 

    // 1 day between tuesday_4_30 and tuesday_6_30 
    assertEquals(weekBetween(tuesday_4_30, tuesday_6_30), 1); 

    // 0 day between previous_monday and tuesday_4_30 
    assertEquals(weekBetween(previous_monday, tuesday_4_30), 0); 
} 

private static DayOfWeek dayOfWeek(LocalDateTime date) { 
    return date.atOffset(ZoneOffset.ofHoursMinutes(5, 30)).withOffsetSameInstant(UTC).getDayOfWeek(); 
} 
private static int weekBetween(LocalDateTime date1, LocalDateTime date2) { 
    OffsetDateTime date1UTC = date1.atOffset(ZoneOffset.ofHoursMinutes(5, 30)).withOffsetSameInstant(UTC); 
    OffsetDateTime date2UTC = date2.atOffset(ZoneOffset.ofHoursMinutes(5, 30)).withOffsetSameInstant(UTC); 
    int w1 = date1UTC.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR); 
    if (dayOfWeek(date1).getValue() >= TUESDAY.getValue()) w1++; 

    int w2 = date2UTC.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR); 
    if (dayOfWeek(date2).getValue() >= TUESDAY.getValue()) w2++; 

    return w2 - w1; 
} 

realizzazione alternativa, forse più puliti:

private static DayOfWeek dayOfWeek(LocalDateTime date) { 
    return adjust(date).getDayOfWeek(); 
} 

private static int weekBetween(LocalDateTime date1, LocalDateTime date2) { 
    int w1 = adjust(date1).get(IsoFields.WEEK_OF_WEEK_BASED_YEAR); 
    if (dayOfWeek(date1).getValue() >= TUESDAY.getValue()) w1++; 

    int w2 = adjust(date2).get(IsoFields.WEEK_OF_WEEK_BASED_YEAR); 
    if (dayOfWeek(date2).getValue() >= TUESDAY.getValue()) w2++; 

    return w2 - w1; 
} 

private static LocalDateTime adjust(LocalDateTime date) { 
    return date.minusHours(5).minusMinutes(30); 
} 
+0

Che dire di giorni tra? Il tuo codice funziona perché il mio caso funziona correttamente per entrambi. Ma suppongo che dovrei implementare gli stessi "giorni tra" come la tua "settimana tra"? – Gui13

+0

Sì, dovresti reimplementare tutti questi metodi. Potrebbe esserci un modo migliore. – assylias

Problemi correlati