Java计算从当前时间到事件的时间

我正在计算直到足球比赛开始的时间量。

这就是我所知道的:

  • 我有时间参加活动: 2016-08-16T19:45:00Z
  • 我知道它的字符串格式是“ yyyy-M-dd’T’h:m:s’Z’
  • 我知道时区是“CET”。

我希望能够计算从当前时间到此日期的差异。

这是我尝试过的:

String gameDate = "2016-03-19T19:45:00'Z'" DateFormat apiFormat = new SimpleDateFormat("yyyy-M-dd'T'h:m:s'Z'"); apiFormat.setTimeZone(TimeZone.getTimeZone("CET")); Date dateOfGame = apiFormat.parse(gameDate); DateFormat currentDateFormat = new SimpleDateFormat("yyyy-M-dd'T'h:m:s'Z'"); currentDateFormat.setTimeZone(TimeZone.getTimeZone(userTimezone)); Date currentDate = apiFormat.parse(currentDateFormat.format(new Date())); long lGameDate = dateOfGame.getTime(); long lcurrDate = currentDate.getTime(); long difference = lGameDate - lcurrDate; Date timeDifference = new Date(difference); String daysAway = new SimpleDateFormat("d").format(timeDifference); Integer intDaysAway = Integer.parseInt(daysAway); 

你可能想知道为什么我不只是得到游戏的日期(8)并减去当前的日期(19)。 我不会在当前日期是第29天且游戏日期是下个月的第3天的边缘情况下这样做。

尝试使用/使用TimeUnit

例:

 final String gameDate = "2016-03-19T19:45:00Z"; final SimpleDateFormat apiFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); apiFormat.setTimeZone(TimeZone.getTimeZone("CET")); final Date dateOfGame = apiFormat.parse(gameDate); final long millis = dateOfGame.getTime() - System.currentTimeMillis(); System.out.println(dateOfGame.getTime() - System.currentTimeMillis()); final String hms = String.format("%02d:%02d:%02d", TimeUnit.MILLISECONDS.toHours(millis), TimeUnit.MILLISECONDS.toMinutes(millis) - TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis)), TimeUnit.MILLISECONDS.toSeconds(millis) - TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))); System.out.println(hms); 

这将打印输出:

72:57:34

从现在起72小时57分34秒直到gameDate

还没java.time提供Java 8 java.time答案……

  String eventStr = "2016-08-16T19:45:00Z"; DateTimeFormatter fmt = DateTimeFormatter.ISO_ZONED_DATE_TIME; Instant event = fmt.parse(eventStr, Instant::from); Instant now = Instant.now(); Duration diff = Duration.between(now, event); long days = diff.toDays(); System.out.println(days); 

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)等exception,那么您将得到开始和结束时刻之间的总秒数,并将其除以24小时。 在这种方法中,我们忽略日历及其日期。

差异示例:周一晚上,午夜前一小时开始。 周三早上午夜后停一小时。 对于24小时的块,总共26小时是一天。 但是,按照两个过去几天的日历日期,已触及三个日历日。

为什么两天如果我们触及三个? 日期时间工作通常使用半开放方法,其中开头是包容性的,而结尾是独占的

避免遗留日期时间类

执行此工作的现代方法是使用java.time类,而不是麻烦的旧旧日期时间类( DateCalendar等)。

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时间轴上的一个时刻,分辨率为纳秒 (最多九(9)位小数)。

 Instant start = Instant.parse( startInput ); Instant stop = Instant.parse( stopInput ); 

我知道时区是“CET”。

时区与解析字符串无关。 但是,如果按日历日期计算而不是每个通用日24小时计算经过的天数,时区就很重要。

continent/region的格式指定适当的时区名称 ,例如America/MontrealAfrica/CasablancaPacific/Auckland 。 切勿使用3-4字母缩写,例如ESTISTCET因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

 ZoneId z = ZoneId.of( "Europe/Paris" ); 

将我们的开始和停止时刻调整到该时区。

 ZonedDateTime zdtStart = start.atZone( z ); ZonedDateTime zdtStop = stop.atZone( z ); 

java.time框架为时间跨度提供了两个类:

  • Period月 – 天
  • 小时 – 分钟 – 秒的Duration

Period类采用一对LocalDate对象,仅限日期值,没有时间和没有时区。 我们可以从ZonedDateTime对象中提取LocalDate对象。 请记住,日期由区域决定。 因此,我们将UTC值调整为ZonedDateTime对象至关重要。

 Period p = Period.between( zdtStart.toLocalDate() , zdtStop.toLocalDate() ); 

您可以查询该Period以查看该时间段的年数,月数和天数。

如果您想要总天数,请使用ChronoUnit 枚举 。

 long days = ChronoUnit.DAYS.between( zdtStart , zdtStop ); 

以上是基于日历日期的天数。

如果要按24小时周期的通用组块计数,请使用“应用程序”中显示的“ Duration类。

 Duration.between( start , stop ).toDays() 

关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

现在处于维护模式的Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。

您可以直接与数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC驱动程序 。 不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

  • Java SE 8Java SE 9Java SE 10及更高版本
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小function和修复。
  • Java SE 6Java SE 7
    • 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
  • Android的
    • 更高版本的Android捆绑java.time类的实现。
    • 对于早期的Android(<26), ThreeTenABP项目采用ThreeTen-Backport (如上所述)。 请参见如何使用ThreeTenABP ….

ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如IntervalYearWeekYearQuarter等。

这就是你需要的:

 public static void main (String[] args) throws Exception { String gameDate = "2016-03-19T19:45:00Z"; DateFormat apiFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); apiFormat.setTimeZone(TimeZone.getTimeZone("CET")); Date dateOfGame = apiFormat.parse(gameDate); long now = new Date().getTime() / (3600000 * 24); long game = dateOfGame.getTime() / (3600000 * 24); System.out.println(now - game); } 

这将有效,因为你从游戏日期的纪元以来获得了整整一天的数量,现在只需要找到差异。 其他解决方案在边境情况下会出错。

您可以简单地从long difference = lGameDate - lcurrDate;获取结果long difference = lGameDate - lcurrDate; ,这是以毫秒为单位的差异,并转换为您喜欢的任何单位。

例如,在days: int days = difference/1000/3600/24 ;

变量difference包含以毫秒为单位的时差。 要将这些毫秒转换为天,小时,分钟,秒,我建议您使用java.util.concurrent.TimeUnit类。

例:

 final long durationMinutes = TimeUnit.MILLISECONDS.toMinutes(difference); final long durationSeconds = TimeUnit.MILLISECONDS.toSeconds(difference) - TimeUnit.MINUTES.toSeconds(durationMinutes); final long durationMillis = difference- TimeUnit.MINUTES.toMillis(durationMinutes) - TimeUnit.SECONDS.toMillis(durationSeconds); final String durationString = String.format("%d min, %ds, %d ms", durationMinutes, durationSeconds, durationMillis); 

首先,你的日期格式是错误的。 它应该是yyyy-MM-dd'T'HH:mm:ss'Z'而不是yyyy-M-dd'T'h:m:s'Z'

此外,您的gameDate字符串应以Z结尾,而不是'Z'

只需在当前和给定日期调用getTime()函数,即可轻松获得天数差异。 您甚至不必格式化当前日期。

这是代码片段:

 public static void main (String[] args) throws Exception { String gameDate = "2016-03-19T19:45:00Z"; DateFormat apiFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); apiFormat.setTimeZone(TimeZone.getTimeZone("CET")); Date dateOfGame = apiFormat.parse(gameDate); long difference = new Date().getTime() - dateOfGame.getTime(); System.out.println((double)difference / (3600000d * 24d)); } 

如果需要,可以对结果进行舍入。