Added support for date types (date, time, timestamp).

With this change, .getMetadata() reports the correct java.sql.Date
type for columns marked as date. The .getDate() on a row also returns a
java.sql.Date object. Since jdbc expects dates to be in the GMT
timezone, the dates are converted first.
diff --git a/pom.xml b/pom.xml
index 73c5b21..51a6e0c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -111,6 +111,11 @@
       <version>1.1.7</version>
       <scope>test</scope>
     </dependency>
+	<dependency>
+	    <groupId>org.apache.commons</groupId>
+	    <artifactId>commons-lang3</artifactId>
+	    <version>3.2</version>
+	</dependency>
   </dependencies>
 
   <reporting>
diff --git a/src/main/java/net/hydromatic/optiq/impl/csv/CsvEnumerator.java b/src/main/java/net/hydromatic/optiq/impl/csv/CsvEnumerator.java
index b632b26..f1f3fac 100644
--- a/src/main/java/net/hydromatic/optiq/impl/csv/CsvEnumerator.java
+++ b/src/main/java/net/hydromatic/optiq/impl/csv/CsvEnumerator.java
@@ -21,7 +21,13 @@
 
 import au.com.bytecode.opencsv.CSVReader;
 
+import org.apache.commons.lang3.time.FastDateFormat;
+
 import java.io.*;
+import java.text.ParseException;
+import java.util.Date;
+import java.util.TimeZone;
+
 
 /** Enumerator that reads from a CSV file. */
 class CsvEnumerator implements Enumerator<Object> {
@@ -29,6 +35,19 @@
   private final RowConverter rowConverter;
   private Object current;
 
+  private static final FastDateFormat TIME_FORMAT_DATE;
+  private static final FastDateFormat TIME_FORMAT_TIME;
+  private static final FastDateFormat TIME_FORMAT_TIMESTAMP;
+
+  static {
+
+    TimeZone gmt = TimeZone.getTimeZone("GMT");
+    TIME_FORMAT_DATE = FastDateFormat.getInstance("yyyy-MM-dd", gmt);
+    TIME_FORMAT_TIME = FastDateFormat.getInstance("hh:mm:ss", gmt);
+    TIME_FORMAT_TIMESTAMP = FastDateFormat.getInstance(
+        "yyyy-MM-dd hh:mm:ss", gmt);
+  }
+
   public CsvEnumerator(File file, CsvFieldType[] fieldTypes) {
     this(file, fieldTypes, identityList(fieldTypes.length));
   }
@@ -131,6 +150,40 @@
           return null;
         }
         return Double.parseDouble(string);
+      case DATE:
+        if (string.length() == 0) {
+          return null;
+        }
+
+        try {
+          Date date = TIME_FORMAT_DATE.parse(string);
+          return new java.sql.Date(date.getTime());
+        } catch (ParseException e) {
+          return null;
+        }
+
+      case TIME:
+        if (string.length() == 0) {
+          return null;
+        }
+
+        try {
+          Date date = TIME_FORMAT_TIME.parse(string);
+          return new java.sql.Time(date.getTime());
+        } catch (ParseException e) {
+          return null;
+        }
+
+      case TIMESTAMP:
+        if (string.length() == 0) {
+          return null;
+        }
+        try {
+          Date date = TIME_FORMAT_TIMESTAMP.parse(string);
+          return new java.sql.Timestamp(date.getTime());
+        } catch (ParseException e) {
+          return null;
+        }
       }
     }
   }
diff --git a/src/main/java/net/hydromatic/optiq/impl/csv/CsvFieldType.java b/src/main/java/net/hydromatic/optiq/impl/csv/CsvFieldType.java
index 1e4569b..12e94d2 100644
--- a/src/main/java/net/hydromatic/optiq/impl/csv/CsvFieldType.java
+++ b/src/main/java/net/hydromatic/optiq/impl/csv/CsvFieldType.java
@@ -34,7 +34,7 @@
  * makes it easier to write SQL.</p>
  */
 enum CsvFieldType {
-  STRING(null, String.class),
+  STRING(null, String.class, "string"),
   BOOLEAN(Primitive.BOOLEAN),
   BYTE(Primitive.BYTE),
   CHAR(Primitive.CHAR),
@@ -43,32 +43,32 @@
   LONG(Primitive.LONG),
   FLOAT(Primitive.FLOAT),
   DOUBLE(Primitive.DOUBLE),
-  DATE(null, java.sql.Date.class),
-  TIME(null, java.sql.Time.class),
-  TIMESTAMP(null, java.sql.Timestamp.class);
+  DATE(null, java.sql.Date.class, "date"),
+  TIME(null, java.sql.Time.class, "time"),
+  TIMESTAMP(null, java.sql.Timestamp.class, "timestamp");
 
   private final Primitive primitive;
   private final Class clazz;
+  private final String simpleName;
 
   private static final Map<String, CsvFieldType> MAP =
     new HashMap<String, CsvFieldType>();
 
   static {
     for (CsvFieldType value : values()) {
-      MAP.put(value.clazz.getSimpleName(), value);
-      if (value.primitive != null) {
-        MAP.put(value.primitive.primitiveClass.getSimpleName(), value);
-      }
+      MAP.put(value.simpleName, value);
     }
   }
 
   CsvFieldType(Primitive primitive) {
-    this(primitive, primitive.boxClass);
+    this(primitive, primitive.boxClass,
+      primitive.primitiveClass.getSimpleName());
   }
 
-  CsvFieldType(Primitive primitive, Class clazz) {
+  CsvFieldType(Primitive primitive, Class clazz, String simpleName) {
     this.primitive = primitive;
     this.clazz = clazz;
+    this.simpleName = simpleName;
   }
 
   public RelDataType toType(JavaTypeFactory typeFactory) {
diff --git a/src/test/java/net/hydromatic/optiq/test/CsvTest.java b/src/test/java/net/hydromatic/optiq/test/CsvTest.java
index a4749fd..5847c8b 100644
--- a/src/test/java/net/hydromatic/optiq/test/CsvTest.java
+++ b/src/test/java/net/hydromatic/optiq/test/CsvTest.java
@@ -267,6 +267,60 @@
         "select empno, slacker from emps where slacker",
         "EMPNO=100; SLACKER=true");
   }
+
+  @Test
+  public void testDateType() throws SQLException {
+
+    Properties info = new Properties();
+    info.put("model", "target/test-classes/bug.json");
+
+    Connection connection = DriverManager
+        .getConnection("jdbc:optiq:", info);
+
+    try {
+
+      ResultSet res = connection.getMetaData().getColumns(null, null,
+          "DATE", "JOINEDAT");
+      res.next();
+      Assert.assertEquals(res.getInt("DATA_TYPE"), java.sql.Types.DATE);
+
+      res = connection.getMetaData().getColumns(null, null,
+          "DATE", "JOINTIME");
+      res.next();
+      Assert.assertEquals(res.getInt("DATA_TYPE"), java.sql.Types.TIME);
+
+      res = connection.getMetaData().getColumns(null, null,
+          "DATE", "JOINTIMES");
+      res.next();
+      Assert.assertEquals(res.getInt("DATA_TYPE"), java.sql.Types.TIMESTAMP);
+
+      Statement statement = connection.createStatement();
+      ResultSet resultSet = statement.executeQuery(
+          "select \"JOINEDAT\", \"JOINTIME\", \"JOINTIMES\" from \"DATE\" where EMPNO = 100");
+      resultSet.next();
+
+      // date
+      Assert.assertEquals(java.sql.Date.class, resultSet.getDate(1).getClass());
+      Assert.assertEquals(java.sql.Date.valueOf("1996-08-03"),
+          resultSet.getDate(1));
+
+      // time
+      Assert.assertEquals(java.sql.Time.class, resultSet.getTime(2).getClass());
+      Assert.assertEquals(java.sql.Time.valueOf("00:01:02"),
+          resultSet.getTime(2));
+
+      // timestamp
+      Assert.assertEquals(java.sql.Timestamp.class,
+          resultSet.getTimestamp(3).getClass());
+      Assert.assertEquals(java.sql.Timestamp.valueOf("1996-08-03 00:01:02"),
+          resultSet.getTimestamp(3));
+
+    } finally {
+      connection.close();
+    }
+
+
+  }
 }
 
 // End CsvTest.java
diff --git a/src/test/resources/bug/DATE.csv b/src/test/resources/bug/DATE.csv
new file mode 100644
index 0000000..ea5ef35
--- /dev/null
+++ b/src/test/resources/bug/DATE.csv
@@ -0,0 +1,6 @@
+EMPNO:int,JOINEDAT:date,JOINTIME:time,JOINTIMES:timestamp
+100,"1996-08-03","00:01:02","1996-08-03 00:01:02"
+110,"2001-01-01","00:00:00","2001-01-01 00:00:00"
+110,"2002-05-03","00:00:00","2002-05-03 00:00:00"
+120,"2005-09-07","00:00:00","2005-09-07 00:00:00"
+130,"2007-01-01","00:00:00","2007-01-01 00:00:00"