0

While I'm reading a complete data table with the Fill() method of SQLiteDataAdapter I get a “String not recognized as a valid datetime” exception.

The exception is thrown while reading a column of type DATETIME NOT NULL which contains Unix epoch time stamps in milliseconds. And yes I know that there is no specific DateTime type in SQLite. I know (from sqlite throwing a "String not recognized as a valid datetime") that I can adapt the ConnectionString and set "DateTimeFormat=UnixEpoch".
But this setting interprets the value as seconds not milliseconds since January 1, 1970.
Using it anyway results in a ArgumentOutOfRangeException. There is another parameter for the connection string: DateTimeFormatString. But I don't see a way to use it with my format.

I cannot change the data in the table. And I also don't want to enumerate the columns manually. Is there a simple way to get the table filled with "select * from ..."? Also just reading it as string would be helpful. There is a workouround with "DateTimeFormat=Ticks" but this is an ugly solution because it is not based on January 1, 1970.

Any help would be greatly appreciated.

Regards

I stripped down my code to a minimalistic example to demonstrate the behavior.

using System.Data;
using System.Data.SQLite;

namespace SQLite
{
    public class Program
    {
        public static void Main()
        {
            //using (var connection = new SQLiteConnection(@"Data Source=d:\src\C#\SQLite\SQLite\db\sampledb.db; DateTimeFormat=Ticks;"))
            using (var connection = new SQLiteConnection(@"Data Source=d:\src\C#\SQLite\SQLite\db\sampledb.db; DateTimeFormat=UnixEpoch;"))
            {
                connection.Open();
                using (var sqlDataAdapter = new SQLiteDataAdapter("SELECT * FROM TimeStamps;", connection))
                {
                    var dataTable = new DataTable();
                    sqlDataAdapter.Fill(dataTable);
                }
            }
        }
    }
}

Also the the DB now just contains one table. Both dates i.e. 1586948400000 are in Year 2020.
Table in sample DB

The code above produces an ArgumentOutOfRangeException. If the code is executed with DateTimeFormat=Ticks in the ConnectionString it runs but creates the wrong calendar dates.

The table was created with this SQL:

CREATE TABLE "TimeStamps" (
    "Id"    INTEGER,
    "TimeStamps"    DATETIME,
    PRIMARY KEY("Id")
)
ebiondi
  • 23
  • 9
  • Can you just change the type in your DataTable to be an Int64, and then apply a conversion wherever you *use* the column? That would probably be the simplest approach. – Jon Skeet Jul 10 '20 at 13:41
  • If you're using a strongly typed DataTable, you could have a property for the "raw" value and a delegating property that performs the conversion for you. If you could provide more context, we could probably help you more. – Jon Skeet Jul 10 '20 at 13:47
  • Thank you for trying to help me @Jon Skeet. The database has been created with the help of [flyway](https://flywaydb.org/). I get these databases from customers. In an early version of the SW the data in the column was entered as a localized date i.e. "15.04.2019". Later versions were using the ms Unix timestamps. My code has to deal with both kinds. I have no problem to read the localized dates. – ebiondi Jul 10 '20 at 15:28
  • At the moment we don't know what your code looks like at all, which makes it much harder to help you. We know that you're using `SQLiteDataAdapter`, but we don't know how you're setting things up to call `Fill`. Ideally, you'd give the data adapter the appropriate schema depending on what the table has at execution time, and then perform a suitable conversion where required. – Jon Skeet Jul 10 '20 at 15:52
  • @Jon Skeet: In the meantime I provided the code you asked for. It would be nice if you could point me to right direction. Thank you in advance. – ebiondi Jul 13 '20 at 14:43
  • Right - I'm slightly surprised to see DATETIME as a valid column type given the lack of real support for it in SQLite, but never mind. I haven't used this aspect of ADO.NET for years, but I *suspect* if you populate the `TimeStamps` column in your DataTable yourself, specifying a suitable integer data type, that *might* avoid the data adapter trying to do the conversion for you. – Jon Skeet Jul 13 '20 at 15:38

0 Answers0