Last active
August 29, 2015 14:02
-
-
Save MrZoidberg/c98b891180a3499216e7 to your computer and use it in GitHub Desktop.
DateTime struct with support of parsing and storing dates like this: {CURRENT_DATE}+1h5m2s
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
[Serializable] | |
public struct SmartDateTime : IFormattable, ISerializable, IXmlSerializable, IEquatable<SmartDateTime>, IConvertible | |
{ | |
private bool _current; | |
private TimeSpan _diff; | |
private DateTime _value; | |
public bool IsCurrent | |
{ | |
get { return _current; } | |
} | |
public DateTime Value | |
{ | |
get { return _current ? DateTime.UtcNow + _diff : _value; } | |
} | |
public SmartDateTime(TimeSpan diffTimeSpan) | |
: this() | |
{ | |
_current = true; | |
_diff = diffTimeSpan; | |
_value = DateTime.MinValue; | |
} | |
public SmartDateTime(DateTime value) | |
: this() | |
{ | |
_current = false; | |
_diff = TimeSpan.Zero; | |
_value = value.ToUniversalTime(); | |
} | |
// this constructor is used for deserialization | |
public SmartDateTime(SerializationInfo info, StreamingContext text): this() | |
{ | |
_value = info.GetDateTime("Value"); | |
_current = info.GetBoolean("IsCurrent"); | |
_diff = ReadableTimeReader.ToTimeSpan(info.GetString("Diff")); | |
} | |
private static readonly SmartDateTime CurrentSmartDateTime = new SmartDateTime(TimeSpan.Zero); | |
public static SmartDateTime Current | |
{ | |
get { return CurrentSmartDateTime; } | |
} | |
public bool Equals(SmartDateTime other) | |
{ | |
return base.Equals(other); | |
} | |
public override string ToString() | |
{ | |
if (_current) | |
{ | |
return "Current date " + _diff; | |
} | |
return _value.ToString(); | |
} | |
public string ToString(string format, IFormatProvider formatProvider) | |
{ | |
if (_current) | |
{ | |
return "Current date " + _diff; | |
} | |
return _value.ToString(format, formatProvider); | |
} | |
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] | |
public void GetObjectData(SerializationInfo info, StreamingContext context) | |
{ | |
info.AddValue("IsCurrent", _current); | |
info.AddValue("Value", _value); | |
info.AddValue("Diff", ReadableTimeReader.TimeSpanToString(_diff)); | |
} | |
public XmlSchema GetSchema() | |
{ | |
throw new NotImplementedException(); | |
} | |
private const string CurrentDateKey = "{CURRENT_DATE}"; | |
public void ReadXml(XmlReader reader) | |
{ | |
string content = reader.ReadContentAsString(); | |
if (content.Contains(CurrentDateKey)) | |
{ | |
_current = true; | |
_value = DateTime.MinValue; | |
string diffString = content.Replace(CurrentDateKey+"+", "").Trim(); | |
if (String.IsNullOrEmpty(diffString)) | |
{ | |
_diff = ReadableTimeReader.ToTimeSpan(diffString); | |
} | |
} | |
else | |
{ | |
_current = false; | |
_value = DateTime.Parse(content, CultureInfo.InvariantCulture); | |
} | |
} | |
public void WriteXml(XmlWriter writer) | |
{ | |
if (_current) | |
{ | |
if (_diff != TimeSpan.Zero) | |
{ | |
writer.WriteValue(String.Format("{0}+{1}", CurrentDateKey, ReadableTimeReader.TimeSpanToString(_diff, true))); | |
} | |
else | |
{ | |
writer.WriteValue(CurrentDateKey); | |
} | |
} | |
else | |
{ | |
writer.WriteValue(_value.ToString(CultureInfo.InvariantCulture)); | |
} | |
} | |
public static explicit operator SmartDateTime(DateTime dateTime) | |
{ | |
SmartDateTime smartDateTime = new SmartDateTime(dateTime); | |
return smartDateTime; | |
} | |
public static implicit operator DateTime(SmartDateTime smartDateTime) | |
{ | |
return smartDateTime.Value; | |
} | |
public TypeCode GetTypeCode() | |
{ | |
return TypeCode.Object; | |
} | |
public bool ToBoolean(IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
public char ToChar(IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
public sbyte ToSByte(IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
public byte ToByte(IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
public short ToInt16(IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
public ushort ToUInt16(IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
public int ToInt32(IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
public uint ToUInt32(IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
public long ToInt64(IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
public ulong ToUInt64(IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
public float ToSingle(IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
public double ToDouble(IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
public decimal ToDecimal(IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
public DateTime ToDateTime(IFormatProvider provider) | |
{ | |
return Value; | |
} | |
public string ToString(IFormatProvider provider) | |
{ | |
if (_current) | |
{ | |
return "Current date " + _diff; | |
} | |
return _value.ToString(provider); | |
} | |
public object ToType(Type conversionType, IFormatProvider provider) | |
{ | |
throw new InvalidCastException(); | |
} | |
} | |
public static class ReadableTimeReader | |
{ | |
private const char HoursChar = 'h'; | |
private const char MinutesChar = 'm'; | |
private const char SecondsChar = 's'; | |
public static TimeSpan ToTimeSpan(string value) | |
{ | |
if (String.IsNullOrWhiteSpace(value)) | |
return TimeSpan.Zero; | |
value = value.ToLowerInvariant().Replace(" ", String.Empty); | |
string[] parts = Regex.Split(value, @"(h)|(m)|(s)"); | |
int hours = 0; | |
int minutes = 0; | |
int seconds = 0; | |
for (int index = 0; index < parts.Length - 1; index += 2) | |
{ | |
string part = parts[index]; | |
char partChar = parts[index + 1][0]; | |
int partValue = Int32.Parse(part, CultureInfo.InvariantCulture); | |
switch (partChar) | |
{ | |
case HoursChar: | |
{ | |
hours = partValue; | |
break; | |
} | |
case MinutesChar: | |
{ | |
minutes = partValue; | |
break; | |
} | |
case SecondsChar: | |
{ | |
seconds = partValue; | |
break; | |
} | |
} | |
} | |
TimeSpan timeSpan = new TimeSpan(hours, minutes, seconds); | |
return timeSpan; | |
} | |
public static string TimeSpanToString(TimeSpan timeSpan, bool withoutSpaces = false) | |
{ | |
StringBuilder sb = new StringBuilder(); | |
if (timeSpan.Days > 0) | |
{ | |
sb.AppendFormat("{0}d", timeSpan.Days); | |
} | |
string spaceChar = withoutSpaces ? "" : " "; | |
sb.AppendFormat("{1}{0}h", timeSpan.Hours, spaceChar); | |
sb.AppendFormat("{1}{0}m", timeSpan.Minutes, spaceChar); | |
sb.AppendFormat("{1}{0}s", timeSpan.Seconds, spaceChar); | |
return sb.ToString().Trim(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment