【发布时间】:2010-12-03 17:24:54
【问题描述】:
我有 2 台不同的计算机,每台都有不同的时区。
在一台计算机上打印System.currentTimeMillis(),然后在两台计算机上打印以下命令:
System.out.println(new Date(123456)); --> 123456 代表计算机#1 中currentTimeMillis 中的号码。
第二次打印(尽管是硬编码的)导致两台计算机上的打印不同。 这是为什么呢?
【问题讨论】:
我有 2 台不同的计算机,每台都有不同的时区。
在一台计算机上打印System.currentTimeMillis(),然后在两台计算机上打印以下命令:
System.out.println(new Date(123456)); --> 123456 代表计算机#1 中currentTimeMillis 中的号码。
第二次打印(尽管是硬编码的)导致两台计算机上的打印不同。 这是为什么呢?
【问题讨论】:
见https://docs.oracle.com/javase/7/docs/api/java/util/Date.html#toString()。
是的,它使用时区。它还应该将它们打印出来(年份之前的三个字符)。
【讨论】:
javadoc 很好地解释了这一点, System.currentTimeMillis() 请注意,虽然返回值的时间单位是毫秒,但值的粒度取决于底层操作系统并且可能更大。例如,许多操作系统以几十毫秒为单位测量时间。
【讨论】:
一些迂腐的细节怎么样。
java.util.Date 与时区无关。在 javadoc 中这么说。
您想要与特定时区相关的东西吗?那是java.util.Calendar。
棘手的部分?当您打印这些东西(使用java.text.DateFormat 或subclass)时,会涉及到日历(涉及时区)。见DateFormat.setTimeZone()。
它确实看起来(没有检查实现)像 java.util.Date.toString() 通过 DateFormat。因此,即使是我们(大部分)独立于时区的类也会因时区而变得混乱。
想要从我们的纯无时区 Date 对象中获取时区信息吗?有Date.toGMTString()。或者您可以创建自己的 SimpleDateFormatter 并使用 setTimeZone() 来控制自己使用哪个区域。
【讨论】:
TimeZone zi = date.getZone(); if (zi != null) { sb.append(zi.getDisplayName(date.isDaylightTime(), zi.SHORT, Locale.US)); // zzz } else { sb.append("GMT"); } date 是 BaseCalendar 时区设置为 TimeZone.getDefaultRef()
Date 对象与具有时区的cdate 成员(即BaseCalendar)一起使用。然后发生了没有人真正关心的事情,并且Date 的行为与时区无关,只要您不打印它。无意反驳你的回答。
toString()方法的Java-doc说如果时区信息不可用,那么zzz是空的——也就是说,它由根本没有字符。 但是 afaik 当没有可用的时区信息时,代码将应用GMT(zi != null 解析为错误条件)。
这是为什么?
因为像“2009 年 10 月 4 日,14:20”这样的内容在不知道它所指的时区的情况下毫无意义 - 您现在很可能会看到,因为这是我写这篇文章的时间,而且可能相差几个小时从你的时间,即使它是同一时刻。
计算机时间戳通常以 UTC(基本上是英格兰格林威治的时区)为单位,在将其格式化为人类可读的格式时必须考虑时区。
【讨论】:
因为毫秒数是 1970 年 1 月 1 日 UTC 之后的毫秒数。如果您随后转换到不同的时区,则呈现的时间会有所不同。
例如123456 可能对应于格林威治 (UTC) 的中午。但在纽约,那将是一个不同的时间。
要确认这一点,请将SimpleDateFormat 与时区输出一起使用,和/或更改第二台计算机上的时区以匹配第一台计算机。
【讨论】: