Solrj formats my dates from UTC to CEST

2019-08-02 14:23发布

问题:

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.

回答1:

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" ) );


回答2:

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"));



回答3:

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.



回答4:

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;
}
}