Created
November 26, 2015 14:30
-
-
Save krmrn42/b8bc9b152dd55cb6483a to your computer and use it in GitHub Desktop.
SmallDate - A C# class for a short (UInt16) date (work in progress)
This file contains hidden or 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
/// <summary> | |
/// A UInt16 date with hour-precision. Not valid for dates far away from today. | |
/// </summary> | |
public struct SmallDate | |
{ | |
private const long TicksInHour = 36000000000; | |
private readonly ushort _value; | |
public SmallDate(DateTime datetime) : this (datetime, DateTime.UtcNow) | |
{ | |
} | |
public SmallDate(DateTime datetime, DateTime anchorDate) | |
{ | |
var anchor = GetAnchor(anchorDate); | |
var value = (datetime.Ticks - anchor) / TicksInHour; | |
checked { _value = (ushort)value; } | |
} | |
public SmallDate(ushort hours) | |
{ | |
_value = hours; | |
} | |
public DateTime ToDateTime() | |
{ | |
var now = DateTime.UtcNow; | |
var datetime = ToDateTime(now); | |
if (datetime > now.AddMonths(1)) | |
datetime = ToDateTime(now.AddYears(-1)); | |
return datetime; | |
} | |
public DateTime ToDateTime(DateTime anchor) | |
{ | |
return new DateTime(GetAnchor(anchor) + _value * TicksInHour); | |
} | |
public static SmallDate MinValue => new SmallDate(UInt16.MinValue); | |
public static SmallDate MaxValue => new SmallDate(UInt16.MaxValue); | |
public static implicit operator DateTime(SmallDate value) | |
{ | |
return value.ToDateTime(); | |
} | |
public static implicit operator SmallDate(DateTime value) | |
{ | |
return new SmallDate(value); | |
} | |
private static long GetAnchor(DateTime value) | |
{ | |
var year = value.Year; | |
return new DateTime(year - (year % 2), 1, 1).Ticks; | |
} | |
} | |
[TestFixture] | |
class SmallDateTests | |
{ | |
[Test] | |
public void DefaultTest() | |
{ | |
TestWith(DateTime.UtcNow); | |
} | |
[Test] | |
public void ClosePast() | |
{ | |
TestWith(DateTime.UtcNow.AddDays(-5)); | |
} | |
[Test] | |
public void MidPast() | |
{ | |
TestWith(DateTime.UtcNow.AddMonths(-5)); | |
} | |
[Test] | |
public void FarPast() | |
{ | |
TestWith(DateTime.UtcNow.AddYears(-1)); | |
} | |
[Test] | |
public void NearFuture() | |
{ | |
TestWith(DateTime.UtcNow.AddDays(5)); | |
} | |
[Test] | |
public void MidFuture() | |
{ | |
TestWith(DateTime.UtcNow.AddDays(20)); | |
} | |
[Test] | |
[ExpectedException(typeof(OverflowException))] | |
public void PastDateOverflow() | |
{ | |
new SmallDate(new DateTime(DateTime.UtcNow.Year - 3, 1, 1, 1, 2, 3)); | |
} | |
[Test] | |
[ExpectedException(typeof(OverflowException))] | |
public void FutureDateOverflow() | |
{ | |
new SmallDate(new DateTime(DateTime.UtcNow.Year + 10, 1, 1, 1, 2, 3)); | |
} | |
[Test] | |
public void FarFuture() | |
{ | |
var date = DateTime.UtcNow; | |
if (date.Year % 2 == 0) | |
date = date.AddYears(-1); | |
else | |
date = date.AddYears(1); | |
TestWith(date); | |
} | |
public void TestWith(DateTime date) | |
{ | |
var smallDate = new SmallDate(date); | |
var newDate = (DateTime)smallDate; | |
var expectedDate = new DateTime(date.Year, date.Month, date.Day, date.Hour, 0, 0); | |
Assert.AreEqual(expectedDate, newDate); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment