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

Thu*_*wat 4 java calendar

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

Java 文档。说:

getInstance public static Calendar getInstance(Locale aLocale) 获取使用默认时区和指定区域设置的日历。返回的日历基于具有给定语言环境的默认时区中的当前时间。 参数: aLocale - 周数据的区域设置 返回: 日历。

我的代码:

 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
 }
Run Code Online (Sandbox Code Playgroud)

输出:

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

2015 年 4 月 29 日

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

Bas*_*que 6

Loc回答是正确的:您的调用会Calendar::getTime产生一个java.util.Date对象。该java.util.Date班有没有明确的时区,但其toString方法混淆的应用JVM的当前默认时区而产生的字符串。

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

时间

获取UTC 中的当前时刻。该Instant级表示时间轴上的时刻UTC,分辨率为纳秒(最多小数的9个位数)。

Instant instant = Instant.now();
Run Code Online (Sandbox Code Playgroud)

您可以创建一个字符串来表示与标准值ISO 8601的格式通过调用toString

String output = instant.toString();
Run Code Online (Sandbox Code Playgroud)

2016-09-28T19:38:21Z

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

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

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

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

Locale locale = new Locale("pt", "BR");
ZoneId z = ZoneId.of( "Pacific/Auckland" );
Run Code Online (Sandbox Code Playgroud)

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

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

ZonedDateTime zdt = instant.atZone( z );
Run Code Online (Sandbox Code Playgroud)

Locale不影响意义上的呈现。我们可以让Locale对象在生成 String 时驱动自动定位,以通过DateTimeFormatter类来表示日期时间值。指定 aFormatStyle以确定字符串的长度或缩写。

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL )
                                       .withLocale( locale );
String output = zdt.format( f );
Run Code Online (Sandbox Code Playgroud)

转储到控制台。这里看到的instantzdt物体代表了同一时刻,时间线上的同一点。唯一的区别是不同地区挂钟时间的视角。

System.out.println ( "instant.toString(): " + instant 
                     + " | zdt: " + zdt 
                     + " | output: " + output );
Run Code Online (Sandbox Code Playgroud)

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 ) ;
Run Code Online (Sandbox Code Playgroud)

而且,走向另一个方向:

ZonedDateTime zdt = myGregorianCalendar.toZonedDateTime() ;
Run Code Online (Sandbox Code Playgroud)

关于 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,反向移植,并进一步用于安卓ThreeTenABP(见如何使用......)。

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多