首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用新的date time API设置日期格式

使用新的date time API设置日期格式
EN

Stack Overflow用户
提问于 2014-04-15 04:08:30
回答 3查看 93.8K关注 0票数 150

我使用的是新的date time API,但在运行以下代码时:

代码语言:javascript
复制
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);
    }
}

它抛出:

代码语言:javascript
复制
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类的源代码时,我看到:

代码语言:javascript
复制
  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不允许我们使用一些模式字母呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-04-15 04:10:22

LocalDate只表示一个日期,而不是一个DateTime。因此,"HH:mm:ss“在格式化LocalDate时没有任何意义。假设您想同时表示日期和时间,请改用LocalDateTime

票数 287
EN

Stack Overflow用户

发布于 2014-04-15 23:33:18

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

背景:大多数日期和时间库(Java语言中的java.util.Calendar,另请参阅.Net-DateTime或JavaScript中的Date或Perl语言中的DateTime )都基于通用唯一时态类型的概念(在德语中有一个富有诗意的表达"eierlegende Wollmilchsau")。在此设计中,不能存在不受支持的字段。但代价很高:许多时间问题不能用这种不灵活的方法充分处理,因为很难甚至不可能为所有类型的时间对象找到一个公分母。

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

代码语言:javascript
复制
•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 

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

代码语言:javascript
复制
/** 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),并让它决定是否接受解析的中间对象中的所有字段值。

票数 38
EN

Stack Overflow用户

发布于 2017-12-25 07:54:02

对我来说最合适的类是ZonedDateTime,它同时包含时区和时区。

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

您可以使用LocalDateTime,但是您没有时区信息,所以如果您尝试访问它(即使使用某个预定义的格式化程序),您将得到一个UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23069370

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档