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

时间:2016-03-16 17:35:12

标签: java

我正在尝试计算足球比赛开始前的时间。

这就是我所知道的:

  • 我有时间参加活动: 2016-08-16T19:45:00Z
  • 我知道它的字符串格式是" yyyy-M-dd'' 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天的情况下这样做。

7 个答案:

答案 0 :(得分:4)

还没有人提供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);

答案 1 :(得分:3)

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类而不是麻烦的旧遗留日期时间类(DateCalendar等。)。

Answer by dcsohl是正确的但可能更短。无需明确DateTimeFormatter,因为输入字符串是默认使用的标准ISO 8601格式之一。

  

我知道它的字符串格式是“yyyy-M-dd'T'h:m:s'Z'”

作为ISO 8601标准的一部分,最后的ZZulu的缩写,意为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/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTISTCET之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的( !)。

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

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

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

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

  • Period年 - 月 -
  • Duration小时 - 分钟 - 秒

Period类使用一对LocalDate个对象,仅限日期值,没有时间和没有时区。我们可以从LocalDate个对象中提取ZonedDateTime个对象。请记住,日期由区域决定。因此,我们将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.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

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

从哪里获取java.time类?

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

答案 2 :(得分:2)

尝试使用/ 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

答案 3 :(得分:1)

这就是你需要的:

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);
}

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

答案 4 :(得分:0)

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

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

答案 5 :(得分:0)

首先,您的日期格式是错误的。它应该是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));
}

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

答案 6 :(得分:0)

您的变量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, %d s, %d ms", durationMinutes, durationSeconds, durationMillis);