我刚刚在应用程序中发现了日期字段的问题。我有一个以SOLr格式索引的日期字段。例如,"parution_date": "2014-09-29T22:00:00Z",
。当我使用数据透视表向Solr发出请求时,我希望获得此值,Solr将我的日期转换为CET(我在欧洲)。
这是我收到同一份文件的日期:Tue Sep 30 00:00:00 CEST 2014
。
正如您在此处所看到的,它不是将日期保持为原始格式(UTC),而是将日期转换为CEST。我想保留UTC格式,因为我使用此字段来研究一些文档。
对于此请求,我使用的是facet pivot。以下是我得到的结果:
for(PivotField pv : pivotFields){
Date value = (Date) pv.getValue();
String parutionDate = formatDate(value, DateHelper.DD_MM_YYYY_FORMAT);
}
getValue方法返回一个对象,因此我必须将其强制转换为Date对象。
我看到了一些解决方案:
处理此问题的最佳解决方案是什么?任何帮助,将不胜感激。
答案 0 :(得分:1)
看来Solr与您的问题无关。
java.util.Date有一个令人烦恼的坏功能,其中对象没有时区,但它的toString
方法应用了JVM的当前默认时区。
最好的方法是避免使用java.util.Date和.Calendar类,因为它们非常麻烦。而是使用Joda-Time库或与Java 8捆绑在一起的新java.time包(受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" ) );
答案 1 :(得分:1)
我使用SolrJ时遇到了同样的问题,因为我只是使用toString()将所有属性值转换为字符串。 SolrJ要求Solr以javabin格式返回结果(通过使用HttpClient的调试级别记录URL中的wt-parameter),所以我假设java.util.Date对象在Solr端序列化并在SolrJ客户端反序列化并且此Date实例不包含任何时区信息。这就是为什么在调用toString()时将本地时区作为默认值。
因此,没有其他方法可以使用您选择的模式明确地格式化Date。
Apache Commons Lang软件包的DateFormatUtils类可以用作自编写工具的替代方法,如上面的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"));
答案 2 :(得分:0)
Solr在UTC中工作。如果可能的话,您应该尝试将其保持在UTC中,并且只能转换为演示目的。
此外,问题是否可能发生在客户端库中,而不是Solr本身?尝试做一个Web查询,这个请求对应,看看你得到了什么。我很确定它都是UTC。
答案 3 :(得分:0)
我找到了解决问题的临时解决方案。我不得不在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);
}
}
现在非常难看的解决方案。我仍然对更好的解决方案感兴趣。
[编辑]我找到了更好的解决方案。我正在使用apache FastDateFormat
中的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;
}
}