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