I just discovered a problem with a date field in my application. I have a date field that is indexed in Solr in UTC format. For instance, "parution_date": "2014-09-29T22:00:00Z",
. When I make request to Solr using a pivot, and I want to get this value, Solr converts my date to CET (I'm in Europe).
Here the date I received for the same document: Tue Sep 30 00:00:00 CEST 2014
.
As you see here, instead of keeping the date to its original format which is UTC, it converts the date CEST. I want to keep the UTC format because I using this field to research some documents.
For this request, I am using a facet pivot. Here is how, I get the results :
for(PivotField pv : pivotFields){
Date value = (Date) pv.getValue();
String parutionDate = formatDate(value, DateHelper.DD_MM_YYYY_FORMAT);
}
The getValue method, returns an object so I have to cast it to a Date object.
I see some solutions :
- When I am making a request to Solr, convert my CEST date to UTC, but I don't know how to do it for now. I am beginner at Solr.
- or keep my date to UTC formats.
What are the best solutions to deal with this issue? Any help would be appreciated.
Appears that Solr has nothing to do with your problem.
The java.util.Date has an annoying bad feature where the object has no time zone yet it's toString
method applies the JVM's current default time zone.
Best approach is to avoid using java.util.Date and .Calendar classes as they are notoriously troublesome. Instead use either Joda-Time library or the new java.time package bundled with Java 8 (inspired by Joda-Time).
Example in Joda-Time 2.4.
java.util.Date date = ( java.util.Date ) PC.getValue();
DateTime dateTimeUtc = new DateTime( date, DateTimeZone.UTC );
String output = dateTimeUtc.toString();
Adjust to a local zone.
DateTime dateTimeBerlin = dateTimeUtc.withZone( DateTimeZone.forID( "Europe/Berlin" ) );
I had the same issue using SolrJ as I simply used toString() to convert all attribute values to strings. SolrJ asks Solr to return the results in javabin format (saw the wt-parameter in the URL by logging with debug level for the HttpClient), so I assume the java.util.Date object is serialized on Solr side and deserialized on SolrJ client side and this Date instance does not wear any timezone information. That is why it takes the local timezone as default when toString() is called.
So there will be no other way to format the Date explicitely using the pattern of your choice.
The DateFormatUtils class of the Apache Commons Lang package may be used as an alternative to a self written util like the DateHelper above.
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 works in UTC. You should try to keep it in UTC all the way to the end if possible and only convert for presentation purposes.
Also, is it possible that the issue is happening in the client library, not Solr itself? Try doing a web query this request corresponds to and see what you get back. I am quite sure it will all be UTC.
I found a temporary solution for my problem. I had to manually change the timezone in a try/finally clause.
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);
}
}
Very ugly solutions for now. I'm still interested for a better solution.
[EDIT] I have found a better solution. I am using the FastDateFormat
from the apache commons-lang3
and this class can also receive a timezone as a parameter. Here is a modified version of my code :
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);
}
}
The method getStringFromDateSolr
is defined as such :
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;
}
}