yyyy parse example ejemplos .net datetime rss rfc822

.net - parse - ¿Cómo analizo y convierto DateTime al formato de fecha y hora RFC 822?



datetime.parse format dd/mm/yyyy (6)

¿Cómo convierto una estructura de DateTime a su representación de cadena formateada de fecha RFC 822 equivalente y analizo esta representación de cadena de nuevo a una estructura DateTime en .NET? El formato de fecha y hora RFC-822 se utiliza en varias especificaciones, como el formato de distribución de RSS .


Prueba esto:

DateTime today = DateTime.Now; String rfc822 = today.ToString("r"); Console.WriteLine("RFC-822 date: {0}", rfc822); DateTime parsedRFC822 = DateTime.Parse(rfc822); Console.WriteLine("Date: {0}", parsedRFC822);

El especificador de formato "r" pasado al método ToString () de DateTime realmente produce una cadena de fecha y hora formateada en RFC-1123, pero también pasa como una fecha RFC-822, basada en la lectura de la especificación encontrada en http: //www.w3. org / Protocols / rfc822 / # z28 . Utilicé este método para crear feeds RSS y aprobaron la validación basada en el validador disponible en http://validator.w3.org/feed/check.cgi .

La desventaja es que, en la conversión, convierte la fecha y hora a GMT. Para convertir de nuevo a la hora local, necesitaría aplicar su desplazamiento de zona horaria local. Para eso, puede usar la clase TimeZone para obtener su compensación de zona horaria actual, y reemplazar "GMT" con una cadena de compensación de zona horaria:

TimeZone tz = TimeZone.CurrentTimeZone; String offset = tz.GetUtcOffset().ToString(); // My locale is Mountain time; offset is set to "-07:00:00" // if local time is behind utc time, offset should start with "-". // otherwise, add a plus sign to the beginning of the string. if (!offset.StartsWith("-")) offset = "+" + offset; // Add a (+) if it''s a UTC+ timezone offset = offset.Substring(0,6); // only want the first 6 chars. offset = offset.Replace(":", ""); // remove colons. // offset now looks something like "-0700". rfc822 = rfc822.Replace("GMT", offset); // The rfc822 string can now be parsed back to a DateTime object, // with the local time accounted for. DateTime new = DateTime.Parse(rfc822);


Así es como Microsoft lo hace en Rss20FeedFormatter. El código de oposición no elimina el ":" en la porción de compensación GMT. Jeff Woodman parece hacer esto. El código siguiente también lo hace (si no usa Atom10FeedFormatter.zeroOffset).

private string AsString(DateTimeOffset dateTime) { if (dateTime.Offset == Atom10FeedFormatter.zeroOffset) { return dateTime.ToUniversalTime().ToString("ddd, dd MMM yyyy HH:mm:ss Z", CultureInfo.InvariantCulture); } StringBuilder builder = new StringBuilder(dateTime.T)oString("ddd, dd MMM yyyy HH:mm:ss zzz", CultureInfo.InvariantCulture)); builder.Remove(builder.Length - 3, 1); return builder.ToString(); }


Aquí está mi implementación usando un método de extensión:

namespace MyNamespace { public static partial class ExtensionMethods { public static string ToRFC822String(this DateTime timestamp) { return timestamp.ToString("ddd'','' d MMM yyyy HH'':''mm'':''ss") + " " + timestamp.ToString("zzzz").Replace(":", ""); } } }

Usar:

using MyNamespace; .... string MyRFC822String = DateTime.Now.ToRFC822String();


Esta es una implementación en C # de cómo analizar y convertir un DateTime desde y hacia su representación RFC-822. La única restricción que tiene es que DateTime está en hora universal coordinada (UTC). Estoy de acuerdo en que este código no es muy elegante, pero cumple su función.

/// <summary> /// Provides methods for converting <see cref="DateTime"/> structures /// to and from the equivalent <a href="http://www.w3.org/Protocols/rfc822/#z28">RFC 822</a> /// string representation. /// </summary> public class Rfc822DateTime { //============================================================ // Private members //============================================================ #region Private Members /// <summary> /// Private member to hold array of formats that RFC 822 date-time representations conform to. /// </summary> private static string[] formats = new string[0]; /// <summary> /// Private member to hold the DateTime format string for representing a DateTime in the RFC 822 format. /// </summary> private const string format = "ddd, dd MMM yyyy HH:mm:ss K"; #endregion //============================================================ // Public Properties //============================================================ #region Rfc822DateTimeFormat /// <summary> /// Gets the custom format specifier that may be used to represent a <see cref="DateTime"/> in the RFC 822 format. /// </summary> /// <value>A <i>DateTime format string</i> that may be used to represent a <see cref="DateTime"/> in the RFC 822 format.</value> /// <remarks> /// <para> /// This method returns a string representation of a <see cref="DateTime"/> that utilizes the time zone /// offset (local differential) to represent the offset from Greenwich mean time in hours and minutes. /// The <see cref="Rfc822DateTimeFormat"/> is a valid date-time format string for use /// in the <see cref="DateTime.ToString(String, IFormatProvider)"/> method. /// </para> /// <para> /// The <a href="http://www.w3.org/Protocols/rfc822/#z28">RFC 822</a> Date and Time specification /// specifies that the year will be represented as a two-digit value, but the /// <a href="http://www.rssboard.org/rss-profile#data-types-datetime">RSS Profile</a> recommends that /// all date-time values should use a four-digit year. The <see cref="Rfc822DateTime"/> class /// follows the RSS Profile recommendation when converting a <see cref="DateTime"/> to the equivalent /// RFC 822 string representation. /// </para> /// </remarks> public static string Rfc822DateTimeFormat { get { return format; } } #endregion #region Rfc822DateTimePatterns /// <summary> /// Gets an array of the expected formats for RFC 822 date-time string representations. /// </summary> /// <value> /// An array of the expected formats for RFC 822 date-time string representations /// that may used in the <see cref="DateTime.TryParseExact(String, string[], IFormatProvider, DateTimeStyles, out DateTime)"/> method. /// </value> /// <remarks> /// The array of the expected formats that is returned assumes that the RFC 822 time zone /// is represented as or converted to a local differential representation. /// </remarks> /// <seealso cref="ConvertZoneToLocalDifferential(String)"/> public static string[] Rfc822DateTimePatterns { get { if (formats.Length > 0) { return formats; } else { formats = new string[35]; // two-digit day, four-digit year patterns formats[0] = "ddd'','' dd MMM yyyy HH'':''mm'':''ss''.''fffffff zzzz"; formats[1] = "ddd'','' dd MMM yyyy HH'':''mm'':''ss''.''ffffff zzzz"; formats[2] = "ddd'','' dd MMM yyyy HH'':''mm'':''ss''.''fffff zzzz"; formats[3] = "ddd'','' dd MMM yyyy HH'':''mm'':''ss''.''ffff zzzz"; formats[4] = "ddd'','' dd MMM yyyy HH'':''mm'':''ss''.''fff zzzz"; formats[5] = "ddd'','' dd MMM yyyy HH'':''mm'':''ss''.''ff zzzz"; formats[6] = "ddd'','' dd MMM yyyy HH'':''mm'':''ss''.''f zzzz"; formats[7] = "ddd'','' dd MMM yyyy HH'':''mm'':''ss zzzz"; // two-digit day, two-digit year patterns formats[8] = "ddd'','' dd MMM yy HH'':''mm'':''ss''.''fffffff zzzz"; formats[9] = "ddd'','' dd MMM yy HH'':''mm'':''ss''.''ffffff zzzz"; formats[10] = "ddd'','' dd MMM yy HH'':''mm'':''ss''.''fffff zzzz"; formats[11] = "ddd'','' dd MMM yy HH'':''mm'':''ss''.''ffff zzzz"; formats[12] = "ddd'','' dd MMM yy HH'':''mm'':''ss''.''fff zzzz"; formats[13] = "ddd'','' dd MMM yy HH'':''mm'':''ss''.''ff zzzz"; formats[14] = "ddd'','' dd MMM yy HH'':''mm'':''ss''.''f zzzz"; formats[15] = "ddd'','' dd MMM yy HH'':''mm'':''ss zzzz"; // one-digit day, four-digit year patterns formats[16] = "ddd'','' d MMM yyyy HH'':''mm'':''ss''.''fffffff zzzz"; formats[17] = "ddd'','' d MMM yyyy HH'':''mm'':''ss''.''ffffff zzzz"; formats[18] = "ddd'','' d MMM yyyy HH'':''mm'':''ss''.''fffff zzzz"; formats[19] = "ddd'','' d MMM yyyy HH'':''mm'':''ss''.''ffff zzzz"; formats[20] = "ddd'','' d MMM yyyy HH'':''mm'':''ss''.''fff zzzz"; formats[21] = "ddd'','' d MMM yyyy HH'':''mm'':''ss''.''ff zzzz"; formats[22] = "ddd'','' d MMM yyyy HH'':''mm'':''ss''.''f zzzz"; formats[23] = "ddd'','' d MMM yyyy HH'':''mm'':''ss zzzz"; // two-digit day, two-digit year patterns formats[24] = "ddd'','' d MMM yy HH'':''mm'':''ss''.''fffffff zzzz"; formats[25] = "ddd'','' d MMM yy HH'':''mm'':''ss''.''ffffff zzzz"; formats[26] = "ddd'','' d MMM yy HH'':''mm'':''ss''.''fffff zzzz"; formats[27] = "ddd'','' d MMM yy HH'':''mm'':''ss''.''ffff zzzz"; formats[28] = "ddd'','' d MMM yy HH'':''mm'':''ss''.''fff zzzz"; formats[29] = "ddd'','' d MMM yy HH'':''mm'':''ss''.''ff zzzz"; formats[30] = "ddd'','' d MMM yy HH'':''mm'':''ss''.''f zzzz"; formats[31] = "ddd'','' d MMM yy HH'':''mm'':''ss zzzz"; // Fall back patterns formats[32] = "yyyy''-''MM''-''dd''T''HH'':''mm'':''ss''.''fffffffK"; // RoundtripDateTimePattern formats[33] = DateTimeFormatInfo.InvariantInfo.UniversalSortableDateTimePattern; formats[34] = DateTimeFormatInfo.InvariantInfo.SortableDateTimePattern; return formats; } } } #endregion //============================================================ // Public Methods //============================================================ #region Parse(string s) /// <summary> /// Converts the specified string representation of a date and time to its <see cref="DateTime"/> equivalent. /// </summary> /// <param name="s">A string containing a date and time to convert.</param> /// <returns> /// A <see cref="DateTime"/> equivalent to the date and time contained in <paramref name="s"/>, /// expressed as <i>Coordinated Universal Time (UTC)</i>. /// </returns> /// <remarks> /// The string <paramref name="s"/> is parsed using formatting information in the <see cref="DateTimeFormatInfo.InvariantInfo"/> object. /// </remarks> /// <exception cref="ArgumentNullException"><paramref name="s"/> is a <b>null</b> reference (Nothing in Visual Basic).</exception> /// <exception cref="ArgumentNullException"><paramref name="s"/> is an empty string.</exception> /// <exception cref="FormatException"><paramref name="s"/> does not contain a valid RFC 822 string representation of a date and time.</exception> public static DateTime Parse(string s) { //------------------------------------------------------------ // Validate parameter //------------------------------------------------------------ if (String.IsNullOrEmpty(s)) { throw new ArgumentNullException("s"); } DateTime result; if (Rfc822DateTime.TryParse(s, out result)) { return result; } else { throw new FormatException(String.Format(null, "{0} is not a valid RFC 822 string representation of a date and time.", s)); } } #endregion #region ConvertZoneToLocalDifferential(string s) /// <summary> /// Converts the time zone component of an RFC 822 date and time string representation to its local differential (time zone offset). /// </summary> /// <param name="s">A string containing an RFC 822 date and time to convert.</param> /// <returns>A date and time string that uses local differential to describe the time zone equivalent to the date and time contained in <paramref name="s"/>.</returns> /// <exception cref="ArgumentNullException"><paramref name="s"/> is a <b>null</b> reference (Nothing in Visual Basic).</exception> /// <exception cref="ArgumentNullException"><paramref name="s"/> is an empty string.</exception> public static string ConvertZoneToLocalDifferential(string s) { string zoneRepresentedAsLocalDifferential = String.Empty; //------------------------------------------------------------ // Validate parameter //------------------------------------------------------------ if (String.IsNullOrEmpty(s)) { throw new ArgumentNullException("s"); } if(s.EndsWith(" UT", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" UT") + 1) ), "+00:00"); } else if (s.EndsWith(" GMT", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" GMT") + 1 ) ), "+00:00"); } else if (s.EndsWith(" EST", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" EST") + 1)), "-05:00"); } else if (s.EndsWith(" EDT", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" EDT") + 1)), "-04:00"); } else if (s.EndsWith(" CST", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" CST") + 1)), "-06:00"); } else if (s.EndsWith(" CDT", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" CDT") + 1)), "-05:00"); } else if (s.EndsWith(" MST", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" MST") + 1)), "-07:00"); } else if (s.EndsWith(" MDT", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" MDT") + 1)), "-06:00"); } else if (s.EndsWith(" PST", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" PST") + 1)), "-08:00"); } else if (s.EndsWith(" PDT", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" PDT") + 1)), "-07:00"); } else if (s.EndsWith(" Z", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" Z") + 1)), "+00:00"); } else if (s.EndsWith(" A", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" A") + 1)), "-01:00"); } else if (s.EndsWith(" M", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" M") + 1)), "-12:00"); } else if (s.EndsWith(" N", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" N") + 1)), "+01:00"); } else if (s.EndsWith(" Y", StringComparison.OrdinalIgnoreCase)) { zoneRepresentedAsLocalDifferential = String.Concat(s.Substring(0, (s.LastIndexOf(" Y") + 1)), "+12:00"); } else { zoneRepresentedAsLocalDifferential = s; } return zoneRepresentedAsLocalDifferential; } #endregion #region ToString(DateTime utcDateTime) /// <summary> /// Converts the value of the specified <see cref="DateTime"/> object to its equivalent string representation. /// </summary> /// <param name="utcDateTime">The Coordinated Universal Time (UTC) <see cref="DateTime"/> to convert.</param> /// <returns>A RFC 822 string representation of the value of the <paramref name="utcDateTime"/>.</returns> /// <exception cref="ArgumentException">The specified <paramref name="utcDateTime"/> object does not represent a <see cref="DateTimeKind.Utc">Coordinated Universal Time (UTC)</see> value.</exception> public static string ToString(DateTime utcDateTime) { if (utcDateTime.Kind != DateTimeKind.Utc) { throw new ArgumentException("utcDateTime"); } return utcDateTime.ToString(Rfc822DateTime.Rfc822DateTimeFormat, DateTimeFormatInfo.InvariantInfo); } #endregion #region TryParse(string s, out DateTime result) /// <summary> /// Converts the specified string representation of a date and time to its <see cref="DateTime"/> equivalent. /// </summary> /// <param name="s">A string containing a date and time to convert.</param> /// <param name="result"> /// When this method returns, contains the <see cref="DateTime"/> value equivalent to the date and time /// contained in <paramref name="s"/>, expressed as <i>Coordinated Universal Time (UTC)</i>, /// if the conversion succeeded, or <see cref="DateTime.MinValue">MinValue</see> if the conversion failed. /// The conversion fails if the s parameter is a <b>null</b> reference (Nothing in Visual Basic), /// or does not contain a valid string representation of a date and time. /// This parameter is passed uninitialized. /// </param> /// <returns><b>true</b> if the <paramref name="s"/> parameter was converted successfully; otherwise, <b>false</b>.</returns> /// <remarks> /// The string <paramref name="s"/> is parsed using formatting information in the <see cref="DateTimeFormatInfo.InvariantInfo"/> object. /// </remarks> public static bool TryParse(string s, out DateTime result) { //------------------------------------------------------------ // Attempt to convert string representation //------------------------------------------------------------ bool wasConverted = false; result = DateTime.MinValue; if (!String.IsNullOrEmpty(s)) { DateTime parseResult; if (DateTime.TryParseExact(Rfc822DateTime.ConvertZoneToLocalDifferential(s), Rfc822DateTime.Rfc822DateTimePatterns, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AdjustToUniversal, out parseResult)) { result = DateTime.SpecifyKind(parseResult, DateTimeKind.Utc); wasConverted = true; } } return wasConverted; } #endregion }


Siguiendo la idea de Kirk, descompilé fuentes para la clase System.ServiceModel.Syndication.Rss20FeedFormatter ( System.ServiceModel.dll ) y aquí está el analizador interno de Microsoft para el formato de fechas RFC 822 (simplifiqué un poco su lógica de manejo de excepciones para reducir las dependencias):

public static class DateTimeParser { public static DateTimeOffset ParseDateTimeRFC822(string dateTimeString) { StringBuilder dateTimeStringBuilder = new StringBuilder(dateTimeString.Trim()); if (dateTimeStringBuilder.Length < 18) { throw new FormatException("Invalid date format. Expected date in RFC 822 format"); } if (dateTimeStringBuilder[3] == '','') { // There is a leading (e.g.) "Tue, ", strip it off dateTimeStringBuilder.Remove(0, 4); // There''s supposed to be a space here but some implementations dont have one RemoveExtraWhiteSpaceAtStart(dateTimeStringBuilder); } ReplaceMultipleWhiteSpaceWithSingleWhiteSpace(dateTimeStringBuilder); if (char.IsDigit(dateTimeStringBuilder[1])) { // two-digit day, we are good } else { dateTimeStringBuilder.Insert(0, ''0''); } if (dateTimeStringBuilder.Length < 19) { throw new FormatException("Invalid date format. Expected date in RFC 822 format"); } bool thereAreSeconds = (dateTimeStringBuilder[17] == '':''); int timeZoneStartIndex; if (thereAreSeconds) { timeZoneStartIndex = 21; } else { timeZoneStartIndex = 18; } string timeZoneSuffix = dateTimeStringBuilder.ToString().Substring(timeZoneStartIndex); dateTimeStringBuilder.Remove(timeZoneStartIndex, dateTimeStringBuilder.Length - timeZoneStartIndex); bool isUtc; dateTimeStringBuilder.Append(NormalizeTimeZone(timeZoneSuffix, out isUtc)); string wellFormattedString = dateTimeStringBuilder.ToString(); DateTimeOffset theTime; string parseFormat; if (thereAreSeconds) { parseFormat = "dd MMM yyyy HH:mm:ss zzz"; } else { parseFormat = "dd MMM yyyy HH:mm zzz"; } if (DateTimeOffset.TryParseExact(wellFormattedString, parseFormat, CultureInfo.InvariantCulture.DateTimeFormat, (isUtc ? DateTimeStyles.AdjustToUniversal : DateTimeStyles.None), out theTime)) { return theTime; } throw new FormatException("Invalid date format. Expected date in RFC 822 format"); } static string NormalizeTimeZone(string rfc822TimeZone, out bool isUtc) { isUtc = false; // return a string in "-08:00" format if (rfc822TimeZone[0] == ''+'' || rfc822TimeZone[0] == ''-'') { // the time zone is supposed to be 4 digits but some feeds omit the initial 0 StringBuilder result = new StringBuilder(rfc822TimeZone); if (result.Length == 4) { // the timezone is +/-HMM. Convert to +/-HHMM result.Insert(1, ''0''); } result.Insert(3, '':''); return result.ToString(); } switch (rfc822TimeZone) { case "UT": case "Z": isUtc = true; return "-00:00"; case "GMT": return "-00:00"; case "A": return "-01:00"; case "B": return "-02:00"; case "C": return "-03:00"; case "D": case "EDT": return "-04:00"; case "E": case "EST": case "CDT": return "-05:00"; case "F": case "CST": case "MDT": return "-06:00"; case "G": case "MST": case "PDT": return "-07:00"; case "H": case "PST": return "-08:00"; case "I": return "-09:00"; case "K": return "-10:00"; case "L": return "-11:00"; case "M": return "-12:00"; case "N": return "+01:00"; case "O": return "+02:00"; case "P": return "+03:00"; case "Q": return "+04:00"; case "R": return "+05:00"; case "S": return "+06:00"; case "T": return "+07:00"; case "U": return "+08:00"; case "V": return "+09:00"; case "W": return "+10:00"; case "X": return "+11:00"; case "Y": return "+12:00"; default: return ""; } } static void RemoveExtraWhiteSpaceAtStart(StringBuilder stringBuilder) { int i = 0; while (i < stringBuilder.Length) { if (!char.IsWhiteSpace(stringBuilder[i])) { break; } ++i; } if (i > 0) { stringBuilder.Remove(0, i); } } static void ReplaceMultipleWhiteSpaceWithSingleWhiteSpace(StringBuilder builder) { int index = 0; int whiteSpaceStart = -1; while (index < builder.Length) { if (char.IsWhiteSpace(builder[index])) { if (whiteSpaceStart < 0) { whiteSpaceStart = index; // normalize all white spaces to be '' '' so that the date time parsing works builder[index] = '' ''; } } else if (whiteSpaceStart >= 0) { if (index > whiteSpaceStart + 1) { // there are at least 2 spaces... replace by 1 builder.Remove(whiteSpaceStart, index - whiteSpaceStart - 1); index = whiteSpaceStart + 1; } whiteSpaceStart = -1; } ++index; } // we have already trimmed the start and end so there cannot be a trail of white spaces in the end Debug.Assert(builder.Length == 0 || builder[builder.Length - 1] != '' '', "The string builder doesnt end in a white space"); } }

Lo primero que puede parecer inusual es que devuelven la clase [DateTimeOffset][1] lugar de DateTime . Pero cuando leemos más sobre esto, parece ser completamente lógico: DateTimeOffset almacena información de fecha, hora y zona horaria (exactamente como la cadena en formato RFC 822). Si devolviera el objeto DateTime, en qué zona horaria estaría : UTC, local o el especificado en la cadena analizada, cualquier respuesta sería incorrecta en algunos casos. Entonces DateTimeOffset resuelve un importante problema de incertidumbre. Y puede convertirlo a la zona horaria que necesite más adelante utilizando los métodos DateTimeOffset.ToUniversalTime() , DateTimeOffset.ToLocalTime() .

Lo probé en algunos casos y parece que hace el trabajo a la perfección.

Sin embargo, no estoy seguro de por qué Microsoft decidió hacer esta implementación privada; no parece necesitar mucho apoyo.


Basado en la respuesta de Kirk Liemohn, utilicé este método con éxito:

private DateTimeOffset? ParseDate(string date) { const string FORMAT = "ddd, d MMM yyyy HH:mm:ss zzz"; const string FORMAT2 = "ddd, dd MMM yyyy HH:mm:ss zzz"; const string FORMAT3 = "dd MMM yyyy HH:mm:ss zzz"; const string FORMAT4 = "d MMM yyyy HH:mm:ss zzz"; DateTimeOffset d; if (DateTimeOffset.TryParseExact(date, new string[] { FORMAT, FORMAT2, FORMAT3, FORMAT4 }, CultureInfo.InvariantCulture, DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite, out d)) return d; return null; }

Ejemplo:

DateTimeOffset? date = ParseDate("Thu, 5 Apr 2012 23:47:37 +0200"); Console.WriteLine(date.ToString()); // => 05/04/2012 23:47:37 +02:00

No respeta la especificación completa de RFC, pero funciona para mis casos de uso.

Específicamente, no funciona con timezone express como: "GMT", "CST", etc. (ver "zona" en RFC822 Sección 5.1 ). Vea la mejor respuesta de Oleksandr Pshenychnyy .