当丹麦语设置为 VM 参数时,org.joda.time.DateTime 的 toString() 方法失败

toString() method of org.joda.time.DateTime failed when Danish is set as VM argument

import java.text.SimpleDateFormat;
import java.util.Locale;

import org.joda.time.DateTime;
import org.joda.time.Interval;

public class JordaTimeTest {

    public static void main(String[] args) {
        SimpleDateFormat dateFormat1 = new SimpleDateFormat("EEE dd/MM HH:mm", Locale.getDefault());
        SimpleDateFormat dateFormat = dateFormat1;

        Interval interval = new Interval(1499628963860L, 1511809983860L);
        DateTime start = new DateTime(interval.getStart());
        DateTime end = new DateTime(interval.getEnd());

        System.out.println(start.toString(dateFormat.toLocalizedPattern()));
    }
}

我按照How to set eclipse console locale/language

中指定的方式进行了操作

我使用 -Duser.language=da -Duser.country=DK 作为 VM 参数。我遇到异常:

java.lang.IllegalArgumentException: Illegal pattern component: tt

有什么办法解决这个问题吗?

将区域设置设置为 da_DK 时,方法 toLocalizedPattern returns EEE tt/MM HH:mmtt is not a recognized pattern 在乔达时代。

如果您希望以特定语言输出,则无需更改 JVM 默认语言环境(因为这会影响同一 JVM 中的所有其他应用程序 运行)。相反,您可以创建一个 org.joda.time.format.DateTimeFormatter 并仅在格式化程序中设置语言环境:

DateTimeFormatter fmt = DateTimeFormat
    // set pattern
    .forPattern("EEE dd/MM HH:mm")
    // set locale
    .withLocale(new Locale("da", "DK"));
System.out.println(fmt.print(start));
System.out.println(fmt.print(end));

这将输出:

sø 09/07 16:36
ma 27/11 17:13

请注意,输出取决于 JVM 默认时区:1499628963860 对应于 UTC 2017-07-09T19:36:03.860Z,在我的 JVM 默认时区 (America/Sao_Paulo) 中是 16:36 .在您的机器中,这些值会有所不同。

如果您想指定一个时区,您可以像这样创建日期:

// create date in UTC
DateTime start = new DateTime(interval.getStart(), DateTimeZone.UTC);

现在 DateTime 是 UTC,所以输出将是 sø 09/07 19:36

您还可以使用 DateTimeZone.forID("zonename") 设置特定时区,其中 zonename 是有效的 IANA timezone name(始终采用 Region/City 格式,例如 America/Sao_PauloEurope/Berlin)。 避免使用 3 个字母的缩写(如 CSTPST),因为它们是 ambiguous and not standard.

您可以通过调用 DateTimeZone.getAvailableIDs().

获取可用时区列表(并选择最适合您的系统的时区)

中所述,无需使用 SimpleDateFormat(因为它设计用于 java.util.Datejava.util.Calendar)。


Java 新 Date/Time API

Joda-Time 处于维护模式,正在被新的 APIs 取代,所以我不建议用它开始一个新项目。即使在 joda's website 它说:"Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".

如果您不能(或不想)从 Joda-Time 迁移到新的 API,您可以忽略此部分。

如果您正在使用 Java 8,请考虑使用 new java.time API. It's easier, less bugged and less error-prone than the old APIs.

如果您使用 Java 6 或 7,您可以使用 ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, you'll also need the ThreeTenABP (more on how to use it ).

下面的代码适用于两者。 唯一的区别是包名称(在 Java 8 中是 java.time,在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp),但是 类和方法名称相同。

您不需要创建间隔并从中获取开始和结束。您可以直接创建日期:

// use system default timezone
ZoneId zone = ZoneId.systemDefault();
ZonedDateTime start = Instant.ofEpochMilli(1499628963860L).atZone(zone);
ZonedDateTime end = Instant.ofEpochMilli(1511809983860L).atZone(zone);

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("EEE dd/MM HH:mm", new Locale("da", "DK"));
System.out.println(start.format(fmt));
System.out.println(end.format(fmt));

输出为:

sø 09/07 16:36
ma 27/11 17:13

如果你想转换到另一个时区(而不是 JVM 默认值),你可以使用 ZoneId.of("zonename"),或者 ZoneOffset.UTC 使用 UTC。

SimpleDateFormat dateFormat1 = new SimpleDateFormat("EEE dd/MM HH:mm", Locale.getDefault());
SimpleDateFormat dateFormat = dateFormat1;
DateFormatSymbols dfs = dateFormat.getDateFormatSymbols();
dfs.setLocalPatternChars("GyMdkHmsSEDFwWahKzZ");
dateFormat.setDateFormatSymbols(dfs);
Interval interval = new Interval(1499628963860L, 1511809983860L);
DateTime start = new DateTime(interval.getStart());
DateTime end = new DateTime(interval.getEnd());

System.out.println(start.toString(dateFormat.toLocalizedPattern()));

这是解决问题的另一种方法

它是解释日期和时间的字符集

ex :-  y = year 
d = day
M = month 
m = minutes etc 

在 DK 中,t 用于 Y 而 u 用于 d 但是 Joda 时间不支持 t 和 u