我正在尝试计算足球比赛开始前的时间。
这就是我所知道的:
我希望能够计算从当前时间到此日期的差异。
这就是我的尝试:
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天的情况下这样做。
答案 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)
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小时的块,总共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
。切勿使用诸如EST
或IST
或CET
之类的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 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance 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的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 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);