【问题标题】:Lowercase z in date time format is returning offset, not abbreviation日期时间格式中的小写 z 返回偏移量,而不是缩写
【发布时间】:2018-07-31 06:07:09
【问题描述】:

我被难住了。我必须承认我可能没有在正确的地方寻找这个错误。那就是……

我们使用dd MMM YYY HH:mm:ss z 作为日期格式字符串。小写的z 应该返回该区域的三个字母缩写,例如PSTCET。它确实如此。无处不在,但生产。在生产中,我们得到偏移量,例如-08:00。我们通过 WAR 验证了我们在所有地方都在使用 joda 2.9.2。

我们使用dateTime.withZone(DateTimeZone.forID(timezone)).toString(dateFormat, locale),其中dateTimeDateTimetimezoneString(已验证跨实例相同,America/Los_Angeles)。 dateFormat 如上所述,dd MMM YYY HH:mm:ss zlocale 在多个实例中被验证为 en

我注意到这个SO question 提出了这样一种想法,即语言环境信息正在丢失,只留下偏移量。尽管如此,无论我对timezonelocale 使用什么,我都无法重现它。当然,我们不使用forOffsetHours

编辑:对于它的价值,我不认为这是语言环境,因为我可以使用 .toString(dateFormat, locale) 中的语言环境的组合值,如 new Locale("hasdf") 和预期的日期格式。我可以得到这种意外格式的唯一方法是使用大写的Z 代替小写的z

第二次编辑:哦,JVM 到处都是一样的。

【问题讨论】:

  • 哪个特定时区正在回馈偏移量?您是否知道 TZDB 很久以前就开始删除许多时区的“发明”缩写?
  • 所有时区都给出偏移量而不是缩写。

标签: java datetime timezone jodatime datetime-format


【解决方案1】:

这可能与您的 JVM 中的语言环境数据有关(检查您的版本以确保它们在所有环境中都相同)。

无论如何,有一种解决方法可以覆盖 Joda 用于时区名称的文本。你需要扩展org.joda.time.tz.DefaultNameProvider:

public class MyNameProvider extends DefaultNameProvider {

    @Override
    public String getShortName(Locale locale, String id, String nameKey, boolean standardTime) {
        if (Locale.ENGLISH.equals(locale) && "America/Los_Angeles".equals(id)) {
            // return the correct name for Daylight Saving Time
            return standardTime ? "PST" : "PDT";
        }

        return super.getShortName(locale, id, nameKey, standardTime);
    }
}

然后你做:

DateTimeZone.setNameProvider(new MyNameProvider());

DateTime d = new DateTime().withZone(DateTimeZone.forID("America/Los_Angeles"));
System.out.println(d.toString("dd MMM YYY HH:mm:ss z", Locale.ENGLISH));

这将覆盖 JVM 正在使用的任何数据,并始终在英语语言环境中为 America/Los_Angeles 使用“PST”和“PDT”。

【讨论】:

  • 是的,仔细检查 - 相同的 JVM eeeeeverywhere O.o
【解决方案2】:

我无法重现此问题,但我认为 Joda 从 JVM 本身获取此信息。

您可以通过此代码检查 Joda 使用的数据:

String[][] zoneStringsEn = DateTimeUtils.getDateFormatSymbols(Locale.ENGLISH).getZoneStrings();
for (String[] strings : zoneStringsEn) {
    if (strings != null && strings.length >= 5 && "America/Los_Angeles".equals(strings[0])) {
        System.out.println(strings[2]); // "PST" in my JVM
    }
}

可能不工作的环境有不同的JVM版本。

【讨论】:

  • 双重检查 - 相同的 JVM eeeeeverywhere -_-
【解决方案3】:

我能得到这种完全出乎意料的格式的唯一方法是使用大写的 Z 代替小写的 z

嗯,这是因为一个大写的 Z 为您提供了偏移量,如 javadoc 中所述:http://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormat.html

区域:'Z' 输出不带冒号的偏移量,'ZZ' 输出带冒号的偏移量,'ZZZ' 或更多输出区域 id。

小写的 z 为您提供区域名称:

Symbol  Meaning               Presentation   Examples
------  -------               ------------   -------
z       time zone             text           Pacific Standard Time; PST
Z       time zone offset/id   zone           -0800; -08:00; America/Los_Angeles

【讨论】:

    【解决方案4】:

    很有可能是一些类路径问题。

    在我们的项目中,我们能够在类路径中重现此问题,包括 JodaTime 2.9.2 和 2.4。

    我们不知道我们包含旧的 2.4 版本。它没有显示在依赖树中。最终,我们在一些我们实际上不再需要的旧的胖 JAR 依赖项中找到了 joda 类。

    请记住,类路径问题在环境之间可能是不确定的。

    【讨论】:

      猜你喜欢
      • 2016-06-21
      • 1970-01-01
      • 1970-01-01
      • 2017-03-31
      • 2013-11-27
      • 1970-01-01
      • 1970-01-01
      • 2020-04-13
      • 2020-08-30
      相关资源
      最近更新 更多