Skip to content

Instantly share code, notes, and snippets.

@ngbrown
Created October 13, 2017 23:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ngbrown/195e09681572371011fb2c78c5fcf04d to your computer and use it in GitHub Desktop.
Save ngbrown/195e09681572371011fb2c78c5fcf04d to your computer and use it in GitHub Desktop.
SQLiteDateRoundTripTests
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