Skip to content

Instantly share code, notes, and snippets.

@aynurin
Created November 26, 2015 14:30
Show Gist options
  • Save aynurin/b8bc9b152dd55cb6483a to your computer and use it in GitHub Desktop.
Save aynurin/b8bc9b152dd55cb6483a to your computer and use it in GitHub Desktop.
SmallDate - A C# class for a short (UInt16) date (work in progress)
/// <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