00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "earth_time.h"
00016
00017 #include <basis/astring.h>
00018 #include <basis/utf_conversion.h>
00019
00020 #include <time.h>
00021 #if defined(__WIN32__) || defined(__UNIX__)
00022 #include <sys/timeb.h>
00023 #endif
00024
00025 using namespace basis;
00026 using namespace structures;
00027
00028 namespace timely {
00029
00030 const int days_in_month[12]
00031 = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
00032
00033 const int leap_days_in_month[12]
00034 = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
00035
00036 const int julian_days_in_month[12]
00037 = { 31, 29, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30 };
00038
00039
00040 const int julian_leap_days_in_month[12]
00041 = { 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30 };
00042
00044
00045 void clock_time::pack(byte_array &packed_form) const
00046 {
00047 attach(packed_form, hour);
00048 attach(packed_form, minute);
00049 attach(packed_form, second);
00050 attach(packed_form, millisecond);
00051 attach(packed_form, microsecond);
00052 }
00053
00054 bool clock_time::unpack(byte_array &packed_form)
00055 {
00056 if (!detach(packed_form, hour)) return false;
00057 if (!detach(packed_form, minute)) return false;
00058 if (!detach(packed_form, second)) return false;
00059 if (!detach(packed_form, millisecond)) return false;
00060 if (!detach(packed_form, microsecond)) return false;
00061 return true;
00062 }
00063
00064 #define EASY_LT(x, y) \
00065 if (x < y) return true; \
00066 if (x > y) return false
00067
00068 bool clock_time::operator < (const clock_time &to_compare) const
00069 {
00070 EASY_LT(hour, to_compare.hour);
00071 EASY_LT(minute, to_compare.minute);
00072 EASY_LT(second, to_compare.second);
00073 EASY_LT(millisecond, to_compare.millisecond);
00074 EASY_LT(microsecond, to_compare.microsecond);
00075 return false;
00076 }
00077
00078 bool clock_time::operator == (const clock_time &to_compare) const
00079 {
00080 return (hour == to_compare.hour)
00081 && (minute == to_compare.minute)
00082 && (second == to_compare.second)
00083 && (millisecond == to_compare.millisecond)
00084 && (microsecond == to_compare.microsecond);
00085 }
00086
00087 astring clock_time::text_form(int how) const
00088 {
00089 astring to_return;
00090 text_form(to_return, how);
00091 return to_return;
00092 }
00093
00094 void clock_time::text_form(astring &to_return, int how) const
00095 {
00096 if (!how) return;
00097 if (how & MILITARY)
00098 to_return += a_sprintf("%02d:%02d", hour, minute);
00099 else {
00100 int uhr = hour;
00101 if (uhr > 12) uhr -= 12;
00102 to_return += a_sprintf("%2d:%02d", uhr, minute);
00103 }
00104 if ( (how & SECONDS) || (how & MILLISECONDS) )
00105 to_return += a_sprintf(":%02d", second);
00106 if (how & MILLISECONDS)
00107 to_return += a_sprintf(":%03d", millisecond);
00108 if (how & MERIDIAN) {
00109 if (hour >= 12) to_return += "PM";
00110 else to_return += "AM";
00111 }
00112 }
00113
00114
00115
00116 #define limit_value(val, max) \
00117 if (val < 0) { \
00118 rolls = val / max; \
00119 rolls--; \
00120 val += max * -rolls; \
00121 } else if (val >= max) { \
00122 rolls = val / max; \
00123 val -= max * rolls; \
00124 } else { rolls = 0; }
00125
00126 int clock_time::normalize(clock_time &to_fix)
00127 {
00128 int rolls = 0;
00129 limit_value(to_fix.microsecond, 1000);
00130 to_fix.millisecond += rolls;
00131 limit_value(to_fix.millisecond, 1000);
00132 to_fix.second += rolls;
00133 limit_value(to_fix.second, 60);
00134 to_fix.minute += rolls;
00135 limit_value(to_fix.minute, 60);
00136 to_fix.hour += rolls;
00137 limit_value(to_fix.hour, 24);
00138 return rolls;
00139 }
00140
00142
00143 void day_in_year::pack(byte_array &packed_form) const
00144 {
00145 attach(packed_form, day_of_year);
00146 attach(packed_form, abyte(day_of_week));
00147 attach(packed_form, abyte(month));
00148 attach(packed_form, day_in_month);
00149 attach(packed_form, abyte(1));
00150
00151 }
00152
00153 bool day_in_year::unpack(byte_array &packed_form)
00154 {
00155 if (!detach(packed_form, day_of_year)) return false;
00156 abyte temp;
00157 if (!detach(packed_form, temp)) return false;
00158 day_of_week = days(temp);
00159 if (!detach(packed_form, temp)) return false;
00160 month = months(temp);
00161 if (!detach(packed_form, day_in_month)) return false;
00162 if (!detach(packed_form, temp)) return false;
00163 return true;
00164 }
00165
00166 bool day_in_year::operator < (const day_in_year &to_compare) const
00167 {
00168 EASY_LT(month, to_compare.month);
00169 EASY_LT(day_in_month, to_compare.day_in_month);
00170 return false;
00171 }
00172
00173 bool day_in_year::operator == (const day_in_year &to_compare) const
00174 {
00175 return (month == to_compare.month)
00176 && (day_in_month == to_compare.day_in_month);
00177 }
00178
00179 astring day_in_year::text_form(int how) const
00180 {
00181 astring to_return;
00182 text_form(to_return, how);
00183 return to_return;
00184 }
00185
00186 void day_in_year::text_form(astring &to_stuff, int how) const
00187 {
00188 if (!how) return;
00189 if (how & INCLUDE_DAY) to_stuff += astring(day_name(day_of_week)) + " ";
00190 const char *monat = short_month_name(month);
00191 if (how & LONG_MONTH)
00192 monat = month_name(month);
00193
00194 to_stuff += monat;
00195 to_stuff += a_sprintf(" %02d", day_in_month);
00196 }
00197
00198
00199 int limit_day_of_month(int &day, int days_in_month, int days_in_prev_month)
00200 {
00201 if (day > days_in_month) {
00202 day -= days_in_month;
00203 return 1;
00204 } else if (day < 1) {
00205 day += days_in_prev_month;
00206 return -1;
00207 }
00208 return 0;
00209 }
00210
00211 int day_in_year::normalize(day_in_year &to_fix, bool leap_year)
00212 {
00213 int rolls = 0;
00214 int daysinm = leap_year?
00215 leap_days_in_month[to_fix.month] : days_in_month[to_fix.month];
00216 int prev_month = to_fix.month - 1;
00217 if (prev_month < 0) prev_month = 11;
00218 int daysinpm = leap_year?
00219 leap_days_in_month[prev_month] : days_in_month[prev_month];
00220 rolls = limit_day_of_month(to_fix.day_in_month, daysinm, daysinpm);
00221 int monat = to_fix.month + rolls;
00222 limit_value(monat, 12);
00223 to_fix.month = months(monat);
00224 return rolls;
00225 }
00226
00228
00229 void time_locus::pack(byte_array &packed_form) const
00230 {
00231 attach(packed_form, year);
00232 clock_time::pack(packed_form);
00233 day_in_year::pack(packed_form);
00234 }
00235
00236 bool time_locus::unpack(byte_array &packed_form)
00237 {
00238 if (!detach(packed_form, year)) return false;
00239 if (!clock_time::unpack(packed_form)) return false;
00240 if (!day_in_year::unpack(packed_form)) return false;
00241 return true;
00242 }
00243
00244 astring time_locus::text_form_long(int t, int d, int y) const
00245 {
00246 astring to_return;
00247 text_form_long(to_return, t, d, y);
00248 return to_return;
00249 }
00250
00251 bool time_locus::equal_to(const equalizable &s2) const {
00252 const time_locus *s2_cast = dynamic_cast<const time_locus *>(&s2);
00253 if (!s2_cast) throw "error: time_locus::==: unknown type";
00254 return (year == s2_cast->year)
00255 && ( (const day_in_year &) *this == *s2_cast)
00256 && ( (const clock_time &) *this == *s2_cast);
00257 }
00258
00259 bool time_locus::less_than(const orderable &s2) const {
00260 const time_locus *s2_cast = dynamic_cast<const time_locus *>(&s2);
00261 if (!s2_cast) throw "error: time_locus::<: unknown type";
00262 EASY_LT(year, s2_cast->year);
00263 if (day_in_year::operator < (*s2_cast)) return true;
00264 if (!(day_in_year::operator == (*s2_cast))) return false;
00265 if (clock_time::operator < (*s2_cast)) return true;
00266 return false;
00267 }
00268
00269 void time_locus::text_form_long(astring &to_stuff, int t, int d, int y) const
00270 {
00271
00272 if (!y) {
00273 text_form_long(to_stuff, t, d);
00274 return;
00275 }
00276
00277 day_in_year::text_form(to_stuff, d);
00278 to_stuff += " ";
00279
00280 if (y & SHORT_YEAR)
00281 to_stuff += a_sprintf("%2d", year % 100);
00282 else
00283 to_stuff += a_sprintf("%4d", year);
00284
00285 to_stuff += " ";
00286 clock_time::text_form(to_stuff, t);
00287 }
00288
00289 int time_locus::normalize(time_locus &to_fix)
00290 {
00291 int rolls = clock_time::normalize(to_fix);
00292 to_fix.day_in_month += rolls;
00293
00294
00295 bool leaping = !(to_fix.year % 4);
00296 if (!(to_fix.year % 100)) leaping = false;
00297 if (!(to_fix.year % 400)) leaping = true;
00298
00299 rolls = day_in_year::normalize(to_fix, leaping);
00300 to_fix.year += rolls;
00301 return 0;
00302
00303
00304 }
00305
00307
00308 time_locus convert(const tm &to_convert, int ms)
00309 {
00310 time_locus r;
00311
00312
00313 r.microsecond = 0;
00314
00315 r.second = to_convert.tm_sec;
00316 r.minute = to_convert.tm_min;
00317 r.hour = to_convert.tm_hour;
00318 r.day_in_month = to_convert.tm_mday;
00319 r.month = months(to_convert.tm_mon);
00320 r.year = to_convert.tm_year + 1900;
00321 r.day_of_week = days(to_convert.tm_wday);
00322 r.day_of_year = to_convert.tm_yday;
00323 r.millisecond = ms;
00324 return r;
00325 }
00326
00327 time_locus now()
00328 {
00329 timeb current;
00330 ftime(¤t);
00331 tm split_time(*localtime(¤t.time));
00332 return convert(split_time, current.millitm);
00333 }
00334
00335 time_locus greenwich_now()
00336 {
00337 timeb current;
00338 ftime(¤t);
00339 tm split_time(*gmtime(¤t.time));
00340 return convert(split_time, current.millitm);
00341 }
00342
00343 clock_time time_now() { return now(); }
00344
00345 days day_now() { return now().day_of_week; }
00346
00347 months month_now() { return now().month; }
00348
00349 int year_now() { return now().year; }
00350
00351 day_in_year date_now() { return now(); }
00352
00353 const char *day_name(days to_name)
00354 {
00355 switch (to_name) {
00356 case SUNDAY: return "Sunday";
00357 case MONDAY: return "Monday";
00358 case TUESDAY: return "Tuesday";
00359 case WEDNESDAY: return "Wednesday";
00360 case THURSDAY: return "Thursday";
00361 case FRIDAY: return "Friday";
00362 case SATURDAY: return "Saturday";
00363 default: return "Not_a_day";
00364 }
00365 }
00366
00367 const char *month_name(months to_name)
00368 {
00369 switch (to_name) {
00370 case JANUARY: return "January";
00371 case FEBRUARY: return "February";
00372 case MARCH: return "March";
00373 case APRIL: return "April";
00374 case MAY: return "May";
00375 case JUNE: return "June";
00376 case JULY: return "July";
00377 case AUGUST: return "August";
00378 case SEPTEMBER: return "September";
00379 case OCTOBER: return "October";
00380 case NOVEMBER: return "November";
00381 case DECEMBER: return "December";
00382 default: return "Not_a_month";
00383 }
00384 }
00385
00386 const char *short_month_name(months to_name)
00387 {
00388 switch (to_name) {
00389 case JANUARY: return "Jan";
00390 case FEBRUARY: return "Feb";
00391 case MARCH: return "Mar";
00392 case APRIL: return "Apr";
00393 case MAY: return "May";
00394 case JUNE: return "Jun";
00395 case JULY: return "Jul";
00396 case AUGUST: return "Aug";
00397 case SEPTEMBER: return "Sep";
00398 case OCTOBER: return "Oct";
00399 case NOVEMBER: return "Nov";
00400 case DECEMBER: return "Dec";
00401 default: return "Not";
00402 }
00403 }
00404
00405 }
00406