using System; namespace Disco { public static class DateTimeExtensions { public static string From(this DateTime moment, DateTime to, bool withoutSuffix) { var duration = to - moment; return duration.Humanize(!withoutSuffix); } public static string From(this DateTime moment, DateTime to) { return moment.From(to, false); } public static string From(this DateTime? moment, DateTime to, bool withoutSuffix, string nullValue) { if (moment.HasValue) return moment.Value.From(to, withoutSuffix); else return nullValue; } public static string From(this DateTime? moment, DateTime to, string nullValue) { if (moment.HasValue) return moment.Value.From(to); else return nullValue; } public static string From(this DateTime? moment, DateTime to) { return moment.From(to, "n/a"); } public static string FromNow(this DateTime moment, bool withoutSuffix) { return DateTime.Now.From(moment, withoutSuffix); } public static string FromNow(this DateTime moment) { return moment.FromNow(false); } public static string FromNow(this DateTime? moment, bool withoutSuffix, string nullValue) { if (moment.HasValue) return moment.Value.FromNow(withoutSuffix); else return nullValue; } public static string FromNow(this DateTime? moment, string nullValue) { if (moment.HasValue) return moment.Value.FromNow(); else return nullValue; } public static string FromNow(this DateTime? moment) { return moment.FromNow("n/a"); } public static string Humanize(this TimeSpan duration, bool withSuffix) { string output = RelativeTime(duration.Ticks > 0 ? duration : duration.Negate(), true); if (withSuffix) if (duration.TotalMilliseconds > 0) output = "in " + output; else output = output + " ago"; return output; } private static string RelativeTime(this TimeSpan difference, bool withoutSuffix) { string output; if (Math.Round(difference.TotalSeconds) < 45) output = "a few seconds"; else if (Math.Round(difference.TotalMinutes) == 1) output = "a minute"; else if (Math.Round(difference.TotalMinutes) < 45) output = (int)Math.Round(difference.TotalMinutes) + " minutes"; else if (Math.Round(difference.TotalHours) == 1) output = "an hour"; else if (Math.Round(difference.TotalHours) < 22) output = (int)Math.Round(difference.TotalHours) + " hours"; else if (Math.Round(difference.TotalDays) == 1) output = "a day"; else if (Math.Round(difference.TotalDays) <= 25) output = (int)Math.Round(difference.TotalDays) + " days"; else if (Math.Round(difference.TotalDays) <= 45) output = "a month"; else if (Math.Round(difference.TotalDays) < 345) output = (int)Math.Round(difference.TotalDays / 30) + " months"; else if (Math.Round(difference.TotalDays / 365) == 1) output = "a year"; else output = (int)Math.Round(difference.TotalDays / 365) + " years"; if (!withoutSuffix) if (difference.TotalMilliseconds > 0) output = "in " + output; else output = output + " ago"; return output; } public static string ToFullDateTime(this DateTime d) { return d.ToString("ddd, d MMM yyyy h:mm:sstt"); } public static string ToFullDateTime(this DateTime? d, string NullValue = "N/A") { if (d.HasValue) return ToFullDateTime(d.Value); else return NullValue; } private const long unixEpocOffset = 621355968000000000; public static long ToUnixEpoc(this DateTime d) { var epoc = new DateTime(unixEpocOffset, DateTimeKind.Utc); var offset = d.ToUniversalTime() - epoc; return offset.Ticks / TimeSpan.TicksPerMillisecond; } public static long? ToUnixEpoc(this DateTime? d) { if (d.HasValue) return d.Value.ToUnixEpoc(); else return null; } public static DateTime FromUnixEpoc(this long d) { var epoc = new DateTime(unixEpocOffset, DateTimeKind.Utc); return epoc.AddMilliseconds(d); } public static string ToISO8601(this DateTime d) { return d.ToString("yyyy-MM-ddTHH\\:mm\\:sszzz"); } public static string ToISO8601(this DateTime? d) { if (d.HasValue) return d.Value.ToISO8601(); else return null; } } }