我写了以下测试代码。
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss",Locale.JAPAN);
Date date1 = format.parse("08:00:01");
Date date2 = format.parse("23:00:05");
Date date = new Date(date2.getTime() - date1.getTime());
System.out.println(format.format(date));
但令我惊讶的是结果是00:00:04
,我无法理解为什么。
如果我将date2
更改为“08:00:01”,结果将更改为09:00:00
。
怎么会发生这种情况?
答案 0 :(得分:2)
Date
是时刻的类型,而不是时间间隔(时间)。
因此,如果您想计算两个时间点(Date对象)之间的时差(time inverval),您将获得另一种类型的时差,例如long
(以秒为单位)或输入外部图书馆。
请参阅http://www.mkyong.com/java/how-to-calculate-date-time-difference-in-java/
第一个代码不使用外部库,但您必须将毫秒转换为秒,分钟,小时等。
这是重要的部分:
Date d1 = ...;
Date d2 = ...;
//in milliseconds
long diff = d2.getTime() - d1.getTime();
long diffSeconds = diff / 1000 % 60;
long diffMinutes = diff / (60 * 1000) % 60;
long diffHours = diff / (60 * 60 * 1000) % 24;
long diffDays = diff / (24 * 60 * 60 * 1000);
System.out.print(diffDays + " days, ");
System.out.print(diffHours + " hours, ");
System.out.print(diffMinutes + " minutes, ");
System.out.print(diffSeconds + " seconds.");
第二个代码 使用外部库Joda-Time,它是时间最着名的Java库之一。
这是重要的部分:
DateTime dt1 = new DateTime(d1);
DateTime dt2 = new DateTime(d2);
System.out.print(Days.daysBetween(dt1, dt2).getDays() + " days, ");
System.out.print(Hours.hoursBetween(dt1, dt2).getHours() % 24 + " hours, ");
System.out.print(Minutes.minutesBetween(dt1, dt2).getMinutes() % 60 + " minutes, ");
System.out.print(Seconds.secondsBetween(dt1, dt2).getSeconds() % 60 + " seconds.");
如果您想使用Joda-Time库,您还可以使用其他类型进行时间间隔Interval
:http://joda-time.sourceforge.net/key_interval.html
<小时/> 的修改:
Date
类使用内部长变量来表示时刻。
长值是某个时刻之间的时间差(以毫秒为单位),
即January 1, 1970, 00:00:00 GMT
(在http://docs.oracle.com/javase/7/docs/api/java/util/Date.html中指定),
由于JST( UTC +09:00 ),日本标准时间为January 1, 1970, 09:00:00
。
所以,23:00:05 - 08:00:01将是15:00:04,并将转换为日本标准时间(UTC +09:00)= 24:00:04(1970年1月1日) ),即00:00:04(1970年1月2日)。
如果您计算08:00:01 - 08:00:01,那么它将是UTC的1970-01-01 00:00:00,即日本的1970-01-01 09:00:00标准时间。
<小时/> EDIT2 :我犯了一些错误。解析时我没有使用日本标准时间。无论如何,结果是一样的。
date1 = 08:00:01 in Japan = 23:00:01 in UTC date2 = 23:00:05 in Japan = 14:00:05 in UTC date = 14:00:05 in UTC - 23:00:01 in UTC = 15:00:04 in UTC = 23:00:05 in Japan - 08:00:01 in Japan = 15:00:04 in UTC (NOT in JAPAN)
为什么呢?因为计算是使用前面提到的长值完成的,该值是以 GMT (UTC +00:00,或仅UTC)计算的。
即使您指定使用日本时间,长值也是UTC。 Date
将其转换为UTC,因此它会获得您提供-09:00
的时间,Date
中的内部流程将使用UTC完成。如果您要打印它,Date
只需添加+09:00
计算。
您还可以将其视为:
23:00:05 with (+09:00) - 08:00:01 with (+09:00) = 15:00:04 with (+00:00)
无论如何,15:00:04 UTC
为00:00:04 JST
,因此如果您打印它,您将看到日本时间00:00:04
,因为您指定使用的是日本标准时间。
答案 1 :(得分:2)
您的代码存在问题:
Date
实例时,这意味着在1970年第一天下午3点后几秒钟(1970-01-01T15:00:04.000Z
)。然后使用自动使用本地时区偏移的格式进行打印,以调整字符串中呈现的时间。在美国西海岸(从UTC的-08:00)运行相同的代码,结果是1970年1月1日的07:00:04。这是15:00:04调整回8小时。the given pattern and the default date format symbols
。如果您有兴趣搜索StackOverflow.com或其他来源,您会发现许多示例和讨论。您应该(a)阅读您正在使用的课程的文档,以及(b)谷歌/ bing的日期,时间,间隔,期间,持续时间,跨度等词语。
标准ISO 8601定义了一种将时间跨度描述为PnYnMnDTnHnMnS
// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;
// Better to specify a time zone explicitly rather than rely on default.
// Time Zone list… http://joda-time.sourceforge.net/timezones.html (not quite up-to-date, read page for details)
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime dateTime1 = new DateTime( 2014, 1, 2, 8, 0, 1, timeZone );
DateTime dateTime2 = new DateTime( 2014, 1, 2, 23, 0, 5, timeZone );
// Calculate the span of time between them.
Period period = new Period( dateTime1, dateTime2 );
格式的字符串的方式。
Joda-Time使用ISO 8601作为其大部分默认值。
Duration 2.3库有多个类,专门用于表示时间跨度:Period,Interval和Duration。
即将推出的Java 8中新的java.time。*类(受Joda-Time启发)有类似的类。这些类取代了java.util.Date&amp;目前捆绑在Java中的日历类。
System.out.println( "dateTime1: " + dateTime1 );
System.out.println( "dateTime2: " + dateTime2 );
System.out.println( "period in ISO Duration format: " + period );
System.out.println( "period in words: " + PeriodFormat.getDefault().print( period ) );
System.out.println( "period in words, en français: " + PeriodFormat.wordBased( Locale.FRANCE ).print( period ) );
System.out.println( "period in words, for Japan: " + PeriodFormat.wordBased( Locale.JAPAN ).print( period ) );
转换为单词,并转储到控制台......
dateTime1: 2014-01-02T08:00:01.000+01:00
dateTime2: 2014-01-02T23:00:05.000+01:00
period in ISO Duration format: PT15H4S
period in words: 15 hours and 4 seconds
period in words, en français: 15 heures et 4 secondes
period in words, for Japan: 15時間4秒
跑步时......
{{1}}
答案 2 :(得分:1)
Date date = new Date(date2.getTime() - date1.getTime());
date2.getTime() - date1.getTime()
将始终返回相同的long
值。Date
创建long
对象时,它表示自标准基准时间称为“纪元”以来的指定毫秒数,即1970年1月1日,00:00:00 <强> GMT 强> SimpleDateFormatter
以日本TZ 显示时间时,它会将 09:00:00 添加到您的ans。 (回答您的以下问题) 我无法理解为什么。如果我将date2更改为“08:00:01”,结果将更改为09:00:00。怎么会发生这种情况?
在代码中添加以下行:
System.setProperty("user.timezone", "<your preferred timezone>");
答案 3 :(得分:0)
我使用joda-time,但是,从这段代码(只是将代码包装在适当的java类中):
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
public class DateTest {
public static void main (String[] args) throws Throwable{
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss",Locale.JAPAN);
Date date1 = format.parse("08:00:01");
Date date2 = format.parse("23:00:05");
Date date = new Date(date2.getTime() - date1.getTime());
System.out.println(format.format(date));
}
}
我明白了:
07:00:04
这是在Mac OS X Mavericks上的JDK 1.7.0_40上。