tl;博士
ChronoUnit.DAYS.between(
Instant.parse( "2016-08-16T19:45:00Z" ).atZone( ZoneId.of( "Europe/Paris" ) ),
Instant.parse( "2016-08-23T12:34:00Z" ).atZone( ZoneId.of( "Europe/Paris" ) )
);
定义“天”
有两种方法可以计算天数。您的问题不太清楚您的意图。此答案显示了两种方式的示例代码。
- 基于日历的日期按日期
应用预期的时区来确定开始和停止的日期。日期由区域确定,因为对于任何特定时刻,全球范围内的日期都不同,“明天”向东,而“昨天”向西,具体取决于您所在的位置。例如,在法国巴黎午夜过后几分钟,新的一天在魁北克蒙特利尔仍然是“昨天”。
- 24 小时时间段
如果您只考虑 24 小时时间段中的一般天数而忽略夏令时 (DST) 等异常情况,那么您将获得从开始到结束之间的总秒数时刻并将其除以 24 小时。在这种方法中,我们忽略了日历及其日期。
差异示例:从星期一深夜开始,午夜前一小时开始。周三早上午夜后一小时停止。对于 24 小时的块,总共 26 小时是一天。但是按日历日期,这将经过两天,已经触及三个日历日。
如果我们碰了三天,为什么要两天?日期时间工作通常使用半开放方法,其中开始是包含,而结束是独占。
避免使用旧的日期时间类
完成这项工作的现代方法是使用 java.time 类,而不是麻烦的旧旧日期时间类(Date、Calendar 等)。
Answer by dcsohl 是正确的,但可以更短。无需明确说明 DateTimeFormatter,因为输入字符串是默认使用的标准 ISO 8601 格式之一。
我知道它的字符串格式是“yyyy-M-dd'T'h:m:s'Z'”
作为 ISO 8601 标准的一部分,末尾的 Z 是 Zulu 的缩写,表示 UTC。
String startInput = "2016-08-16T19:45:00Z" ;
String stopInput = "2016-08-23T12:34:00Z" ;
解析为Instant 对象。 Instant 类代表UTC 中时间线上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。
Instant start = Instant.parse( startInput );
Instant stop = Instant.parse( stopInput );
我知道时区是“CET”。
时区与解析字符串无关。但是,如果按日历日期而不是按每个普通日的 24 小时计算,则时区在计算经过的天数方面确实很重要。
以continent/region 的格式指定proper time zone name,例如America/Montreal、Africa/Casablanca 或Pacific/Auckland。切勿使用 3-4 个字母的缩写,例如 EST 或 IST 或 CET,因为它们不是真正的时区,没有标准化,甚至不是唯一的 (!)。
ZoneId z = ZoneId.of( "Europe/Paris" );
将我们的开始和停止时刻都调整到那个时区。
ZonedDateTime zdtStart = start.atZone( z );
ZonedDateTime zdtStop = stop.atZone( z );
java.time 框架为时间跨度提供了两个类:
Period 类采用一对LocalDate 对象,只有日期值,没有时间和时区。我们可以从ZonedDateTime 对象中提取LocalDate 对象。请记住,日期由区域确定。因此,我们将 UTC 值调整为 ZonedDateTime 对象至关重要。
Period p = Period.between( zdtStart.toLocalDate() , zdtStop.toLocalDate() );
您可以向 Period 询问该时间跨度的年数、月数和天数。
如果您需要总天数,请使用 ChronoUnit enum。
long days = ChronoUnit.DAYS.between( zdtStart , zdtStop );
以上是基于日历日期的天数计算。
如果您想按 24 小时周期的通用块进行计数,请使用 Duration 类,如 Answer by dcsohl 所示。
Duration.between( start , stop ).toDays()
关于java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.Date、Calendar 和 SimpleDateFormat。
Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。
要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。
从哪里获得 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如Interval、YearWeek、YearQuarter 和more。