使用 FormatStyle.MEDIUM 加时区格式化 LocalDateTime

J W*_*uck 7 java date

我有一个 LocalDateTime 对象,其格式如下:

LocalDateTime localDateTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
System.out.println(localDateTime.format(formatter));
Run Code Online (Sandbox Code Playgroud)

这会打印出一个易于阅读的日期Oct 20, 2021 1:00:02 PM

但我还想添加时区。我的理解是我需要使用 ZonedDateTime:

ZonedDateTime zdt = localDateTime.atZone(ZoneId.of("America/New_York"));
System.out.println(zdt);
Run Code Online (Sandbox Code Playgroud)

但这会产生不太可读的2021-10-20T13:00:02.921-04:00[America/New_York].

有没有某种方法可以格式化 ZonedDateTime ,使其像FormatStyle.MEDIUM生成的那样简洁易读,但还附加时区(例如:Oct 20, 2021 1:00:02 PM EST)?

注意:我从这个答案中得知,由于它们的非标准化性质,我实际上应该使用“伪区域”,例如EST 。

Bas*_*que 5

太长了;博士

如果您需要有关所使用时区的提示,请使用LONG一天中时间部分的格式。可以选择指定不同的格式,例如MEDIUM日期部分。

ZonedDateTime
    .now( ZoneId.of( "America/New_York" ) )
    .format(
        DateTimeFormatter
            .ofLocalizedDateTime( 
                FormatStyle.MEDIUM ,     // Date portion style.
                FormatStyle.LONG         // Time-of-day portion style.
            )   
            .withLocale( Locale.US )     // Locale determines the human language and cultural norms used in localizing.
    )
Run Code Online (Sandbox Code Playgroud)

请参阅在 IdeOne.com 上实时运行的代码

2021 年 10 月 20 日下午 4:48:46(美国东部时间)

切勿使用EDTCSTIST等进行数据交换。不要尝试解析此类值。这些不是真正的时区,不是标准化的,甚至不是唯一的!

避免LocalDateTime.now

我无法想象在任何情况下打电话LocalDateTime.now都是正确的做法。您捕获了日期和时间,但缺少时区上下文或相对于 UTC 的偏移量。因此,LocalDateTime根据定义,a不能代表时刻也不是时间线上的点。

如果您想捕获当前时刻而不提交特定时区,请捕获与 UTC 的偏移量为零时-分-秒的当前时刻。

Instant instant = Instant.now() ;  // Current moment as seen in UTC. 
Run Code Online (Sandbox Code Playgroud)

使用ZonedDateTime.now

如果您想捕捉America/New_York时区中看到的当前时刻,请从 开始ZonedDateTime

ZonedDateTime.now( ZoneId.of( "America/New_York" ) )
Run Code Online (Sandbox Code Playgroud)

要生成表示java.time对象的文本,请使用toString方法获取标准ISO 8601格式的文本。虽然这样的输出乍一看似乎不太可读,但标准格式的设计目的是最大限度地让不同文化的人可读。

要获得本地化格式,我建议您让java.time自动本地化。

Instant instant = Instant.now() ;  // Current moment as seen in UTC. 
Run Code Online (Sandbox Code Playgroud)

运行时。

ZonedDateTime.now( ZoneId.of( "America/New_York" ) )
Run Code Online (Sandbox Code Playgroud)

日期和时间的单独格式

您可以为日期部分和时间部分指定不同的格式。如果您愿意,可以对时间部分使用较长的格式来获取时区的提示,同时对日期部分使用较短的格式。

ZoneId z = ZoneId.of( "America/New_York" );
ZonedDateTime zdt = ZonedDateTime.now( z );
System.out.println( "zdt represented in standard ISO 8601 format: " + zdt.toString() );

Locale locale = Locale.US ; 
DateTimeFormatter f_US = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.MEDIUM ).withLocale( locale ) ;
String outputLocalized_US = zdt.format( f_US ) ;
String outputLocalized_CA_fr = zdt.format( f_US.withLocale( Locale.CANADA_FRENCH ) ) ;

System.out.println( outputLocalized_US ) ;
System.out.println( outputLocalized_CA_fr ) ;
Run Code Online (Sandbox Code Playgroud)

  • @JWoodchuck 生成文本时没有单独的时区部分。时区指示器的格式由当天时间格式控制。 (2认同)