Kea 3.1.5
date_time.cc
Go to the documentation of this file.
1// Copyright (C) 2016-2025 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
7#include <config.h>
8
9#include <http/date_time.h>
10
11#include <locale>
12#include <sstream>
13
14#ifdef __GNUC__
15#pragma GCC diagnostic push
16#pragma GCC diagnostic ignored "-Wdeprecated-copy"
17#endif
18#include <boost/date_time/local_time/local_time.hpp>
19#ifdef __GNUC__
20#pragma GCC diagnostic pop
21#endif
22#include <boost/date_time/time_facet.hpp>
23
24using namespace boost::local_time;
25using namespace boost::posix_time;
26
27namespace isc {
28namespace http {
29
31 : time_(boost::posix_time::second_clock::universal_time()) {
32}
33
34HttpDateTime::HttpDateTime(const boost::posix_time::ptime& t)
35 : time_(t) {
36}
37
38std::string
40 return (toString("%a, %d %b %Y %H:%M:%S GMT", "RFC 1123"));
41}
42
43std::string
45 return (toString("%A, %d-%b-%y %H:%M:%S GMT", "RFC 850"));
46}
47
48std::string
50 return (toString("%a %b %e %H:%M:%S %Y", "asctime"));
51}
52
54HttpDateTime::fromRfc1123(const std::string& time_string) {
55 return (HttpDateTime(fromString(time_string,
56 "%a, %d %b %Y %H:%M:%S %ZP",
57 "RFC 1123")));
58}
59
61HttpDateTime::fromRfc850(const std::string& time_string) {
62 return (HttpDateTime(fromString(time_string,
63 "%A, %d-%b-%y %H:%M:%S %ZP",
64 "RFC 850")));
65}
66
68HttpDateTime::fromAsctime(const std::string& time_string) {
69 // The asctime() puts space instead of leading 0 in days of
70 // month. The %e # formatter of time_input_facet doesn't deal
71 // with this. To deal with this, we make a copy of the string
72 // holding formatted time and replace a space preceding day
73 // number with 0. Thanks to this workaround we can use the
74 // %d formatter which seems to work fine. This has a side
75 // effect of accepting timestamps such as Sun Nov 06 08:49:37 1994,
76 // but it should be ok to be liberal in this case.
77 std::string time_string_copy(time_string);
78 boost::replace_all(time_string_copy, " ", " 0");
79 return (HttpDateTime(fromString(time_string_copy,
80 "%a %b %d %H:%M:%S %Y",
81 "asctime",
82 false)));
83}
84
86HttpDateTime::fromAny(const std::string& time_string) {
87 HttpDateTime date_time;
88 // Try to parse as a timestamp specified in RFC 1123 format.
89 try {
90 date_time = fromRfc1123(time_string);
91 return (date_time);
92 } catch (...) {
93 // Ignore errors, simply try different format.
94 }
95
96 // Try to parse as a timestamp specified in RFC 850 format.
97 try {
98 date_time = fromRfc850(time_string);
99 return (date_time);
100 } catch (...) {
101 // Ignore errors, simply try different format.
102 }
103
104 // Try to parse as a timestamp output by asctime() function.
105 try {
106 date_time = fromAsctime(time_string);
107 } catch (...) {
109 "unsupported time format of the '" << time_string
110 << "'");
111 }
112
113 return (date_time);
114
115}
116
117std::string
118HttpDateTime::toString(const std::string& format,
119 const std::string& method_name) const {
120 std::ostringstream s;
121 // Create raw pointer. The output stream will take responsibility for
122 // deleting the object.
123 time_facet* df(new time_facet(format.c_str()));
124 s.imbue(std::locale(std::locale::classic(), df));
125
126 // Convert time value to a string.
127 s << time_;
128 if (s.fail()) {
129 isc_throw(HttpTimeConversionError, "unable to convert "
130 << "time value of '" << time_ << "'"
131 << " to " << method_name << " format");
132 }
133 return (s.str());
134}
135
136
137ptime
138HttpDateTime::fromString(const std::string& time_string,
139 const std::string& format,
140 const std::string& method_name,
141 const bool zone_check) {
142 std::istringstream s(time_string);
143 // Create raw pointer. The input stream will take responsibility for
144 // deleting the object.
145 time_input_facet* tif(new time_input_facet(format));
146 s.imbue(std::locale(std::locale::classic(), tif));
147
148 time_zone_ptr zone(new posix_time_zone("GMT"));
149 local_date_time ldt = local_microsec_clock::local_time(zone);
150
151 // Parse the time value. The stream will not automatically detect whether
152 // the zone is GMT. We need to check it on our own.
153 s >> ldt;
154 if (s.fail() ||
155 (zone_check && (!ldt.zone() ||
156 ldt.zone()->std_zone_abbrev() != "GMT"))) {
157 isc_throw(HttpTimeConversionError, "unable to parse "
158 << method_name << " time value of '"
159 << time_string << "'");
160 }
161
162 return (ldt.local_time());
163}
164
165
166} // namespace http
167} // namespace isc
This class parses and generates time values used in HTTP.
Definition date_time.h:41
std::string rfc1123Format() const
Returns time value formatted as specified in RFC 1123.
Definition date_time.cc:39
HttpDateTime()
Default constructor.
Definition date_time.cc:30
std::string asctimeFormat() const
Returns time value formatted as output of ANSI C's asctime().
Definition date_time.cc:49
static HttpDateTime fromRfc850(const std::string &time_string)
Creates an instance from a string containing time value formatted as specified in RFC 850.
Definition date_time.cc:61
static HttpDateTime fromRfc1123(const std::string &time_string)
Creates an instance from a string containing time value formatted as specified in RFC 1123.
Definition date_time.cc:54
std::string rfc850Format() const
Returns time value formatted as specified in RFC 850.
Definition date_time.cc:44
static HttpDateTime fromAsctime(const std::string &time_string)
Creates an instance from a string containing time value formatted as output from asctime() function.
Definition date_time.cc:68
static HttpDateTime fromAny(const std::string &time_string)
Creates an instance from a string containing time value formatted in one of the supported formats.
Definition date_time.cc:86
Exception thrown when there is an error during time conversion.
Definition date_time.h:21
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Defines the logger used by the top-level component of kea-lfc.