Как разобрать и преобразовать DateTime в формат даты и времени RFC 3339?

Как преобразовать структуру DateTime в ее эквивалентное строковое представление в формате RFC 3339 и / или проанализировать это строковое представление обратно в структуру DateTime ? Формат даты и времени RFC-3339 используется в ряде спецификаций, таких как формат синдикации атома .

19.08.2008 21:40:11
5 ОТВЕТОВ
РЕШЕНИЕ

Это реализация в C # того, как анализировать и преобразовывать DateTime в и из его представления RFC-3339. Единственное ограничение, которое он имеет, состоит в том, что DateTime находится в универсальном координированном времени (UTC).

using System;
using System.Globalization;

namespace DateTimeConsoleApplication
{
    /// <summary>
    /// Provides methods for converting <see cref="DateTime"/> structures to and from the equivalent RFC 3339 string representation.
    /// </summary>
    public static class Rfc3339DateTime
    {
        //============================================================
        //  Private members
        //============================================================
        #region Private Members
        /// <summary>
        /// Private member to hold array of formats that RFC 3339 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 3339 format.
        /// </summary>
        private const string format = "yyyy-MM-dd'T'HH:mm:ss.fffK";
        #endregion

        //============================================================
        //  Public Properties
        //============================================================
        #region Rfc3339DateTimeFormat
        /// <summary>
        /// Gets the custom format specifier that may be used to represent a <see cref="DateTime"/> in the RFC 3339 format.
        /// </summary>
        /// <value>A <i>DateTime format string</i> that may be used to represent a <see cref="DateTime"/> in the RFC 3339 format.</value>
        /// <remarks>
        /// <para>
        /// This method returns a string representation of a <see cref="DateTime"/> that 
        /// is precise to the three most significant digits of the seconds fraction; that is, it represents 
        /// the milliseconds in a date and time value. The <see cref="Rfc3339DateTimeFormat"/> is a valid 
        /// date-time format string for use in the <see cref="DateTime.ToString(String, IFormatProvider)"/> method.
        /// </para>
        /// </remarks>
        public static string Rfc3339DateTimeFormat
        {
            get
            {
                return format;
            }
        }
        #endregion

        #region Rfc3339DateTimePatterns
        /// <summary>
        /// Gets an array of the expected formats for RFC 3339 date-time string representations.
        /// </summary>
        /// <value>
        /// An array of the expected formats for RFC 3339 date-time string representations 
        /// that may used in the <see cref="DateTime.TryParseExact(String, string[], IFormatProvider, DateTimeStyles, out DateTime)"/> method.
        /// </value>
        public static string[] Rfc3339DateTimePatterns
        {
            get
            {
                if (formats.Length > 0)
                {
                    return formats;
                }
                else
                {
                    formats = new string[11];

                    // Rfc3339DateTimePatterns
                    formats[0] = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffK";
                    formats[1] = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ffffffK";
                    formats[2] = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffK";
                    formats[3] = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ffffK";
                    formats[4] = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffK";
                    formats[5] = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ffK";
                    formats[6] = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fK";
                    formats[7] = "yyyy'-'MM'-'dd'T'HH':'mm':'ssK";

                    // Fall back patterns
                    formats[8] = "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'fffffffK"; // RoundtripDateTimePattern
                    formats[9] = DateTimeFormatInfo.InvariantInfo.UniversalSortableDateTimePattern;
                    formats[10] = 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"/>.</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="FormatException"><paramref name="s"/> does not contain a valid RFC 3339 string representation of a date and time.</exception>
        public static DateTime Parse(string s)
        {
            //------------------------------------------------------------
            //  Validate parameter
            //------------------------------------------------------------
            if(s == null)
            {
                throw new ArgumentNullException("s");
            }

            DateTime result;
            if (Rfc3339DateTime.TryParse(s, out result))
            {
                return result;
            }
            else
            {
                throw new FormatException(String.Format(null, "{0} is not a valid RFC 3339 string representation of a date and time.", s));
            }
        }
        #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 3339 string representation of the value of the <paramref name="utcDateTime"/>.</returns>
        /// <remarks>
        /// <para>
        /// This method returns a string representation of the <paramref name="utcDateTime"/> that 
        /// is precise to the three most significant digits of the seconds fraction; that is, it represents 
        /// the milliseconds in a date and time value.
        /// </para>
        /// <para>
        /// While it is possible to display higher precision fractions of a second component of a time value, 
        /// that value may not be meaningful. The precision of date and time values depends on the resolution 
        /// of the system clock. On Windows NT 3.5 and later, and Windows Vista operating systems, the clock's 
        /// resolution is approximately 10-15 milliseconds.
        /// </para>
        /// </remarks>
        /// <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(Rfc3339DateTime.Rfc3339DateTimeFormat, 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"/>, 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(s, Rfc3339DateTime.Rfc3339DateTimePatterns, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.AdjustToUniversal, out parseResult))
                {
                    result          = DateTime.SpecifyKind(parseResult, DateTimeKind.Utc);
                    wasConverted    = true;
                }
            }

            return wasConverted;
        }
        #endregion
    }
}
16
19.08.2008 21:42:45
Зачем писать этот код для чего-то, что уже есть в BCL?
Matt Howells 1.04.2010 14:50:13
Должен согласиться с Мэттом здесь. RFC3339 не удовлетворяется ни одним из стандартных форматов DateTime.ToString - что удивительно - но XmlConvert делает свою работу. Например, я использую XmlConvert.ToString (value, XmlDateTimeSerializationMode.Utc)
Andrew Webb 5.03.2012 17:23:03
Привет @AndrewWebb, что если данные отформатированы вот 2015-05-04T10:08:15+00:00так. Я слышал, что это также считается RFC3339, но RFC3339не будет распознавать его как действительный DateTime, ни один из нихXmlDateTimeSerializationMode
Stoyan Dimov 4.05.2015 11:50:52
@StoyanDimov: var d = System.Xml.XmlConvert.ToDateTime("2015-05-04T10:08:15+00:00", System.Xml.XmlDateTimeSerializationMode.Utc);работает для меня.
Andrew Webb 5.05.2015 12:51:45
Спасибо за это, если вы используете .NET Core. XmlConvert недоступен.
wonea 21.10.2016 09:41:39

В .NET (при условии UTC):

 datetime.ToString("YYYY-MM-DD'T'HH:mm:ssZ")

DateTime.Parse()может быть использован для преобразования обратно в DateTimeструктуру.

0
5.03.2012 18:25:48
Не думайте, что «ГГГГ-ММ-ДД'ТХХ: мм: сс» может быть правильным; он не имеет смещения от UTC или «Z» (= смещение нуля от UTC).
Andrew Webb 2.03.2012 14:05:48
Это не сработало для меня. Я должен был использоватьdatetime.ToUniversalTime().ToString("yyyy-MM-dd'T'HH:mm:ssZ")
Tomáš Linhart 8.06.2016 21:29:50
Это работает только тогда, когда DateTime находится в часовом поясе UTC ( универсальное время ).
Mark Cidade 9.06.2016 00:20:20

Вам не нужно писать свой собственный код конверсии. Просто используйте

XmlConvert.ToDateTime(string s, XmlDateTimeSerializationMode dateTimeOption)

проанализировать строку RFC-3339 и

XmlConvert.ToString(DateTime value, XmlDateTimeSerializationMode dateTimeOption)

преобразовать дату и время (UTC) в строку.

Ссылка
http://msdn.microsoft.com/en-us/library/ms162342(v=vs.110).aspx
http://msdn.microsoft.com/en-us/library/ms162344(v=vs.110) .aspx

51
22.10.2014 14:50:02
Просто добавьте, что эта библиотека отлично работает при разборе и преобразовании дат из событий календаря Google в / из .NET Datetime
Yiannis Mpourkelis 3.12.2014 23:35:37

Простое уравнение сможет получить результат, который вы после:

rfcFormat = DateDiff("s", "1/1/1970", Now())
-3
12.04.2017 00:32:01

Для полноты картины, Newtonsoft.Json также с радостью сделает это:

JsonConvert.SerializeObject(DateTime.Now);

(В отличие от XmlConvert на каждом конце будут экранированные двойные кавычки.)

0
27.01.2020 14:27:43