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 int
00214 GetMonthFromString
00215 (
00216 IN const char * month
00217 )
00218 throw()
00219 {
00220 ASSERT(month, "NULL month");
00221
00222 for (const month_entry_t * p = s_Months; p->name; ++p) {
00223 if (!strcasecmp(p->name, month))
00224 return p->month;
00225 }
00226
00227
00228 return 0;
00229 }
00230
00231
00232
00233 void
00234 getDisplayableDateFromNetTime
00235 (
00236 IN long time,
00237 OUT std::string& display
00238 )
00239 {
00240 ASSERT(time > 0, "Bad time: %ld", time);
00241
00242 char buffer[32];
00243
00244 #ifdef WIN32
00245
00246 strncpy(buffer, ctime(&time), 26);
00247 #else // WIN32
00248 ctime_r(&time, buffer);
00249 #endif // WIN32
00250
00251 buffer[24] = 0;
00252
00253 display = buffer;
00254 }
00255
00256
00257 const char *
00258 getDateString
00259 (
00260 IN long timestamp
00261 )
00262 {
00263 struct tm * t = localtime(×tamp);
00264 ASSERT(t, "null");
00265
00266 static const int s_bufSize = 32;
00267 static char s_buffer[s_bufSize];
00268 sprintf(s_buffer, "%02d-%s-%04d %02d:%02d:%02d",
00269 t->tm_mday, get_month_display(t->tm_mon), t->tm_year + 1900,
00270 t->tm_hour, t->tm_min, t->tm_sec);
00271
00272 return s_buffer;
00273 }
00274
00275
00276
00277 void
00278 getDateStringFromNetTime
00279 (
00280 IN long time,
00281 OUT std::string& display
00282 )
00283 {
00284 ASSERT(time > 0, "Bad time: %ld", time);
00285
00286 display = getDateString(time);
00287 }
00288
00289
00290
00291 static const char *
00292 extractInteger
00293 (
00294 IN const char * s,
00295 IN char separator,
00296 OUT int& x,
00297 IN int min,
00298 IN int max,
00299 IN int digits_required
00300 )
00301 throw()
00302 {
00303 ASSERT(s, "null");
00304
00305 ASSERT(max > min, "Bad range?");
00306
00307 int digits_read = 0;
00308 x = 0;
00309 while (*s && *s != separator) {
00310 int i = *s - '0';
00311 x = (10 * x) + i;
00312 ++digits_read;
00313 ++s;
00314 }
00315 if (*s)
00316 ++s;
00317
00318
00319
00320 if (digits_read < digits_required)
00321 return NULL;
00322 if (x < min)
00323 return NULL;
00324 if (x > max)
00325 return NULL;
00326
00327 return s;
00328 }
00329
00330
00331
00332 static const char *
00333 extractString
00334 (
00335 IN const char * s,
00336 IN char separator,
00337 IO char * buf,
00338 IN int size
00339 )
00340 throw()
00341 {
00342 ASSERT(s, "null");
00343 ASSERT(buf, "null");
00344 ASSERT(size > 0, "Bad buffer size: %d", size);
00345
00346 int idx = 0;
00347 while (*s && *s != separator && idx < size - 1) {
00348 buf[idx] = *s;
00349 ++idx;
00350 ++s;
00351 }
00352 buf[idx] = 0;
00353 if (*s)
00354 ++s;
00355
00356 if (0 == idx)
00357 return 0;
00358
00359 return s;
00360 }
00361
00362
00363
00364 long
00365 getNetTimeFromDateString
00366 (
00367 IN const char * s
00368 )
00369 throw()
00370 {
00371 ASSERT(s, "null");
00372
00373 struct tm t;
00374
00375
00376
00377
00378 s = extractInteger(s, '-', t.tm_mday, 1, 31, 1);
00379 if (!s)
00380 return -1;
00381
00382
00383 static const int s_bufSize = 4;
00384 char buffer[s_bufSize];
00385 s = extractString(s, '-', buffer, s_bufSize);
00386 if (!s)
00387 return -1;
00388 t.tm_mon = GetMonthFromString(buffer);
00389 if (t.tm_mon < 1)
00390 return -1;
00391 --t.tm_mon;
00392
00393
00394 s = extractInteger(s, ' ', t.tm_year, -10000, +10000, 4);
00395 if (!s)
00396 return -1;
00397 t.tm_year -= 1900;
00398
00399
00400 s = extractInteger(s, ':', t.tm_hour, 0, 23, 2);
00401 if (!s)
00402 return -1;
00403
00404
00405 s = extractInteger(s, ':', t.tm_min, 0, 59, 2);
00406 if (!s)
00407 return -1;
00408
00409
00410 s = extractInteger(s, 0, t.tm_sec, 0, 59, 2);
00411 if (!s)
00412 return -1;
00413
00414
00415
00416
00417
00418
00419
00420 return mktime(&t);
00421 }
00422
00423
00424
00425 int
00426 getWeekdayFromNetTime
00427 (
00428 IN long time
00429 )
00430 throw()
00431 {
00432 ASSERT(time > 0, "Bad net time");
00433
00434 long day = time / (24 * 3600);
00435
00436
00437 return (day + 4) % 7;
00438 }
00439
00440
00441 const char *
00442 GetWeekday
00443 (
00444 IN int weekday_index
00445 )
00446 throw()
00447 {
00448 ASSERT(weekday_index >= 0, "Bad weekday index");
00449 ASSERT(weekday_index < 7, "Bad weekday index");
00450
00451 return s_Weekdays[weekday_index];
00452 }
00453
00454
00455
00456 const char *
00457 GetMonth
00458 (
00459 IN int month_index
00460 )
00461 throw()
00462 {
00463 return get_month_display(month_index);
00464 }
00465
00466
00467
00468
00469
00470
00471
00472 long
00473 getDayBucket
00474 (
00475 IN long timestamp
00476 )
00477 throw()
00478 {
00479 ASSERT(timestamp > 0, "bad timestamp: %ld", timestamp);
00480
00481
00482 return timestamp / s_secondsPerDay;
00483 }
00484
00485
00486 long
00487 getWeekBucket
00488 (
00489 IN long timestamp
00490 )
00491 throw()
00492 {
00493 ASSERT(timestamp > 0, "bad timestamp: %ld", timestamp);
00494
00495 return (timestamp - s_firstSunday) / (s_secondsPerWeek);
00496 }
00497
00498
00499
00500 long
00501 getMonthBucket
00502 (
00503 IN long timestamp
00504 )
00505 throw()
00506 {
00507 ASSERT(timestamp > 0, "bad timestamp: %ld", timestamp);
00508
00509 struct tm * tm = gmtime(×tamp);
00510 return tm->tm_mon + (tm->tm_year * 12);
00511 }
00512
00513
00514
00515 long
00516 getYearBucket
00517 (
00518 IN long timestamp
00519 )
00520 throw()
00521 {
00522 ASSERT(timestamp > 0, "bad timestamp: %ld", timestamp);
00523
00524 struct tm * tm = gmtime(×tamp);
00525 return tm->tm_year;
00526 }
00527
00528
00529
00530 std::string
00531 getDayBucketName
00532 (
00533 IN long day_bucket
00534 )
00535 {
00536 return getDateString(day_bucket * s_secondsPerDay);
00537 }
00538
00539
00540
00541 std::string
00542 getWeekBucketName
00543 (
00544 IN long week_bucket
00545 )
00546 {
00547 return getDateString((week_bucket * s_secondsPerWeek) + s_firstSunday);
00548 }
00549
00550
00551 std::string
00552 getMonthBucketName
00553 (
00554 IN long month_bucket
00555 )
00556 {
00557 std::ostringstream out;
00558 out << s_MonthsDisplay[month_bucket % 12] << " " << (1900 + (month_bucket / 12));
00559 return out.str();
00560 }
00561
00562
00563 std::string
00564 getYearBucketName
00565 (
00566 IN long year_bucket
00567 )
00568 {
00569 std::ostringstream out;
00570 out << (1900 + year_bucket);
00571 return out.str();
00572 }
00573