简短明了
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年1月1日UTC的第一个时刻的纪元引用以来的计数。旧类使用毫秒计数,而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
的格式指定一个正确的时区名称,例如 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
枚举来计算经过的周数。
long weeks = 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 );
请查看 在IdeOne.com上运行代码。
start.toString() = 2020-01-23T15:30:00Z
stop.toString() = 2020-03-12T15:30:00Z
startZdt.toString() = 2020-01-23T10:30-05:00[America/Montreal]
stopZdt.toString() = 2020-03-12T11:30-04:00[America/Montreal]
weeksCount: 7
ThreeTen-Extra
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 时间线上具有以纳秒为分辨率的时刻。查看旧日期时间类中添加的新方法。要从 Date 转换为 Instant,请调用 java.util.Date::toInstant
。
Weeks weeks = Weeks.between( startZdt , stopZdt )
您可以询问周数。
int weeksNumber = weeks.getAmount()
你可以做更多的事情。
生成一个符合
ISO 8601标准格式的字符串。
P
表示开始,
W
表示一定数量的周数。
PW7
关于java.time
java.time框架内置于Java 8及以后版本中。这些类代替了老旧的遗留日期时间类,例如java.util.Date
、Calendar
和SimpleDateFormat
。
要了解更多,请参阅Oracle教程。并在Stack Overflow上搜索许多示例和解释。规范是JSR 310。
Joda-Time项目现在处于维护模式,建议迁移到java.time类。
您可以直接使用java.time对象与数据库交换。使用符合JDBC 4.2或更高版本的JDBC驱动程序。无需字符串,无需java.sql.*
类。
从哪里获取java.time类?
这个
ThreeTen-Extra 项目扩展了 java.time 的附加类。该项目是 java.time 可能未来添加的一个试验场。您可能会在这里找到一些有用的类,例如
Interval
,
YearWeek
,
YearQuarter
和
更多。请注意,保留html标记。