stoicflame / ofx4j

Apache License 2.0
75 stars 50 forks source link

Problem with timeZone. In Brazil when file contains date in this format yyyyMMdd. For example (<DTPOSTED>20190102). That information is parsed for 20190101. #30

Open darlanads opened 5 years ago

darlanads commented 5 years ago

Problem with timeZone. In Brazil when file contains date in this format yyyyMMdd. For example (20190102). That information is parsed for 20190101.

stoicflame commented 5 years ago

Do you have a proposed fix?

edudoda commented 4 years ago

Hi @darlanads, today I suffered the same problem as you. This happens because Default implementation of StringConversion uses GMT time: public static final TimeZone GMT_TIME_ZONE = TimeZone.getTimeZone("GMT");

Usually OFX Date fields like <DTPOSTED>, <DTSERVER>, <DTSTART> ... (should) come with TimeZone explicitly (eg: <DTPOSTED>20180312120000[-3:BRT]</DTPOSTED>), but some banks/files are coming without it (like Banrisul, in my case: <DTPOSTED>20191203000000).

So the solution is to create a new class, implementing StingConversion and setting the default timezone to one you want: TimeZone.getTimeZone("Brazil/East") in my case.

Then when parseDate(String value) is invoked, it will not found an informed TimeZone and will use the one you specified.

public class StringConversionOfx implements StringConversion {

      public static final TimeZone GMT_TIME_ZONE = TimeZone.getTimeZone("Brazil/East");  
     //original default is: TimeZone.getTimeZone("GMT");
...

protected Date parseDate(String value) {
...
if (index < valueChars.length && valueChars[index] == '[') {
      String tzoffset = value.substring(index);
      calendar.setTimeZone(parseTimeZone(tzoffset));
    }
    else {
      calendar.setTimeZone(GMT_TIME_ZONE); //default
...  
  }
...  

To use it, just setConversion for AggregateUnmarshaller:

 AggregateUnmarshaller a = new AggregateUnmarshaller(ResponseEnvelope.class);
    ResponseEnvelope re = null;    
    StringConversionOfx conv = new StringConversionOfx(); 
        a.setConversion(conv);
        re = (ResponseEnvelope) a.unmarshal(reader);
      ...