我的代码中有2个文件:
文件1的内容:
public static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
public static final SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
文件2的内容:
sdf.format(formatter.parse("2015-02-02")));
问题:文件2上方的行最初打印“ 2015-02-02 12:00:00”几个小时,但之后打印“ 2015-02-01 06:00:00”。 知道这里可能是什么问题。
其他信息:
我的服务器正在美国的某些云计算机上运行。
new java.util.Date( )
始终正确地提供UTC时区值。
使用命令java -jar xyz.jar
启动服务器。
还有其他文件正在使用sdf
和formatter
变量。
我无法在本地计算机上重现此内容。
一旦问题开始在服务器上发生,它将显示错误的日期时间,直到重新启动服务器。
答案 0 :(得分:3)
如果您查看Oracle的官方文档,则表示
日期格式不同步。建议创建 每个线程使用单独的格式实例。如果有多个线程访问 同时使用一种格式,则必须在外部进行同步。
通过查看代码,您似乎正在多个线程中重用同一实例。那是不正确的!
要么维护一个格式化程序池,要么同步访问(不推荐),或者每次都可以创建一个新实例。
答案 1 :(得分:1)
Nathan Hughes和我本人的评论足以将其组合成一个答案:使用java.time,现代日期时间API,尤其是其DateTimeFormatter
。
public static final DateTimeFormatter printFormatter
= DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss");
例如,现在您的格式可能如下:
String stringToPrint = LocalDate.parse("2015-02-02")
.atStartOfDay(ZoneOffset.UTC)
.format(printFormatter);
System.out.println(stringToPrint);
此打印:
2015-02-02 00:00:00
在格式转换代码中,我利用了以下事实:您的原始字符串2015-02-02
采用标准的ISO 8601格式表示日期。 LocalDate
将此格式解析为默认格式,即没有任何显式格式化程序。
从您的问题看来,您观察到的行为可能有两种解释:
观察到的行为(6小时的错误),在启动后一直持续到服务器重新启动,这似乎与第一个解释更加一致,您也已在自己的回答中确认了这一点,并感谢您这样做。
与SimpleDateFormat
相反,现代的DateTimeFormatter
是线程安全的,可以防止任何线程问题,并且是不可变的,可以防止其他类修改格式化程序。因此,这两种情况都可以解决您的问题。
顺便说一句,我认为您知道在格式模式字符串中对小写hh
的错误使用。 hh
是从01到12的AM或PM中的一个小时,而您则需要从00到23的一个小时的大写HH
(SimpleDateFormat
和{{1}都适用) }。
链接: Oracle tutorial: Date Time解释了如何使用DateTimeFormatter
。
答案 2 :(得分:0)
另一个API中的某些代码为window.open()
设置了时区,这引起了问题。以下是在本地复制问题的示例示例:
sdf
}