00001 #ifndef EARTH_TIME_IMPLEMENTATION_FILE
00002 #define EARTH_TIME_IMPLEMENTATION_FILE
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "convert_utf.h"
00019 #include "earth_time.h"
00020 #include "istring.h"
00021 #include "portable.h"
00022
00023 #include <time.h>
00024 #if defined(__WIN32__) || defined(__UNIX__)
00025 #include <sys/timeb.h>
00026 #endif
00027
00028 using namespace basis;
00029
00030 namespace earth_time {
00031
00032 const int days_in_month[12]
00033 = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
00034
00035 const int leap_days_in_month[12]
00036 = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
00037
00038 const int julian_days_in_month[12]
00039 = { 31, 29, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30 };
00040
00041
00042 const int julian_leap_days_in_month[12]
00043 = { 31, 30, 31, 30, 31, 30, 31, 30, 31, 30, 31, 30 };
00044
00046
00047 void clock_time::pack(byte_array &packed_form) const
00048 {
00049 attach(packed_form, hour);
00050 attach(packed_form, minute);
00051 attach(packed_form, second);
00052 attach(packed_form, millisecond);
00053 attach(packed_form, microsecond);
00054 }
00055
00056 bool clock_time::unpack(byte_array &packed_form)
00057 {
00058 if (!detach(packed_form, hour)) return false;
00059 if (!detach(packed_form, minute)) return false;
00060 if (!detach(packed_form, second)) return false;
00061 if (!detach(packed_form, millisecond)) return false;
00062 if (!detach(packed_form, microsecond)) return false;
00063 return true;
00064 }
00065
00066 #define EASY_LT(x, y) \
00067 if (x < y) return true; \
00068 if (x > y) return false
00069
00070 bool clock_time::operator < (const clock_time &to_compare) const
00071 {
00072 EASY_LT(hour, to_compare.hour);
00073 EASY_LT(minute, to_compare.minute);
00074 EASY_LT(second, to_compare.second);
00075 EASY_LT(millisecond, to_compare.millisecond);
00076 EASY_LT(microsecond, to_compare.microsecond);
00077 return false;
00078 }
00079
00080 bool clock_time::operator == (const clock_time &to_compare) const
00081 {
00082 return (hour == to_compare.hour)
00083 && (minute == to_compare.minute)
00084 && (second == to_compare.second)
00085 && (millisecond == to_compare.millisecond)
00086 && (microsecond == to_compare.microsecond);
00087 }
00088
00089 istring clock_time::text_form(int how) const
00090 {
00091 istring to_return;
00092 text_form(to_return, how);
00093 return to_return;
00094 }
00095
00096 void clock_time::text_form(istring &to_return, int how) const
00097 {
00098 if (!how) return;
00099 if (how & MILITARY)
00100 to_return += isprintf("%02d:%02d", hour, minute);
00101 else {
00102 int uhr = hour;
00103 if (uhr > 12) uhr -= 12;
00104 to_return += isprintf("%2d:%02d", uhr, minute);
00105 }
00106 if ( (how & SECONDS) || (how & MILLISECONDS) )
00107 to_return += isprintf(":%02d", second);
00108 if (how & MILLISECONDS)
00109 to_return += isprintf(":%03d", millisecond);
00110 if (how & MERIDIAN) {
00111 if (hour >= 12) to_return += "PM";
00112 else to_return += "AM";
00113 }
00114 }
00115
00116
00117
00118 #define limit_value(val, max) \
00119 if (val < 0) { \
00120 rolls = val / max; \
00121 rolls--; \
00122 val += max * -rolls; \
00123 } else if (val >= max) { \
00124 rolls = val / max; \
00125 val -= max * rolls; \
00126 } else { rolls = 0; }
00127
00128 int clock_time::normalize(clock_time &to_fix)
00129 {
00130 int rolls = 0;
00131 limit_value(to_fix.microsecond, 1000);
00132 to_fix.millisecond += rolls;
00133 limit_value(to_fix.millisecond, 1000);
00134 to_fix.second += rolls;
00135 limit_value(to_fix.second, 60);
00136 to_fix.minute += rolls;
00137 limit_value(to_fix.minute, 60);
00138 to_fix.hour += rolls;
00139 limit_value(to_fix.hour, 24);
00140 return rolls;
00141 }
00142
00144
00145 void day_in_year::pack(byte_array &packed_form) const
00146 {
00147 attach(packed_form, day_of_year);
00148 attach(packed_form, byte(day_of_week));
00149 attach(packed_form, byte(month));
00150 attach(packed_form, day_in_month);
00151 attach(packed_form, byte(1));
00152
00153 }
00154
00155 bool day_in_year::unpack(byte_array &packed_form)
00156 {
00157 if (!detach(packed_form, day_of_year)) return false;
00158 byte temp;
00159 if (!detach(packed_form, temp)) return false;
00160 day_of_week = days(temp);
00161 if (!detach(packed_form, temp)) return false;
00162 month = months(temp);
00163 if (!detach(packed_form, day_in_month)) return false;
00164 if (!detach(packed_form, temp)) return false;
00165 return true;
00166 }
00167
00168 bool day_in_year::operator < (const day_in_year &to_compare) const
00169 {
00170 EASY_LT(month, to_compare.month);
00171 EASY_LT(day_in_month, to_compare.day_in_month);
00172 return false;
00173 }
00174
00175 bool day_in_year::operator == (const day_in_year &to_compare) const
00176 {
00177 return (month == to_compare.month)
00178 && (day_in_month == to_compare.day_in_month);
00179 }
00180
00181 istring day_in_year::text_form(int how) const
00182 {
00183 istring to_return;
00184 text_form(to_return, how);
00185 return to_return;
00186 }
00187
00188 void day_in_year::text_form(istring &to_stuff, int how) const
00189 {
00190 if (!how) return;
00191 if (how & INCLUDE_DAY) to_stuff += istring(day_name(day_of_week)) + " ";
00192 const char *monat = short_month_name(month);
00193 if (how & LONG_MONTH)
00194 monat = month_name(month);
00195
00196 to_stuff += monat;
00197 to_stuff += isprintf(" %02d", day_in_month);
00198 }
00199
00200
00201 int limit_day_of_month(int &day, int days_in_month, int days_in_prev_month)
00202 {
00203 if (day > days_in_month) {
00204 day -= days_in_month;
00205 return 1;
00206 } else if (day < 1) {
00207 day += days_in_prev_month;
00208 return -1;
00209 }
00210 return 0;
00211 }
00212
00213 int day_in_year::normalize(day_in_year &to_fix, bool leap_year)
00214 {
00215 int rolls = 0;
00216 int daysinm = leap_year?
00217 leap_days_in_month[to_fix.month] : days_in_month[to_fix.month];
00218 int prev_month = to_fix.month - 1;
00219 if (prev_month < 0) prev_month = 11;
00220 int daysinpm = leap_year?
00221 leap_days_in_month[prev_month] : days_in_month[prev_month];
00222 rolls = limit_day_of_month(to_fix.day_in_month, daysinm, daysinpm);
00223 int monat = to_fix.month + rolls;
00224 limit_value(monat, 12);
00225 to_fix.month = months(monat);
00226 return rolls;
00227 }
00228
00230
00231 void time_locus::pack(byte_array &packed_form) const
00232 {
00233 attach(packed_form, year);
00234 clock_time::pack(packed_form);
00235 day_in_year::pack(packed_form);
00236 }
00237
00238 bool time_locus::unpack(byte_array &packed_form)
00239 {
00240 if (!detach(packed_form, year)) return false;
00241 if (!clock_time::unpack(packed_form)) return false;
00242 if (!day_in_year::unpack(packed_form)) return false;
00243 return true;
00244 }
00245
00246 istring time_locus::text_form(int t, int d, int y) const
00247 {
00248 istring to_return;
00249 text_form(to_return, t, d, y);
00250 return to_return;
00251 }
00252
00253 bool time_locus::operator < (const time_locus &to_compare) const
00254 {
00255 EASY_LT(year, to_compare.year);
00256 if (day_in_year::operator < (to_compare)) return true;
00257 if (!(day_in_year::operator == (to_compare))) return false;
00258 if (clock_time::operator < (to_compare)) return true;
00259 return false;
00260 }
00261
00262 bool time_locus::operator == (const time_locus &to_compare) const
00263 {
00264 return (year == to_compare.year)
00265 && ( (const day_in_year &) *this == to_compare)
00266 && ( (const clock_time &) *this == to_compare);
00267 }
00268
00269 void time_locus::text_form(istring &to_stuff, int t, int d, int y) const
00270 {
00271
00272 if (!y) {
00273 text_form(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 += isprintf("%2d", year % 100);
00282 else
00283 to_stuff += isprintf("%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 bool set_time(const time_locus &new_time)
00406 {
00407 #ifdef __WIN32__
00408 SYSTEMTIME os_time;
00409 os_time.wYear = WORD(new_time.year);
00410 os_time.wMonth = new_time.month;
00411 os_time.wDayOfWeek = new_time.day_of_week;
00412 os_time.wDay = new_time.day_of_year;
00413 os_time.wHour = new_time.hour;
00414 os_time.wMinute = new_time.minute;
00415 os_time.wSecond = new_time.second;
00416 os_time.wMilliseconds = 0;
00417
00418
00419 HANDLE petoken;
00420 OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES
00421 | TOKEN_QUERY, &petoken);
00422
00423
00424
00425 LUID our_id;
00426 LookupPrivilegeValue(NULL, to_unicode_temp("SeSystemTimePrivilege"), &our_id);
00427
00428 TOKEN_PRIVILEGES privs;
00429 privs.PrivilegeCount = 1;
00430 privs.Privileges[0].Luid = our_id;
00431 privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
00432
00433 AdjustTokenPrivileges(petoken, false, &privs, sizeof(TOKEN_PRIVILEGES),
00434 NULL, NULL);
00435
00436 SetLocalTime(&os_time);
00437
00438
00439 AdjustTokenPrivileges(petoken, true, &privs, sizeof(TOKEN_PRIVILEGES),
00440 NULL, NULL);
00441
00442
00443
00444 ::PostMessage(HWND_BROADCAST, WM_TIMECHANGE, 0, 0);
00445
00446
00447 CloseHandle(petoken);
00448
00449 return true;
00450 #elif defined(__UNIX__)
00451
00452
00453
00454 time_locus ted = new_time;
00455 return ted.year ? 0:1;
00456
00457 #else
00458 return false;
00459 #endif
00460 }
00461
00462 }
00463
00464
00465 #endif //EARTH_TIME_IMPLEMENTATION_FILE
00466