You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by "Manuel Gallego (JIRA)" <ji...@apache.org> on 2012/11/19 10:48:57 UTC

[jira] [Created] (AXIS2-5458) ConverterTool date conversion without timezone returns Date with day before before 1901

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: java-dev-unsubscribe@axis.apache.org
For additional commands, e-mail: java-dev-help@axis.apache.org