Java - 在 Netbeans 中将毫秒转换为“HH:mm:ss:SSS”时的结果不正确 IDE
Java - Incorrect result when convert Millisecond to `HH:mm:ss:SSS` in Netbeans IDE
我正在尝试将 5007
转换为 HH:mm:ss:SSS
,我正在使用 Netbeans IDE v8.2:
Date date = new Date(5007);
DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS");
String dateFormatted = formatter.format(date);
但这给了我一个错误的结果:
01:00:05:007
^^-------------------------why does it print to me 01 in the hours?
但它应该得到:
00:00:05:007
^^-------------------------correct result
例如,当我使用 ideone 时,它给出了正确的结果:
有没有关于这个问题的解释?
我测试了两个版本:Java 7 和 Java 8。
Date date = new Date(5007);
创建一个在 January 1, 1970, 00:00:00 GMT
后 5007 毫秒的日期。
当您使用 SimpleDateFormat
格式化时,它会转换为您机器的时区(我假设是 GMT+1)。
当我运行你的代码时我得到
02:00:05:007
我的时区是 GMT+2。
如果将 DateFormat
实例的时区设置为 GMT
,您将获得预期的输出:
Date date = new Date(5007);
DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS");
formatter.setTimeZone (TimeZone.getTimeZone ("GMT"));
String dateFormatted = formatter.format(date);
System.out.println (dateFormatted);
这会打印
00:00:05:007
肯定是语言环境问题。当您不指定时,它将使用(您的系统)默认值。要覆盖它;
尝试添加这个
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
或者在构造 SimpleDateFormat 实例时传递 Locale。例如:
DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS", Locale.ENGLISH);
我假设 Locale.ENGLISH 有 UTC 时区顺便说一下,但我希望你明白了。
当你要求解释你的问题时,我会诚实地告诉你:你误用了 SimpleDateFormat
来格式化持续时间。它从来就不是为了这种用途而设计的,而且如果您尝试它,也不会为您提供预期的结果。您遇到的问题并不是您将遇到的唯一问题。如果你的持续时间增长到超过 24 小时,整天都不会被格式化,所以你的结果会以不同的方式出错。
除此之外,最近我建议完全不要使用 SimpleDateFormat
class。它的替代品是 java.time.format.DateTimeFormatter
,它于 2014 年问世,带来的负面惊喜要少得多。不过,这也不是格式化持续时间的好选择。
那么什么是好的选择呢?我会先给你 Java 9 个答案,因为它很简单:
Duration dur = Duration.ofMillis(5007);
String hmss = String.format("%02d:%02d:%02d:%03d",
dur.toHours(),
dur.toMinutesPart(),
dur.toSecondsPart(),
dur.toMillisPart());
主要优点甚至不是简单,而是清晰。例如,使用此代码,没有人需要问我在评论中提出的问题,它是时间点还是持续时间?代码写的很清楚,就是一个时长。
对于 Java 6、7 和 8,您仍然可以使用 Duration
class(在 Java 6 和 7 中通过 ThreeTen Backport), but it doesn’t lend itself that easily to formatting, so I think I would resort to using the TimeUnit
enum as in the question I had linked to( link 你让我再次删除):
long millis = 5007;
long hours = TimeUnit.MILLISECONDS.toHours(millis);
millis -= TimeUnit.HOURS.toMillis(hours);
long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
millis -= TimeUnit.MINUTES.toMillis(minutes);
long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
millis -= TimeUnit.SECONDS.toMillis(seconds);
String hmss = String.format("%02d:%02d:%02d:%03d", hours, minutes, seconds, millis);
结果如愿
00:00:05:007
为了说明我试图说明的关于持续时间超过 24 小时时会发生什么的观点,让我们尝试给它 100 000 000 毫秒(一天有 86 400 000 毫秒):
27:46:40:000
我正在尝试将 5007
转换为 HH:mm:ss:SSS
,我正在使用 Netbeans IDE v8.2:
Date date = new Date(5007);
DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS");
String dateFormatted = formatter.format(date);
但这给了我一个错误的结果:
01:00:05:007
^^-------------------------why does it print to me 01 in the hours?
但它应该得到:
00:00:05:007
^^-------------------------correct result
例如,当我使用 ideone 时,它给出了正确的结果:
有没有关于这个问题的解释?
我测试了两个版本:Java 7 和 Java 8。
Date date = new Date(5007);
创建一个在 January 1, 1970, 00:00:00 GMT
后 5007 毫秒的日期。
当您使用 SimpleDateFormat
格式化时,它会转换为您机器的时区(我假设是 GMT+1)。
当我运行你的代码时我得到
02:00:05:007
我的时区是 GMT+2。
如果将 DateFormat
实例的时区设置为 GMT
,您将获得预期的输出:
Date date = new Date(5007);
DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS");
formatter.setTimeZone (TimeZone.getTimeZone ("GMT"));
String dateFormatted = formatter.format(date);
System.out.println (dateFormatted);
这会打印
00:00:05:007
肯定是语言环境问题。当您不指定时,它将使用(您的系统)默认值。要覆盖它;
尝试添加这个
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
或者在构造 SimpleDateFormat 实例时传递 Locale。例如:
DateFormat formatter = new SimpleDateFormat("HH:mm:ss:SSS", Locale.ENGLISH);
我假设 Locale.ENGLISH 有 UTC 时区顺便说一下,但我希望你明白了。
当你要求解释你的问题时,我会诚实地告诉你:你误用了 SimpleDateFormat
来格式化持续时间。它从来就不是为了这种用途而设计的,而且如果您尝试它,也不会为您提供预期的结果。您遇到的问题并不是您将遇到的唯一问题。如果你的持续时间增长到超过 24 小时,整天都不会被格式化,所以你的结果会以不同的方式出错。
除此之外,最近我建议完全不要使用 SimpleDateFormat
class。它的替代品是 java.time.format.DateTimeFormatter
,它于 2014 年问世,带来的负面惊喜要少得多。不过,这也不是格式化持续时间的好选择。
那么什么是好的选择呢?我会先给你 Java 9 个答案,因为它很简单:
Duration dur = Duration.ofMillis(5007);
String hmss = String.format("%02d:%02d:%02d:%03d",
dur.toHours(),
dur.toMinutesPart(),
dur.toSecondsPart(),
dur.toMillisPart());
主要优点甚至不是简单,而是清晰。例如,使用此代码,没有人需要问我在评论中提出的问题,它是时间点还是持续时间?代码写的很清楚,就是一个时长。
对于 Java 6、7 和 8,您仍然可以使用 Duration
class(在 Java 6 和 7 中通过 ThreeTen Backport), but it doesn’t lend itself that easily to formatting, so I think I would resort to using the TimeUnit
enum as in the question I had linked to( link 你让我再次删除):
long millis = 5007;
long hours = TimeUnit.MILLISECONDS.toHours(millis);
millis -= TimeUnit.HOURS.toMillis(hours);
long minutes = TimeUnit.MILLISECONDS.toMinutes(millis);
millis -= TimeUnit.MINUTES.toMillis(minutes);
long seconds = TimeUnit.MILLISECONDS.toSeconds(millis);
millis -= TimeUnit.SECONDS.toMillis(seconds);
String hmss = String.format("%02d:%02d:%02d:%03d", hours, minutes, seconds, millis);
结果如愿
00:00:05:007
为了说明我试图说明的关于持续时间超过 24 小时时会发生什么的观点,让我们尝试给它 100 000 000 毫秒(一天有 86 400 000 毫秒):
27:46:40:000