00001
00025 #include <stdio.h>
00026 #include <time.h>
00027 #include <ctype.h>
00028
00029 #include "magic/mmath.h"
00030 #include "magic/mdatetime.h"
00031 #include "magic/mclass.h"
00032
00033 BEGIN_NAMESPACE (MagiC);
00034
00035 decl_module (datetime);
00036
00037 impl_dynamic (DateTime, {"Object"});
00038 impl_dynamic (JulianDay, {"Object"});
00039
00041
00042
00043 #define sign(x) ((x)>0)? 1:(((x)<0)? -1:0)
00044
00045 #define FERR 0.000000001
00046
00047 FloatType torange (FloatType initial, FloatType rmin, FloatType rmax) {
00048 while (initial<rmin || initial>rmax) {
00049 if (initial<rmin)
00050 initial += rmax-rmin;
00051 if (initial>rmax)
00052 initial -= rmax-rmin;
00053 }
00054 return initial;
00055 }
00056
00057 String Hours::toString () const {
00058 return format ("%dh %dm %2.4fs", hour(), min(), sec());
00059 }
00060
00062
00063
00064
00065
00066
00067
00068
00070
00071 void settimezone (DateTime* dt) {
00072
00073 time_t aika_s = time (0);
00074 struct tm* aika = localtime (&aika_s);
00075 dt->timezone = -timezone/3600;
00076 dt->dst = aika->tm_isdst;
00077 dt->utcdiff = dt->timezone + dt->dst;
00078 }
00079
00080 DateTime::DateTime (int d, int mo, int y, int h, int mi, FloatType s) {
00081 make (d, mo, y, h, mi, s);
00082 }
00083
00084 void DateTime::make (int d, int mo, int y, int h, int mi, FloatType s) {
00085 day = d;
00086 month = mo;
00087 year = y;
00088 hours = h + mi/60.0 + s/3600.0;
00089 settimezone (this);
00090 }
00091
00092 void DateTime::make () {
00093 day = 0;
00094 month = 0;
00095 year = 0;
00096 hours = 0.0;
00097 settimezone (this);
00098 }
00099
00100 void DateTime::make (const time_t& tt) {
00101 struct tm* time_tm = localtime (&tt);
00102 day = time_tm->tm_mday;
00103 month = time_tm->tm_mon+1;
00104 year = time_tm->tm_year+1900;
00105 hours = time_tm->tm_hour
00106 + time_tm->tm_min/60.0
00107 + time_tm->tm_sec/3600.0;
00108 settimezone (this);
00109 }
00110
00111 DateTime& DateTime::makecurrent () {
00112 make (time (0));
00113 return *this;
00114 }
00115
00116 int DateTime::daynumber () const {
00117 int leap=0;
00118 if ((year/4)*4==year && (year/100)*100!=year)
00119 leap=1;
00120
00121 if (month <3)
00122 return int ((month-1)*(63-leap)/2)+day;
00123 return int ((month+1)*30.6001)-63+leap+day;
00124 }
00125
00126 int DateTime::weekday () const {
00127 return 0;
00128 }
00129
00130 void DateTime::make (const JulianDay& jd) {
00131 double JD = jd+0.5;
00132 int Z = int(JD);
00133 double F = JD-Z;
00134 double A, B, C, D, E;
00135
00136 if (Z<2299161)
00137 A = Z;
00138 else {
00139 double alpha = int ((Z-1867216.25)/36524.25);
00140 A = Z+1+alpha-int(alpha/4);
00141 }
00142
00143 B = A+1524;
00144 C = int ((B-122.1)/365.25);
00145 D = int (365.25*C);
00146 E = int ((B-D)/30.6001);
00147 day = int(int (B-D-int (30.6001*E))+F);
00148 month = int ((E<14)? E-1 : E-13);
00149 year = int ((month>2)? C-4716 : C-4715);
00150
00151
00152 hours = F*24;
00153 }
00154
00155 DateTime& DateTime::operator= (const DateTime& o) {
00156 memcpy (this, &o, sizeof(DateTime));
00157 return *this;
00158 }
00159
00160 int DateTime::setstrict (const String& str, const String& tformat) {
00161 int mins=0, secs=0;
00162
00163 make ();
00164
00165 if (str.length() != tformat.length())
00166 return 1;
00167
00168 for (uint i=0; i<str.length(); i++) {
00169 char num = str[i] - '0';
00170 char f = tformat[i];
00171 switch (f) {
00172 case 'Y': year = year*10 + num; break;
00173 case 'M': month = month*10 + num; break;
00174 case 'D': day = day*10 + num; break;
00175 case 'h': hours = hours*10 + num; break;
00176 case 'm': mins = mins*10 + num; break;
00177 case 's': secs = secs*10 + num; break;
00178 };
00179 }
00180
00181 hours += mins/60.0 + secs/3600.0;
00182
00183 return 0;
00184 }
00185
00186 int DateTime::compare (const DateTime& other) const {
00187 if (year < other.year) return -1;
00188 if (year > other.year) return 1;
00189
00190 if (month < other.month) return -1;
00191 if (month > other.month) return 1;
00192
00193 if (day < other.day) return -1;
00194 if (day > other.day) return 1;
00195
00196 if (hours < other.hours) return -1;
00197 if (hours > other.hours) return 1;
00198
00199 return 0;
00200 }
00201
00202 double DateTime::operator- (const DateTime& o) const {
00203 return FloatType(JulianDay (*this)) - FloatType(JulianDay (o));
00204 }
00205
00206 DateTime DateTime::lt2GMT () const {
00207 DateTime result;
00208 result.make (day,month,year,0,0,0);
00209 result.hours = hours - Hours(utcdiff);
00210 result.corrange ();
00211 return result;
00212 }
00213
00214 void DateTime::nextday () {
00215 day=day+1;
00216 if (day>28 && month==2)
00217 day = 1,
00218 month++;
00219 else
00220 if (day>30 && (month==4 || month==6 || month==9 || month==11))
00221 day = 1,
00222 month++;
00223 else
00224 if (day>31 && (month==1 || month==3 || month==5 || month==7
00225 || month==8 || month==10 || month==12))
00226 day = 1,
00227 month++;
00228 }
00229
00230 void DateTime::prevday () {
00231 day=day-1;
00232 if (day<1) {
00233 month--;
00234 if (month<1)
00235 year--,
00236 month=12;
00237 if (month==2)
00238 day=28;
00239 else
00240 if (month==4 || month==6 || month==9 || month==11)
00241 day=30;
00242 else
00243 if (month==1 || month==3 || month==5 || month==7
00244 || month==8 || month==10 || month==12)
00245 day=31;
00246 }
00247 }
00248
00249 void DateTime::corrange () {
00250 while (hours<0)
00251 hours+=24,
00252 prevday();
00253 while (hours>24)
00254 hours-=24,
00255 nextday();
00256 }
00257
00258 String DateTime::text () const {
00259 String res = format ("%02d.%02d.%04d %02d:%02d:%02.2g",
00260 day, month, year, hour(), min(), sec());
00261 return res;
00262 }
00263
00264 String DateTime::text_time () const {
00265 String res = format ("%02d:%02d:%02.2g", hour(), min(), sec());
00266 return res;
00267 }
00268
00269 String DateTime::text_time (const String& form) const {
00270
00271 struct tm* tms = to_tm ();
00272
00273
00274 char buffer [80];
00275 strftime (buffer, 80, (CONSTR) form, tms);
00276
00277 delete tms;
00278
00279 return buffer;
00280 }
00281
00282 int DateTime::isduring (const TimePeriod& period) const {
00283 return operator> (period.start) && operator< (period.end);
00284 }
00285
00286 typedef struct tm tmstr;
00287
00288 struct tm* DateTime::to_tm () const {
00289 struct tm* result = (struct tm*) new tmstr;
00290 result->tm_sec = int (sec ());
00291 result->tm_min = min ();
00292 result->tm_hour = int (hours);
00293 result->tm_mday = day;
00294 result->tm_mon = month-1;
00295 result->tm_year = year-1900;
00296 result->tm_wday = 0;
00297 result->tm_yday = 0;
00298 result->tm_isdst= dst;
00299 return result;
00300 }
00301
00302
00303
00305
00306
00307
00308
00309
00310
00311
00313
00314 double _JD (int day, int month, int year) {
00315 ASSERT (month!=0);
00316
00317 if (month<=2)
00318 year = year-1,
00319 month = month+12;
00320
00321 double b = 0.0;
00322 if (year > 1582 || (year==1582 && (month>10 || (month==10 && day>=15)))) {
00323 double a = int (year/100.0);
00324 b = 2 - a + int (a/4.0);
00325 }
00326
00327 return int (365.25*(year+4716)) + int ((month+1)*30.6001) + day + b - 1524.5;
00328 }
00329
00330 void JulianDay::make (const DateTime& dt) {
00331 mJD = _JD (dt.day,dt.month,dt.year) + dt.dectime();
00332 }
00333
00334 END_NAMESPACE;
00335