Java:将时区添加到DateTimeFormatter

Java:将时区添加到DateTimeFormatter,java,datetime,Java,Datetime,LocalDateTime API允许使用格式化程序中的键“z”添加时区名称。我在添加这个密钥时遇到了一个异常,我不明白为什么。我正在寻找类似以下示例的内容“11:59:22 PM GMT”,而不是“**”。。。城市轨道交通+2**' 我的代码: public class TimeZone { public static void main(String[] args) { LocalDateTime now = LocalDateTime.now();

LocalDateTime API允许使用格式化程序中的键“z”添加时区名称。我在添加这个密钥时遇到了一个异常,我不明白为什么。我正在寻找类似以下示例的内容“
11:59:22 PM GMT
”,而不是“
**”。。。城市轨道交通+2**
'

我的代码:

public class TimeZone
{
    public static void main(String[] args)
    {
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm:ss a z");
        System.out.println(now.format(formatter));
    }
}
例外情况:

Exception in thread "main" java.time.DateTimeException: Unable to extract value: class java.time.LocalDateTime
at java.time.format.DateTimePrintContext.getValue(Unknown Source)
at java.time.format.DateTimeFormatterBuilder$ZoneTextPrinterParser.format(Unknown Source)
at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(Unknown Source)
at java.time.format.DateTimeFormatter.formatTo(Unknown Source)
at java.time.format.DateTimeFormatter.format(Unknown Source)
at java.time.LocalDateTime.format(Unknown Source)
at tz.TimeZone.main(TimeZone.java:12)
以下是DateTimeFormatter API部分:

All letters 'A' to 'Z' and 'a' to 'z' are reserved as pattern letters. The following pattern letters are defined: 
  Symbol  Meaning                     Presentation      Examples
  ------  -------                     ------------      -------
   G       era                         text              AD; Anno Domini; A
   u       year                        year              2004; 04
   y       year-of-era                 year              2004; 04
   D       day-of-year                 number            189
   M/L     month-of-year               number/text       7; 07; Jul; July; J
   d       day-of-month                number            10

   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
   Y       week-based-year             year              1996; 96
   w       week-of-week-based-year     number            27
   W       week-of-month               number            4
   E       day-of-week                 text              Tue; Tuesday; T
   e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
   F       week-of-month               number            3

   a       am-pm-of-day                text              PM
   h       clock-hour-of-am-pm (1-12)  number            12
   K       hour-of-am-pm (0-11)        number            0
   k       clock-hour-of-am-pm (1-24)  number            0

   H       hour-of-day (0-23)          number            0
   m       minute-of-hour              number            30
   s       second-of-minute            number            55
   S       fraction-of-second          fraction          978
   A       milli-of-day                number            1234
   n       nano-of-second              number            987654321
   N       nano-of-day                 number            1234000000

   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
   z       time-zone name              zone-name         Pacific Standard Time; PST
   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;

有人知道问题出在哪里吗?

LocalDateTime类不支持时区;您可以使用

这将不再引发异常并为我打印东部夏令时06:08:20 PM
,但时区将根据您的位置而不同。

有两个类型为
LocalDate
LocalTime
的字段
字段
hour
minute
second
nano
字段

那里没有一个时区。这是自然的,因为
LocalDateTime
的javadoc说:

没有时区的日期时间

因此,如果“本地”日期/时间值已经表示UTC中的时间,并且您希望将其格式化为表示UTC的时间,那么您有多个选项:

  • 通过调用以下命令将
    LocalDateTime
    更改为a:

  • 通过调用以下命令在格式化程序中指定覆盖时区:

  • 使用文字
    Z
    字符格式化:

    System.out.println(time.format(DateTimeFormatter.ofPattern("hh:mm:ss a 'Z'")));
    
上述三项产出:

11:59:22 PM Z


现在,如果“本地”日期/时间确实位于不同的时区,则可以使用前两个时区中的任意一个,只需指定实际的时区即可

例如,如果时区为
-04:00
,则使用
时区时间偏移(-4)
,您将得到:

11:59:22 PM-04:00

或者,如果您在纽约,使用ZoneId.of(“America/New_York”)
,您将获得:

东部夏令时晚上11:59:22

如果“本地”日期/时间用于纽约,但您希望格式化文本为UTC,请同时使用这两个日期/时间,即

System.out.println(time.atZone(ZoneId.of("America/New_York"))
                       .format(DateTimeFormatter.ofPattern("hh:mm:ss a z")
                                                .withZone(ZoneOffset.UTC)));
这样,您就可以将时间转换为:


03:59:22 AM Z

一些人发现类名中的“local”让人困惑
LocalDate
LocalTime
LocalDateTime
等。意思是“没有时区”。如果您想要一个日期时间对象“知道”它在哪个时区是本地的,请使用
ZonedDateTime
。谢谢您的详细回答。我试试你的解决办法!这个问题似乎引出了一个问题,那就是计算机是如何获得它当时的数字的。因此,如果我想显示与我所在地区不同的时区,我必须手动计算偏移量?@Herr.Roehrig如果您希望当前时间在纽约,无论默认时区是什么,请调用
LocalDateTime.now(ZoneId.of(“America/New_York”)
。所以如果你从我的答案中学到了什么,你会发现以UTC为单位获取当前时间,你就需要
LocalDateTime.now(ZoneId.of(ZoneOffset.UTC))
@Herr.Roehrig谈论:因为你调用了
now()
的no-arg重载,所以时间是在默认时区,即在时区中,这就是你想在答案代码中指定的时区。
System.out.println(time.format(DateTimeFormatter.ofPattern("hh:mm:ss a z")
                                                .withZone(ZoneOffset.UTC)));
System.out.println(time.format(DateTimeFormatter.ofPattern("hh:mm:ss a 'Z'")));
System.out.println(time.atZone(ZoneId.of("America/New_York"))
                       .format(DateTimeFormatter.ofPattern("hh:mm:ss a z")
                                                .withZone(ZoneOffset.UTC)));