Uploaded image for project: 'Axis2'
  1. Axis2
  2. AXIS2-5458

ConverterTool date conversion without timezone returns Date with day before before 1901

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 1.5.4, 1.6.2
    • None
    • adb
    • None
    • Diverse linux (at least)

    Description

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

      }

      Attachments

        Activity

          People

            Unassigned Unassigned
            manuel.gallego Manuel Gallego
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated: