Yeni tarih saat API'sini kullanarak bir tarihi biçimlendirme


119

Yeni tarih saati API'siyle oynuyordum ama bunu çalıştırırken:

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);
    }
}

Atar:

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 sınıfının kaynak koduna baktığımda şunu görüyorum:

  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);
    }

Belgede açıklandığı gibi:

Bu yöntem, sınıf belgelerinde açıklandığı gibi basit bir harf ve simge modeline dayalı bir biçimlendirici yaratacaktır.

Ve tüm bu harfler tanımlanmıştır .

Öyleyse neden DateTimeFormatter.ofPatternbazı kalıp harfleri kullanmamıza izin vermiyor?

Yanıtlar:


220

LocalDateDateTime'ı değil yalnızca bir tarihi temsil eder. Yani "HH: mm: ss", a biçimlendirirken bir anlam ifade etmiyor LocalDate. LocalDateTimeHem tarihi hem de saati temsil etmek istediğinizi varsayarak bunun yerine a kullanın.


3
Bu yanıta nasıl yukarı oy verebilirim ve hem bir LocalDate hem de LocalDateTime nesnesi olduğu gerçeğine nasıl olumsuz oy verebilirim ...
Xials

Yalnızca LocalTime ile çalışmak istiyorum, bu istisnayla karşılaşmadan nasıl biçimlendirme gerçekleştirirsinizjava.time.temporal.UnsupportedTemporalTypeException: Unsupported field: DayOfWeek
samuel owino

Boşver: bu işe yarıyorDateTimeFormatter.ofPattern("HH:mm:ss")
samuel owino

36

@ James_D'nin doğru cevabına aşağıdaki ayrıntıları eklemek istiyorum:

Arka plan: Çoğu tarih ve saat kitaplığı ( java.util.CalendarJava'da, ayrıca bkz. .Net-DateTime veya DateJavaScript veyaDateTime Perl'de) evrensel, çok amaçlı benzersiz bir zamansal tür kavramına dayanmaktadır (Almanca'da şiirsel ifade vardır " eierlegende Wollmilchsau "). Bu tasarımda desteklenmeyen bir alan olamaz. Ancak fiyat yüksektir: Çoğu zaman problemi bu kadar esnek olmayan bir yaklaşımla yeterince ele alınamaz çünkü her tür zamansal nesne için ortak bir payda bulmak imkansızdır.

JSR-310, desteklenen yerleşik alanların türe özgü kümelerinden oluşan farklı geçici türlere izin vermek için başka bir yol seçmiştir . Bunun doğal sonucu, olası her alanın her tür tarafından desteklenmemesidir (ve kullanıcılar kendi özel alanlarını bile tanımlayabilirler). Ayrıca, her türden nesneye belirli desteklenen alanlar kümesini programlı olarak sormak da mümkündür TemporalAccessor. Bulduğumuz LocalDateiçin:

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 

Sorununu açıklayan HOUR_OF_DAY alanı yok UnsupportedTemporalTypeException. Ve desen sembollerinin alanlara JSR-310- eşlemesine bakarsak, H sembolünün desteklenmeyen HOUR_OF_DAY ile eşlendiğini görürüz:

/** 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);    
}

Bu alan haritalama, alanın somut tip tarafından desteklendiği anlamına gelmez. Ayrıştırma birkaç adımda gerçekleşir. Alan haritalama yalnızca ilk adımdır. İkinci adım daha sonra bir tür ham nesneye ayrıştırmaktır TemporalAccessor. Ve son olarak, delegeleri hedef türüne (burada LocalDate:) ayrıştırın ve ayrıştırılmış ara nesnedeki tüm alan değerlerini kabul edip etmediğine karar vermesine izin verin.


4
en.wiktionary.org/wiki/eierlegende_Wollmilchsau (kelimenin tam anlamıyla “yumurtlayan yün-süt-ekmek”) Yalnızca olumlu özelliklere sahip olan (veya sahip olduğunu iddia eden) ve yapabilen (veya yapmaya teşebbüs eden) hepsi bir arada bir cihaz veya kişi birkaç özel aracın işini yapın. :-)
Trevor Robinson

6

Benim için doğru sınıf ZonedDateTime, hem Zaman hem de Zaman Dilimini içeren sınıftı .

LocalDateSaat bilgisine sahip olmadığından bir UnsupportedTemporalTypeException: Unsupported field: HourOfDay.

Kullanabilirsiniz, LocalDateTimeancak Saat Dilimi bilgisine sahip değilsiniz, bu nedenle buna erişmeye çalışırsanız (önceden tanımlanmış biçimlendiricilerden birini kullanarak bile) bir UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.