Java8 java.time:如何更改星期几和当天的开始时间?

时间:2016-06-23 14:48:45

标签: java java-8 java-time

说我希望我的星期在星期二开始,那天应该从早上5:30开始。

这意味着,像这样的代码应该有效:

// 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()一起使用,所以我没有走得太远。看起来我不得不编写自己的年表,这似乎太过拉伸了。

你能帮助我吗?

1 个答案:

答案 0 :(得分:3)

注意:ChronoUnit.WEEKS.between计算两个日期之间的整周数(7天)。在你的情况下,星期一和星期二之间只有一天,所以它将返回0.你可能想要比较一年中的星期字段。

除非您想编写自己的年表(这会很痛苦),否则您可以通过以下方式“伪造”您的日历:

  • 在UTC和UTC + 5:30之间来回转换以表示您的截止时间/或从日期中减去5:30
  • 为本周计算添加一些简单的逻辑

请参阅下面一个基于您的代码的粗略示例,它使所有测试都通过 - 您可能希望将逻辑提取到一个单独的类等。这有点hacky但可能足以满足您的用例。

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