代码之家  ›  专栏  ›  技术社区  ›  Thierry Roy

什么会导致SimpleDateFormat格式错误?

  •  2
  • Thierry Roy  · 技术社区  · 15 年前

    我在数据库中将日期存储为java.sql.timestamp。日期为“2010-01-20t19:10:35.000z”,相当于1264014635743 ms。

    与开发机器相比,在prod机器上日期的格式有所不同。

    设置日期格式的代码是:

    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”。但是在Prod中我有“2010-01-21”,一天之后!

    当然,由于错误发生在prod服务器上,所以我的调试选项受到限制…

    我进行了双重检查,两台服务器的时间和时区都相同。两个时钟都与NTP服务器同步。


    [更新]Prod中的数据库的日期字段值为:“10-01-20 19:10:35743000000”

    3 回复  |  直到 15 年前
        1
  •  4
  •   kdgregory    15 年前

    我的第一个想法是这是一个并发问题。 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 “您没有运行您认为正在运行的代码。”这可能是因为您的演示文稿代码没有在服务器上正确卸载,或者有另一个日期格式化程序在四处浮动。

        2
  •  2
  •   digitaljoel    15 年前

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

        3
  •  0
  •   Spike Williams    15 年前

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