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
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "date.h"
00036
00037 #include <sstream>
00038
00039 #include <time.h>
00040 #include <math.h>
00041
00042
00043
00044 static const long s_secondsPerDay = 24 * 3600;
00045 static const long s_secondsPerWeek = 7 * s_secondsPerDay;
00046
00047 static const long s_firstSunday = 3 * s_secondsPerDay;
00048
00049
00050
00051
00052
00053
00054
00055 struct month_entry_t {
00056 const char *name;
00057 int month;
00058 };
00059
00060
00061
00062
00063
00064
00065
00066 #define MONTH_ENTRY(name, month) { #name , month },
00067
00068 static const month_entry_t s_Months[] = {
00069 MONTH_ENTRY(1, 1)
00070 MONTH_ENTRY(01, 1)
00071 MONTH_ENTRY(jan, 1)
00072 MONTH_ENTRY(january, 1)
00073
00074 MONTH_ENTRY(2, 2)
00075 MONTH_ENTRY(02, 2)
00076 MONTH_ENTRY(feb, 2)
00077 MONTH_ENTRY(february, 2)
00078
00079 MONTH_ENTRY(3, 3)
00080 MONTH_ENTRY(03, 3)
00081 MONTH_ENTRY(mar, 3)
00082 MONTH_ENTRY(march, 3)
00083
00084 MONTH_ENTRY(4, 4)
00085 MONTH_ENTRY(04, 4)
00086 MONTH_ENTRY(apr, 4)
00087 MONTH_ENTRY(april, 4)
00088
00089 MONTH_ENTRY(5, 5)
00090 MONTH_ENTRY(05, 5)
00091 MONTH_ENTRY(may, 5)
00092
00093 MONTH_ENTRY(6, 6)
00094 MONTH_ENTRY(06, 6)
00095 MONTH_ENTRY(jun, 6)
00096 MONTH_ENTRY(june, 6)
00097
00098 MONTH_ENTRY(7, 7)
00099 MONTH_ENTRY(07, 7)
00100 MONTH_ENTRY(jul, 7)
00101 MONTH_ENTRY(july, 7)
00102
00103 MONTH_ENTRY(8, 8)
00104 MONTH_ENTRY(08, 8)
00105 MONTH_ENTRY(aug, 8)
00106 MONTH_ENTRY(august, 8)
00107
00108 MONTH_ENTRY(9, 9)
00109 MONTH_ENTRY(09, 9)
00110 MONTH_ENTRY(sep, 9)
00111 MONTH_ENTRY(september, 9)
00112
00113 MONTH_ENTRY(10, 10)
00114 MONTH_ENTRY(oct, 10)
00115 MONTH_ENTRY(october, 10)
00116
00117 MONTH_ENTRY(11, 11)
00118 MONTH_ENTRY(nov, 11)
00119 MONTH_ENTRY(november, 11)
00120
00121 MONTH_ENTRY(12, 12)
00122 MONTH_ENTRY(dec, 12)
00123 MONTH_ENTRY(december, 12)
00124
00125
00126 { NULL, 0 }
00127 };
00128
00129
00130
00131 static const char * s_MonthsDisplay[] = {
00132 "jan",
00133 "feb",
00134 "mar",
00135 "apr",
00136 "may",
00137 "jun",
00138 "jul",
00139 "aug",
00140 "sep",
00141 "oct",
00142 "nov",
00143 "dec"
00144 };
00145
00146
00147
00148 static const char * s_Weekdays[] = {
00149 "sun",
00150 "mon",
00151 "tue",
00152 "wed",
00153 "thu",
00154 "fri",
00155 "sat"
00156 };
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 static const char *
00167 get_month_display
00168 (
00169 IN int month
00170 )
00171 throw()
00172 {
00173 ASSERT(month >= 0, "invalid month index");
00174 ASSERT(month < 12, "invalid month index");
00175
00176 return s_MonthsDisplay[month];
00177 }
00178
00179
00180
00181 static double
00182 my_trunc
00183 (
00184 IN double x
00185 )
00186 throw()
00187 {
00188 ASSERT(x < 2.0e9, "x too big");
00189 ASSERT(x > -2.0e9, "x too small");
00190
00191 double t;
00192
00193 if (x >= 0.0) {
00194 long l = (long) x;
00195 double frac = x - l;
00196 t = x - frac;
00197 } else {
00198 t = -my_trunc(-x);
00199 }
00200
00201
00202
00203 return t;
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 int
00215 GetMonthFromString
00216 (
00217 IN const char * month
00218 )
00219 throw()
00220 {
00221 ASSERT(month, "NULL month");
00222
00223 for (const month_entry_t * p = s_Months; p->name; ++p) {
00224 if (!strcasecmp(p->name, month))
00225 return p->month;
00226 }
00227
00228
00229 return 0;
00230 }
00231
00232
00233
00234 void
00235 getDisplayableDateFromNetTime
00236 (
00237 IN long time,
00238 OUT std::string& display
00239 )
00240 {
00241 ASSERT(time > 0, "Bad time: %ld", time);
00242
00243 char buffer[32];
00244
00245 #ifdef WIN32
00246
00247 time_t ttTime;
00248 strncpy(buffer, ctime(&ttTime), 26);
00249 #else // WIN32
00250 ctime_r(&time, buffer);
00251 #endif // WIN32
00252
00253 buffer[24] = 0;
00254
00255 display = buffer;
00256 }
00257
00258
00259 const char *
00260 getDateString
00261 (
00262 IN long timestamp
00263 )
00264 {
00265 time_t ttTime = timestamp;
00266 struct tm * t = localtime(&ttTime);
00267 ASSERT(t, "null");
00268
00269 static const int s_bufSize = 32;
00270 static char s_buffer[s_bufSize];
00271 sprintf(s_buffer, "%02d-%s-%04d %02d:%02d:%02d",
00272 t->tm_mday, get_month_display(t->tm_mon), t->tm_year + 1900,
00273 t->tm_hour, t->tm_min, t->tm_sec);
00274
00275 return s_buffer;
00276 }
00277
00278
00279
00280 void
00281 getDateStringFromNetTime
00282 (
00283 IN long time,
00284 OUT std::string& display
00285 )
00286 {
00287 ASSERT(time > 0, "Bad time: %ld", time);
00288
00289 display = getDateString(time);
00290 }
00291
00292
00293
00294 static const char *
00295 extractInteger
00296 (
00297 IN const char * s,
00298 IN char separator,
00299 OUT int& x,
00300 IN int min,
00301 IN int max,
00302 IN int digits_required
00303 )
00304 throw()
00305 {
00306 ASSERT(s, "null");
00307
00308 ASSERT(max > min, "Bad range?");
00309
00310 int digits_read = 0;
00311 x = 0;
00312 while (*s && *s != separator) {
00313 int i = *s - '0';
00314 x = (10 * x) + i;
00315 ++digits_read;
00316 ++s;
00317 }
00318 if (*s)
00319 ++s;
00320
00321
00322
00323 if (digits_read < digits_required)
00324 return NULL;
00325 if (x < min)
00326 return NULL;
00327 if (x > max)
00328 return NULL;
00329
00330 return s;
00331 }
00332
00333
00334
00335 static const char *
00336 extractString
00337 (
00338 IN const char * s,
00339 IN char separator,
00340 IO char * buf,
00341 IN int size
00342 )
00343 throw()
00344 {
00345 ASSERT(s, "null");
00346 ASSERT(buf, "null");
00347 ASSERT(size > 0, "Bad buffer size: %d", size);
00348
00349 int idx = 0;
00350 while (*s && *s != separator && idx < size - 1) {
00351 buf[idx] = *s;
00352 ++idx;
00353 ++s;
00354 }
00355 buf[idx] = 0;
00356 if (*s)
00357 ++s;
00358
00359 if (0 == idx)
00360 return 0;
00361
00362 return s;
00363 }
00364
00365
00366
00367 long
00368 getNetTimeFromDateString
00369 (
00370 IN const char * s
00371 )
00372 throw()
00373 {
00374 ASSERT(s, "null");
00375
00376 struct tm t;
00377
00378
00379
00380
00381 s = extractInteger(s, '-', t.tm_mday, 1, 31, 1);
00382 if (!s)
00383 return -1;
00384
00385
00386 static const int s_bufSize = 4;
00387 char buffer[s_bufSize];
00388 s = extractString(s, '-', buffer, s_bufSize);
00389 if (!s)
00390 return -1;
00391 t.tm_mon = GetMonthFromString(buffer);
00392 if (t.tm_mon < 1)
00393 return -1;
00394 --t.tm_mon;
00395
00396
00397 s = extractInteger(s, ' ', t.tm_year, -10000, +10000, 4);
00398 if (!s)
00399 return -1;
00400 t.tm_year -= 1900;
00401
00402
00403 s = extractInteger(s, ':', t.tm_hour, 0, 23, 2);
00404 if (!s)
00405 return -1;
00406
00407
00408 s = extractInteger(s, ':', t.tm_min, 0, 59, 2);
00409 if (!s)
00410 return -1;
00411
00412
00413 s = extractInteger(s, 0, t.tm_sec, 0, 59, 2);
00414 if (!s)
00415 return -1;
00416
00417
00418
00419
00420
00421
00422
00423 return mktime(&t);
00424 }
00425
00426
00427
00428 int
00429 getWeekdayFromNetTime
00430 (
00431 IN long time
00432 )
00433 throw()
00434 {
00435 ASSERT(time > 0, "Bad net time");
00436
00437 long day = time / (24 * 3600);
00438
00439
00440 return (day + 4) % 7;
00441 }
00442
00443
00444 const char *
00445 GetWeekday
00446 (
00447 IN int weekday_index
00448 )
00449 throw()
00450 {
00451 ASSERT(weekday_index >= 0, "Bad weekday index");
00452 ASSERT(weekday_index < 7, "Bad weekday index");
00453
00454 return s_Weekdays[weekday_index];
00455 }
00456
00457
00458
00459 const char *
00460 GetMonth
00461 (
00462 IN int month_index
00463 )
00464 throw()
00465 {
00466 return get_month_display(month_index);
00467 }
00468
00469
00470
00471
00472
00473
00474
00475 long
00476 getDayBucket
00477 (
00478 IN long timestamp
00479 )
00480 throw()
00481 {
00482 ASSERT(timestamp > 0, "bad timestamp: %ld", timestamp);
00483
00484
00485 return timestamp / s_secondsPerDay;
00486 }
00487
00488
00489 long
00490 getWeekBucket
00491 (
00492 IN long timestamp
00493 )
00494 throw()
00495 {
00496 ASSERT(timestamp > 0, "bad timestamp: %ld", timestamp);
00497
00498 return (timestamp - s_firstSunday) / (s_secondsPerWeek);
00499 }
00500
00501
00502
00503 long
00504 getMonthBucket
00505 (
00506 IN long timestamp
00507 )
00508 throw()
00509 {
00510 ASSERT(timestamp > 0, "bad timestamp: %ld", timestamp);
00511
00512 time_t ttTime = timestamp;
00513 struct tm * tm = gmtime(&ttTime);
00514 return tm->tm_mon + (tm->tm_year * 12);
00515 }
00516
00517
00518
00519 long
00520 getYearBucket
00521 (
00522 IN long timestamp
00523 )
00524 throw()
00525 {
00526 ASSERT(timestamp > 0, "bad timestamp: %ld", timestamp);
00527
00528 time_t ttTime = timestamp;
00529 struct tm * tm = gmtime(&ttTime);
00530 return tm->tm_year;
00531 }
00532
00533
00534
00535 std::string
00536 getDayBucketName
00537 (
00538 IN long day_bucket
00539 )
00540 {
00541 return getDateString(day_bucket * s_secondsPerDay);
00542 }
00543
00544
00545
00546 std::string
00547 getWeekBucketName
00548 (
00549 IN long week_bucket
00550 )
00551 {
00552 return getDateString((week_bucket * s_secondsPerWeek) + s_firstSunday);
00553 }
00554
00555
00556 std::string
00557 getMonthBucketName
00558 (
00559 IN long month_bucket
00560 )
00561 {
00562 std::ostringstream out;
00563 out << s_MonthsDisplay[month_bucket % 12] << " " << (1900 + (month_bucket / 12));
00564 return out.str();
00565 }
00566
00567
00568 std::string
00569 getYearBucketName
00570 (
00571 IN long year_bucket
00572 )
00573 {
00574 std::ostringstream out;
00575 out << (1900 + year_bucket);
00576 return out.str();
00577 }
00578