Mono.Data.Sqlite: Add support for TIMESTAMP / UnixEpoch column. Fixes #638.
authorRolf Bjarne Kvinge <rolf@xamarin.com>
Tue, 6 Mar 2012 23:32:53 +0000 (00:32 +0100)
committerRolf Bjarne Kvinge <rolf@xamarin.com>
Tue, 6 Mar 2012 23:45:47 +0000 (00:45 +0100)
mcs/class/Mono.Data.Sqlite/Mono.Data.Sqlite_2.0/SQLiteConvert.cs
mcs/class/Mono.Data.Sqlite/Test/SqliteDataReaderTest.cs

index 550854088a573598323bedcc6ee11118ade246a6..386f912aab117fec9618d956a3d01a2c6a6cb39a 100644 (file)
@@ -25,6 +25,11 @@ namespace Mono.Data.Sqlite
   public abstract class SqliteConvert\r
   {\r
     /// <summary>\r
+    /// The value for the Unix epoch (e.g. January 1, 1970 at midnight, in UTC).\r
+    /// </summary>\r
+    protected static readonly DateTime UnixEpoch =\r
+        new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);\r
+    /// <summary>\r
     /// An array of ISO8601 datetime formats we support conversion from\r
     /// </summary>\r
     private static string[] _datetimeFormats = new string[] {\r
@@ -159,6 +164,8 @@ namespace Mono.Data.Sqlite
           return new DateTime(Convert.ToInt64(dateText, CultureInfo.InvariantCulture));\r
         case SQLiteDateFormats.JulianDay:\r
           return ToDateTime(Convert.ToDouble(dateText, CultureInfo.InvariantCulture));\r
+        case SQLiteDateFormats.UnixEpoch:\r
+          return UnixEpoch.AddSeconds(Convert.ToInt32(dateText, CultureInfo.InvariantCulture));\r
         default:\r
           return DateTime.ParseExact(dateText, _datetimeFormats, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None);\r
       }\r
@@ -197,6 +204,8 @@ namespace Mono.Data.Sqlite
           return dateValue.Ticks.ToString(CultureInfo.InvariantCulture);\r
         case SQLiteDateFormats.JulianDay:\r
           return ToJulianDay(dateValue).ToString(CultureInfo.InvariantCulture);\r
+        case SQLiteDateFormats.UnixEpoch:\r
+          return ((long)(dateValue.Subtract(UnixEpoch).Ticks / TimeSpan.TicksPerSecond)).ToString();\r
         default:\r
           return dateValue.ToString(_datetimeFormats[7], CultureInfo.InvariantCulture);\r
       }\r
@@ -685,6 +694,7 @@ namespace Mono.Data.Sqlite
       new SQLiteTypeNames("NOTE", DbType.String),\r
       new SQLiteTypeNames("SMALLINT", DbType.Int16),\r
       new SQLiteTypeNames("BIGINT", DbType.Int64),\r
+      new SQLiteTypeNames("TIMESTAMP", DbType.DateTime),\r
     };\r
   }\r
 \r
@@ -754,7 +764,11 @@ namespace Mono.Data.Sqlite
     /// <summary>\r
     /// JulianDay format, which is what SQLite uses internally\r
     /// </summary>\r
-    JulianDay = 2\r
+    JulianDay = 2,\r
+    /// <summary>\r
+    /// The whole number of seconds since the Unix epoch (January 1, 1970).\r
+    /// </summary>\r
+    UnixEpoch = 3,\r
   }\r
 \r
   /// <summary>\r
index 96867d8e0c936785f735ad00d9ef31994b7d9fc7..a5a5604e45ab83dce62b34643d92e1dfb629905c 100644 (file)
@@ -97,5 +97,49 @@ namespace MonoTests.Mono.Data.Sqlite
                                }
                        }
                }
+               
+               [Test]
+               public void TimestampTest ()
+               {
+                       _conn.ConnectionString = _connectionString;
+                       using (_conn) {
+                               _conn.Open ();
+                               var cmd = (SqliteCommand) _conn.CreateCommand ();
+                               cmd.CommandText = @"CREATE TABLE IF NOT EXISTS TestNullableDateTime (nullable TIMESTAMP NULL, dummy int); INSERT INTO TestNullableDateTime (nullable, dummy) VALUES (124123, 2);";
+                               cmd.ExecuteNonQuery ();
+                       
+                               var query = "SELECT * FROM TestNullableDateTime;";
+                               cmd = (SqliteCommand) _conn.CreateCommand ();
+                               cmd.CommandText = query;
+                               cmd.CommandType = CommandType.Text;
+                       
+                               using (var reader = cmd.ExecuteReader ()) {
+                                       try {
+                                               var dt = reader ["nullable"];
+                                               Assert.Fail ("Expected: FormatException");
+                                       } catch (FormatException ex) {
+                                               // expected this one
+                                       }
+                               }
+                       }
+                       
+                       _conn.ConnectionString = _connectionString + ",DateTimeFormat=UnixEpoch";
+                       using (_conn) {
+                               _conn.Open ();
+                               var cmd = (SqliteCommand) _conn.CreateCommand ();
+                               cmd.CommandText = @"CREATE TABLE IF NOT EXISTS TestNullableDateTime (nullable TIMESTAMP NULL, dummy int); INSERT INTO TestNullableDateTime (nullable, dummy) VALUES (124123, 2);";
+                               cmd.ExecuteNonQuery ();
+                       
+                               var query = "SELECT * FROM TestNullableDateTime;";
+                               cmd = (SqliteCommand) _conn.CreateCommand ();
+                               cmd.CommandText = query;
+                               cmd.CommandType = CommandType.Text;
+                       
+                               using (var reader = cmd.ExecuteReader ()) {
+                                       // this should succeed now
+                                       var dt = reader ["nullable"];
+                               }
+                       }
+               }
         }
 }