Created
October 13, 2017 23:22
-
-
Save ngbrown/195e09681572371011fb2c78c5fcf04d to your computer and use it in GitHub Desktop.
SQLiteDateRoundTripTests
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Globalization; | |
using NUnit.Framework; | |
namespace UnitTestProject1 | |
{ | |
[TestFixture] | |
public class SQLiteDateRoundTripTests | |
{ | |
private int _optionToStringInSqLite = 1; // Currently implemented in System.Data.SQLite | |
private int _optionToDateTimeInSqLite = 1; // Currently implemented in System.Data.SQLite | |
//private int _optionToDateTimeInSqLite = 2; // proposed by frederic | |
//private int _optionToDateTimeInSqLite = 3; // variation proposed by nathan - would let UTC marker back through on read if saved | |
private int _optionAdjustCommand = 1; // no driver change | |
//private int _optionAdjustCommand = 2; // all date kind to Unspecified | |
private int _optionAdjustInType = 1; // current state in NHibernate | |
//private int _optionAdjustInType = 2; // proposed by Nathan | |
public SQLiteDateRoundTripTests() | |
{ | |
} | |
public SQLiteDateRoundTripTests(int optionToStringInSqLite, int optionToDateTimeInSqLite, int optionAdjustCommand, int optionAdjustInType) | |
{ | |
this._optionToStringInSqLite = optionToStringInSqLite; | |
this._optionToDateTimeInSqLite = optionToDateTimeInSqLite; | |
this._optionAdjustCommand = optionAdjustCommand; | |
this._optionAdjustInType = optionAdjustInType; | |
} | |
private static string[] _datetimeFormats = new string[] { | |
"yyyy-MM-dd HH:mm:ss.FFFFFFFK", /* NOTE: UTC default (5). */ | |
"yyyy-MM-dd HH:mm:ss.FFFFFFF", /* NOTE: Non-UTC default (19). */ | |
}; | |
private static readonly string _datetimeFormatUtc = _datetimeFormats[0]; | |
private static readonly string _datetimeFormatLocal = _datetimeFormats[1]; | |
[Test] | |
[TestCase(DateTimeKind.Utc)] | |
[TestCase(DateTimeKind.Unspecified)] | |
public void ToStringFromUtcTime(DateTimeKind connectionKind) | |
{ | |
DateTime date = new DateTime(2017, 10, 12, 11, 32, 42, 356, DateTimeKind.Utc); | |
var dateText = ToString(date, connectionKind, null); | |
TestContext.WriteLine(dateText); | |
} | |
[Test] | |
[TestCase(DateTimeKind.Utc)] | |
[TestCase(DateTimeKind.Unspecified)] | |
public void ToStringFromUnspecifiedTime(DateTimeKind connectionKind) | |
{ | |
DateTime date = new DateTime(2017, 10, 12, 11, 32, 42, 356, DateTimeKind.Unspecified); | |
var dateText = ToString(date, connectionKind, null); | |
TestContext.WriteLine(dateText); | |
} | |
[Test] | |
[TestCase(DateTimeKind.Utc)] | |
[TestCase(DateTimeKind.Unspecified)] | |
public void ToStringFromLocalTime(DateTimeKind connectionKind) | |
{ | |
DateTime date = new DateTime(2017, 10, 12, 11, 32, 42, 356, DateTimeKind.Local); | |
var dateText = ToString(date, connectionKind, null); | |
TestContext.WriteLine(dateText); | |
} | |
[Test] | |
[TestCase(DateTimeKind.Utc, "2017-10-12 11:32:42.365")] | |
[TestCase(DateTimeKind.Unspecified, "2017-10-12 11:32:42.365")] | |
[TestCase(DateTimeKind.Utc, "2017-10-12 11:32:42.365Z")] | |
[TestCase(DateTimeKind.Unspecified, "2017-10-12 11:32:42.365Z")] | |
public void ToDateTimeFromString(DateTimeKind connectionKind, string dateText) | |
{ | |
var dateTime = ToDateTime(dateText, connectionKind); | |
TestContext.WriteLine("as received: {0}, kind: {1}", dateTime, dateTime.Kind); | |
TestContext.WriteLine("ToLocalTime: {0}", dateTime.ToLocalTime()); | |
TestContext.WriteLine("ToUniversalTime: {0}", dateTime.ToUniversalTime()); | |
TestContext.WriteLine("Cast as DateTimeOffset: {0}", (DateTimeOffset)dateTime); | |
} | |
[Test] | |
[TestCase(DateTimeKind.Local, DateTimeKind.Local)] | |
[TestCase(DateTimeKind.Local, DateTimeKind.Unspecified)] | |
[TestCase(DateTimeKind.Local, DateTimeKind.Utc)] | |
[TestCase(DateTimeKind.Unspecified, DateTimeKind.Local)] | |
[TestCase(DateTimeKind.Unspecified, DateTimeKind.Unspecified)] | |
[TestCase(DateTimeKind.Unspecified, DateTimeKind.Utc)] | |
[TestCase(DateTimeKind.Utc, DateTimeKind.Local)] | |
[TestCase(DateTimeKind.Utc, DateTimeKind.Unspecified)] | |
[TestCase(DateTimeKind.Utc, DateTimeKind.Utc)] | |
public void RoundTripWithConnectionKindFromOriginalKind(DateTimeKind connectionKind, DateTimeKind typeKind) | |
{ | |
DateTime date = new DateTime(2017, 10, 12, 11, 32, 42, 356, typeKind); | |
var commandDate = NHibernateSqliteDriverAdjustCommand(NHibernateAdjustInType(date, typeKind)); | |
var dateRetreived = SQLiteRoundTrip(connectionKind, commandDate); | |
var adjustedDate = NHibernateAdjustInType(dateRetreived, typeKind); | |
TestContext.WriteLine("as adjusted: {0}, kind: {1}", adjustedDate, adjustedDate.Kind); | |
Assert.That(adjustedDate, Is.EqualTo(date)); | |
} | |
[Test] | |
[TestCase(DateTimeKind.Local, DateTimeKind.Local)] | |
[TestCase(DateTimeKind.Local, DateTimeKind.Unspecified)] | |
[TestCase(DateTimeKind.Local, DateTimeKind.Utc)] | |
[TestCase(DateTimeKind.Unspecified, DateTimeKind.Local)] | |
[TestCase(DateTimeKind.Unspecified, DateTimeKind.Unspecified)] | |
[TestCase(DateTimeKind.Unspecified, DateTimeKind.Utc)] | |
[TestCase(DateTimeKind.Utc, DateTimeKind.Local)] | |
[TestCase(DateTimeKind.Utc, DateTimeKind.Unspecified)] | |
[TestCase(DateTimeKind.Utc, DateTimeKind.Utc)] | |
public void RoundTripWithConnectionKindFromOriginalKindCompareDateTimeOffset(DateTimeKind connectionKind, DateTimeKind typeKind) | |
{ | |
DateTime date = new DateTime(2017, 10, 12, 11, 32, 42, 356, typeKind); | |
var commandDate = NHibernateSqliteDriverAdjustCommand(NHibernateAdjustInType(date, typeKind)); | |
var dateRetreived = SQLiteRoundTrip(connectionKind, commandDate); | |
var adjustedDate = NHibernateAdjustInType(dateRetreived, typeKind); | |
TestContext.WriteLine("as adjusted: {0}, kind: {1}", adjustedDate, adjustedDate.Kind); | |
Assert.That((DateTimeOffset)adjustedDate, Is.EqualTo((DateTimeOffset)date)); | |
} | |
[Test] | |
[TestCase(DateTimeKind.Local, DateTimeKind.Local)] | |
[TestCase(DateTimeKind.Local, DateTimeKind.Unspecified)] | |
[TestCase(DateTimeKind.Local, DateTimeKind.Utc)] | |
[TestCase(DateTimeKind.Unspecified, DateTimeKind.Local)] | |
[TestCase(DateTimeKind.Unspecified, DateTimeKind.Unspecified)] | |
[TestCase(DateTimeKind.Unspecified, DateTimeKind.Utc)] | |
[TestCase(DateTimeKind.Utc, DateTimeKind.Local)] | |
[TestCase(DateTimeKind.Utc, DateTimeKind.Unspecified)] | |
[TestCase(DateTimeKind.Utc, DateTimeKind.Utc)] | |
public void RoundTripWithConnectionKindFromOriginalKindCompareNHibernateEqual(DateTimeKind connectionKind, DateTimeKind typeKind) | |
{ | |
DateTime date = new DateTime(2017, 10, 12, 11, 32, 42, 356, typeKind); | |
var commandDate = NHibernateSqliteDriverAdjustCommand(NHibernateAdjustInType(date, typeKind)); | |
var dateRetreived = SQLiteRoundTrip(connectionKind, commandDate); | |
var adjustedDate = NHibernateAdjustInType(dateRetreived, typeKind); | |
TestContext.WriteLine("as adjusted: {0}, kind: {1}", adjustedDate, adjustedDate.Kind); | |
Assert.That(NHibernateIsEqual(adjustedDate, date, typeKind)); | |
} | |
private DateTime SQLiteRoundTrip(DateTimeKind connectionKind, DateTime date) | |
{ | |
TestContext.WriteLine("as set: {0}, kind: {1}", date, date.Kind); | |
string dateString = ToString(date, connectionKind, null); | |
TestContext.WriteLine("as saved in SQLite: \"{0}\"", dateString); | |
DateTime dateRetreived = ToDateTime(dateString, connectionKind); | |
TestContext.WriteLine("as retreived: {0}, kind: {1}", dateRetreived, dateRetreived.Kind); | |
return dateRetreived; | |
} | |
private static string GetDateTimeKindFormat( | |
DateTimeKind kind, | |
string formatString | |
) | |
{ | |
if (formatString != null) return formatString; | |
return (kind == DateTimeKind.Utc) ? _datetimeFormatUtc : _datetimeFormatLocal; | |
} | |
private DateTime ToDateTime(string dateText, DateTimeKind kind) | |
{ | |
switch (_optionToDateTimeInSqLite) | |
{ | |
case 1: | |
// Currently implemented in System.Data.SQLite | |
return DateTime.SpecifyKind(DateTime.ParseExact( | |
dateText, _datetimeFormats, | |
DateTimeFormatInfo.InvariantInfo, | |
kind == DateTimeKind.Utc ? DateTimeStyles.AdjustToUniversal : DateTimeStyles.None), | |
kind); | |
case 2: | |
{ | |
// proposed by frederic | |
var date = DateTime.ParseExact( | |
dateText, _datetimeFormats, | |
DateTimeFormatInfo.InvariantInfo, | |
DateTimeStyles.AdjustToUniversal); | |
if (kind == DateTimeKind.Local && date.Kind == DateTimeKind.Utc) | |
date = date.ToLocalTime(); | |
return DateTime.SpecifyKind(date, kind); | |
} | |
case 3: | |
{ | |
// variation proposed by nathan - would let UTC marker back through if saved | |
// passes more tests when DateTime is cast to (DateTimeOffset) | |
var date = DateTime.ParseExact( | |
dateText, _datetimeFormats, | |
DateTimeFormatInfo.InvariantInfo, | |
DateTimeStyles.AdjustToUniversal); | |
if (kind == DateTimeKind.Local && date.Kind == DateTimeKind.Utc) | |
date = date.ToLocalTime(); | |
return date; | |
} | |
default: | |
throw new NotImplementedException(); | |
} | |
} | |
public string ToString( | |
DateTime dateValue, | |
DateTimeKind kind, | |
string formatString | |
) | |
{ | |
switch (_optionToStringInSqLite) | |
{ | |
case 1: | |
return (dateValue.Kind == DateTimeKind.Unspecified) | |
? DateTime.SpecifyKind(dateValue, kind).ToString( | |
GetDateTimeKindFormat(kind, formatString), | |
CultureInfo.InvariantCulture) | |
: dateValue.ToString( | |
GetDateTimeKindFormat(dateValue.Kind, formatString), | |
CultureInfo.InvariantCulture); | |
default: | |
throw new NotImplementedException(); | |
} | |
} | |
public DateTime NHibernateSqliteDriverAdjustCommand(DateTime date) | |
{ | |
switch (_optionAdjustCommand) | |
{ | |
case 1: | |
return date; | |
case 2: | |
return DateTime.SpecifyKind(date, DateTimeKind.Unspecified); | |
default: | |
throw new NotImplementedException(); | |
} | |
} | |
public bool NHibernateIsEqual(object x, object y, DateTimeKind nhibernateTypeKind) | |
{ | |
return (x == y || (x != null && y != null && x.Equals(y))) && | |
(nhibernateTypeKind == DateTimeKind.Unspecified || x == null || ((DateTime) x).Kind == ((DateTime) y).Kind); | |
} | |
public DateTime NHibernateAdjustInType(DateTime dateValue, DateTimeKind nhibernateTypeKind) | |
{ | |
switch (_optionAdjustInType) | |
{ | |
case 1: | |
// current state in NHibernate | |
return nhibernateTypeKind == DateTimeKind.Unspecified ? dateValue : DateTime.SpecifyKind(dateValue, nhibernateTypeKind); | |
case 2: | |
// proposed by Nathan | |
return DateTime.SpecifyKind(dateValue, nhibernateTypeKind); | |
default: | |
throw new NotImplementedException(); | |
} | |
} | |
} | |
[TestFixture] | |
public class SQLiteDateRoundTripTests1111 : SQLiteDateRoundTripTests | |
{ | |
public SQLiteDateRoundTripTests1111():base(1,1,1,1) { } | |
} | |
[TestFixture] | |
public class SQLiteDateRoundTripTests1211 : SQLiteDateRoundTripTests | |
{ | |
public SQLiteDateRoundTripTests1211() : base(1, 2, 1, 1) { } | |
} | |
[TestFixture] | |
public class SQLiteDateRoundTripTests1311 : SQLiteDateRoundTripTests | |
{ | |
public SQLiteDateRoundTripTests1311() : base(1, 3, 1, 1) { } | |
} | |
[TestFixture] | |
public class SQLiteDateRoundTripTests1121 : SQLiteDateRoundTripTests | |
{ | |
public SQLiteDateRoundTripTests1121():base(1,1,2,1) { } | |
} | |
[TestFixture] | |
public class SQLiteDateRoundTripTests1221 : SQLiteDateRoundTripTests | |
{ | |
public SQLiteDateRoundTripTests1221() : base(1, 2, 2, 1) { } | |
} | |
[TestFixture] | |
public class SQLiteDateRoundTripTests1321 : SQLiteDateRoundTripTests | |
{ | |
public SQLiteDateRoundTripTests1321() : base(1, 3, 2, 1) { } | |
} | |
[TestFixture] | |
public class SQLiteDateRoundTripTests1112 : SQLiteDateRoundTripTests | |
{ | |
public SQLiteDateRoundTripTests1112() : base(1, 1, 1, 2) { } | |
} | |
[TestFixture] | |
public class SQLiteDateRoundTripTests1212 : SQLiteDateRoundTripTests | |
{ | |
public SQLiteDateRoundTripTests1212() : base(1, 2, 1, 2) { } | |
} | |
[TestFixture] | |
public class SQLiteDateRoundTripTests1312 : SQLiteDateRoundTripTests | |
{ | |
public SQLiteDateRoundTripTests1312() : base(1, 3, 1, 2) { } | |
} | |
[TestFixture] | |
public class SQLiteDateRoundTripTests1122 : SQLiteDateRoundTripTests | |
{ | |
public SQLiteDateRoundTripTests1122() : base(1, 1, 2, 2) { } | |
} | |
[TestFixture] | |
public class SQLiteDateRoundTripTests1222 : SQLiteDateRoundTripTests | |
{ | |
public SQLiteDateRoundTripTests1222() : base(1, 2, 2, 2) { } | |
} | |
[TestFixture] | |
public class SQLiteDateRoundTripTests1322 : SQLiteDateRoundTripTests | |
{ | |
public SQLiteDateRoundTripTests1322() : base(1, 3, 2, 2) { } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment