如何在指定语言环境下使用 Calendar.getInstance

How to use Calendar.getInstance with specified Locale

我正在尝试将 Calendar.getInstance(Locale l) 与指定的 Locale 一起使用,但无法正常工作。我不知道我做错了什么。

Java 文档。说:

getInstance public static Calendar getInstance(Locale aLocale) Gets a calendar using the default time zone and specified locale. The Calendar returned is based on the current time in the default time zone with the given locale. Parameters: aLocale - the locale for the week data Returns: a Calendar.

我的代码:

 public static void main (String[] args){

     Locale local = new Locale("pt", "BR");

     Calendar c = Calendar.getInstance(local); // here I am using the method
     System.out.println(c.getTime()); // and here, I cannot figure out why is not working


     DateFormat dt = DateFormat.getDateInstance(DateFormat.LONG, local);
     String s = dt.format(c.getTime());
     System.out.println(s); // here just a example in portuguese Brasil
 }

输出:

Wed Apr 29 10:18:16 BRT 2015

29 de Abril de 2015

第一个 print 必须是 Locale("pt", "BR"),用葡萄牙语吗?

您的第一个打印件只是打印日期信息,Java 使用此打印件的默认语言环境(英语)

System.out.println(c.getTime());

此打印将执行:c.getTime().toString() 方法,并且此方法使用默认语言环境(英文) - 您可以查看 Date.toString() 源代码以查看Java 使用默认语言环境。

这就是为什么输出是 'Wed Apr 29 10:18:16 BRT 2015'

如果你想打印输出是葡萄牙语。你必须使用第二次打印。

is correct: Your call to Calendar::getTime produces a java.util.Date 对象。 java.util.Date class 没有明确的时区,但它的 toString 方法在生成字符串时混淆地应用了 JVM 当前的默认时区。

所有非常令人困惑的名称和行为 - 许多 避免这些设计不佳、令人困惑和麻烦的旧遗留日期时间 class 的一些原因。相反,您应该使用 java.time classes 正式取代旧的 classes.

java.time

获取 UTC. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds 中的当前时刻(最多九 (9) 位小数)。

Instant instant = Instant.now();

您可以通过调用 toString.

创建一个字符串来表示具有标准 ISO 8601 格式的值
String output = instant.toString();

2016-09-28T19:38:21Z

题目中的代码忽略了时区的问题。如果您未指定时区,则隐式应用 JVM 当前的默认时区。最好明确指定。

请注意 Locale 和时区是两个完全不同的问题

  • Locale 确定 (a) 用于翻译日期名称、月份名称等的人类语言,以及 (b) 决定缩写、大写、标点符号等问题的文化规范.
  • 时区决定了 wall-clock time 用于显示日期时间值。

两者可以任意组合。例如,印度加尔各答的时区使用法语语言环境,或者巴西葡萄牙语语言环境使用新西兰奥克兰时区。

Locale locale = new Locale("pt", "BR");
ZoneId z = ZoneId.of( "Pacific/Auckland" );

将时区应用为 ZoneId 以生成 ZonedDateTime。从概念上讲,将其视为 ZonedDateTime = ( Instant + ZoneID )

continent/region的格式指定一个proper time zone name。切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZonedDateTime zdt = instant.atZone( z );

Locale不影响意思,就介绍一下。我们可以让 Locale 对象在通过 DateTimeFormatter class 生成表示日期时间值的字符串时驱动自动本地化。指定 FormatStyle 以确定字符串的长度或缩写。

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL )
                                       .withLocale( locale );
String output = zdt.format( f );

转储到控制台。此处看到的 instantzdt 对象代表同一时刻,时间轴上的同一点。唯一的区别是通过镜头观察不同地区的挂钟时间。

System.out.println ( "instant.toString(): " + instant 
                     + " | zdt: " + zdt 
                     + " | output: " + output );

instant.toString(): 2016-09-28T20:20:38.242Z | zdt: 2016-09-29T09:20:38.242+13:00[Pacific/Auckland] | output: Quinta-feira, 29 de Setembro de 2016 09h20min38s NZDT

转化

避免使用旧的 .Date.Calendar classes。但是,如果您必须将它们与尚未针对 java.time 类型更新的旧代码一起使用,则可以进行转换。使用添加到旧 classes 的新方法。这里我们调用java.util.GregorianCalendar.from( ZonedDateTime )

java.util.Calendar cal = java.util.GregorianCalendar.from( zdt ) ;

然后,转向另一个方向:

ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime() ;

关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.

Joda-Time project, now in maintenance mode,建议迁移到java.time。

要了解更多信息,请参阅 Oracle Tutorial。并在 Stack Overflow 中搜索许多示例和解释。

许多 java.time 功能被反向移植到 ThreeTen-Backport and further adapted to Android in ThreeTenABP (see 中的 Java 6 和 7)。

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.