Author: adrianc Date: Mon Aug 12 19:39:54 2013 New Revision: 1513232 URL: http://svn.apache.org/r1513232 Log: Improved code for String->Timestamp->String conversions.
Modified: commons/sandbox/convert/trunk/src/main/java/org/apache/commons/convert/DateTimeConverters.java commons/sandbox/convert/trunk/src/test/java/org/apache/commons/convert/TestDateTimeConverters.java Modified: commons/sandbox/convert/trunk/src/main/java/org/apache/commons/convert/DateTimeConverters.java URL: http://svn.apache.org/viewvc/commons/sandbox/convert/trunk/src/main/java/org/apache/commons/convert/DateTimeConverters.java?rev=1513232&r1=1513231&r2=1513232&view=diff ============================================================================== --- commons/sandbox/convert/trunk/src/main/java/org/apache/commons/convert/DateTimeConverters.java (original) +++ commons/sandbox/convert/trunk/src/main/java/org/apache/commons/convert/DateTimeConverters.java Mon Aug 12 19:39:54 2013 @@ -43,10 +43,6 @@ public class DateTimeConverters implemen * JDBC TIME format string: <code>HH:mm:ss</code>. */ public static final String JDBC_TIME_FORMAT = "HH:mm:ss"; - /** - * JDBC TIMESTAMP format string: <code>yyyy-MM-dd HH:mm:ss.SSS</code>. - */ - public static final String JDBC_TIMESTAMP_FORMAT = "yyyy-MM-dd HH:mm:ss.SSS"; /** * Returns an initialized DateFormat object. @@ -746,15 +742,26 @@ public class DateTimeConverters implemen } /** - * Converts <code>obj</code> to a <code>java.sql.Timestamp</code>. If - * <code>formatString</code> is <code>null</code>, the string must be - * formatted as {@link DateTimeConverters#JDBC_TIMESTAMP_FORMAT}. + * Converts <code>obj</code> to a <code>java.sql.Timestamp</code>. + * <p>Note that the string representation is referenced to the <code>timeZone</code> + * argument, not UTC. The <code>Timestamp</code> that is returned is adjusted to UTC. + * This behavior is intended to accommodate user-entered timestamps, where users are + * accustomed to using their own time zone.</p> + * </p> */ public java.sql.Timestamp convert(String obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException { - DateFormat df = toDateTimeFormat(formatString == null ? JDBC_TIMESTAMP_FORMAT : formatString, timeZone, locale); try { - return new java.sql.Timestamp(df.parse(obj).getTime()); - } catch (ParseException e) { + // The String is referenced to the time zone represented by the timeZone + // argument, but the parsing code assumes a reference to UTC. So, we need + // to "adjust" the parsed Timestamp's value. + Timestamp parsedStamp = Timestamp.valueOf(obj); + Calendar cal = Calendar.getInstance(timeZone, locale); + cal.setTime(parsedStamp); + cal.add(Calendar.MILLISECOND, 0 - timeZone.getOffset(parsedStamp.getTime())); + Timestamp result = new Timestamp(cal.getTimeInMillis()); + result.setNanos(parsedStamp.getNanos()); + return result; + } catch (Exception e) { throw new ConversionException(e); } } @@ -851,13 +858,27 @@ public class DateTimeConverters implemen /** * Converts <code>obj</code> to a <code>String</code> using the supplied - * locale, time zone, and format string. If <code>formatString</code> is - * <code>null</code>, the string is formatted as - * {@link DateTimeConverters#JDBC_TIMESTAMP_FORMAT}. + * time zone. + * <p>Note that the string representation is referenced to the <code>timeZone</code> + * argument, not UTC. The <code>Timestamp</code> is adjusted to the specified + * time zone before conversion. This behavior is intended to accommodate user interfaces, + * where users are accustomed to viewing timestamps in their own time zone.</p> + * </p> */ - public String convert(java.sql.Timestamp obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException { - DateFormat df = toDateTimeFormat(formatString == null ? JDBC_TIMESTAMP_FORMAT : formatString, timeZone, locale); - return df.format(obj); + public String convert(Timestamp obj, Locale locale, TimeZone timeZone, String formatString) throws ConversionException { + try { + // The Timestamp is referenced to UTC, but the String result needs to be + // referenced to the time zone represented by the timeZone argument. + // So, we need to "adjust" the Timestamp's value before conversion. + Calendar cal = Calendar.getInstance(timeZone, locale); + cal.setTime(obj); + cal.add(Calendar.MILLISECOND, timeZone.getOffset(obj.getTime())); + Timestamp result = new Timestamp(cal.getTimeInMillis()); + result.setNanos(obj.getNanos()); + return result.toString(); + } catch (Exception e) { + throw new ConversionException(e); + } } } Modified: commons/sandbox/convert/trunk/src/test/java/org/apache/commons/convert/TestDateTimeConverters.java URL: http://svn.apache.org/viewvc/commons/sandbox/convert/trunk/src/test/java/org/apache/commons/convert/TestDateTimeConverters.java?rev=1513232&r1=1513231&r2=1513232&view=diff ============================================================================== --- commons/sandbox/convert/trunk/src/test/java/org/apache/commons/convert/TestDateTimeConverters.java (original) +++ commons/sandbox/convert/trunk/src/test/java/org/apache/commons/convert/TestDateTimeConverters.java Mon Aug 12 19:39:54 2013 @@ -87,6 +87,8 @@ public class TestDateTimeConverters exte java.sql.Date sqlDate = new java.sql.Date(70, 0, 1); java.sql.Time sqlTime = new java.sql.Time(0, 0, 0); java.sql.Timestamp timestamp = new java.sql.Timestamp(currentTime); + java.sql.Timestamp stampWithNanos = new java.sql.Timestamp(currentTime); + stampWithNanos.setNanos(10); // Source class = java.util.Calendar DateFormat df = new SimpleDateFormat(DateTimeConverters.CALENDAR_FORMAT); df.setCalendar(cal); @@ -118,7 +120,7 @@ public class TestDateTimeConverters exte assertConversion("TimestampToLong", new DateTimeConverters.GenericDateToLong<java.sql.Timestamp>(java.sql.Timestamp.class), timestamp, currentTime); assertConversion("TimestampToSqlDate", new DateTimeConverters.TimestampToSqlDate(), new java.sql.Timestamp(sqlDate.getTime()), sqlDate); assertConversion("TimestampToSqlTime", new DateTimeConverters.TimestampToSqlTime(), new java.sql.Timestamp(sqlDate.getTime()), sqlTime); - assertConversion("TimestampToString", new DateTimeConverters.TimestampToString(), timestamp, timestamp.toString()); + assertConversion("TimestampToString", new DateTimeConverters.TimestampToString(), stampWithNanos, stampWithNanos.toString()); assertToCollection("TimestampToCollection", timestamp); // TimeZone tests TimeZone tz = TimeZone.getDefault();