00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00027 #include <config.h>
00028
00029 #if TIME_WITH_SYS_TIME
00030 # include <sys/time.h>
00031 # include <time.h>
00032 #else
00033 # if HAVE_SYS_TIME_H
00034 # include <sys/time.h>
00035 # else
00036 # include <time.h>
00037 # endif
00038 #endif
00039 #include <cstdlib>
00040
00041 #include <drizzled/calendar.h>
00042
00043 namespace drizzled
00044 {
00045
00047 static const uint32_t __leap_days_in_month[12]= {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
00048 static const uint32_t __normal_days_in_month[12]= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
00049 static const uint32_t __leap_days_to_end_month[13]= {0, 31, 60, 91, 121, 151, 182, 213, 244, 274, 305, 335, 366};
00050 static const uint32_t __normal_days_to_end_month[13]= {0, 31, 59, 90, 120, 150, 181, 212, 243, 273, 304, 334, 365};
00051
00056 inline static const uint32_t* days_in_month(uint32_t y, enum calendar c)
00057 {
00058 if (is_leap_year(y, c))
00059 return __leap_days_in_month;
00060 else
00061 return __normal_days_in_month;
00062 }
00063
00064 inline static const uint32_t* days_to_end_month(uint32_t y, enum calendar c)
00065 {
00066 if (is_leap_year(y, c))
00067 return __leap_days_to_end_month;
00068 else
00069 return __normal_days_to_end_month;
00070 }
00071
00072
00101 int64_t julian_day_number_from_gregorian_date(uint32_t year, uint32_t month, uint32_t day)
00102 {
00103 int64_t day_number;
00104 int64_t a= (14 - month) / 12;
00105 int64_t y= year + 4800 - a;
00106 int64_t m= month + (12 * a) - 3;
00107
00108 day_number= day + (((153 * m) + 2) / 5) + (365 * y) + (y / 4) - (y / 100) + (y / 400) - 32045;
00109 return day_number;
00110 }
00111
00119 int64_t absolute_day_number_to_julian_day_number(int64_t absolute_day)
00120 {
00121 return absolute_day + JULIAN_DAY_NUMBER_AT_ABSOLUTE_DAY_ONE;
00122 }
00123
00131 int64_t julian_day_number_to_absolute_day_number(int64_t julian_day)
00132 {
00133 return julian_day - JULIAN_DAY_NUMBER_AT_ABSOLUTE_DAY_ONE;
00134 }
00135
00148 void gregorian_date_from_julian_day_number(int64_t julian_day
00149 , uint32_t *year_out
00150 , uint32_t *month_out
00151 , uint32_t *day_out)
00152 {
00153 int64_t j = julian_day + 32044;
00154 int64_t g = j / 146097;
00155 int64_t dg = j % 146097;
00156 int64_t c = (dg / 36524 + 1) * 3 / 4;
00157 int64_t dc = dg - c * 36524;
00158 int64_t b = dc / 1461;
00159 int64_t db = dc % 1461;
00160 int64_t a = (db / 365 + 1) * 3 / 4;
00161 int64_t da = db - a * 365;
00162 int64_t y = g * 400 + c * 100 + b * 4 + a;
00163 int64_t m = (da * 5 + 308) / 153 - 2;
00164 int64_t d = da - (m + 4) * 153 / 5 + 122;
00165 int64_t Y = y - 4800 + (m + 2) / 12;
00166 int64_t M = (m + 2) % 12 + 1;
00167 int64_t D = (int64_t)((double)d + 1.5);
00168
00169
00170 *year_out= (uint32_t) Y;
00171 *month_out= (uint32_t) M;
00172 *day_out= (uint32_t) D;
00173 }
00174
00185 void gregorian_date_from_absolute_day_number(int64_t absolute_day
00186 , uint32_t *year_out
00187 , uint32_t *month_out
00188 , uint32_t *day_out)
00189 {
00190 gregorian_date_from_julian_day_number(
00191 absolute_day_number_to_julian_day_number(absolute_day)
00192 , year_out
00193 , month_out
00194 , day_out);
00195 }
00196
00218 inline uint32_t days_in_year(const uint32_t year, enum calendar calendar)
00219 {
00220 if (calendar == GREGORIAN)
00221 return days_in_year_gregorian(year);
00222 return days_in_year_julian(year);
00223 }
00224
00230 inline uint32_t days_in_year_julian(const uint32_t year)
00231 {
00232
00233 return (year & 3) == 0;
00234 }
00235
00241 inline uint32_t days_in_year_gregorian(const uint32_t year)
00242 {
00243
00244 if ((year & 1) == 1)
00245 return 365;
00246 return (
00247 (year & 3) == 0
00248 && (year % 100 || ((year % 400 == 0) && year))
00249 ? 366
00250 : 365
00251 );
00252 }
00253
00279 uint32_t day_of_week(int64_t day_number
00280 , bool sunday_is_first_day_of_week)
00281 {
00282 uint32_t tmp= (uint32_t) (day_number % 7);
00283
00284 if (sunday_is_first_day_of_week)
00285 tmp= (tmp == 6 ? 0 : tmp + 1);
00286 return tmp;
00287 }
00288
00297 bool is_valid_gregorian_date(uint32_t year, uint32_t month, uint32_t day)
00298 {
00299 if (year < 1)
00300 return false;
00301 if (month != 2)
00302 return (day <= __normal_days_in_month[month - 1]);
00303 else
00304 {
00305 const uint32_t *p_months= days_in_month(year, (enum calendar) GREGORIAN);
00306 return (day <= p_months[1]);
00307 }
00308 }
00309
00317 uint32_t days_in_gregorian_year_month(uint32_t year, uint32_t month)
00318 {
00319 const uint32_t *p_months= days_in_month(year, GREGORIAN);
00320 return p_months[month - 1];
00321 }
00322
00336 bool in_unix_epoch_range(uint32_t year,
00337 uint32_t month,
00338 uint32_t day,
00339 uint32_t hour,
00340 uint32_t minute,
00341 uint32_t second)
00342 {
00343 if (month == 0 || day == 0)
00344 return false;
00345
00346 if (year < UNIX_EPOCH_MAX_YEARS
00347 && year >= UNIX_EPOCH_MIN_YEARS)
00348 return true;
00349
00350 if (year < UNIX_EPOCH_MIN_YEARS)
00351 return false;
00352
00353 if (year == UNIX_EPOCH_MAX_YEARS)
00354 {
00355 if (month > 1)
00356 {
00357 return false;
00358 }
00359 if (day > 19)
00360 {
00361 return false;
00362 }
00363 else if (day < 19)
00364 {
00365 return true;
00366 }
00367 else
00368 {
00369
00370 uint32_t seconds= (hour * 60 * 60)
00371 + (minute * 60)
00372 + (second);
00373 if (seconds <= ((3 * 60 * 60) + (14 * 60) + 7))
00374 return true;
00375 return false;
00376 }
00377 }
00378 return false;
00379 }
00380
00394 uint32_t week_number_from_gregorian_date(uint32_t year
00395 , uint32_t month
00396 , uint32_t day
00397 , bool sunday_is_first_day_of_week)
00398 {
00399 struct tm broken_time;
00400
00401 broken_time.tm_year= year;
00402 broken_time.tm_mon= month - 1;
00403 broken_time.tm_mday= day;
00404
00405
00406 (void) mktime(&broken_time);
00407
00408 char result[3];
00409 size_t result_len= strftime(result
00410 , sizeof(result)
00411 , (sunday_is_first_day_of_week ? "%U" : "%W")
00412 , &broken_time);
00413
00414 if (result_len != 0)
00415 return (uint32_t) atoi(result);
00416 return 0;
00417 }
00418
00437 uint32_t iso_week_number_from_gregorian_date(uint32_t year
00438 , uint32_t month
00439 , uint32_t day)
00440 {
00441 struct tm broken_time;
00442
00443 broken_time.tm_year= year;
00444 broken_time.tm_mon= month - 1;
00445 broken_time.tm_mday= day;
00446
00447
00448 (void) mktime(&broken_time);
00449
00450 char result[3];
00451 size_t result_len= strftime(result
00452 , sizeof(result)
00453 , "%V"
00454 , &broken_time);
00455
00456
00457 if (result_len == 0)
00458 return 0;
00459
00460 uint32_t week_number= (uint32_t) atoi(result);
00461
00462 return week_number;
00463 }
00464
00471 uint32_t year_month_to_months(uint32_t year_month)
00472 {
00473 if (year_month == 0)
00474 return 0L;
00475
00476 uint32_t years= year_month / 100;
00477 if (years < CALENDAR_YY_PART_YEAR)
00478 years+= 2000;
00479 else if (years < 100)
00480 years+= 1900;
00481
00482 uint32_t months= year_month % 100;
00483 return (years * 12) + (months - 1);
00484 }
00485
00492 uint32_t months_to_year_month(uint32_t months)
00493 {
00494 if (months == 0L)
00495 return 0L;
00496
00497 uint32_t years= (months / 12);
00498
00499 if (years < 100)
00500 years+= (years < CALENDAR_YY_PART_YEAR) ? 2000 : 1900;
00501
00502 return (years * 100) + (months % 12) + 1;
00503 }
00504
00505 }