2016-06-23 2 views
6

Скажите, что я хочу, чтобы моя неделя началась во вторник, и день должен начаться в 5:30.Java8 java.time: как изменить день недели и время начала дня?

Это означает, что код, как это должно работать:

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

Я соблазн использовать временные регулировочные здесь, и я совершенно уверен, что я мог бы компенсировать часы и минуты, так что день начинается в 5: 30, но я не могу понять, как изменить начало недели.

Обратите внимание, что я просмотрел WeekFields, но я не могу заставить его работать с ChronoUnit.XXX.between(), поэтому я не зашел слишком далеко. Похоже, мне пришлось бы закодировать мою собственную хронологию, которая казалась слишком удаленной.

Вы можете мне помочь?

ответ

3

Примечание: ChronoUnit.WEEKS.between подсчитывает количество целых недель (период 7 дней) между двумя датами. В вашем случае есть только один день между понедельником и вторником, поэтому он вернет 0. Вы, вероятно, хотели сравнить поля недели года.

Если вы не хотите, чтобы написать свою собственную хронологию (что будет боль), вы можете «фальшивый» календарь по:

  • преобразовывая назад и вперед между UTC и UTC + 5: 30, чтобы представить ваше время отсечка/или просто вычесть 5:30 от даты
  • добавив некоторую простую логику недели расчетов

см.ниже шероховатой например, на основе кода, что делает все тесты проходят - вы может захотеть извлечь логику в отдельный класс и т. д. Это немного хаки, но может быть достаточно для вашего случая использования.

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

Альтернативная реализация, возможно, очиститель:

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

насчет дней между ними? Ваш код работает, потому что мой случай работает для обоих. Но я предполагаю, что мне придется реализовать те же «daysBetween», что и ваша «weekBetween»? – Gui13

+0

Да, вам придется переопределить все эти методы. Там может быть лучший способ. – assylias

Смежные вопросы