จัดรูปแบบวันที่โดยใช้วันที่และเวลาใหม่ API


119

ฉันกำลังเล่นกับวันที่เวลาใหม่ 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);
    }

ตามที่อธิบายไว้ในเอกสาร:

วิธีนี้จะสร้างฟอร์แมตเตอร์ตามรูปแบบตัวอักษรและสัญลักษณ์ง่ายๆตามที่อธิบายไว้ในเอกสารประกอบของคลาส

และตัวอักษรทั้งหมดเหล่านี้จะกำหนด

เหตุใดจึงDateTimeFormatter.ofPatternไม่อนุญาตให้เราใช้ตัวอักษรรูปแบบบางอย่าง?

คำตอบ:


220

LocalDateแสดงเพียงวันที่ไม่ใช่ DateTime ดังนั้น "HH: mm: ss" จึงไม่สมเหตุสมผลเมื่อฟอร์แมต a LocalDate. ใช้LocalDateTimeแทนโดยสมมติว่าคุณต้องการแสดงทั้งวันที่และเวลา


3
ฉันจะโหวตคำตอบนี้และลงคะแนนได้อย่างไรว่ามีทั้งวัตถุ LocalDate และ LocalDateTime ...
Xials

ฉันอยากจะทำงานกับ LocalTime คุณจะจัดรูปแบบอย่างไรโดยไม่พบข้อยกเว้นนี้java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: DayOfWeek
samuel owino

ไม่เป็นไร: ได้ผลDateTimeFormatter.ofPattern("HH:mm:ss")
samuel owino

36

ฉันต้องการเพิ่มรายละเอียดต่อไปนี้ในคำตอบที่ถูกต้องของ @James_D:

ความเป็นมา:ไลบรารีวันที่และเวลาส่วนใหญ่ ( java.util.Calendarใน Java โปรดดูที่. Net-DateTime หรือDateใน JavaScript หรือDateTimeใน Perl) ขึ้นอยู่กับแนวคิดของประเภทชั่วคราวที่ไม่ซ้ำกันอเนกประสงค์สากล (ในภาษาเยอรมันมีสำนวนกวี " eierlegende Wollmilchsau ") ในการออกแบบนี้ต้องไม่มีฟิลด์ที่ไม่รองรับ แต่ราคาสูง: ปัญหาเกี่ยวกับเวลาหลายอย่างไม่สามารถจัดการได้อย่างเพียงพอด้วยวิธีการที่ไม่ยืดหยุ่นเช่นนี้เพราะยากที่จะหาตัวส่วนร่วมสำหรับวัตถุชั่วคราวทุกชนิดไม่ได้

JSR-310 ได้เลือกอีกวิธีหนึ่งคือการอนุญาตประเภทชั่วคราวที่แตกต่างกันซึ่งประกอบด้วยชุดเฉพาะประเภทของฟิลด์ในตัวที่รองรับ ผลที่ตามมาคือไม่ใช่ทุกฟิลด์ที่เป็นไปได้จะได้รับการสนับสนุนจากทุกประเภท (และผู้ใช้สามารถกำหนดฟิลด์เฉพาะของตนเองได้) นอกจากนี้ยังเป็นไปได้ที่จะถามออบเจ็กต์ทุกประเภทโดยทางโปรแกรม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- การแมปสัญลักษณ์รูปแบบกับฟิลด์เราจะเห็นว่าสัญลักษณ์ 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และปล่อยให้มันตัดสินใจว่ายอมรับค่าฟิลด์ทั้งหมดในออบเจ็กต์กลางที่แยกวิเคราะห์หรือไม่


4
en.wiktionary.org/wiki/eierlegende_Wollmilchsau (ตามตัวอักษร "ไข่ - ขน - นม - หว่าน") อุปกรณ์ออลอินวันหรือบุคคลที่มี (หรืออ้างว่ามี) เฉพาะคุณลักษณะเชิงบวกและสิ่งที่สามารถ (หรือพยายาม) ทำงานกับเครื่องมือพิเศษหลายอย่าง :-)
Trevor Robinson

6

คลาสที่เหมาะสำหรับฉันคือคลาสZonedDateTimeที่มีทั้งเวลาและไทม์โซน

LocalDateไม่มีข้อมูลเวลาดังนั้นคุณจึงได้รับไฟล์UnsupportedTemporalTypeException: Unsupported field: HourOfDay.

คุณสามารถใช้ได้LocalDateTimeแต่คุณไม่มีข้อมูลโซนเวลาดังนั้นหากคุณพยายามเข้าถึงข้อมูลนั้น (แม้จะใช้รูปแบบที่กำหนดไว้ล่วงหน้าอย่างใดอย่างหนึ่ง) คุณจะได้รับไฟล์UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds.

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.