date_time.h 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Copyright (C) 2016 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #ifndef HTTP_DATE_TIME_H
  7. #define HTTP_DATE_TIME_H
  8. #include <exceptions/exceptions.h>
  9. #include <boost/date_time/posix_time/posix_time.hpp>
  10. #include <string>
  11. namespace isc {
  12. namespace http {
  13. /// @brief Exception thrown when there is an error during time conversion.
  14. ///
  15. /// The most common reason for this exception is that the unsupported time
  16. /// format was used as an input to the time parsing functions.
  17. class HttpTimeConversionError : public Exception {
  18. public:
  19. HttpTimeConversionError(const char* file, size_t line, const char* what) :
  20. isc::Exception(file, line, what) { };
  21. };
  22. /// @brief This class parses and generates time values used in HTTP.
  23. ///
  24. /// The HTTP protocol have historically allowed 3 different date/time formats
  25. /// (see https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html). These are:
  26. /// - Sun, 06 Nov 1994 08:49:37 GMT
  27. /// - Sunday, 06-Nov-94 08:49:37 GMT
  28. /// - Sun Nov 6 08:49:37 1994
  29. ///
  30. /// The first format is preferred but implementations must also support
  31. /// remaining two obsolete formats for compatibility. This class implements
  32. /// parsers and generators for all three formats. It uses @c boost::posix_time
  33. /// to represent time and date. It uses @ref boost::date_time::time_facet
  34. /// and @ref boost::date_time::time_input_facet to generate and parse the
  35. /// timestamps.
  36. class HttpDateTime {
  37. public:
  38. /// @brief Default constructor.
  39. ///
  40. /// Sets current universal time as time value.
  41. HttpDateTime();
  42. /// @brief Construct from @ref boost::posix_time::ptime object.
  43. ///
  44. /// @param t time value to be set.
  45. explicit HttpDateTime(const boost::posix_time::ptime& t);
  46. /// @brief Returns time encapsulated by this class.
  47. ///
  48. /// @return @ref boost::posix_time::ptime value encapsulated by the instance
  49. /// of this class.
  50. boost::posix_time::ptime getPtime() const {
  51. return (time_);
  52. }
  53. /// @brief Returns time value formatted as specified in RFC 1123.
  54. ///
  55. /// @return A string containing time value formatted as
  56. /// Sun, 06 Nov 1994 08:49:37 GMT.
  57. std::string rfc1123Format() const;
  58. /// @brief Returns time value formatted as specified in RFC 850.
  59. ///
  60. /// @return A string containing time value formatted as
  61. /// Sunday, 06-Nov-94 08:49:37 GMT.
  62. std::string rfc850Format() const;
  63. /// @brief Returns time value formatted as output of ANSI C's
  64. /// asctime().
  65. ///
  66. /// @return A string containing time value formatted as
  67. /// Sun Nov 6 08:49:37 1994.
  68. std::string asctimeFormat() const;
  69. /// @brief Creates an instance from a string containing time value
  70. /// formatted as specified in RFC 1123.
  71. ///
  72. /// @param time_string Input string holding formatted time value.
  73. /// @return Instance of @ref HttpDateTime.
  74. /// @throw HttpTimeConversionError if provided timestamp has invalid
  75. /// format.
  76. static HttpDateTime fromRfc1123(const std::string& time_string);
  77. /// @brief Creates an instance from a string containing time value
  78. /// formatted as specified in RFC 850.
  79. ///
  80. /// @param time_string Input string holding formatted time value.
  81. /// @return Instance of @ref HttpDateTime.
  82. /// @throw HttpTimeConversionError if provided timestamp has invalid
  83. /// format.
  84. static HttpDateTime fromRfc850(const std::string& time_string);
  85. /// @brief Creates an instance from a string containing time value
  86. /// formatted as output from asctime() function.
  87. ///
  88. /// @param time_string Input string holding formatted time value.
  89. /// @return Instance of @ref HttpDateTime.
  90. /// @throw HttpTimeConversionError if provided timestamp has invalid
  91. /// format.
  92. static HttpDateTime fromAsctime(const std::string& time_string);
  93. /// @brief Creates an instance from a string containing time value
  94. /// formatted in one of the supported formats.
  95. ///
  96. /// This method will detect the format of the time value and parse it.
  97. /// It tries parsing the value in the following order:
  98. /// - a format specified in RFC 1123,
  99. /// - a format specified in RFC 850,
  100. /// - a format of asctime output.
  101. ///
  102. /// @param time_string Input string holding formatted time value.
  103. /// @return Instance of @ref HttpDateTime.
  104. /// @throw HttpTimeConversionError if provided value doesn't match any
  105. /// of the supported formats.
  106. static HttpDateTime fromAny(const std::string& time_string);
  107. private:
  108. /// @brief Generic method formatting a time value to a specified format.
  109. ////
  110. /// @param format Time format as accepted by the
  111. /// @c boost::date_time::time_facet.
  112. std::string toString(const std::string& format,
  113. const std::string& method_name) const;
  114. /// @brief Generic method parsing time value and converting it to the
  115. /// instance of @c boost::posix_time::ptime.
  116. ///
  117. /// @param time_string Input string holding formatted time value.
  118. /// @param format Time format as accepted by the
  119. /// @c boost::date_time::time_input_facet.
  120. /// @param method_name Name of the expected format to appear in the error
  121. /// message if parsing fails, e.g. RFC 1123, RFC 850 or asctime.
  122. /// @param zone_check Indicates if the time zone name should be validated
  123. /// during parsing. This should be set to false for the formats which
  124. /// lack time zones (e.g. asctime).
  125. ///
  126. /// @return Instance of the @ref boost::posix_time::ptime created from the
  127. /// input string.
  128. /// @throw HttpTimeConversionError if provided value doesn't match the
  129. /// specified format.
  130. static boost::posix_time::ptime
  131. fromString(const std::string& time_string, const std::string& format,
  132. const std::string& method_name, const bool zone_check = true);
  133. /// @brief Time value encapsulated by this class instance.
  134. boost::posix_time::ptime time_;
  135. };
  136. } // namespace http
  137. } // namespace isc
  138. #endif