Как я могу разобрать и отформатировать эту строку date 2022-11-08 10:28:04.282551-06?

У меня есть этот код:

public static void main(String[] args) throws ParseException {
        String fecha = "2022-11-08 10:28:04.282551-06";
        
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ");
        Date e = simpleDateFormat.parse(fecha);
        SimpleDateFormat newSimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        System.out.println(newSimpleDateFormat.format(e));
        
    }

И эта ошибка:

Exception in thread "main" java.text.ParseException: Unparseable date: "2022-11-08 10:28:04.282551-06"
    at java.text.DateFormat.parse(DateFormat.java:366)
    at Ejemplos.main(Ejemplos.java:11)

Я хочу, чтобы моя новая дата была такой: 2022-11-08 10:28:04.282551 Это значение после точки *282551 *иногда может быть меньше, например: *282 *или 2825, а иногда точки нет, например: 2022-11-08 10:28:04-06

Попросите производителя даты обеспечить стабильное представление этой даты и времени, лучше всего использовать формат даты и времени ISO8601. Если это невозможно, вы можете использовать java.util.regex.Pattern для определения формата заранее, прежде чем выбрать соответствующий DateTimeFormatter. Не используйте больше SimpleDateFormat или Date, переключитесь на типы из java.time.*

Christoph Dahlen 11.11.2022 07:56

Я настоятельно рекомендую вам не использовать SimpleDateFormat и Date. Они хлопотны и давно устарели. Также нет способа, которым SimpleDateFormat может разобрать 6 знаков после запятой доли секунды, так что это не сработает. Используйте OffsetDateTime и DateTimeFormatter, возможно также DateTimeFormatterBuilder; все взяты из java.time, современного API даты и времени Java.

Ole V.V. 11.11.2022 09:28
LeetCode запись решения 2536. Увеличение подматриц на единицу
LeetCode запись решения 2536. Увеличение подматриц на единицу
Увеличение подматриц на единицу - LeetCode
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Как включить TLS в gRPC-клиенте и сервере : 2
Как включить TLS в gRPC-клиенте и сервере : 2
Здравствуйте! 🙏🏻 Надеюсь, у вас все хорошо и добро пожаловать в мой блог.
Сортировка hashmap по значениям
Сортировка hashmap по значениям
На Leetcode я решал задачу с хэшмапой и подумал, что мне нужно отсортировать хэшмапу по значениям.
0
2
155
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

public static void main(String[] args) throws ParseException {
    String fecha = "2022-11-08 10:28:04.282551-06";
    String[] parts = fecha.split("\\.");
    String part1 = parts[0];
    String part2 = parts[1];

    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    System.out.println(simpleDateFormat.parse(part1));

}

Спасибо за желание внести свой вклад. (1) Использование SimpleDateFormat не рекомендуется (хотя оно также использовалось в вопросе). (2) Это неправильно. Вы игнорируете долю секунды и смещение. Первое приводит к погрешности менее секунды, второе — до 26 часов, что, вероятно, неприемлемо. Ожидаемый результат в моем часовом поясе (Европа/Копенгаген, на 1 час впереди UTC): Tue Nov 08 17:28:04 CET 2022. Наблюдаемый результат: Tue Nov 08 10:28:04 CET 2022. Ошибся на 7 часов.

Ole V.V. 11.11.2022 09:57
Ответ принят как подходящий

Настоятельно рекомендуется прекратить использование устаревших классов Date, Calendar, SimpleDateFormat, ... - они были заменены классами из пакета java.time и подпакетов, таких как LocalDateTime, ZonedDateTime, DateTimeFormatter, ...

Поскольку у нас есть дробная часть с переменным размером, нам нужен DateTimeFormatterBuilder, чтобы создать соответствующий модуль форматирования для разбора строки. В нем мы повторно используем существующий ISO_LOCAL_TIME, который обрабатывает требование, принимая от нуля до 9 знаков после запятой доли секунды.

private static final DateTimeFormatter PARSE_FORMATTER = 
        new DateTimeFormatterBuilder()
                .append(DateTimeFormatter.ISO_LOCAL_DATE)
                .appendLiteral(' ')
                .append(DateTimeFormatter.ISO_LOCAL_TIME) // accepts presence or absence of fraction
                .appendOffset("+HHmm", "+00") // accepts -06 and +0530
                .toFormatter(Locale.ROOT);  // replace as needed

public static OffsetDateTime convert(String str) {
    return OffsetDateTime.parse(str, PARSE_FORMATTER);
}

Чтобы иметь строку в формате «2022-11-08 10:28:04.282551», нам нужен дополнительный модуль форматирования:

private static final DateTimeFormatter FORMAT_FORMATTER = 
        DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSSSSS");  // time zone is IGNORED!!

public static String convertToString(OffsetDateTime dateTime) {
    return dateTime.format(FORMAT_FORMATTER);
}

Предыдущие оба метода можно (очевидно) объединить в один метод, но предпочтительнее работать с объектами даты и времени (ZonedDateTime, OffsetDateTime, LocalDateTime, ...) вместо строк - строки должны использоваться только для ввода и вывода !

Вышеупомянутый Formatter не включает информацию о часовом поясе в результат, что может быть очень запутанным (ИМХО) - см. последнюю дату тестового вывода ниже. Пожалуйста, убедитесь, что это действительно необходимо!!! В противном случае мы можем преобразовать OffsetDateTme в ZonedDateTime, как в dateTime.atZoneSameInstant(ZoneId.systemDefault()).format(FORMAT_FORMATTER);. или включите информацию о часовом поясе в средство форматирования вывода, как показано внизу.


Тест для вышеуказанных методов:

public static void main(String[] args) {
    // just for testing
    Locale.setDefault(Category.DISPLAY, Locale.GERMANY);
    Locale.setDefault(Category.FORMAT, Locale.GERMANY);
    TimeZone.setDefault(TimeZone.getTimeZone("Europe/Berlin"));
    
    var data = """
        2022-11-08 10:28:04.282551-06
        2022-11-08 10:28:04.282-06
        2022-11-08 10:28:04-06
        2022-11-08 10:28:04+02
        """.split("\n");
    for (var str : data) {
        test(str);
    }
}

private static void test(String str) {
    try {
        System.out.printf("%-30s  ->  %s%n", str, convertToString(convert(str)));
    } catch (Exception ex) {
        System.err.printf("%-30s  ->   %s%n", str, ex);
    }
}

Вывод:

openjdk version "20-ea" 2023-03-21 OpenJDK Runtime Environment (build 20-ea+12-790) OpenJDK 64-Bit Server VM (build 20-ea+12-790, mixed mode, sharing) 2022-11-08 10:28:04.282551-06 -> 2022-11-08 10:28:04.282551 2022-11-08 10:28:04.282-06 -> 2022-11-08 10:28:04.282000 2022-11-08 10:28:04-06 -> 2022-11-08 10:28:04.000000 2022-11-08 10:28:04+02 -> 2022-11-08 10:28:04.000000

Если мы хотим убедиться, что на выходе указан какой-то конкретный часовой пояс, мы можем, например, указать его в средстве форматирования следующим образом:

private static final DateTimeFormatter FORMAT_FORMATTER = 
        DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.SSSSSS")
                .withZone(ZoneId.of("Europe/Berlin"));

Теперь вывод будет:

2022-11-08 10:28:04.282551-06 -> 2022-11-08 17:28:04.282551 2022-11-08 10:28:04.282-06 -> 2022-11-08 17:28:04.282000 2022-11-08 10:28:04-06 -> 2022-11-08 17:28:04.000000 2022-11-08 10:28:04+02 -> 2022-11-08 09:28:04.000000

Обновлено: версия средства форматирования синтаксического анализа, впервые представленная в этом ответе, была:

private static final DateTimeFormatter PARSE_FORMATTER = 
    new DateTimeFormatterBuilder()
    .appendPattern("uuuu-MM-dd HH:mm:ss")  // date time
    .optionalStart()
    .appendFraction(ChronoField.MICRO_OF_SECOND, 3, 6, true)  // optional fractions
    .optionalEnd()
    .appendPattern("x")  // time zone offset
    .toFormatter()
    .withLocale(Locale.ROOT);  // replace as needed

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