如何使用具有指定语言环境的 Calendar.getInstance

2022-01-11 00:00:00 calendar java

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

Java 文档.说:

<块引用>

获取实例公共静态日历 getInstance(Locale aLocale)获取使用默认时区和指定区域设置的日历.返回的日历基于具有给定区域设置的默认时区的当前时间.参数:aLocale - 周数据的语言环境回报:日历.

我的代码:

 public static void main (String[] args){Locale local = new Locale("pt", "BR");日历 c = Calendar.getInstance(local);//这里我使用的是方法System.out.println(c.getTime());//在这里,我不知道为什么不工作DateFormat dt = DateFormat.getDateInstance(DateFormat.LONG, local);字符串 s = dt.format(c.getTime());System.out.println(s);//这里只是葡萄牙语巴西的一个例子}

输出:

<块引用>

2015 年 4 月 29 日星期三 10:18:16 BRT

2015 年 4 月 29 日

第一个 print 是否应该在葡萄牙语的 Locale("pt", "BR") 中?

解决方案

Loc回答是正确的:您的电话到 Calendar::getTime 产生一个 java.util.Date 对象.java.util.Date 类没有明确的时区,但它的 toString 方法在生成字符串时会混淆地应用 JVM 的当前默认时区.

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

java.time

获取 UTC 中的当前时刻.Instant类代表时间轴上的时刻 UTC 分辨率为 纳秒(最多九 (9) 位小数).

Instant instant = Instant.now();

您可以通过调用 toString.

字符串输出 = instant.toString();

<块引用>

2016-09-28T19:38:21Z

问题中的代码忽略了时区问题.当您不指定时区时,您的 JVM 当前默认时区将被隐式应用.最好明确指定.

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

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

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

Locale locale = new Locale("pt", "BR");ZoneId z = ZoneId.of("太平洋/奥克兰");

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

continent/region的格式指定一个正确的时区名称代码>.切勿使用 3-4 个字母的缩写,例如 ESTIST,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!).

ZonedDateTime zdt = instant.atZone(z);

Locale 不影响表示的含义.我们可以让 Locale 对象在通过 DateTimeFormatter 类生成表示日期时间值的字符串时驱动自动本地化.指定 FormatStyle 确定字符串的长度或缩写.

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL).withLocale( 语言环境 );字符串输出 = zdt.format( f );

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

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

<块引用>

instant.toString(): 2016-09-28T20:20:38.242Z |zdt: 2016-09-29T09:20:38.242+13:00[太平洋/奥克兰] |输出:Quinta-feira, 29 de Setembro de 2016 09h20min38s NZDT

转化

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

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

然后,往另一个方向发展:

ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime() ;

关于java.time

java.time框架内置于 Java 8 及更高版本中.这些类取代了麻烦的旧日期时间类,例如 <代码>java.util.Date, .Calendar, &java.text.SimpleDateFormat.

Joda-Time 项目,现在在 维护模式,建议迁移到 java.time.

要了解更多信息,请参阅 Oracle 教程.并在 Stack Overflow 上搜索许多示例和解释.

大部分 java.time 功能都向后移植到 Java 6 &7 在 ThreeTen-Backport 并进一步适应 Android 在 ThreeTenABP (请参阅如何使用...).

ThreeTen-Extra 项目通过附加类扩展了 java.time.该项目是未来可能添加到 java.time 的试验场.您可以在这里找到一些有用的类,例如 Interval, YearWeek, YearQuarter 和 更多.

I am trying to use Calendar.getInstance(Locale l) with specified Locale and is not working. I cannot figure out what I am doing wrong.

The Java Doc. say:

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.

My code:

 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
 }

Output:

Wed Apr 29 10:18:16 BRT 2015

29 de Abril de 2015

Should the first print must be in Locale("pt", "BR"), in portuguese?

解决方案

The Answer by Loc is correct: Your call to Calendar::getTime produces a java.util.Date object. The java.util.Date class has no explicit time zone yet its toString method confusingly applies the JVM’s current default time zone while generating a String.

All very confusing names and behavior - some of the many reasons to avoid these poorly designed, confusing, and troublesome old legacy date-time classes. Instead you should be using the java.time classes that officially supplant the old classes.

java.time

Get the current moment in UTC. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Instant instant = Instant.now();

You can create a String to represent that value with standard ISO 8601 formatting by calling toString.

String output = instant.toString();

2016-09-28T19:38:21Z

The code in the Question ignores the issue of time zone. When you do not specify a time zone your JVM’s current default time zone is implicitly applied. Better to specify explicitly.

Note that Locale and time zone are two completely separate distinct issues.

  • Locale to determine (a) the human language for translation of name of day, name of month, and such, and (b) the cultural norms deciding issues of abbreviation, capitalization, punctuation, and such.
  • Time zone determines the wall-clock time used to present the date-time value.

You can have any combination of the two. For example, a time zone of Kolkata India with a French locale, or a Brazil Portuguese locale with an Auckland New Zealand time zone.

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

Apply the time zone as a ZoneId to produce a ZonedDateTime. Conceptually, think of it as ZonedDateTime = ( Instant + ZoneID ).

Specify a proper time zone name in the format of continent/region. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZonedDateTime zdt = instant.atZone( z );

The Locale does not affect the meaning, on the presentation. We can let the Locale object drive the automatic localization of when producing a String to represent the date-time value via the DateTimeFormatter class. Specify a FormatStyle to determine how long or abbreviated should the string be.

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

Dump to console. The instant and zdt objects seen here represent the very same moment, the same point on the timeline. The only difference is a view through the lens of a different region’s wall-clock time.

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

Conversion

Avoid the old .Date and .Calendar classes. But if you must use them with old code not yet updated for the java.time types, you can convert. Use new methods added to the old classes. Here we call java.util.GregorianCalendar.from( ZonedDateTime ).

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

And, going the other direction:

ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime() ;

About java.time

The 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.

The Joda-Time project, now in maintenance mode, advises migration to java.time.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).

The 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.

相关文章