我正在开发一个库来存储Object中的复杂数据。该对象中的一个字段是日期。当我使用setter方法设置日期时,假设日期对象在GMT时区中。在内部,Date存储为long,其中包含epoch的毫秒数。在我的get()
方法中,我正在执行以下操作:
return new Date(storedDateinMilliseconds);
问题是如果有人在返回的对象上调用toString()
,它会使用默认时区来返回日期。因此,返回的日期并不总是与GMT中提供的日期匹配。有没有办法来解决这个问题?这样,当他们调用toString()
时,此实现的用户将始终获得GMT日期?
我尝试了以下方法:
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
但这会修改使用它的应用程序的默认时区。
答案 0 :(得分:3)
正如Sotirios Delimanolis的评论所说,你正在向调用程序员提供一个java.util.Date对象。她用它做什么取决于她。并且由她来理解该对象带来的所有愚蠢问题,包括toString
方法应用JVM当前的默认时区来生成其日期时间值的字符串表示。
如果要返回具有指定时区的日期时间值,请返回其他对象。
至少有三种方法可以返回java.util.Date对象。
在Java 8及更高版本中,显而易见的选择是使用新的java.time framework(Tutorial)。为调用程序员提供一个ZonedDateTime
对象,该对象基本上是Instant
对象加上ZoneId
对象。
提示:指定时区时,请使用proper time zone name。切勿使用EST
或IST
等<3-4个字母代码。
Joda-Time是java.time的灵感来源。这个第三方图书馆非常好,而且很受欢迎。它也支持多种版本的Java和Android。
DateTime
类是时间轴上的一个时刻加上一个时区,类似于java.time的ZonedDateTime
。
第三种方法是给调用程序员一个日期时间值的字符串表示。显而易见的格式选择是使用ISO 8601标准定义的格式。这些格式是明智的,深思熟虑的,明确的。
2015-09-16T18:06:14Z
...或...
2015-09-16T11:06:14-07:00
java.time和Joda-Time在解析和生成字符串时默认使用这些格式。这些格式由java.time明智地扩展,以便在方括号中附加时区的正确名称。
2015-09-16T11:06:14-07:00 [美国/洛杉矶]
您声明设置默认时区会影响整个应用。错误。它会影响该JVM中运行的所有线程中所有应用程序的所有代码。更糟糕的是,它会在运行时立即执行,而其他代码正在运行。
当解决日期时间问题的所有其他方法都已用尽时,仅将默认时区设置为最后的手段。这很少见。通常的解决方案是:
所有这些主题都在StackOverflow.com上多次讨论过。请搜索更多信息和示例。
答案 1 :(得分:1)
AFAIK,你有两个选择:
选项1.这可能听起来有点矫枉过正,但您可以为您的这个复杂类推出自己的Date对象,并覆盖toString()方法。也许像是
public class GMTDate extends java.util.Date {
@Override
public String toString() {
//return GMTDate
}
}
选项2:将您的日期保留为java.util.Date,但不要为其公开公共getter。而是公开一个以GMT格式返回你的日期的公共getter,也许是一个公共getter,它将你的日期作为一个长整数(从epoch开始的毫秒数)
编辑: 第三个选项:AspectJ。您可以使用面向方面的编程来拦截对toString()方法的调用并返回GMT字符串日期 相关的堆栈溢出问题:AspectJ: Intercept method execution/call and make it return