【问题标题】:Format a date using the new date time API使用新的日期时间 API 格式化日期
【发布时间】:2014-04-14 20:08:30
【问题描述】:

我正在使用新的日期时间 API,但在运行时:

public class Test {         
    public static void main(String[] args){
        String dateFormatted = LocalDate.now()
                                        .format(DateTimeFormatter
                                              .ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println(dateFormatted);
    }
}

它抛出:

Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: HourOfDay
    at java.time.LocalDate.get0(LocalDate.java:680)
    at java.time.LocalDate.getLong(LocalDate.java:659)
    at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298)
    at java.time.format.DateTimeFormatterBuilder$NumberPrinterParser.format(DateTimeFormatterBuilder.java:2543)
    at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2182)
    at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1745)
    at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1719)
    at java.time.LocalDate.format(LocalDate.java:1685)
    at Test.main(Test.java:23)

查看 LocalDate 类的源代码时,我看到:

  private int get0(TemporalField field) {
        switch ((ChronoField) field) {
            case DAY_OF_WEEK: return getDayOfWeek().getValue();
            case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((day - 1) % 7) + 1;
            case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1;
            case DAY_OF_MONTH: return day;
            case DAY_OF_YEAR: return getDayOfYear();
            case EPOCH_DAY: throw new UnsupportedTemporalTypeException("Invalid field 'EpochDay' for get() method, use getLong() instead");
            case ALIGNED_WEEK_OF_MONTH: return ((day - 1) / 7) + 1;
            case ALIGNED_WEEK_OF_YEAR: return ((getDayOfYear() - 1) / 7) + 1;
            case MONTH_OF_YEAR: return month;
            case PROLEPTIC_MONTH: throw new UnsupportedTemporalTypeException("Invalid field 'ProlepticMonth' for get() method, use getLong() instead");
            case YEAR_OF_ERA: return (year >= 1 ? year : 1 - year);
            case YEAR: return year;
            case ERA: return (year >= 1 ? 1 : 0);
        }
        throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
    }

如文档中所述:

此方法将创建一个基于简单模式的格式化程序 类文档中描述的字母和符号。

所有这些字母都是defined

那么为什么DateTimeFormatter.ofPattern 不允许我们使用一些模式字母呢?

【问题讨论】:

    标签: java datetime java-8 java-time


    【解决方案1】:

    LocalDate 仅表示日期,而不是日期时间。所以“HH:mm:ss”在格式化LocalDate 时没有任何意义。请改用LocalDateTime,假设您想同时表示日期和时间。

    【讨论】:

    • 我怎样才能赞成这个答案并反对同时存在 LocalDate 和 LocalDateTime 对象的事实......
    • 我只想使用 LocalTime,如何在不遇到此异常的情况下执行格式化java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: DayOfWeek
    • 没关系:这行得通DateTimeFormatter.ofPattern("HH:mm:ss")
    • @samuelowino 对我来说这很有效:DateTimeFormatter.ofPattern("HH:mm").withZone(ZoneId.systemDefault()).format(...)。 .withZone(...)。
    • 我用过DateTime dateTime = DateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.RFC_1123_DATE_TIME.withLocale(defaultLocale).withZone(defaultTimeZone.toZoneId()); 这让我得到Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds 就像下面的@isapir,右:ZonedDateTime。然后它也适用于此。所以我最终得到了ZonedDateTime dateTime = ZonedDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.RFC_1123_DATE_TIME.withLocale(defaultLocale).withZone(defaultTimeZone.toZoneId());
    【解决方案2】:

    我想在@James_D 的正确答案中添加以下详细信息:

    背景: 大多数日期和时间库(Java 中的 java.util.Calendar,另请参阅 JavaScript 中的 .Net-DateTime 或 Date 或 Perl 中的 DateTime)基于通用通用唯一时间类型的概念(在德语中有诗意的表达“eierlegende Wollmilchsau”)。在此设计中,不能有不受支持的字段。但代价是高昂的:很多时间问题不能用这种不灵活的方法来充分处理,因为很难找到各种时间对象的共同点。

    JSR-310 选择了另一种方式,即允许不同的时间类型,这些时间类型由特定于类型的支持的内置字段集组成。自然的结果是,并非每种类型都支持所有可能的字段(用户甚至可以定义自己的专业字段)。也可以programmatically ask 类型为TemporalAccessor 的每个对象为其特定的支持字段集。对于LocalDate,我们发现:

    •DAY_OF_WEEK 
    •ALIGNED_DAY_OF_WEEK_IN_MONTH 
    •ALIGNED_DAY_OF_WEEK_IN_YEAR 
    •DAY_OF_MONTH 
    •DAY_OF_YEAR 
    •EPOCH_DAY 
    •ALIGNED_WEEK_OF_MONTH 
    •ALIGNED_WEEK_OF_YEAR 
    •MONTH_OF_YEAR 
    •PROLEPTIC_MONTH 
    •YEAR_OF_ERA 
    •YEAR 
    •ERA 
    

    没有 HOUR_OF_DAY 字段可以解释UnsupportedTemporalTypeException 的问题。如果我们查看 JSR-310-mapping of pattern symbols to fields,我们会看到符号 H 映射到不受支持的 HOUR_OF_DAY:

    /** Map of letters to fields. */  
    private static final Map<Character, TemporalField> FIELD_MAP = new HashMap<>();
    static {
      FIELD_MAP.put('G', ChronoField.ERA);
      FIELD_MAP.put('y', ChronoField.YEAR_OF_ERA);
      FIELD_MAP.put('u', ChronoField.YEAR);
      FIELD_MAP.put('Q', IsoFields.QUARTER_OF_YEAR);
      FIELD_MAP.put('q', IsoFields.QUARTER_OF_YEAR);
      FIELD_MAP.put('M', ChronoField.MONTH_OF_YEAR);
      FIELD_MAP.put('L', ChronoField.MONTH_OF_YEAR);
      FIELD_MAP.put('D', ChronoField.DAY_OF_YEAR);
      FIELD_MAP.put('d', ChronoField.DAY_OF_MONTH);
      FIELD_MAP.put('F', ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH);
      FIELD_MAP.put('E', ChronoField.DAY_OF_WEEK);
      FIELD_MAP.put('c', ChronoField.DAY_OF_WEEK);
      FIELD_MAP.put('e', ChronoField.DAY_OF_WEEK);
      FIELD_MAP.put('a', ChronoField.AMPM_OF_DAY);
      FIELD_MAP.put('H', ChronoField.HOUR_OF_DAY);
      FIELD_MAP.put('k', ChronoField.CLOCK_HOUR_OF_DAY);
      FIELD_MAP.put('K', ChronoField.HOUR_OF_AMPM);
      FIELD_MAP.put('h', ChronoField.CLOCK_HOUR_OF_AMPM);
      FIELD_MAP.put('m', ChronoField.MINUTE_OF_HOUR);
      FIELD_MAP.put('s', ChronoField.SECOND_OF_MINUTE);
      FIELD_MAP.put('S', ChronoField.NANO_OF_SECOND);
      FIELD_MAP.put('A', ChronoField.MILLI_OF_DAY);
      FIELD_MAP.put('n', ChronoField.NANO_OF_SECOND);
      FIELD_MAP.put('N', ChronoField.NANO_OF_DAY);    
    }
    

    此字段映射并不意味着该字段受具体类型的支持。解析分几个步骤进行。字段映射只是第一步。然后第二步解析为TemporalAccessor 类型的原始对象。最后将委托解析为目标类型(此处为:LocalDate)并让它决定是否接受解析后的中间对象中的所有字段值。

    【讨论】:

    【解决方案3】:

    适合我的课程是ZonedDateTime,其中包括时间和时区。

    LocalDate 没有时间信息,所以你得到一个UnsupportedTemporalTypeException: Unsupported field: HourOfDay

    您可以使用LocalDateTime,但您没有时区信息,因此如果您尝试访问该信息(即使使用预定义的格式化程序之一),您将获得UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds

    【讨论】:

    • 这个答案应该是接受的答案,或者应该添加到当前接受的答案中。
    • Inconvertible types; cannot cast 'java.time.LocalDateTime' to 'java.time.ZonedDateTime' :/
    【解决方案4】:

    这段代码我也有类似的问题:

    DateTimeFormatter.RFC_1123_DATE_TIME.format(new Date().toInstant())
    

    java.time.temporal.UnsupportedTemporalTypeException:不支持的字段:DayOfMonth

    我是这样解决的:

    DateTimeFormatter.RFC_1123_DATE_TIME.format(
        ZonedDateTime.ofInstant(new Date().toInstant(), ZoneId.systemDefault()))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多