2

我有一个日期作为 java.sql.Timestamp 存储在数据库中。日期为“2010-01-20T19:10:35.000Z”,相当于 1264014635743 毫秒。

不知何故,与开发机器相比,生产机器上的日期格式不同。

格式化日期的代码是:

private final static String DATE_FORMAT = "yyyy-MM-dd";
public final static SimpleDateFormat APP_DATE_FORMATER = new SimpleDateFormat(DATE_FORMAT);
private static final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone("Etc/UTC");
APP_DATE_FORMATER.setTimeZone(UTC_TIMEZONE);
DateTimeZone.setDefault(DateTimeZone.UTC);

String output = APP_DATE_FORMATER.format(date)

dev 中生成的输出是正确的“2010-01-20”。但是在产品中我有“2010-01-21”,一天后!

当然,由于错误发生在产品服务器上,我的调试选项受到限制......

我已经仔细检查过,两台服务器都有相同的时间和时区。两个时钟都与 ntp 服务器同步。


[更新] prod 中的数据库的值为:日期字段的“10-01-20 19:10:35,743000000”

4

3 回答 3

4

我的第一个想法是这是一个并发问题。SimpleDateFormat不是线程安全的,但您正在共享一个静态实例如果您需要java.text在多线程环境中使用格式化程序,您应该使用 ThreadLocal 来保存它们:

private static ThreadLocal<DateFormat> _datetimeFormatter = new ThreadLocal<DateFormat>();

private static DateFormat getDatetimeFormatter()
{
    DateFormat format = _datetimeFormatter.get();
    if (format == null)
    {
        format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
        _datetimeFormatter.set(format);
    }
    return format;
}

public static String formatDatetime(Date date)
{
    return getDatetimeFormatter().format(date);
}

也有可能(但不太可能)在服务器上找不到“Etc/UTC”。您是否从 中记录值getTimeZone()

第三个选项是,用Inigo Montoya的话说,“你没有运行你认为你正在运行的代码。” 这可能是因为您的演示文稿代码没有在服务器上正确卸载,或者还有另一个日期格式化程序在浮动。

于 2010-01-21T18:43:15.530 回答
2

虽然机器具有相同的时区,但数据库设置呢?数据库是否可能设置为与机器不同的时区?

于 2010-01-21T18:41:04.910 回答
0

您是否检查过生产机器和开发机器上的 JVM 设置是否相同?时间可能在服务器级别是同步的,但 JVM 的设置方式可能对它所在的时区有些混淆。

于 2010-01-21T18:48:11.717 回答