Комментарии 22
Нет, не сравнивал. Моих же собственных преобразований практически нет. Все основные преобразования делаются классом SimpleDateFormat. Устаревший или не устаревший этот класс ? Это определяется целью его использования. На мой взгляд, пользоваться им очень удобно при использовании JDBC.
А Вы сравнивали производительность вашего решения и форматирования посредством "современных" вариантов (например, через Instant или LocalDateTime)?
Интересно было бы увидеть такое сравнение в статье, ибо может и не быть смысла в разработке к устаревшим SimpleDateFormat
см комментарий выше, не правильно ответил на ваш вопрос
Дополню. Лучший способ повышения производительности - исключить лишние преобразования. При преобразовании Timestamp это легко можно сделать без потери качества данных. Передавать Timestamp как число.
Решил все же сравнить производительность двух подходов преобразования. Запустил в цикле (код выше и ниже) без вывода прямое и обратное преобразование
Предложенное мной решение работает быстрее примерно в 2 раза
63 мс - 1000 циклов, вариант предложенный мной
105 мс - 1000 циклов, вариант предложенный foal
Результат многократного запуска стабилен (хоть цифры и меняются)
public static void main(String[] args) {
long start = System.currentTimeMillis();
Timestamp t = new Timestamp(System.currentTimeMillis());
for (int index = 0; index < 1000; index++ ) {
t.setNanos(345012000); // устанавливать наносекунды
TimestampFormatter f = new TimestampFormatter();
String s = f.format(t);
try {
// обратное преобразование для проверки
Timestamp n = f.parse(s);
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(System.currentTimeMillis() - start);
start = System.currentTimeMillis();
for (int index = 0; index < 1000; index++ ) {
t.setNanos(345012000);
DateTimeFormatter f = DateTimeFormatter
.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX")
.withZone(ZoneId.systemDefault());
String s = f.format(t.toInstant());
try {
// обратное преобразование для проверки
Timestamp n = Timestamp.from(f.parse(s, Instant::from));
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println(System.currentTimeMillis() - start);
}
Создание DateTimeFormatter
'а нужно вынести из цикла. И мерить производительность нормальным инструментом типа jmh с прогревом и т.п.
А в чём улучшение по сравнению со стандартным кодом?
public static void main(String[] args) {
Timestamp t = new Timestamp(System.currentTimeMillis());
// устанавливать наносекунды
t.setNanos(345012000);
DateTimeFormatter f = DateTimeFormatter
.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX")
.withZone(ZoneId.systemDefault());
String s = f.format(t.toInstant());
System.out.println(s);
try {
// обратное преобразование для проверки
Timestamp n = Timestamp.from(f.parse(s, Instant::from));
System.out.println(f.format(n.toInstant()));
} catch (Exception e) {
e.printStackTrace();
}
}
Если очень хочется, то спрячьте инициализацию DateTimeFormatter
, t.toInstant()
и Timestamp.from(f.parse(s, Instant::from))
внутрь своего TimestampFormatter, например
public Timestamp parse(String source) {
return Timestamp.from(f.parse(source, Instant::from));
}
public String format(Timestamp timestamp) {
return f.format(t.toInstant());
}
public TimestampFormatter(String pattern, Locale locale, ZoneId tz) {
f = DateTimeFormatter
.ofPattern(pattern)
.withLocale(locale)
.withZone(tz);
}
Плюс еще, конечно, проверка на null
, но, для упрощения, я постарался придерживаться авторской нотации.
Бонусом то что DateTimeFormatter -- thread safe и может спокойно лежать в final поле. SDF нужно оборачивать в ThreadLocal со всеми развлечениями в случае ротации тредов в пуле в управляемой среде.
Ну или создавать на каждый чих, как у автора, но за такое даже джунов бьют линейкой по пальцам
Не нужно относится к своим коллегам с пренебрежением, впросак можете попасть, как коллега
foal
Я, честно говоря, очень старался не переходить на оценку вашей профессиональности, как программиста, но видимо у меня получилось плохо, и вы что-то почувствовали. Да, тут я точно попал впросак, каюсь.
Остальные ваши замечания:
спасибо за похвалу, мне так лестно, что сам Архитектор, Руководитель проекта обратил на меня внимание. Кстати, "проект" лучше тоже написать с большой буквы.
Да, но я бы использовал Optional или Objects.requireNonNull.
Только NPE - скорее просто мой персональный больной вопрос. Хотя вот авторы Котлина, тоже его выделили - видимо у нас было похожее трудное детство :)
"NPE никогда не будет", "никто не передаст туда null" - да, да, продолжайте жить в мире розовых пони. Ну или научитесь писать Unit тесты.
Знаете выражение, "Не судите и не судимы будете", Не я Вас начал учить, но раз Вы начали, почему бы мне заняться тем же самым в отношении Вас.
Значит не справились с домашним заданием. Хотя попробовали мыслить в нужном направлении. Хвалю, но ответ не верный. Значит не гуру!
Ответ на поверхности. Где используется класс Timestamp? В JDBC. Нужно преобразование, которое выполняется в этом классе в связке приложение - база? Нет!. В этой связке все прекрасно работает и без этого преобразования. А где нужно? В REST, SOAP и прочих подобных протоколах. И действительно, при значении null, дело не дойдет до вызова метода format. Не верите, можете проверить. А если даже допустить, что вызов с null значением все же произойдет, то оно успешно будет обработано в одном из методов стека вызова, где есть возможность записать ошибку в лог и вернуть ошибку в протоколе взаимодействия.
Конечно, вы правы. Я думаю, нет я уверен, что ваши коллеги вас очень ценят, и просто молятся на вас в свободное от домашних заданий время.
Очень жаль, что не успел попользоваться выданным званием, но постараюсь долго не плакать.
Завидую я вам. Вам, наверное, очень легко жить.
А теперь можно перейти к предложенному вами решению.
На мой взгляд, пакет java.time очень узко специализированный и, как я понимаю, назначение у него совсем другое чем предложенное Вами решение. Предполагаю, что и в производительности ваше решение проиграет - логика классов более сложная, соответственно, и время на преобразование должно тратиться больше. Да и использовать классы из этого пакета только чтобы получить микро/нано секунды у класса Timestamp, на мой взгляд, как то не оправдано. Избавит ваше решение от использования "устаревшего" класса SimpleDateFormat? Нет! Этот класс используется во многих библиотеках. Поведение этого класса предсказуемо в разных реализациях JVM и разных производителей, "сюрпризов" не ожидается. А то что одни и те же "базовые" класса JVM ведут себя по разному в реализациях JVM разных производителей это факт, что может если и не нарушать работу вашего кода, то сказываться на его логике.
И снова вы чертовски правы маэстро! Долой все эти новомодные штучки! Пещеры — вот она стабильность. Зачем, жить в доме с унитазом, если это не избавит всех остальных от туалетов во дворе?!
В общем, как я уже говорил, в мире розовых пони при тех граничных условиях, что вы здесь расписали ваше решение идеально.
Я хочу извинится еще раз, что сразу не понял его монументальность и крутизну.
Мое решение примерно 2 раза быстрее вашего, как я и предполагал выше
Отвечу Вам той же монетой.
Ваше решение лишь только подтверждает мое утверждение, что и в пакете java.time нет удобного способа преобразования микро/нано секунд для Timestamp.
Молодец, предложили альтернативное решение. Коллеги могут выбирать, чем пользоваться.
И вишенка на торте - NullPointerException. У меня к Вам три вопроса.
Очень любопытно, а что Вы собрались или предполагаете делать с NullPointerException в моем коде, когда пишите "проверка на null"? Могу предположить такой вариант
if (source == null) return null;
Угадал?
Почему у Вас возник вопрос только про NullPointerException? ParseException ведь тоже не обрабатывается в предложенном мной варианте решения, если, как Вы пишите, придерживаться вашей "авторской нотации". В чем в данном случае разница между этими два исключениями?
А если все же немножко подумать? А если подумать, то NullPointerException в этом участке кода никогда не возникнет и любая проверка на null будет мертвым кодом. Спросите почему? А это я Вам оставлю в качестве домашнего задания, Вы же гуру, думаю, справитесь. Так как, справитесь?
Мой комментарий на Вашу реплику ниже, не обновил страницу при ответе и он из за этого похоже попал не туда
Форматирование милли/микро/нано секунд в java.sql.Timestamp