tl;博士
ChronoUnit
.WEEKS
.between(
myJavaUtilDate_Start.toInstant().atZone( ZoneId.of( "Asia/Tokyo" ) ) ,
myJavaUtilDate_Stop.toInstant().atZone( ZoneId.of( "Asia/Tokyo" ) )
)
7
java.time
java.time 框架内置于 Java 8 及更高版本中。这些新类取代了与 Java 的最早版本捆绑在一起的旧日期时间类。
java.time 类也取代了非常成功的Joda-Time 框架。 java.time 和 Joda-Time 均由 Stephen Colbourne 领导。
Instant 替换 java.util.Date
现代类Instant 替换了旧类java.util.Date。两者都代表 UTC 中的一个时刻,即时间线上的一个特定点。两者在内部都使用自 1970 年第一刻(UTC,1970-01-01T00:00Z)的同一纪元参考以来的计数。旧类使用毫秒计数,而Instant 使用更精细的纳秒计数。
要转换,请调用添加到旧类的新方法。
Instant start = myJavaUtilDateStart.toInstant() ;
Instant stop = myJavaUtilDateStop.toInstant() ;
让我们用一些示例值来具体化。
Instant start = OffsetDateTime.of( 2020 , 1 , 23 , 15 , 30 , 0 , 0 , ZoneOffset.UTC ).toInstant();
Instant stop = OffsetDateTime.of( 2020 , 1 , 23 , 15 , 30 , 0 , 0 , ZoneOffset.UTC ).plusWeeks(7 ).toInstant();
时刻与日期
我们的两个Instant 对象都代表一个时刻。目标是数周。周表示天,天表示日历上的某些日期。
所以我们有点不匹配。对于任何给定的时刻,日期在全球范围内因时区而异。法国巴黎午夜过后几分钟是一个新的日期。与此同时,在蒙特利尔魁北克,晚了几个小时,同一时刻仍然是“昨天”,也就是日历上的前一天。所以我们不能直接从一对时刻计算周数。
您必须首先确定您希望在哪个时区感知这些时刻的日历。
以Continent/Region 的格式指定proper time zone name,例如America/Montreal、Africa/Casablanca 或Pacific/Auckland。切勿使用 2-4 个字母的缩写,例如 EST 或 IST,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime
将此ZoneId 应用于我们的Instant 对象以调整到时区,从而产生一对ZonedDateTime 对象。
ZonedDateTime startZdt = start.atZone( z ) ;
ZonedDateTime stopZdt = stop.atZone( z ) ;
ChronoUnit.WEEKS
现在我们可以使用ChronoUnit 枚举来计算经过的周数。
长周 = ChronoUnit.WEEKS.between( startZdt , stopZdt );
转储到控制台。
System.out.println( "start.toString() = " + start );
System.out.println( "stop.toString() = " + stop );
System.out.println( "startZdt.toString() = " + startZdt );
System.out.println( "stopZdt.toString() = " + stopZdt );
System.out.println( "weeksCount: " + weeksCount );
看到这个code run live at IdeOne.com。
start.toString() = 2020-01-23T15:30:00Z
stop.toString() = 2020-03-12T15:30:00Z
startZdt.toString() = 2020-01-23T10:30-05:00[美国/蒙特利尔]
stopZdt.toString() = 2020-03-12T11:30-04:00[美国/蒙特利尔]
周数:7
三十加分
ThreeTen-Extra 项目为 Java 8 及更高版本中内置的java.time 框架添加了功能。
Weeks类
该项目包含一个 Weeks 类来表示周数。它不仅可以计算,还可以在您的代码中用作类型安全的对象。这样的使用还有助于使您的代码自我记录。
您可以通过使用Weeks.between 方法提供一对时间点来实例化。这些时间点可以是实现java.time.temporal.Temporal 的任何内容,包括Instant、LocalDate、OffsetDateTime、ZonedDateTime、Year、YearMonth 等。
您的java.util.Date 对象可以轻松转换为Instant 对象,在UTC 时间轴上的时刻,分辨率以纳秒为单位。查看添加到旧日期时间类的新方法。如需从日期到即时,请致电java.util.Date::toInstant。
Weeks weeks = Weeks.between( startZdt , stopZdt );
您可以询问周数。
int weeksNumber = weeks.getAmount(); // The number of weeks in this Weeks object.
您还可以做得更多。
生成标准ISO 8601 格式的字符串。 P 标志着开始。 W 表示周数。
PW7
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可能会在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。