2016-06-23 21 views
6

Powiedz, że chcę, aby mój tydzień rozpoczął się we wtorek, a dzień powinien rozpocząć się o 5:30 rano.Java8 java.time: jak zmienić dzień tygodnia i godzinę rozpoczęcia dnia?

Oznacza to, kod jak to powinno działać:

// 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); 

Mam pokusę wykorzystania regulatory czasowe tutaj i jestem pewien, mogę przesunięcie godziny i minuty tak, że dzień zaczyna się o 5: 30, ale nie wiem, jak zmodyfikować początek tygodnia.

Zauważ, że zajrzałem do WeekFields, ale nie mogę zadziałać z ChronoUnit.XXX.between(), więc nie posunąłem się za daleko. Wygląda na to, że musiałbym napisać własną Chronologię, która wydawała mi się zbyt daleko posunięta.

Czy możesz mi pomóc?

Odpowiedz

3

Uwaga: zlicza liczbę całych tygodni (okres 7 dni) między dwiema datami. W twoim przypadku jest tylko jeden dzień od poniedziałku do wtorku, więc wróci 0. Prawdopodobnie chciałeś porównać pola tygodni w roku.

ile chcesz napisać swoją chronologię (to będzie ból), można „fake” kalendarza poprzez:

  • konwersji iz powrotem między czasem UTC i czasem UTC + 5: 30 do reprezentowania Twój czas odcięcia/lub po prostu odejmować 5:30 od dat
  • dodając jakąś prostą logikę do obliczeń tygodniu

patrz niżej szorstkiej przykład oparte na kodzie, który sprawia, że ​​wszystkie testy przechodzą - ty może chcieć wyodrębnić logikę do oddzielnej klasy itp. To jest trochę hacky, ale może wystarczyć dla twojego przypadku użycia.

@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; 
} 

alternatywna implementacja, może czystsze:

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

co dzień pomiędzy? Twój kod działa, ponieważ mój przypadek działa dla obu. Ale myślę, że musiałbym zaimplementować te same "dni międzyplanetarne" jako "Tydzień w tygodniu"? – Gui13

+0

Tak, musisz ponownie zastosować wszystkie te metody. Może być lepszy sposób. – assylias

Powiązane problemy