using System; using Microsoft.SPOT; using IndianaJones.NETMF.String; namespace IndianaJones.NETMF.Time { public static class DateTimeExtensions { /// /// Converts a vCal or iCal date string into a DateTime object. /// /// /// public static DateTime FromiCalendar(string iCalendar) { DateTime dt = DateTime.MinValue; string result = string.Empty; if ((iCalendar.Contains("DTSTART")) || (iCalendar.Contains("DTEND"))) { result = iCalendar.Split(':')[1]; } else { result = iCalendar; } // Check to see if format contains the timezone ID, or contains UTC reference // Neither means it's localtime bool tzid = iCalendar.Contains("TZID"); bool utc = iCalendar.EndsWith("Z"); string tzName = string.Empty; string time = string.Empty; if (tzid) { string[] parts = iCalendar.Split(new char[] { ';', '=', ':' }); // parts[0] == DTSTART or DTEND // parts[1] == TZID // parts[2] == the timezone string // parts[3] == localtime string tzName = parts[2]; time = parts[3]; } else if (utc) { time = result.Substring(0, result.Length - 1); // truncate the trailing 'Z' } else { time = result; // localtime } // We now have the time string to parse, and we'll adjust // to UTC or timezone after parsing string year = time.Substring(0, 4); string month = time.Substring(4, 2); string day = time.Substring(6, 2); string hour = time.Substring(9, 2); string minute = time.Substring(11, 2); string second = time.Substring(13, 2); dt = new DateTime(Convert.ToInt32(year), Convert.ToInt32(month), Convert.ToInt32(day), Convert.ToInt32(hour), Convert.ToInt32(minute), Convert.ToInt32(second)); if (utc) { // Convert the Kind to DateTimeKind.Utc dt = new DateTime(0, DateTimeKind.Utc).AddTicks(dt.Ticks); } else if (tzid) { // not sure what to do here } return dt; } /// /// Converts an ISO 8601 time/date format string, which is used by JSON and others, /// into a DateTime object. /// /// /// public static DateTime FromIso8601(string date) { string result = string.Empty; // Check to see if format contains the timezone ID, or contains UTC reference // Neither means it's localtime bool utc = date.EndsWith("Z"); string[] parts = date.Split(new char[] { 'T', 'Z', ':', '-', '.', '+', }); string tzName = string.Empty; string time = string.Empty; // We now have the time string to parse, and we'll adjust // to UTC or timezone after parsing string year = parts[0]; string month = (parts.Length > 1) ? parts[1] : "1"; string day = (parts.Length > 2) ? parts[2] : "1"; string hour = (parts.Length > 3) ? parts[3] : "0"; string minute = (parts.Length > 4) ? parts[4] : "0"; string second = (parts.Length > 5) ? parts[5] : "0"; string ms = (parts.Length > 6) ? parts[6] : "0"; DateTime dt = new DateTime(Convert.ToInt32(year), Convert.ToInt32(month), Convert.ToInt32(day), Convert.ToInt32(hour), Convert.ToInt32(minute), Convert.ToInt32(second), Convert.ToInt32(ms)); // If a time offset was specified instead of the UTC marker, // add/subtract in the hours/minutes if ((utc == false) && (parts.Length >= 9)) { // There better be a timezone offset string hourOffset = (parts.Length > 7) ? parts[7] : ""; string minuteOffset = (parts.Length > 8) ? parts[8] : ""; if(date.Contains("+")) { dt = dt.AddHours(Convert.ToDouble(hourOffset)); dt = dt.AddMinutes(Convert.ToDouble(minuteOffset)); } else { dt = dt.AddHours(-(Convert.ToDouble(hourOffset))); dt = dt.AddMinutes(-(Convert.ToDouble(minuteOffset))); } } if(utc) { // Convert the Kind to DateTimeKind.Utc if string Z present dt = new DateTime(0, DateTimeKind.Utc).AddTicks(dt.Ticks); } return dt; } /// /// Converts a DateTime object into an ISO 8601 string. This version /// always returns the string in UTC format. /// /// /// public static string ToIso8601(DateTime dt) { string result = dt.Year.ToString() + "-" + TwoDigits(dt.Month) + "-" + TwoDigits(dt.Day) + "T" + TwoDigits(dt.Hour) + ":" + TwoDigits(dt.Minute) + ":" + TwoDigits(dt.Second) + "." + ThreeDigits(dt.Millisecond) + "Z"; return result; } /// /// Ensures a two-digit number with leading zero if necessary. /// /// /// private static string TwoDigits(int value) { if(value < 10) { return "0" + value.ToString(); } return value.ToString(); } /// /// Ensures a three-digit number with leading zeros if necessary. /// /// /// private static string ThreeDigits(int value) { if(value < 10) { return "00" + value.ToString(); } else if(value < 100) { return "0" + value.ToString(); } return value.ToString(); } /// /// The ASP.NET Ajax team made up their own time date format for JSON strings, and it's /// explained in this article: http://msdn.microsoft.com/en-us/library/bb299886.aspx /// Converts a DateTime to the ASP.NET Ajax JSON format. /// /// /// public static string ToASPNetAjax(DateTime dt) { string value = dt.Ticks.ToString(); return @"\/Date(" + value + @")\/"; } /// /// Converts an ASP.NET Ajaz JSON string to DateTime /// /// /// public static DateTime FromASPNetAjax(string ajax) { string[] parts = ajax.Split(new char[] { '(', ')' }); long ticks = Convert.ToInt64(parts[1]); // Create a Utc DateTime based on the tick count DateTime dt = new DateTime(ticks, DateTimeKind.Utc); return dt; } } }