Метка времени не может быть проанализирована Проблема java.time.format.DateTimeParseException: текст "25.09.2020, 12:46:00 PM" не может быть проанализирован с индексом 0

Я пытаюсь зафиксировать время до и после того, как проверяю значение временной метки на веб-странице, а затем подтверждаю, что моя временная метка попадает между этими временами. Однако я изо всех сил пытаюсь преобразовать мою временную метку String в сопоставимый формат чистым способом.

        Instant b4 = Instant.now();
                    
        //My code submites a file that then triggers the timestamp. I retrieve it as a string
        //exa string"9/25/2020, 11:03:18 AM"

        DateTimeFormatter dtf = DateTimeFormatter
                .ofPattern("MM/dd/yyyy, HH:mm:ss a")
                .withZone(ZoneId.systemDefault());
        Instant instantTimestamp = Instant.from(dtf.parse(timeStamp));

        Instant after = Instant.now();          

        if (instantTimestamp.isAfter(b4) && instantTimestamp.isBefore(after)) {
            testPass = true;
        }

        Assert.assertTrue(testPass);

Моя ошибка: java.time.format.DateTimeParseException: текст '25.09.2020, 12:46:00 PM' не может быть проанализирован с индексом 0

2 ответа

Решение

Несоответствие формата месяца и его значения в строке. Формат MM который указывает две цифры, но значение равно 9что представляет собой одну цифру. Вы можете использовать отдельные буквы для месяца, дня, года, часа, минуты, секунды и т. Д., Чтобы уместить все допустимое количество цифр. Кроме того, я предлагаю вам проанализировать его без учета регистра, чтобы верхний и нижний регистр (например, AM и am) оба могут быть размещены.

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // Given date-time string
        String dateTimeString = "9/25/2020, 12:46:00 PM";

        DateTimeFormatter dtf = new  DateTimeFormatterBuilder()
                                    .parseCaseInsensitive()
                                    .appendPattern("M/d/u, H:m:s a")
                                    .toFormatter(Locale.ENGLISH);
                                

        // Convert the given date-time string to LocalDateTime
        LocalDateTime ldt = LocalDateTime.parse(dateTimeString, dtf);
        System.out.println(ldt);
        
        //Convert to LocalDateTime Instant if required
        Instant instant=ldt.toInstant(ZoneOffset.UTC);
        System.out.println(instant);
    }
}

Вывод:

2020-09-25T12:46
2020-09-25T12:46:00Z

Ошибка связана с используемой строкой формата. "MM" требует, чтобы часть входной строки, содержащая месяц, состояла из двух цифр, а "9" - это только одна цифра. Другими словами, он работает "25.09.2020, 11:03:18 AM", но не "25.09.2020, 11:03:18 AM".

Здесь нужна буква "M", которая не требует, чтобы перед значением был "0":

        DateTimeFormatter dtf = DateTimeFormatter
                .ofPattern("M/dd/yyyy, HH:mm:ss a")
                .withZone(ZoneId.systemDefault());

Если дата также должна быть одной цифрой и не дополняться нулями для дней 0-9, "M/d/yyyy, HH:mm:ss a" вместо этого следует использовать шаблон.

Это описывается DateTimeFormatter Документация Javadoc:

Все буквы от "A" до "Z" и от "a" до "z" зарезервированы как буквы шаблона. Определены следующие буквы шаблона:

Symbol  Meaning                     Presentation      Examples
------  -------                     ------------      -------
[...]
 M/L     month-of-year               number/text       7; 07; Jul; July; J
[...]

Текст: [...]

Число: если количество букв равно единице, то значение выводится с использованием минимального количества цифр и без заполнения. В противном случае в качестве ширины выходного поля используется количество цифр, при необходимости значение дополняется нулями. [...]

Число / текст: если количество букв шаблона равно 3 или больше, используйте правила для текста, указанные выше. В противном случае используйте числовые правила выше.

Поскольку "M" использует представление "число / текст", а количество букв в вашем формате ("MM") равно 2, то для месяца требуется ровно две цифры. При переключении на одну букву "M" используется минимальное количество цифр (одна цифра для месяцев 1–9 и две цифры для месяцев 10–12).

Другие вопросы по тегам