一年中一周的即时时间
Instant time from week of year
我需要从一年中的周数中获取 Instant
时间。现在我使用旧的 Calendar
API 来计算时间:
int week = 1; // week of year
final Calendar cal = new GregorianCalendar();
cal.set(0, 1, 0, 0, 0, 0); // reset calendar
cal.set(Calendar.YEAR, Year.now().getValue());
cal.set(Calendar.WEEK_OF_YEAR, week);
cal.setTimeZone(TimeZone.getTimeZone(ZoneOffset.UTC));
final Instant start = cal.getTime().toInstant();
final Instant end = start.plus(Period.ofWeeks(1));
是否可以使用新的 Java 时间 API(java.time
包)从一年中的第几周获得 Instant
?
您可以使用以下方法调整星期:
LocalDateTime localDateTime = LocalDateTime.of(2020, 1, 1, 0, 0);
System.out.println(localDateTime); //2020-01-01T00:00
localDateTime = localDateTime.with(ChronoField.ALIGNED_WEEK_OF_YEAR, 2);
System.out.println(localDateTime); //2020-01-08T00:00
localDateTime = localDateTime.plusWeeks(10);
System.out.println(localDateTime); //2020-03-18T00:00
并将其解析为 Instant 取决于您使用的 API 中的 class:
LocalDateTime.now().toInstant(ZoneOffset.of("+04:00"));
ZonedDateTime.now().toInstant();
LocalDateTime
没有区域,因此您必须提供 ZoneOffset
才能将其解析为 Instant。
要设置月份,您可以使用此 lambda 表达式:
LocalDate.now().with(temporal
-> temporal.with(ChronoField.ALIGNED_WEEK_OF_YEAR, 1l)
);
现在很容易获得即时:
LocalDate localDate = LocalDate.now().with(temporal
-> temporal.with(ChronoField.ALIGNED_WEEK_OF_YEAR, 1l)
);
Instant instant = localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
如果你不想让 cto 改变时间,那么你可以用这个代替最后一行:
Instant instant = localDate.atTime(LocalTime.now()).atZone(ZoneId.systemDefault()).toInstant();
WeekFields wf = WeekFields.of(Locale.getDefault());
int week = 1; // week of year
LocalDate startDate = LocalDate.now(ZoneOffset.UTC)
.with(wf.weekOfWeekBasedYear(), week)
.with(wf.dayOfWeek(), 1);
Instant startInstant = startDate.atStartOfDay(ZoneOffset.UTC).toInstant();
LocalDate endDate = startDate.plusWeeks(1);
Instant endInstant = endDate.atStartOfDay(ZoneOffset.UTC).toInstant();
System.out.println("" + startInstant + " - " + endInstant);
我的语言环境使用 ISO 周数。这里的输出是:
2019-12-29T00:00:00Z - 2020-01-05T00:00:00Z
如果您希望独立于区域设置的 ISO 周,请将 wf
设置为 WeekFields.ISO
。如果您想要其他周编号方案,请相应地设置 wf
。
为了防止其他读者疑惑,Kirill 将周末定义为下周的第一时刻。这是推荐的。它被称为使用 半开间隔 作为时间间隔。
我也同意这个问题,即人们显然更喜欢使用 java.time 而不是 Calendar
来完成这项任务。 Calendar
设计不佳且已过时,我相信使用 java.time 的代码更易读。
另外,题中使用Calendar
的代码并没有设置一周的第一天,所以不会给你那一天。虽然我没有测试过,但我怀疑代码有时会在新年前后产生意想不到的结果。
我使用 java.time 中的 WeekFields
的代码将保留在当前 基于周的年份 内,这与日历年不同。例如,如果我在 2019 年 12 月 30 日 运行 它,它仍然会给出 2020 年的第 1 周,因为我们已经在那一周了。
我需要从一年中的周数中获取 Instant
时间。现在我使用旧的 Calendar
API 来计算时间:
int week = 1; // week of year
final Calendar cal = new GregorianCalendar();
cal.set(0, 1, 0, 0, 0, 0); // reset calendar
cal.set(Calendar.YEAR, Year.now().getValue());
cal.set(Calendar.WEEK_OF_YEAR, week);
cal.setTimeZone(TimeZone.getTimeZone(ZoneOffset.UTC));
final Instant start = cal.getTime().toInstant();
final Instant end = start.plus(Period.ofWeeks(1));
是否可以使用新的 Java 时间 API(java.time
包)从一年中的第几周获得 Instant
?
您可以使用以下方法调整星期:
LocalDateTime localDateTime = LocalDateTime.of(2020, 1, 1, 0, 0);
System.out.println(localDateTime); //2020-01-01T00:00
localDateTime = localDateTime.with(ChronoField.ALIGNED_WEEK_OF_YEAR, 2);
System.out.println(localDateTime); //2020-01-08T00:00
localDateTime = localDateTime.plusWeeks(10);
System.out.println(localDateTime); //2020-03-18T00:00
并将其解析为 Instant 取决于您使用的 API 中的 class:
LocalDateTime.now().toInstant(ZoneOffset.of("+04:00"));
ZonedDateTime.now().toInstant();
LocalDateTime
没有区域,因此您必须提供 ZoneOffset
才能将其解析为 Instant。
要设置月份,您可以使用此 lambda 表达式:
LocalDate.now().with(temporal
-> temporal.with(ChronoField.ALIGNED_WEEK_OF_YEAR, 1l)
);
现在很容易获得即时:
LocalDate localDate = LocalDate.now().with(temporal
-> temporal.with(ChronoField.ALIGNED_WEEK_OF_YEAR, 1l)
);
Instant instant = localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
如果你不想让 cto 改变时间,那么你可以用这个代替最后一行:
Instant instant = localDate.atTime(LocalTime.now()).atZone(ZoneId.systemDefault()).toInstant();
WeekFields wf = WeekFields.of(Locale.getDefault());
int week = 1; // week of year
LocalDate startDate = LocalDate.now(ZoneOffset.UTC)
.with(wf.weekOfWeekBasedYear(), week)
.with(wf.dayOfWeek(), 1);
Instant startInstant = startDate.atStartOfDay(ZoneOffset.UTC).toInstant();
LocalDate endDate = startDate.plusWeeks(1);
Instant endInstant = endDate.atStartOfDay(ZoneOffset.UTC).toInstant();
System.out.println("" + startInstant + " - " + endInstant);
我的语言环境使用 ISO 周数。这里的输出是:
2019-12-29T00:00:00Z - 2020-01-05T00:00:00Z
如果您希望独立于区域设置的 ISO 周,请将 wf
设置为 WeekFields.ISO
。如果您想要其他周编号方案,请相应地设置 wf
。
为了防止其他读者疑惑,Kirill 将周末定义为下周的第一时刻。这是推荐的。它被称为使用 半开间隔 作为时间间隔。
我也同意这个问题,即人们显然更喜欢使用 java.time 而不是 Calendar
来完成这项任务。 Calendar
设计不佳且已过时,我相信使用 java.time 的代码更易读。
另外,题中使用Calendar
的代码并没有设置一周的第一天,所以不会给你那一天。虽然我没有测试过,但我怀疑代码有时会在新年前后产生意想不到的结果。
我使用 java.time 中的 WeekFields
的代码将保留在当前 基于周的年份 内,这与日历年不同。例如,如果我在 2019 年 12 月 30 日 运行 它,它仍然会给出 2020 年的第 1 周,因为我们已经在那一周了。