lldate.cpp

Go to the documentation of this file.
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         // should be APR_USEC_PER_SEC, but that relies on INT64_C which
00046         // isn't defined in glib under our build set up for some reason
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 //@ brief Converts time in seconds since EPOCH
00081 //        to RFC 1123 compliant date format
00082 //        E.g. 1184797044.037586 == Wednesday, 18 Jul 2007 22:17:24 GMT
00083 //        in RFC 1123. HTTP dates are always in GMT and RFC 1123
00084 //        is one of the standards used and the prefered format
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     // http://apr.apache.org/docs/apr/0.9/group__apr__time.html
00095     apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC);
00096 
00097     apr_time_exp_t exp_time ; //Apache time module
00098 
00099     if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS)
00100     {
00101         // Return Epoch UTC date
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     // RFC 1123 date does not use microseconds
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(); // skip the hypen
00174         if (c != '-') { return false; }
00175         s >> tm_part;
00176         exp_time.tm_mon = tm_part - 1;
00177         c = s.get(); // skip the hypen
00178         if (c != '-') { return false; }
00179         s >> tm_part;
00180         exp_time.tm_mday = tm_part;
00181         
00182         c = s.get(); // skip the T
00183         if (c != 'T') { return false; }
00184         
00185         s >> tm_part;
00186         exp_time.tm_hour = tm_part;
00187         c = s.get(); // skip the :
00188         if (c != ':') { return false; }
00189         s >> tm_part;
00190         exp_time.tm_min = tm_part;
00191         c = s.get(); // skip the :
00192         if (c != ':') { return false; }
00193         s >> tm_part;
00194         exp_time.tm_sec = tm_part;
00195 
00196         // zero out the unused fields
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         // generate a time_t from that
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         // check for fractional
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(); // skip the Z
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 }

Generated on Fri May 16 08:32:02 2008 for SecondLife by  doxygen 1.5.5