00001
00034 #include "linden_common.h"
00035 #include "lldate.h"
00036
00037 #include "apr-1/apr_time.h"
00038
00039 #include <iomanip>
00040 #include <sstream>
00041
00042 static const F64 DATE_EPOCH = 0.0;
00043
00044 static const F64 LL_APR_USEC_PER_SEC = 1000000.0;
00045
00046
00047
00048
00049 LLDate::LLDate() : mSecondsSinceEpoch(DATE_EPOCH)
00050 {
00051 }
00052
00053 LLDate::LLDate(const LLDate& date) :
00054 mSecondsSinceEpoch(date.mSecondsSinceEpoch)
00055 {
00056 }
00057
00058 LLDate::LLDate(F64 seconds_since_epoch) :
00059 mSecondsSinceEpoch(seconds_since_epoch)
00060 {
00061 }
00062
00063 LLDate::LLDate(const std::string& iso8601_date)
00064 {
00065 if(!fromString(iso8601_date))
00066 {
00067 llwarns << "date " << iso8601_date << " failed to parse; "
00068 << "ZEROING IT OUT" << llendl;
00069 mSecondsSinceEpoch = DATE_EPOCH;
00070 }
00071 }
00072
00073 std::string LLDate::asString() const
00074 {
00075 std::ostringstream stream;
00076 toStream(stream);
00077 return stream.str();
00078 }
00079
00080
00081
00082
00083
00084
00085 std::string LLDate::asRFC1123() const
00086 {
00087 std::ostringstream stream;
00088 toHTTPDateStream(stream);
00089 return stream.str();
00090 }
00091
00092 void LLDate::toHTTPDateStream(std::ostream& s) const
00093 {
00094
00095 apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC);
00096
00097 apr_time_exp_t exp_time ;
00098
00099 if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS)
00100 {
00101
00102 s << "Thursday, 01 Jan 1970 00:00:00 GMT" ;
00103 return;
00104 }
00105
00106 s << std::dec << std::setfill('0');
00107 #if( LL_WINDOWS || __GNUC__ > 2)
00108 s << std::right ;
00109 #else
00110 s.setf(ios::right);
00111 #endif
00112 std::string day = weekdays[exp_time.tm_wday];
00113 std::string month = months[exp_time.tm_mon];
00114
00115 s << std::setw(day.length()) << (day)
00116 << ", " << std::setw(2) << (exp_time.tm_mday)
00117 << ' ' << std::setw(month.length()) << (month)
00118 << ' ' << std::setw(4) << (exp_time.tm_year + 1900)
00119 << ' ' << std::setw(2) << (exp_time.tm_hour)
00120 << ':' << std::setw(2) << (exp_time.tm_min)
00121 << ':' << std::setw(2) << (exp_time.tm_sec)
00122 << " GMT";
00123
00124
00125 llinfos << "Date in RFC 1123 format is " << s << llendl;
00126 }
00127
00128 void LLDate::toStream(std::ostream& s) const
00129 {
00130 apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC);
00131
00132 apr_time_exp_t exp_time;
00133 if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS)
00134 {
00135 s << "1970-01-01T00:00:00Z";
00136 return;
00137 }
00138
00139 s << std::dec << std::setfill('0');
00140 #if( LL_WINDOWS || __GNUC__ > 2)
00141 s << std::right;
00142 #else
00143 s.setf(ios::right);
00144 #endif
00145 s << std::setw(4) << (exp_time.tm_year + 1900)
00146 << '-' << std::setw(2) << (exp_time.tm_mon + 1)
00147 << '-' << std::setw(2) << (exp_time.tm_mday)
00148 << 'T' << std::setw(2) << (exp_time.tm_hour)
00149 << ':' << std::setw(2) << (exp_time.tm_min)
00150 << ':' << std::setw(2) << (exp_time.tm_sec);
00151 if (exp_time.tm_usec > 0)
00152 {
00153 s << '.' << std::setw(2)
00154 << (int)(exp_time.tm_usec / (LL_APR_USEC_PER_SEC / 100));
00155 }
00156 s << 'Z';
00157 }
00158
00159 bool LLDate::fromString(const std::string& iso8601_date)
00160 {
00161 std::istringstream stream(iso8601_date);
00162 return fromStream(stream);
00163 }
00164
00165 bool LLDate::fromStream(std::istream& s)
00166 {
00167 struct apr_time_exp_t exp_time;
00168 apr_int32_t tm_part;
00169 int c;
00170
00171 s >> tm_part;
00172 exp_time.tm_year = tm_part - 1900;
00173 c = s.get();
00174 if (c != '-') { return false; }
00175 s >> tm_part;
00176 exp_time.tm_mon = tm_part - 1;
00177 c = s.get();
00178 if (c != '-') { return false; }
00179 s >> tm_part;
00180 exp_time.tm_mday = tm_part;
00181
00182 c = s.get();
00183 if (c != 'T') { return false; }
00184
00185 s >> tm_part;
00186 exp_time.tm_hour = tm_part;
00187 c = s.get();
00188 if (c != ':') { return false; }
00189 s >> tm_part;
00190 exp_time.tm_min = tm_part;
00191 c = s.get();
00192 if (c != ':') { return false; }
00193 s >> tm_part;
00194 exp_time.tm_sec = tm_part;
00195
00196
00197 exp_time.tm_usec = 0;
00198 exp_time.tm_wday = 0;
00199 exp_time.tm_yday = 0;
00200 exp_time.tm_isdst = 0;
00201 exp_time.tm_gmtoff = 0;
00202
00203
00204 apr_time_t time;
00205 if (apr_time_exp_gmt_get(&time, &exp_time) != APR_SUCCESS)
00206 {
00207 return false;
00208 }
00209
00210 F64 seconds_since_epoch = time / LL_APR_USEC_PER_SEC;
00211
00212
00213 c = s.peek();
00214 if(c == '.')
00215 {
00216 F64 fractional = 0.0;
00217 s >> fractional;
00218 seconds_since_epoch += fractional;
00219 }
00220 c = s.get();
00221 if (c != 'Z') { return false; }
00222
00223 mSecondsSinceEpoch = seconds_since_epoch;
00224 return true;
00225 }
00226
00227 F64 LLDate::secondsSinceEpoch() const
00228 {
00229 return mSecondsSinceEpoch;
00230 }
00231
00232 void LLDate::secondsSinceEpoch(F64 seconds)
00233 {
00234 mSecondsSinceEpoch = seconds;
00235 }
00236
00237 std::ostream& operator<<(std::ostream& s, const LLDate& date)
00238 {
00239 date.toStream(s);
00240 return s;
00241 }
00242
00243 std::istream& operator>>(std::istream& s, LLDate& date)
00244 {
00245 date.fromStream(s);
00246 return s;
00247 }