diff --git a/src/tap/data/ResultSetTableIterator.java b/src/tap/data/ResultSetTableIterator.java index 5bcbbfcabcb7936344123a68b7b6acb86aa6239b..c35d212315f49cd1c2632b819a24748b076d92c5 100644 --- a/src/tap/data/ResultSetTableIterator.java +++ b/src/tap/data/ResultSetTableIterator.java @@ -16,13 +16,16 @@ package tap.data; * You should have received a copy of the GNU Lesser General Public License * along with TAPLibrary. If not, see <http://www.gnu.org/licenses/>. * - * Copyright 2014-2016 - Astronomisches Rechen Institut (ARI) + * Copyright 2014-2017 - Astronomisches Rechen Institut (ARI) */ +import java.sql.Date; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; +import java.sql.Time; import java.sql.Timestamp; +import java.text.SimpleDateFormat; import java.util.NoSuchElementException; import adql.db.DBColumn; @@ -43,7 +46,7 @@ import uws.ISO8601Format; * </i></p> * * @author Grégory Mantelet (ARI) - * @version 2.1 (09/2016) + * @version 2.1 (02/2017) * @since 2.0 */ public class ResultSetTableIterator implements TableIterator { @@ -73,6 +76,11 @@ public class ResultSetTableIterator implements TableIterator { /** Index of the last read column (=0 just after {@link #nextRow()} and before {@link #nextCol()}, ={@link #nbColumns} after the last column has been read). */ private int colIndex; + /** Formatter to use in order to format java.sql.Date values. */ + private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + /** Formatter to use in order to format java.sql.Time values. */ + private static SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss"); + /** * <p>Build a TableIterator able to read rows and columns of the given ResultSet.</p> * @@ -687,7 +695,7 @@ public class ResultSetTableIterator implements TableIterator { * * <p>By default, the following function performs the following formatting:</p> * <ul> - * <li><b>If {@link Timestamp}:</b> the date-time is converted into a string with the ISO8601 format (see {@link ISO8601Format}).</li> + * <li><b>If {@link Timestamp}, {@link Date} or {@link Time}:</b> the date-time is converted into a string with the ISO8601 format (see {@link ISO8601Format}).</li> * <li><b>If a single CHAR is declared and a String is given:</b> only the first character is returned as a {@link Character} object.</li> * <li><b>If the value is declared as a Geometry:</b> the geometry is formatted as a STC-S expression.</li> * </ul> @@ -703,9 +711,16 @@ public class ResultSetTableIterator implements TableIterator { protected Object formatColValue(Object colValue) throws DataReadException{ if (colValue != null){ DBType colType = getColType(); - // if the column value is a Timestamp object, format it in ISO8601: - if (colValue instanceof Timestamp) - colValue = ISO8601Format.format(((Timestamp)colValue).getTime()); + // if the column value is a java.sql.Time object, format it into an ISO8601 time (i.e. with the format: HH:mm:ss): + if (colValue instanceof java.sql.Time) + colValue = timeFormat.format((java.sql.Time)colValue); + // if the column value is a java.sql.Date object, format it into an ISO8601 date (i.e. with the format: yyyy-MM-dd): + else if (colValue instanceof java.sql.Date) + colValue = dateFormat.format((java.sql.Date)colValue); + // if the column value is a Timestamp (or java.util.Date) object, format it into an ISO8601 date-time: + // note: java.sql.Timestamp extends java.util.Date. That's why the next condition also works for java.sql.Timestamp. + else if (colValue instanceof java.util.Date) + colValue = ISO8601Format.format((java.util.Date)colValue); // if the type is Integer but it is declared as a SMALLINT cast the value (absolutely required for the FITS format): else if (colValue instanceof Integer && colType != null && colValue != null && colType.type == DBDatatype.SMALLINT) colValue = new Short(((Integer)colValue).shortValue()); diff --git a/test/tap/data/ResultSetTableIteratorTest.java b/test/tap/data/ResultSetTableIteratorTest.java index bc7891760d5eb4396c54fe60984aa03e25fb10a5..65019ccd119156367a7c75f3426c2847efa0b813 100644 --- a/test/tap/data/ResultSetTableIteratorTest.java +++ b/test/tap/data/ResultSetTableIteratorTest.java @@ -6,6 +6,7 @@ import static org.junit.Assert.fail; import java.sql.Connection; import java.sql.ResultSet; +import java.util.GregorianCalendar; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -64,7 +65,7 @@ public class ResultSetTableIteratorTest { // TEST that all columns have been read: assertEquals(expectedNbColumns, countColumns); } - // TEST that all lines have been read: + // TEST that all lines have been read: assertEquals(expectedNbLines, countLines); }catch(Exception ex){ @@ -92,7 +93,7 @@ public class ResultSetTableIteratorTest { // count lines: while(it.nextRow()) countLines++; - // TEST that no line has been read: + // TEST that no line has been read: assertEquals(countLines, 0); }catch(Exception ex){ @@ -124,4 +125,44 @@ public class ResultSetTableIteratorTest { assertEquals(ex.getClass().getName(), "tap.data.DataReadException"); } } + + @Test + public void testDateFormat(){ + ResultSet rs = null; + try{ + // create a valid ResultSet: + rs = DBTools.select(conn, "SELECT * FROM gums LIMIT 1;"); + + // Create the iterator: + ResultSetTableIterator rsit = new ResultSetTableIterator(rs); + assertTrue(rsit.nextRow()); + assertTrue(rsit.hasNextCol()); + rsit.nextCol(); + + // Set a date-time: + GregorianCalendar cal = new GregorianCalendar(); + cal.set(2017, GregorianCalendar.FEBRUARY, 1, 15, 13, 56); // 1st Feb. 2017 - 15:13:56 CET + + // Try to format it from a java.SQL.Timestamp into a ISO8601 date-time: + assertEquals("2017-02-01T14:13:56Z", rsit.formatColValue(new java.sql.Timestamp(cal.getTimeInMillis()))); + // Try to format it from a java.UTIL.Date into an ISO8601 date-time: + assertEquals("2017-02-01T14:13:56Z", rsit.formatColValue(cal.getTime())); + + // Try to format it from a java.SQL.Date into a simple date (no time indication): + assertEquals("2017-02-01", rsit.formatColValue(new java.sql.Date(cal.getTimeInMillis()))); + + // Try to format it into a simple time (no date indication): + assertEquals("15:13:56", rsit.formatColValue(new java.sql.Time(cal.getTimeInMillis()))); + + }catch(Exception ex){ + ex.printStackTrace(System.err); + fail("An exception occurs while formatting dates/times."); + }finally{ + if (rs != null){ + try{ + rs.close(); + }catch(Exception ex){} + } + } + } }