Я только что обнаружил проблему с полем даты в моем приложении. У меня есть поле даты, которое индексируется в Solr в формате UTC. Например, "parution_date": "2014-09-29T22:00:00Z",
Когда я обращаюсь к Solr с помощью стержня, и я хочу получить эту ценность, Solr преобразует мою дату в CET (я в Европе). Здесь дата, которую я получил за тот же документ: Tue Sep 30 00:00:00 CEST 2014
.
Как вы видите здесь, вместо сохранения даты в ее исходном формате, который является UTC, он преобразует дату CEST. Я хочу сохранить формат UTC, потому что я использую это поле для исследования некоторых документов.
Для этого запроса я использую ось фасет. Вот как я получаю результаты:
for(PivotField pv : pivotFields){
Date value = (Date) pv.getValue();
String parutionDate = formatDate(value, DateHelper.DD_MM_YYYY_FORMAT);
}
Метод getValue возвращает объект, поэтому я должен передать его объекту Date.
Я вижу некоторые решения:
Каковы наилучшие решения для решения этой проблемы? Любая помощь будет оценена по достоинству.
У меня была такая же проблема с использованием SolrJ, поскольку я просто использовал toString() для преобразования всех значений атрибутов в строки. SolrJ просит Solr вернуть результаты в формате javabin (увидели wt-параметр в URL-адресе, выполнив вход с уровнем отладки для HttpClient), поэтому я предполагаю, что объект java.util.Date сериализуется на стороне Solr и десериализован на стороне клиента SolrJ и этот экземпляр Date не содержит информацию о часовом поясе. Вот почему для вызова toString() используется локальный часовой пояс по умолчанию.
Таким образом, не будет другого способа форматировать Date, используя шаблон по вашему выбору.
Класс DateFormatUtils пакета Apache Commons Lang может использоваться как альтернатива самонастраиваемому утилиту, например, DateHelper выше.
DateFormatUtils.format(yourDateObj, "yyyy-MM-dd'T'HH:mm:ss'Z'"); DateFormatUtils.format(yourDateObj, "yyyy-MM-dd'T'HH:mm:ss'Z'", TimeZone.getTimeZone("UTC"));
Похоже, что Solr не имеет ничего общего с вашей проблемой.
У java.util.Date есть раздражающая плохая функция, в которой объект не имеет часового пояса, но метод toString
применяет текущий часовой пояс JVM.
Лучший подход - избегать использования классов java.util.Date и.Calendar, поскольку они, как известно, являются неприятными. Вместо этого используйте либо библиотеку Joda-Time, либо новый пакет java.time в комплекте с Java 8 (вдохновленный Joda-Time).
Пример в Joda-Time 2.4.
java.util.Date date = ( java.util.Date ) PC.getValue();
DateTime dateTimeUtc = new DateTime( date, DateTimeZone.UTC );
String output = dateTimeUtc.toString();
Настройте на локальную зону.
DateTime dateTimeBerlin = dateTimeUtc.withZone( DateTimeZone.forID( "Europe/Berlin" ) );
Я нашел временное решение для своей проблемы. Мне пришлось вручную изменить часовой пояс в предложении try/finally.
Timezone default = null;
try {
for(PivotField pv : pivotFields){
default = Timezone.getDefault(); //save the default timezone
Date value = (Date) pv.getValue();
TimeZone.setDefault(TimeZone.getTimeZone("UTC")); // change it to UTC
String parutionDate = formatDate(value, DateHelper.DD_MM_YYYY_FORMAT);
}
} finally {
if(default != null){
TimeZone.setDefault(default);
}
}
На данный момент очень уродливые решения. Меня все еще интересует лучшее решение.
[EDIT] Я нашел лучшее решение. Я использую FastDateFormat
из apache commons-lang3
и этот класс также может получать часовой пояс в качестве параметра. Вот измененная версия моего кода:
public class Mapper {
public void mapMyObject(List<PivotField> pivotFields){
for(PivotField pv : pivotFields){
Date value = (Date) pv.getValue();
String parutionDate = formatDate(value, DateHelper.DD_MM_YYYY_FORMAT);
}
}
private String formatDate(Date date, String pattern){
return DateHelper.getStringFromDateSolr(date, pattern);
}
}
Метод getStringFromDateSolr
определяется как таковой:
public class DateHelper {
public static String getStringFromDateSolr(Date date, String format) {
return formatDate(date, FastDateFormat.getInstance(format, TimeZone.getTimeZone("UTC")));
}
private static String formatDate(Date date, FastDateFormat format) {
if (date != null) {
try {
return format.format(date);
} catch (Exception e) {
LOGGER.error(e.getMessage());
}
}
return null;
}
}
Solr работает в UTC. Вы должны попытаться сохранить его в формате UTC до конца, если это возможно, и только конвертировать для целей презентации.
Кроме того, возможно ли, что проблема происходит в клиентской библиотеке, а не сама Solr? Попробуйте выполнить веб-запрос, соответствующий этому запросу, и посмотрите, что вы вернетесь. Я абсолютно уверен, что это будет UTC.
2014-09-29T22:00:00Z
совпадает сTue Sep 30 00:00:00 CEST 2014
, потому что CEST - это UTC + 2, какая точность теряется? Есть ли вероятность, что для проверки вы просто печатаете объект даты из Solr на экране? Потому что так будет показано в часовом поясе по умолчанию