PLearn 0.1
|
00001 // -*- C++ -*- 00002 00003 // PDateTime 00004 // Copyright (c) 2002 by Nicolas Chapados 00005 00006 // Redistribution and use in source and binary forms, with or without 00007 // modification, are permitted provided that the following conditions are met: 00008 // 00009 // 1. Redistributions of source code must retain the above copyright 00010 // notice, this list of conditions and the following disclaimer. 00011 // 00012 // 2. Redistributions in binary form must reproduce the above copyright 00013 // notice, this list of conditions and the following disclaimer in the 00014 // documentation and/or other materials provided with the distribution. 00015 // 00016 // 3. The name of the authors may not be used to endorse or promote 00017 // products derived from this software without specific prior written 00018 // permission. 00019 // 00020 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 00021 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00022 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN 00023 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00024 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00025 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00026 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00027 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00028 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00029 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00030 // 00031 // This file is part of the PLearn library. For more information on the PLearn 00032 // library, go to the PLearn Web site at www.plearn.org 00033 00034 /* ******************************************************* 00035 * $Id: PDateTime.cc 6351 2006-10-25 19:05:45Z chapados $ 00036 * This file is part of the PLearn library. 00037 ******************************************************* */ 00038 00039 //#include <limits.h> // from stdc 00040 #include "PDateTime.h" 00041 #include <plearn/base/stringutils.h> 00042 #include <plearn/base/lexical_cast.h> // for toint 00043 #include <plearn/base/tostring.h> 00044 #include "general.h" // for MISSING_VALUE 00045 00046 namespace PLearn { 00047 using namespace std; 00048 00049 PDateTime::PDateTime() 00050 { 00051 setMissing(); 00052 } 00053 00054 PDateTime::PDateTime(double julian_day) 00055 { 00056 int jw = (int)((julian_day - 1867216.25)/36524.25); 00057 int jx = (int)(jw/4); 00058 int ja = (int)(julian_day + 1 + jw - jx); 00059 int jb = ja + 1524; 00060 int jc = (int)((jb - 122.1)/365.25); 00061 int jd = (int)(365.25*jc); 00062 int je = (int)((jb - jd)/30.6001); 00063 int jf = (int)(30.6001*je); 00064 00065 day = jb - jd - jf; 00066 month = (je>13) ? je-13 : je-1; 00067 year = (month>2) ? jc-4716 : jc-4715; 00068 00069 double fraction = julian_day - floor(julian_day); 00070 int hh,mm,ss; 00071 double_to_hhmmss(fraction,hh,mm,ss); 00072 hour = hh; 00073 min = mm; 00074 sec = ss; 00075 } 00076 00077 PDateTime::PDateTime(string date) 00078 { 00079 // Parse either "YYYY/MM/DD" or "YYYY/MM/DD hh:mm:ss" format 00080 if ((date.size() == 10 || date.size() == 19) && 00081 date[4] == '/' && date[7] == '/' && 00082 (date.size() == 19? date[13] == ':' && date[16] == ':' : true)) { 00083 year = toint(date.substr(0,4)); 00084 month = toint(date.substr(5,2)); 00085 day = toint(date.substr(8,2)); 00086 if (date.size() == 10) 00087 hour = min = sec = 0; 00088 else { 00089 hour = toint(date.substr(11,2)); 00090 min = toint(date.substr(14,2)); 00091 sec = toint(date.substr(17,2)); 00092 } 00093 } 00094 else 00095 PLERROR("PDateTime::PDateTime: the passed date-time string is not in " 00096 "\"YYYY/MM/DD\" or \"YYYY/MM/DD hh:mm:ss\" format"); 00097 } 00098 00100 // isMissing // 00102 bool PDateTime::isMissing() const 00103 { 00104 return year == SHRT_MIN && month == 0 && day == 0; 00105 } 00106 00108 // setMissing // 00110 void PDateTime::setMissing() 00111 { 00112 year = SHRT_MIN; 00113 month = 0; 00114 day = 0; 00115 } 00116 00118 // incSecond // 00120 void PDateTime::incSecond(int sec_inc) 00121 { 00122 int new_sec = int(sec) + sec_inc; 00123 int min_inc = new_sec / 60; 00124 sec = (unsigned char) (new_sec % 60); 00125 incMinute(min_inc); 00126 } 00127 00129 // incMinute // 00131 void PDateTime::incMinute(int min_inc) 00132 { 00133 int new_min = int(min) + min_inc; 00134 int hour_inc = new_min / 60; 00135 min = (unsigned char) (new_min % 60); 00136 incHour(hour_inc); 00137 } 00138 00140 // incHour // 00142 void PDateTime::incHour(int hour_inc) 00143 { 00144 int new_hour = int(hour) + hour_inc; 00145 int day_inc = new_hour / 24; 00146 hour = (unsigned char) (new_hour % 24); 00147 incDay(day_inc); 00148 } 00149 00151 // incDay // 00153 void PDateTime::incDay(int day_inc) 00154 { 00155 PLASSERT( day_inc >= 0 ); 00156 int new_day = int(day) + day_inc; 00157 int max_day = 31; 00158 if (month == 2) { 00159 if (year < 1900 || year > 2100) 00160 PLERROR("In PDateTime::incDay - This code is probably not going to" 00161 " work for year %d", int(year)); 00162 max_day = year % 4 == 0 ? 29 : 28; 00163 } else if (month == 4 || month == 6 || month == 9 || month == 11) 00164 max_day = 30; 00165 if (new_day <= max_day) { 00166 day = (unsigned char) new_day; 00167 return; 00168 } 00169 // We need to switch to next month. 00170 PLASSERT( max_day >= int(day) ); 00171 int days_to_next_month = max_day - int(day) + 1; 00172 month++; 00173 if (month == 13) { 00174 // We need to switch to next year. 00175 year++; 00176 month = 1; 00177 } 00178 day = 1; 00179 incDay(day_inc - days_to_next_month); 00180 } 00181 00183 // info // 00185 string PDateTime::info() const 00186 { 00187 return tostring(year)+ slash+ 00188 right(tostring(int(month)), 2, '0') + slash+ 00189 right(tostring(int(day)), 2, '0') + " "+ 00190 right(tostring(int(hour)), 2, '0') + ":"+ 00191 right(tostring(int(min)), 2, '0') + ":"+ 00192 right(tostring(int(sec)), 2, '0'); 00193 } 00194 00196 // currentLocalTime // 00198 PDateTime PDateTime::currentLocalTime() { 00199 time_t current; 00200 tm* ptr; 00201 time(¤t); 00202 ptr = ::localtime(¤t); 00203 return PDateTime(ptr->tm_year + 1900, ptr->tm_mon + 1, ptr->tm_mday, 00204 ptr->tm_hour, ptr->tm_min, ptr->tm_sec); 00205 } 00206 00208 // toJulianDay // 00210 double PDateTime::toJulianDay() const 00211 { 00212 if (year < 1582) 00213 PLERROR("toJulianDay works safely only for year > 1581 (%d)", year); 00214 00215 double fraction = hhmmss_to_double(hour,min,sec); 00216 00217 int jy = (month>2) ? year : year-1; 00218 int jm = (month>2) ? month : month+12; 00219 int ja = (int)(jy/100); 00220 int jb = (int)(ja/4); 00221 int jc = 2 - ja + jb; 00222 int je = (int)(365.25*(jy + 4716)); 00223 int jf = (int)(30.6001*(jm + 1)); 00224 00225 return jc + day + je + jf - 1524 + fraction; 00226 } 00227 00228 double datetime_to_double(const PDateTime& t) 00229 { 00230 if (t.isMissing()) 00231 return MISSING_VALUE; 00232 else 00233 return double((t.year-1900)*10000 + t.month*100 + t.day) + 00234 hhmmss_to_double(t.hour,t.min,t.sec); 00235 } 00236 00237 PDateTime double_to_datetime(double f) 00238 { 00239 PDateTime date; // missing by default 00240 if (! is_missing(f)) { 00241 long d = long(f); 00242 double fraction = f-d; 00243 date.year = short(1900 + d/10000); 00244 d %= 10000; 00245 date.month = (unsigned char) (d/100); 00246 date.day = (unsigned char) (d%100); 00247 00248 int hh,mm,ss; 00249 double_to_hhmmss(fraction,hh,mm,ss); 00250 date.hour = hh; 00251 date.min = mm; 00252 date.sec = ss; 00253 } 00254 return date; 00255 } 00256 00257 double hhmmss_to_double(int hh, int mm, int ss) 00258 { 00259 // There are 1440 minutes in a day. 00260 // There are 86400 seconds in a day. 00261 return double(hh)/24. + double(mm)/1440. + double(ss)/86400; 00262 } 00263 00264 void double_to_hhmmss(double fraction, int& hh, int& mm, int& ss) 00265 { 00266 hh = int(fraction *= 24); 00267 fraction -= hh; 00268 mm = int(fraction *= 60); 00269 fraction -= mm; 00270 ss = int(fraction * 60); 00271 } 00272 00273 int delta_seconds(const PDateTime& current, const PDateTime& past) 00274 { 00275 if ( current == past ) 00276 return 0; 00277 00278 double jcurrent = current.toJulianDay(); 00279 double jpast = past.toJulianDay(); 00280 double delta_days = jcurrent - jpast; 00281 00282 return int( round(delta_days*SECONDS_PER_DAY) ); 00283 } 00284 00285 00286 } // end of namespace PLearn 00287 00288 00289 /* 00290 Local Variables: 00291 mode:c++ 00292 c-basic-offset:4 00293 c-file-style:"stroustrup" 00294 c-file-offsets:((innamespace . 0)(inline-open . 0)) 00295 indent-tabs-mode:nil 00296 fill-column:79 00297 End: 00298 */ 00299 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :