Java 时间 API 语言环境(一年中的一周)

Java Time API Locale (week of the year)

如何将本地化传递给新的 Java 时间 API?

在这个简单的示例中,我尝试打印一年中的当前一周,但结果总是错误的。

import java.text.*;
import java.time.*;
import java.time.format.*;
import java.util.*;

//wrong result
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy ww");
System.out.println(LocalDateTime.now(ZoneId.of("Europe/Berlin")).format(formatter));

//this works
System.out.println(new SimpleDateFormat("yyyy ww",Locale.GERMANY).format(new Date()));

将 Locale 传递给 DateTimeFormatter

的 ofPattern 方法
 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy ww",Locale.GERMANY);
 System.out.println(LocalDateTime.now().format(formatter));

tl;博士

使用正确的格式化模式,区分大小写:"YYYY ww".

LocalDate.now( ZoneId.of( "Europe/Berlin" ) )    // Get the current date (date-only value) as seen in the wall-clock time used by the people of a certain region (a time zone).
.format(                                         // Generate a string representing the week and week-based-year according to a particular locale’s definition of ‘week’.
    DateTimeFormatter.ofPattern( "YYYY ww" ).withLocale( Locale.GERMANY )
)

yyyy ww无效

java.time中的yyyy编码表示日历年。接下来是 ww 标准 ISO 8601 基于周的年份的周数具有误导性和荒谬性。

您应该将周数与 基于周的年 数字相结合,而不是 日历年 数字。其格式代码为大写 YYYY。所以你会想要 YYYY ww.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "YYYY ww" ) ;

区域设置影响 YYYY 而不是 yyyy

由于 yyyy 小写表示日历年,因此指定 Locale 无效。如上所述,如果您想要语言环境定义的基于周的年份,请使用 YYYY 大写字母。

有关详细信息,请参阅问题:

Locale locale = Locale.GERMANY ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "YYYY ww" ).withLocale( locale ) ;
LocalDate ld = LocalDate.now( ZoneId.of( "Europe/Berlin" ) ) ; // Or "Africa/Tunis", "Pacific/Auckland" etc. Time zone is unrelated (orthogonal) to locale.
String output = ld.format( f ) ;

标准周

也许您想要 ISO 8601 standard definition of week 而不是语言环境定义的定义。这是第 1 周包含日历年的第一个星期四,从星期一开始,每年总共 52 或 53 周。

ISO 8601 定义了基于周的年和周的标准格式。您可能要考虑使用标准格式而不是自定义格式。

标准格式是 yyyy-Www 表示年-周,yyyy-Www-d 也显示星期几,其中 1-7 表示周一至周日。例如,2012-W48-6 是 2012-12-01,星期六(星期六)。

DateTimeFormatter class 带有预定义的格式,DateTimeFormatter.ISO_WEEK_DATE

String input = "2012-W48-6";
LocalDate ld = LocalDate.parse( input , DateTimeFormatter.ISO_WEEK_DATE );
System.out.println( ld );

2012-12-01

你可以生成这样的字符串。

String output = ld.format( DateTimeFormatter.ISO_WEEK_DATE );

2012-W48-6

如果您想要整个星期,没有星期几,只需截断字符串即可。

String output = ld.format( DateTimeFormatter.ISO_WEEK_DATE ).substring( 0 , 8 ) ;

2012-W48

YearWeek

如果您要完成大部分这项工作,我建议添加 ThreeTen-Extra library to your project. That library offers many handy classes, one of which is YearWeek 来代表整个标准 ISO 8601 周。

YearWeek yw = YearWeek.parse( "2012-W48" ) ;

获取当前周。

YearWeek yw = YearWeek.now( ZoneId.of( "Europe/Berlin" ) )     

yw.toString(): 2012-W48


关于java.time

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

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

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes.

在哪里获取 java.time classes?

  • Java SE 8, Java SE 9, Java SE 10,后来
  • 内置。
  • 标准 Java API 的一部分,带有捆绑实施。
  • Java 9 添加了一些小功能和修复。
  • Java SE 6 and Java SE 7
  • 许多 java.time 功能被反向移植到 ThreeTen-Backport 中的 Java 6 和 7。
  • Android
  • Android java.time classes.
  • 捆绑实施的更高版本
  • 对于较早的 Android (<26),ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See .

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.