SimpleDateFormat неправильно обрабатывает строку

String s = 19.17.38.008000;
DateFormat f = new SimpleDateFormat("HH.mm.ss.SSSSSS");
Date d = f.parse(s);
system.out.println(d);

это код, который я запускаю, он работает нормально, за исключением случаев, когда он печатает, печатает время 19:17:46. Пожалуйста, кто-нибудь объясните мне

Как примечание стороны:

String s = 19.17.38.008000;
DateFormat f = new SimpleDateFormat("HH.mm.ss");
Date d = f.parse(s);
system.out.println(d);

этот код будет печатать ту же строку правильно минус миллисекунды. Кто-нибудь, пожалуйста, скажите мне, что мне здесь не хватает.

РЕДАКТИРОВАТЬ: Спасибо за ответы, я думаю, что проблема здесь заключается в том, что я читал 38,008000 как 0,008 секунды, но sdf читает SSS как 8000 миллисекунд, что не одно и то же.

3 ответа

Решение

SSSSSS еще миллисекунды, даже если вы поставите 6 из них. 19:17:38 + 008000 мс - 19:17:46, так что это правильно, если удивительно.

AFAIK java.time библиотека в Java 8 поддерживает микросекундные (и наносекундные) временные метки.

Спасибо @Meno за исправления.

SimpleDateFormat класс переводит 008000 как 8000 миллисекунд, или 8 секунд, и добавление его к 38 секундам уже истолковано.

Если бы у нас было это:

String s = "19.17.38.009000";

Тогда мы получим этот вывод с добавлением 9 секунд:

Thu Jan 01 19:17:47 PST 1970

Удалите 3 лишних нуля с конца строки. Если есть 6 цифр, то они выглядят так, как будто они должны представлять микросекунды (миллионные доли секунды), а не миллисекунды (тысячные доли секунды).

String s = "19.17.38.008";

Выход:

Thu Jan 01 19:17:38 PST 1970

не выполняет синтаксический анализ с точностью до миллисекунд . Также обратите внимание на следующее описание из документации (выделено мной):

Анализирует текст с начала данной строки для получения даты. Метод не может использовать весь текст данной строки .

Таким образом, даже если в вашем шаблоне шесть Ss, использует только первые три из них, т.е.

      HH.mm.ss.SSS

Другими словами, для вашей строки вы получите тот же результат, независимо от того, используете ли вы или HH.mm.ss.SSSSSS. полна таких сюрпризов. Для того, чтобы устранить проблему при использовании, нужно сбросить три 0s с конца строки, т.е. если вы передадите 19.17.38.008, даст желаемый результат.

Таким образом, устаревший API даты и времени ( java.utilтипы даты и времени и их API форматирования) не только устарели, но и подвержены ошибкам. Рекомендуется полностью прекратить их использование и перейти на * .

Демо с использованием современного API даты и времени:

      import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String args[]) {
        String s = "19.17.38.008000";
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH.mm.ss.SSSSSS", Locale.ENGLISH);
        LocalTime time = LocalTime.parse(s, dtf);
        System.out.println(time);
    }
}

Выход:

      19:17:38.008

Обратите внимание, что если вы попытаетесь использовать HH.mm.ss.SSS, для вашей строки с java.time API, он выдаст исключение, предупреждающее вас о том, что что-то не так, тогда как SimpleDateFormat молча анализирует вашу строку, давая вам нежелательный результат.

Узнайте больше о современный API даты и временисовременном API даты и времени* из Trail: Date Time .


* По любой причине, если вам нужно придерживаться Java 6 или Java 7, вы можете использовать ThreeTen-Backport, который поддерживает большую часть функций java.time для Java 6 и 7. Если вы работаете над проектом Android и своим Android API level по-прежнему не соответствует Java-8, проверьте API-интерфейсы Java 8+, доступные через десугаринг, и Как использовать ThreeTenABP в Android Project .

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