Manuel Gallego created AXIS2-5458:
-------------------------------------

             Summary: ConverterTool date conversion without timezone returns 
Date with day before before 1901
                 Key: AXIS2-5458
                 URL: https://issues.apache.org/jira/browse/AXIS2-5458
             Project: Axis2
          Issue Type: Bug
          Components: adb
    Affects Versions: 1.6.2, 1.5.4
         Environment: Diverse linux (at least)
            Reporter: Manuel Gallego


GIVEN ConverterUtil.convertToDate("1940-01-01")
THEN resulting date is one day before at 23:00

GIVEN ConverterUtil.convertToDate("1900-01-01Z")
THEN resulting date is one day before at 23:00

---------------------------------------------------------------------------------------------------------

Test that reproduce the issue:
        @Test
        public void testCustomConvertToDateTimeZone() {
                for (int year = 2012; year > 1800; year--) {
                        for (int month = 12; month > 0; month--) {
                                Date date = 
ConverterUtil.convertToDate(createFormattedDate(year, month, 1, ""));
                                assertParsedDateFieldsEquals(year, month, 1, 
date);
                        }
                }
        }

        public void assertParsedDateFieldsEquals(int year, int month, int day, 
Date date) {
                Assert.assertNotNull(date);
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(date);
                String message = "failed conversion " + 
createFormattedDate(year, month, day) + " not equals " + date;
                Assert.assertEquals(message, year, calendar.get(Calendar.YEAR));
                Assert.assertEquals(message, month, 
calendar.get(Calendar.MONTH) + 1);
                Assert.assertEquals(message, day, 
calendar.get(Calendar.DAY_OF_MONTH));
        }

        public String createFormattedDate(int year, int month, int day, String 
suffix) {
                return new DecimalFormat("0000").format(year) + "-" + new 
DecimalFormat("00").format(month) + "-" + new DecimalFormat("00").format(day) + 
suffix;
        }

-------------------------------------------------------------------

The following implementation solves this issue. I'm not 100% sure it works in 
all other cases.

Essentially I'm setting the timezone offset for the particular date because of 
the historical information that TimeZone may contain..

Another problem I found is that I could not find a way to override the static 
method so I had to manually change the wsdl2java generated code.

        /**
         * Converts a given string into a date. Code from Axis1 
DateDeserializer.
         * 
         * @param source
         * @return Returns Date.
         */
        public static Date convertToDate(String source) {

                // the lexical form of the date is '-'? yyyy '-' mm '-' dd 
zzzzzz?
                if ((source == null) || source.trim().equals("")) {
                        return null;
                }
                source = source.trim();
                boolean bc = false;
                if (source.startsWith("-")) {
                        source = source.substring(1);
                        bc = true;
                }

                int year = 0;
                int month = 0;
                int day = 0;
                Integer timeZoneOffSet = null;

                if (source.length() >= 10) {
                        // first 10 numbers must give the year
                        if ((source.charAt(4) != '-') || (source.charAt(7) != 
'-')) {
                                throw new RuntimeException("invalid date format 
(" + source + ") with out - s at correct place ");
                        }
                        year = Integer.parseInt(source.substring(0, 4));
                        month = Integer.parseInt(source.substring(5, 7));
                        day = Integer.parseInt(source.substring(8, 10));

                        if (source.length() > 10) {
                                String restpart = source.substring(10);
                                if (restpart.startsWith("Z")) {
                                        // this is a gmt time zone value
                                        timeZoneOffSet = 0;
                                } else if (restpart.startsWith("+") || 
restpart.startsWith("-") || restpart.startsWith("T")) {
                                        // this is a specific time format string
                                        if (restpart.charAt(3) != ':') {
                                                throw new 
RuntimeException("invalid time zone format (" + source + ") without : at 
correct place");
                                        }
                                        int hours = 
Integer.parseInt(restpart.substring(1, 3));
                                        int minits = 
Integer.parseInt(restpart.substring(4, 6));
                                        timeZoneOffSet = ((hours * 60) + 
minits) * 60000;
                                        if (restpart.startsWith("-")) {
                                                timeZoneOffSet = timeZoneOffSet 
* -1;
                                        }
                                } else {
                                        throw new RuntimeException("In valid 
string sufix");
                                }
                        }
                } else {
                        throw new RuntimeException("In valid string to parse");
                }

                Calendar calendar = Calendar.getInstance();
                calendar.clear();
                calendar.setLenient(false);
                calendar.set(Calendar.YEAR, year);
                // xml month stars from the 1 and calendar month is starts with 0
                calendar.set(Calendar.MONTH, month - 1);
                calendar.set(Calendar.DAY_OF_MONTH, day);
                
                if (timeZoneOffSet != null){
                        calendar.set(Calendar.ZONE_OFFSET, timeZoneOffSet);
                }
                else {
                        calendar.set(Calendar.ZONE_OFFSET, 
TimeZone.getDefault().getOffset(calendar.getTimeInMillis()));
                }

                // set the day light off set only if time zone
                if (source.length() >= 10) {
                        calendar.set(Calendar.DST_OFFSET, 0);
                }
                calendar.getTimeInMillis();
                if (bc) {
                        calendar.set(Calendar.ERA, GregorianCalendar.BC);
                }

                return calendar.getTime();

        }




--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to