SimpleDateFormat在部署一段时间后给出错误的日期和时间

时间:2019-02-08 04:05:49

标签: java simpledateformat

我的代码中有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启动服务器。 还有其他文件正在使用sdfformatter变量。 我无法在本地计算机上重现此内容。 一旦问题开始在服务器上发生,它将显示错误的日期时间,直到重新启动服务器。

3 个答案:

答案 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将此格式解析为默认格式,即没有任何显式格式化程序。

您的代码出了什么问题?

从您的问题看来,您观察到的行为可能有两种解释:

  1. 使用两个格式化程序的服务器上程序的其他类别之一,将其中一个格式化为时区,例如设置为America / Chicago。
  2. 两个或多个线程同时使用这些格式,这将导致其中一个行为不正确。

观察到的行为(6小时的错误),在启动后一直持续到服务器重新启动,这似乎与第一个解释更加一致,您也已在自己的回答中确认了这一点,并感谢您这样做。

SimpleDateFormat相反,现代的DateTimeFormatter是线程安全的,可以防止任何线程问题,并且是不可变的,可以防止其他类修改格式化程序。因此,这两种情况都可以解决您的问题。

顺便说一句,我认为您知道在格式模式字符串中对小写hh的错误使用。 hh是从01到12的AM或PM中的一个小时,而您则需要从00到23的一个小时的大写HHSimpleDateFormat和{{1}都适用) }。

链接: Oracle tutorial: Date Time解释了如何使用DateTimeFormatter

答案 2 :(得分:0)

另一个API中的某些代码为window.open()设置了时区,这引起了问题。以下是在本地复制问题的示例示例:

sdf

}

相关问题