【问题标题】:What could cause this SimpleDateFormat formatting error?什么可能导致此 SimpleDateFormat 格式错误?
【发布时间】:2011-01-07 21:14:13
【问题描述】:

我有一个日期作为 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”,一天后!

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

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


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

【问题讨论】:

    标签: java date timezone simpledateformat


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      我的第一个想法是这是一个并发问题。 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-21...
      • 在这种情况下,您正在查看时区问题。你能让系统管理员运行一个简单地格式化和打印特定时间戳值的 SSCEP 吗?
      • 我可以访问 prod 服务器,但我不知道“SSCEP”是什么(它是 Windows Server 2008 机器)。我通过双击任务栏中的日期/时间检查了两台机器上的时区设置,它们是相同的。顺便感谢 ThreadLocal 代码!
      • SSCEP 是一个小型、独立的示例程序。它应该是一个包含原始帖子中的代码的类,并简单地格式化和打印已知的日期值。您还可以为时区值添加打印语句。如果它有效(正确格式化日期),那么您就会知道在代码中的其他地方查看(也许您有一些不使用日期格式或使用不同格式的东西)。如果它不起作用,您无需接触服务器代码即可找出原因。
      • 您可能还对我在我的博客上发布的一系列调试文章感兴趣:blog.kdgregory.com/2009/12/debugging-101-assumptions.html
      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-01-15
        • 1970-01-01
        • 2020-05-02
        • 1970-01-01
        • 2023-03-24
        • 2012-05-05
        • 1970-01-01
        相关资源
        最近更新 更多