Skip to content

Commit 345e57e

Browse files
committed
Allow custom DateTime string format
1 parent 91c17ad commit 345e57e

File tree

3 files changed

+57
-10
lines changed

3 files changed

+57
-10
lines changed

src/SQLite.cs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,18 @@ public partial class SQLiteConnection : IDisposable
210210
/// </summary>
211211
public bool StoreDateTimeAsTicks { get; private set; }
212212

213+
/// <summary>
214+
/// The format to use when storing DateTime properties as strings. Ignored if StoreDateTimeAsTicks is true.
215+
/// </summary>
216+
/// <value>The date time string format.</value>
217+
public string DateTimeStringFormat { get; private set; }
218+
219+
/// <summary>
220+
/// The DateTimeStyles value to use when parsing a DateTime property string.
221+
/// </summary>
222+
/// <value>The date time style.</value>
223+
internal System.Globalization.DateTimeStyles DateTimeStyle { get; private set; }
224+
213225
#if USE_SQLITEPCL_RAW && !NO_SQLITEPCL_RAW_BATTERIES
214226
static SQLiteConnection ()
215227
{
@@ -298,6 +310,8 @@ public SQLiteConnection (SQLiteConnectionString connectionString)
298310
_open = true;
299311

300312
StoreDateTimeAsTicks = connectionString.StoreDateTimeAsTicks;
313+
DateTimeStringFormat = connectionString.DateTimeStringFormat;
314+
DateTimeStyle = connectionString.DateTimeStyle;
301315

302316
BusyTimeout = TimeSpan.FromSeconds (0.1);
303317
Tracer = line => Debug.WriteLine (line);
@@ -2091,9 +2105,13 @@ public enum NotifyTableChangedAction
20912105
/// </summary>
20922106
public class SQLiteConnectionString
20932107
{
2108+
const string DateTimeSqliteDefaultFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff";
2109+
20942110
public string UniqueKey { get; }
20952111
public string DatabasePath { get; }
20962112
public bool StoreDateTimeAsTicks { get; }
2113+
public string DateTimeStringFormat { get; }
2114+
public System.Globalization.DateTimeStyles DateTimeStyle { get; }
20972115
public object Key { get; }
20982116
public SQLiteOpenFlags OpenFlags { get; }
20992117
public Action<SQLiteConnection> PreKeyAction { get; }
@@ -2130,8 +2148,11 @@ public static bool IsInMemoryPath(string databasePath)
21302148
/// If you use DateTimeOffset properties, it will be always stored as ticks regardingless
21312149
/// the storeDateTimeAsTicks parameter.
21322150
/// </param>
2133-
public SQLiteConnectionString (string databasePath, bool storeDateTimeAsTicks = true)
2134-
: this (databasePath, SQLiteOpenFlags.Create | SQLiteOpenFlags.ReadWrite, storeDateTimeAsTicks)
2151+
/// <param name="dateTimeStringFormat">
2152+
/// Specifies the format to use when storing DateTime properties as strings.
2153+
/// </param>
2154+
public SQLiteConnectionString (string databasePath, bool storeDateTimeAsTicks = true, string dateTimeStringFormat = DateTimeSqliteDefaultFormat)
2155+
: this (databasePath, SQLiteOpenFlags.Create | SQLiteOpenFlags.ReadWrite, storeDateTimeAsTicks, dateTimeStringFormat: dateTimeStringFormat)
21352156
{
21362157
}
21372158

@@ -2195,13 +2216,18 @@ public SQLiteConnectionString (string databasePath, bool storeDateTimeAsTicks, o
21952216
/// <param name="vfsName">
21962217
/// Specifies the Virtual File System to use on the database.
21972218
/// </param>
2198-
public SQLiteConnectionString (string databasePath, SQLiteOpenFlags openFlags, bool storeDateTimeAsTicks, object key = null, Action<SQLiteConnection> preKeyAction = null, Action<SQLiteConnection> postKeyAction = null, string vfsName = null)
2219+
/// <param name="dateTimeStringFormat">
2220+
/// Specifies the format to use when storing DateTime properties as strings.
2221+
/// </param>
2222+
public SQLiteConnectionString (string databasePath, SQLiteOpenFlags openFlags, bool storeDateTimeAsTicks, object key = null, Action<SQLiteConnection> preKeyAction = null, Action<SQLiteConnection> postKeyAction = null, string vfsName = null, string dateTimeStringFormat = DateTimeSqliteDefaultFormat)
21992223
{
22002224
if (key != null && !((key is byte[]) || (key is string)))
22012225
throw new ArgumentException ("Encryption keys must be strings or byte arrays", nameof (key));
22022226

22032227
UniqueKey = string.Format ("{0}_{1:X8}", databasePath, (uint)openFlags);
22042228
StoreDateTimeAsTicks = storeDateTimeAsTicks;
2229+
DateTimeStringFormat = dateTimeStringFormat;
2230+
DateTimeStyle = "o".Equals (DateTimeStringFormat, StringComparison.OrdinalIgnoreCase) || "r".Equals (DateTimeStringFormat, StringComparison.OrdinalIgnoreCase) ? System.Globalization.DateTimeStyles.RoundtripKind : System.Globalization.DateTimeStyles.None;
22052231
Key = key;
22062232
PreKeyAction = preKeyAction;
22072233
PostKeyAction = postKeyAction;
@@ -2921,15 +2947,13 @@ void BindAll (Sqlite3Statement stmt)
29212947
b.Index = nextIdx++;
29222948
}
29232949

2924-
BindParameter (stmt, b.Index, b.Value, _conn.StoreDateTimeAsTicks);
2950+
BindParameter (stmt, b.Index, b.Value, _conn.StoreDateTimeAsTicks, _conn.DateTimeStringFormat);
29252951
}
29262952
}
29272953

29282954
static IntPtr NegativePointer = new IntPtr (-1);
29292955

2930-
const string DateTimeExactStoreFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fff";
2931-
2932-
internal static void BindParameter (Sqlite3Statement stmt, int index, object value, bool storeDateTimeAsTicks)
2956+
internal static void BindParameter (Sqlite3Statement stmt, int index, object value, bool storeDateTimeAsTicks, string dateTimeStringFormat)
29332957
{
29342958
if (value == null) {
29352959
SQLite3.BindNull (stmt, index);
@@ -2961,7 +2985,7 @@ internal static void BindParameter (Sqlite3Statement stmt, int index, object val
29612985
SQLite3.BindInt64 (stmt, index, ((DateTime)value).Ticks);
29622986
}
29632987
else {
2964-
SQLite3.BindText (stmt, index, ((DateTime)value).ToString (DateTimeExactStoreFormat, System.Globalization.CultureInfo.InvariantCulture), -1, NegativePointer);
2988+
SQLite3.BindText (stmt, index, ((DateTime)value).ToString (dateTimeStringFormat, System.Globalization.CultureInfo.InvariantCulture), -1, NegativePointer);
29652989
}
29662990
}
29672991
else if (value is DateTimeOffset) {
@@ -3046,7 +3070,7 @@ object ReadCol (Sqlite3Statement stmt, int index, SQLite3.ColType type, Type clr
30463070
else {
30473071
var text = SQLite3.ColumnString (stmt, index);
30483072
DateTime resultDate;
3049-
if (!DateTime.TryParseExact (text, DateTimeExactStoreFormat, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out resultDate)) {
3073+
if (!DateTime.TryParseExact (text, _conn.DateTimeStringFormat, System.Globalization.CultureInfo.InvariantCulture, _conn.DateTimeStyle, out resultDate)) {
30503074
resultDate = DateTime.Parse (text);
30513075
}
30523076
return resultDate;
@@ -3150,7 +3174,7 @@ public int ExecuteNonQuery (object[] source)
31503174
//bind the values.
31513175
if (source != null) {
31523176
for (int i = 0; i < source.Length; i++) {
3153-
SQLiteCommand.BindParameter (Statement, i + 1, source[i], Connection.StoreDateTimeAsTicks);
3177+
SQLiteCommand.BindParameter (Statement, i + 1, source[i], Connection.StoreDateTimeAsTicks, Connection.DateTimeStringFormat);
31543178
}
31553179
}
31563180
r = SQLite3.Step (Statement);

tests/DateTimeTest.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,14 @@ public void AsStrings ()
3939
TestDateTime (db);
4040
}
4141

42+
[TestCase("o")]
43+
[TestCase("MMM'-'dd'-'yyyy' 'HH':'mm':'ss'.'fffffff")]
44+
public void AsCustomStrings (string format)
45+
{
46+
var db = new TestDb (false, format);
47+
TestDateTime (db);
48+
}
49+
4250
[Test]
4351
public void AsyncAsTicks ()
4452
{
@@ -53,6 +61,14 @@ public void AsyncAsString ()
5361
TestAsyncDateTime (db);
5462
}
5563

64+
[TestCase("o")]
65+
[TestCase("MMM'-'dd'-'yyyy' 'HH':'mm':'ss'.'fffffff")]
66+
public void AsyncAsCustomStrings (string format)
67+
{
68+
var db = new SQLiteAsyncConnection (new SQLiteConnectionString (TestPath.GetTempFileName (), false, dateTimeStringFormat: format));
69+
TestAsyncDateTime (db);
70+
}
71+
5672
void TestAsyncDateTime (SQLiteAsyncConnection db)
5773
{
5874
db.CreateTableAsync<TestObj> ().Wait ();

tests/TestDb.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,13 @@ public TestDb (bool storeDateTimeAsTicks = true, object key = null, bool wal = t
6060
EnableWriteAheadLogging ();
6161
}
6262

63+
public TestDb (bool storeDateTimeAsTicks, string dateTimeFormat, bool wal = true) : base (new SQLiteConnectionString (TestPath.GetTempFileName (), storeDateTimeAsTicks, dateTimeStringFormat: dateTimeFormat))
64+
{
65+
Trace = true;
66+
if (wal)
67+
EnableWriteAheadLogging ();
68+
}
69+
6370
public TestDb (string path, bool storeDateTimeAsTicks = true, object key = null, bool wal = true) : base (new SQLiteConnectionString (path, storeDateTimeAsTicks, key: key))
6471
{
6572
Trace = true;

0 commit comments

Comments
 (0)