ptime.cxx (7362B)
1 /* 2 * 3 * C++ Portable Types Library (PTypes) 4 * Version 2.1.1 Released 27-Jun-2007 5 * 6 * Copyright (C) 2001-2007 Hovik Melikyan 7 * 8 * http://www.melikyan.com/ptypes/ 9 * 10 */ 11 12 // altzone fix for Sun/GCC 3.2. any better ideas? 13 #if defined(__sun__) && defined(__GNUC__) && defined(_XOPEN_SOURCE) 14 # undef _XOPEN_SOURCE 15 #endif 16 17 #ifdef WIN32 18 # include <windows.h> 19 #else 20 # include <sys/time.h> 21 #endif 22 23 #include <time.h> 24 #include <string.h> 25 26 #include "ptime.h" 27 28 29 namespace ptypes { 30 31 32 datetime ptdecl mkdt(int days, int msecs) 33 { 34 return large(days) * _msecsmax + msecs; 35 } 36 37 38 bool ptdecl isvalid(datetime d) 39 { 40 return d >= 0 && d < _datetimemax; 41 } 42 43 44 bool ptdecl isleapyear(int year) 45 { 46 return year > 0 && year % 4 == 0 47 && (year % 100 != 0 || year % 400 == 0); 48 } 49 50 51 int ptdecl daysinmonth(int year, int month) 52 { 53 if (month < 1 || month > 12) 54 return 0; 55 static const int mdays[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 56 int res = mdays[month - 1]; 57 if (month == 2) 58 if (isleapyear(year)) 59 res++; 60 return res; 61 } 62 63 64 int ptdecl daysinyear(int year, int month) 65 { 66 if (month < 1 || month > 12) 67 return 0; 68 static const int ndays[12] = {31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; 69 int res = ndays[month - 1]; 70 if (month > 1) 71 if (isleapyear(year)) 72 res++; 73 return res; 74 } 75 76 77 int ptdecl dayofweek(datetime d) 78 { 79 return (days(d) + 1) % 7; 80 } 81 82 83 bool ptdecl isdatevalid(int year, int month, int day) 84 { 85 return year >= 1 && year <= 9999 86 && month >= 1 && month <= 12 87 && day >= 1 && day <= daysinmonth(year, month); 88 } 89 90 91 datetime ptdecl encodedate(int year, int month, int day) 92 { 93 if (!isdatevalid(year, month, day)) 94 return invdatetime; 95 int y = year - 1; 96 return mkdt(day // days in this month 97 + daysinyear(year, month - 1) // plus days since the beginning of the year 98 + y * 365 // plus "pure" days 99 + y / 4 - y / 100 + y / 400 // plus leap year correction 100 - 1, 0); // ... minus one (guess why :) 101 } 102 103 104 bool ptdecl decodedate(datetime date, int& year, int& month, int& day) 105 { 106 int d = days(date); 107 if (d < 0 || d >= _daysmax) // allowed date range is 01/01/0001 - 12/31/9999 108 { 109 year = 0; 110 month = 0; 111 day = 0; 112 return false; 113 } 114 115 const int d1 = 365; // number of days in 1 year 116 const int d4 = d1 * 4 + 1; // ... in 4 year period 117 const int d100 = d4 * 25 - 1; // ... in 100 year period 118 const int d400 = d100 * 4 + 1; // ... in 400 year period 119 120 year = (d / d400) * 400 + 1; 121 d %= d400; 122 123 int t = d / d100; 124 d %= d100; 125 if (t == 4) 126 { 127 t--; 128 d += d100; 129 } 130 year += t * 100; 131 132 year += (d / d4) * 4; 133 d %= d4; 134 135 t = d / d1; 136 d %= d1; 137 if (t == 4) 138 { 139 t--; 140 d += d1; 141 } 142 year += t; 143 144 month = d / 29; // approximate month no. (to avoid loops) 145 if (d < daysinyear(year, month)) // month no. correction 146 month--; 147 148 day = d - daysinyear(year, month) + 1; 149 month++; 150 return true; 151 } 152 153 154 bool ptdecl istimevalid(int hour, int min, int sec, int msec) 155 { 156 return hour >= 0 && hour < 24 157 && min >= 0 && min < 60 158 && sec >= 0 && sec < 60 159 && msec >= 0 && msec < 1000; 160 } 161 162 163 datetime ptdecl encodetime(int hour, int min, int sec, int msec) 164 { 165 large res = large(hour) * 3600000 + large(min) * 60000 + large(sec) * 1000 + msec; 166 if (!isvalid(res)) 167 res = invdatetime; 168 return res; 169 } 170 171 172 bool ptdecl decodetime(datetime t, int& hour, int& min, int& sec, int& msec) 173 { 174 if (!isvalid(t)) 175 { 176 hour = 0; 177 min = 0; 178 sec = 0; 179 msec = 0; 180 return false; 181 } 182 int m = msecs(t); 183 hour = m / 3600000; 184 m %= 3600000; 185 min = m / 60000; 186 m %= 60000; 187 sec = m / 1000; 188 msec = m % 1000; 189 return true; 190 } 191 192 193 bool ptdecl decodetime(datetime t, int& hour, int& min, int& sec) 194 { 195 int msec; 196 return decodetime(t, hour, min, sec, msec); 197 } 198 199 200 tm* ptdecl dttotm(datetime dt, tm& t) 201 { 202 memset(&t, 0, sizeof(tm)); 203 if (!decodedate(dt, t.tm_year, t.tm_mon, t.tm_mday) 204 || !decodetime(dt, t.tm_hour, t.tm_min, t.tm_sec)) 205 return nil; 206 t.tm_mon--; 207 t.tm_yday = daysinyear(t.tm_year, t.tm_mon) + t.tm_mday - 1; 208 t.tm_wday = dayofweek(dt); 209 t.tm_year -= 1900; 210 return &t; 211 } 212 213 214 string ptdecl dttostring(datetime dt, const char* fmt) 215 { 216 char buf[128]; 217 tm t; 218 int r = (int)strftime(buf, sizeof(buf), fmt, dttotm(dt, t)); 219 buf[r] = 0; 220 return string(buf); 221 } 222 223 224 datetime ptdecl now(bool utc) 225 { 226 #ifdef WIN32 227 SYSTEMTIME t; 228 if (utc) 229 GetSystemTime(&t); 230 else 231 GetLocalTime(&t); 232 return encodedate(t.wYear, t.wMonth, t.wDay) + 233 encodetime(t.wHour, t.wMinute, t.wSecond, t.wMilliseconds); 234 235 #else // Unix 236 // we can't use localtime() and gmtime() here as they don't return 237 // milliseconds which are needed for our datetime format. instead, 238 // we call gettimeofday() which have microsecond precision, and then 239 // adjust the time according to timzone info returned by localtime() 240 // on BSD and Linux, and global variables altzone/timezone on SunOS. 241 242 // NOTE: at the moment of passing the DST adjustment (twice a year) 243 // the local time value returned by now() may be incorrect. 244 // the application should call tzupdate() from time to time if it 245 // is supposed to be running infinitely, e.g. if it's a daemon. 246 247 // always rely on UTC time inside your application whenever possible. 248 timeval tv; 249 gettimeofday(&tv, nil); 250 int edays = tv.tv_sec / 86400 // days since Unix "Epoch", i.e. 01/01/1970 251 + 719162; // plus days between 01/01/0001 and Unix Epoch 252 int esecs = tv.tv_sec % 86400; // the remainder, i.e. seconds since midnight 253 datetime res = mkdt(edays, esecs * 1000 + tv.tv_usec / 1000); 254 255 if (!utc) 256 res += tzoffset() * 60 * 1000; 257 return res; 258 #endif 259 } 260 261 262 void ptdecl tzupdate() 263 { 264 tzset(); 265 } 266 267 268 int ptdecl tzoffset() 269 { 270 #if defined(WIN32) 271 TIME_ZONE_INFORMATION tz; 272 DWORD res = GetTimeZoneInformation(&tz); 273 if ((res == TIME_ZONE_ID_DAYLIGHT) && (tz.DaylightDate.wMonth != 0)) 274 return - (tz.Bias + tz.DaylightBias); 275 else 276 return - tz.Bias; 277 278 #else // UNIX 279 time_t t0 = time(0); 280 281 #if defined(__sun__) 282 #ifdef PTYPES_ST 283 // localtime_r() is not available without -D_REENTRANT 284 tm* t = localtime(&t0); 285 if(t->tm_isdst != 0 && daylight != 0) 286 #else 287 tm t; 288 localtime_r(&t0, &t); 289 if(t.tm_isdst != 0 && daylight != 0) 290 #endif 291 return - altzone / 60; 292 else 293 return - timezone / 60; 294 295 #elif defined(__CYGWIN__) 296 time_t local_time = time(NULL); 297 tm gt; 298 gmtime_r(&local_time, >); 299 time_t gmt_time = mktime(>); 300 return (local_time - gmt_time) / 60; 301 302 #elif defined(__hpux) 303 tm local; 304 localtime_r(&t0, &local); 305 local.tm_isdst = 0; 306 time_t t1 = mktime(&local); 307 return - (timezone - (t1 - t0)) / 60; 308 309 #else // other UNIX 310 tm t; 311 localtime_r(&t0, &t); 312 return t.tm_gmtoff / 60; 313 #endif 314 315 #endif 316 } 317 318 319 datetime ptdecl utodatetime(time_t u) 320 { 321 return _unixepoch + large(u) * 1000; 322 } 323 324 325 }