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
не выполняет синтаксический анализ с точностью до миллисекунд . Также обратите внимание на следующее описание из документации (выделено мной):
Анализирует текст с начала данной строки для получения даты. Метод не может использовать весь текст данной строки .
Таким образом, даже если в вашем шаблоне шесть
S
s, использует только первые три из них, т.е.
HH.mm.ss.SSS
Другими словами, для вашей строки вы получите тот же результат, независимо от того, используете ли вы или
HH.mm.ss.SSSSSS
. полна таких сюрпризов. Для того, чтобы устранить проблему при использовании, нужно сбросить три
0
s с конца строки, т.е. если вы передадите
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 .