Java8 java.time : how to change the day of the week and the start time of the day?

标签 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() 一起工作,所以我没有走得太远。看起来我必须编写自己的编年史,这似乎太过分了。

你能帮帮我吗?

最佳答案

注意: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);
}

关于Java8 java.time : how to change the day of the week and the start time of the day?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37995022/

相关文章:

java - 在 Java 中实现队列的最快方法

java - Activity销毁时如何调用overridePendingTransition()?

java - Apache CommonsVFS 连接到 https 服务器

java - Google Drive API 文件上传错误 : “Missing end boundary in multipart body.”

java - DateTime ("2019-08-07T19:20-5:00") 转换为具有偏移值的本地日期时间

java - 如何使用 lambda 初始化 map ?

java - 服务器关闭使用 httpclient 和 Java 7 建立的连接

java - 方法引用,协方差逆变

Java 8 可选时间部分不起作用

java - 如何计算Java中特定两个日期之间的星期日