Skip to content

Instantly share code, notes, and snippets.

@huyderman
Created February 9, 2012 11:22
Show Gist options
  • Save huyderman/1779385 to your computer and use it in GitHub Desktop.
Save huyderman/1779385 to your computer and use it in GitHub Desktop.
An object for working with time as commonly found in languages like java, c/c++, or *NIX platforms.
/** @file
* This software is licensed under the MIT license.
*
* @par The MIT License
*
* Copyright (c) 2012 Jo-Herman Haugholt
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
using System;
using System.Globalization;
using System.Xml.Serialization;
namespace Huyderman.Calendar
{
/**
* This stuct stores an date and time as milliseconds since Jan 1, 1970 00:00:00.000Z in an 64-bit integer.
*
* It is common in many languages and systems to store dates relative to the "unix epoch".
* This object makes it easier to work with dates in that format, and interoperate with System.DateTime object used in .NET.
*
* @author Jo-Herman Haugholt <johannes@huyderman.com>
* @version 1.0.0.0
*/
[Serializable]
public struct EpochDateTime : IComparable,
IComparable<EpochDateTime>,
IComparable<DateTime>,
IEquatable<EpochDateTime>,
IEquatable<DateTime>,
IFormattable
{
//
// The UnixEpoch, it begins on Jan 1, 1970 at 00:00:00, expressed
// in Ticks
//
private const long UnixEpoch = 621355968000000000L;
private const long TicksPerMillisecond = TimeSpan.TicksPerMillisecond;
/**
* Milliseconds since the Epoch
*/
[XmlText]
public long Milliseconds { get; set; }
/**
* Seconds since the Epoch
*/
public long Seconds { get { return Milliseconds / 1000; } set { Milliseconds = value * 1000; } }
/**
* The EpochDateTime as Ticks since 0001-01-01
* @see System.DateTime
*/
public long Ticks { get { return Milliseconds * TicksPerMillisecond + UnixEpoch; } set { Milliseconds = (value - UnixEpoch) / TicksPerMillisecond; } }
/**
* Creates a new EpochDateTime from the given 64-bit timestamp
*/
public EpochDateTime(long timestamp) : this() { Milliseconds = timestamp; }
/**
* Creates a new EpochDateTime from the given DateTime
*/
public EpochDateTime(DateTime dt) : this() { Ticks = dt.ToUniversalTime().Ticks; }
// Conversions
#region
public static EpochDateTime Now
{
get
{
return new EpochDateTime(DateTime.Now);
}
}
public DateTime ToDateTime() { return new DateTime(Ticks, DateTimeKind.Utc); }
public DateTime ToLocalDateTime() { return new DateTime(Ticks, DateTimeKind.Utc).ToLocalTime(); }
public override string ToString()
{
return ToDateTime().ToString(CultureInfo.InvariantCulture);
}
public string ToString(string format, IFormatProvider formatProvider)
{
return ToDateTime().ToString(format, formatProvider);
}
public static implicit operator DateTime(EpochDateTime ut) { return ut.ToDateTime(); }
public static explicit operator EpochDateTime(DateTime dt) { return new EpochDateTime(dt); }
#endregion
// Math
#region
public EpochDateTime Add(long milliseconds)
{
return new EpochDateTime(Milliseconds + milliseconds);
}
public static EpochDateTime operator +(EpochDateTime ut, long milliseconds)
{
return new EpochDateTime(ut.Milliseconds + milliseconds);
}
public EpochDateTime Add(TimeSpan ts)
{
return new EpochDateTime(Milliseconds + (long)ts.TotalMilliseconds);
}
public static EpochDateTime operator +(EpochDateTime ut, TimeSpan ts)
{
return new EpochDateTime(ut.Milliseconds + (long)ts.TotalMilliseconds);
}
private static TimeSpan Subtract(EpochDateTime ut1, EpochDateTime ut2)
{
return new TimeSpan(ut1.Ticks - ut2.Ticks);
}
public static TimeSpan operator -(EpochDateTime ut1, EpochDateTime ut2)
{
return Subtract(ut1, ut2);
}
public static EpochDateTime operator -(EpochDateTime ut, long milliseconds)
{
return Subtract(ut, milliseconds);
}
private static EpochDateTime Subtract(EpochDateTime ut, long milliseconds)
{
return new EpochDateTime(ut.Milliseconds - milliseconds);
}
public static EpochDateTime operator -(EpochDateTime ut, TimeSpan ts)
{
return Subtract(ut, ts);
}
private static EpochDateTime Subtract(EpochDateTime ut, TimeSpan ts)
{
return new EpochDateTime(ut.Milliseconds - (long)ts.TotalMilliseconds);
}
#endregion
// Comparisons
#region
public static int Compare(EpochDateTime ut1, EpochDateTime ut2)
{
return ut1.Milliseconds < ut2.Milliseconds ? -1 : (ut1.Milliseconds > ut2.Milliseconds ? 1 : 0);
}
public int CompareTo(EpochDateTime ut)
{
return Compare(this, ut);
}
public int CompareTo(DateTime dt)
{
var ticks = Ticks;
var utcDt = dt.ToUniversalTime();
return ticks < utcDt.Ticks ? -1 : (ticks > utcDt.Ticks ? 1 : 0);
}
public int CompareTo(object obj)
{
if (ReferenceEquals(null, obj)) throw new ArgumentNullException("obj");
if (obj is EpochDateTime) return CompareTo((EpochDateTime)obj);
if (obj is DateTime) return CompareTo((DateTime)obj);
throw new ArgumentException("obj");
}
public bool Equals(EpochDateTime ut) { return Milliseconds == ut.Milliseconds; }
public bool Equals(DateTime dt) { return Ticks == dt.ToUniversalTime().Ticks; }
public bool Equals(EpochDateTime ut1, EpochDateTime ut2) { return ut1.Milliseconds == ut2.Milliseconds; }
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (obj is EpochDateTime) return Equals((EpochDateTime)obj);
if (obj is DateTime) return Equals((DateTime)obj);
return false;
}
public static bool operator ==(EpochDateTime ut1, EpochDateTime ut2) { return ut1.Equals(ut2); }
public static bool operator !=(EpochDateTime ut1, EpochDateTime ut2) { return !ut1.Equals(ut2); }
public static bool operator ==(EpochDateTime ut, DateTime dt) { return ut.Equals(dt); }
public static bool operator !=(EpochDateTime ut, DateTime dt) { return !ut.Equals(dt); }
public static bool operator >(EpochDateTime ut1, EpochDateTime ut2) { return ut1.Milliseconds > ut2.Milliseconds; }
public static bool operator <(EpochDateTime ut1, EpochDateTime ut2) { return ut1.Milliseconds < ut2.Milliseconds; }
public static bool operator >=(EpochDateTime ut1, EpochDateTime ut2) { return ut1.Milliseconds >= ut2.Milliseconds; }
public static bool operator <=(EpochDateTime ut1, EpochDateTime ut2) { return ut1.Milliseconds <= ut2.Milliseconds; }
#endregion
public override int GetHashCode() { return (int)Ticks; }
public string ToString(string format) { return ToString(format, null); }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment