Problem z formatem daty z DateTimeFormatter [duplicate]

Oct 05 2020

Mam datę w następującym formacie: 1/1/2020 3:4:7 AMPróbuję sformatować ją za pomocą DateTimeFormatter.

Mam następujący kod z programem formatującym do przeanalizowania go, ale to nie działa.

LocalDateTime date = LocalDateTime.parse("1/1/2020 3:4:7 AM", DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a"));

Otrzymuję następujący wyjątek:

java.time.format.DateTimeParseException: Text '1/1/2020 3:4:7 AM' could not be parsed at index 0

Czy ktoś może mi pomóc?

Odpowiedzi

7 rzwitserloot Oct 05 2020 at 21:07

Dwa oddzielne problemy:

Źle się liczy

Używasz np. MMCo jest jawne: Zawsze pełna liczba cyfr, uzupełniona zerami. Twój ciąg nie jest taki, to tylko liczba. Więc zrób to M/d/uuuu h:m:s a.

EDYCJA: Zmieniono yyyyna uuuu, dzięki, @deHaar. Rozumowanie: yyyy lub uuuu rzadko mają znaczenie, ale pamiętaj, że to oznacza, że wymagane są 4 cyfry . Różnica pojawia się latami przed 0: uuuustaje się ujemna, yyyynie ma i oczekuje, że użyjesz np. Aby GGuzyskać 44 BCzamiast -44. W ten sposób uuuujest po prostu bardziej poprawny, chociaż zwykle różnica nie będzie się pojawiać.

Brak języka

Drugi problem polega na tym, że prawie nigdy nie powinieneś używać tej wersji ofPattern- ma błąd, którego nie można złapać za pomocą testów jednostkowych, co sprawia, że ​​jest to błąd, który jest tysiące razy „cięższy”, a tym samym prawdziwy problem .

Musisz określić lokalizację. Bez tego 'AM' nie będzie analizować, chyba że domyślnym językiem platformy jest angielski.

Składając to razem

LocalDateTime date = LocalDateTime.parse("1/1/2020 3:4:7 AM",
  DateTimeFormatter.ofPattern("M/d/uuuu h:m:s a", Locale.ENGLISH));

działa świetnie.

3 GiorgiTsiklauri Oct 05 2020 at 21:09

W Twoim fragmencie:

LocalDateTime
    .parse("1/1/2020 3:4:7 AM", DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a"));
  • 1 - nie pasuje MM
  • 1 - nie pasuje dd
  • 3 - nie pasuje hh
  • 4 - nie pasuje mm
  • 7 - nie pasuje ss

tzn. długości części wzorca formatera (np. MM) i ich odpowiednich części z tekstu ciągu (np. 1) nie są zgodne.

Możesz je dopasować na kilka sposobów, np. Możesz albo zmienić tekst ciągu, aby pasował do wzorca formatera, albo odwrotnie.

Zamiast tego możesz spróbować:

LocalDateTime
    .parse("01/01/2020 03:04:07 AM", DateTimeFormatter.ofPattern("MM/dd/yyyy hh:mm:ss a"));

Ponadto spójrz na Wzory liter i symboli .

3 LiveandLetLive Oct 05 2020 at 21:05
  1. Użyj pojedynczych liter dla składników daty i godziny (miesiąc, dzień, rok, godzina, minuta i sekunda).

  2. Możesz również sprawić, aby program formatujący obsługiwał wzorzec w sposób niewrażliwy na wielkość liter (np. Rano, przed południem, rano), jak pokazano poniżej:

    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.time.format.DateTimeFormatterBuilder;
    import java.util.Locale;
    
    public class Main {
        public static void main(String[] args) {
             // Formatter to handle the pattern in case insensitive way (e.g. am, AM, Am)
            DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                                                .parseCaseInsensitive()
                                                .appendPattern("M/d/u h:m:s a")
                                                .toFormatter(Locale.ENGLISH);
            LocalDateTime date = LocalDateTime.parse("1/1/2020 3:4:7 AM", formatter);
            System.out.println(date);
        }
    }
    

Wynik:

2020-01-01T03:04:07
2 0009laH Oct 05 2020 at 21:08

Zgodnie z dokumentacją DateTimeFormatter :

Liczba: jeśli liczba liter wynosi jeden , wartość jest wyprowadzana przy użyciu minimalnej liczby cyfr i bez dopełnienia. W przeciwnym razie liczba cyfr jest używana jako szerokość pola wyjściowego, przy czym w razie potrzeby wartość jest uzupełniana zerami.

Odwracając rozumowanie, możesz spróbować użyć tego programu formatującego:

DateTimeFormatter.ofPattern("M/d/yyyy h:m:s a")