Drizzled Public API Documentation

calendar.cc
Go to the documentation of this file.
1 /* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3  *
4  * Copyright (C) 2008 Sun Microsystems, Inc.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
27 #include <config.h>
28 
29 #if TIME_WITH_SYS_TIME
30 # include <sys/time.h>
31 # include <time.h>
32 #else
33 # if HAVE_SYS_TIME_H
34 # include <sys/time.h>
35 # else
36 # include <time.h>
37 # endif
38 #endif
39 #include <cstdlib>
40 
41 #include <drizzled/calendar.h>
42 
43 namespace drizzled
44 {
45 
47 static const uint32_t __leap_days_in_month[12]= {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
48 static const uint32_t __normal_days_in_month[12]= {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
49 static const uint32_t __leap_days_to_end_month[13]= {0, 31, 60, 91, 121, 151, 182, 213, 244, 274, 305, 335, 366};
50 static const uint32_t __normal_days_to_end_month[13]= {0, 31, 59, 90, 120, 150, 181, 212, 243, 273, 304, 334, 365};
51 
56 inline static const uint32_t* days_in_month(uint32_t y, enum calendar c)
57 {
58  if (is_leap_year(y, c))
59  return __leap_days_in_month;
60  else
61  return __normal_days_in_month;
62 }
63 
64 inline static const uint32_t* days_to_end_month(uint32_t y, enum calendar c)
65 {
66  if (is_leap_year(y, c))
67  return __leap_days_to_end_month;
68  else
69  return __normal_days_to_end_month;
70 }
71 
72 
101 int64_t julian_day_number_from_gregorian_date(uint32_t year, uint32_t month, uint32_t day)
102 {
103  int64_t day_number;
104  int64_t a= (14 - month) / 12;
105  int64_t y= year + 4800 - a;
106  int64_t m= month + (12 * a) - 3;
107 
108  day_number= day + (((153 * m) + 2) / 5) + (365 * y) + (y / 4) - (y / 100) + (y / 400) - 32045;
109  return day_number;
110 }
111 
119 int64_t absolute_day_number_to_julian_day_number(int64_t absolute_day)
120 {
121  return absolute_day + JULIAN_DAY_NUMBER_AT_ABSOLUTE_DAY_ONE;
122 }
123 
131 int64_t julian_day_number_to_absolute_day_number(int64_t julian_day)
132 {
133  return julian_day - JULIAN_DAY_NUMBER_AT_ABSOLUTE_DAY_ONE;
134 }
135 
149  , uint32_t *year_out
150  , uint32_t *month_out
151  , uint32_t *day_out)
152 {
153  int64_t j = julian_day + 32044;
154  int64_t g = j / 146097;
155  int64_t dg = j % 146097;
156  int64_t c = (dg / 36524 + 1) * 3 / 4;
157  int64_t dc = dg - c * 36524;
158  int64_t b = dc / 1461;
159  int64_t db = dc % 1461;
160  int64_t a = (db / 365 + 1) * 3 / 4;
161  int64_t da = db - a * 365;
162  int64_t y = g * 400 + c * 100 + b * 4 + a;
163  int64_t m = (da * 5 + 308) / 153 - 2;
164  int64_t d = da - (m + 4) * 153 / 5 + 122;
165  int64_t Y = y - 4800 + (m + 2) / 12;
166  int64_t M = (m + 2) % 12 + 1;
167  int64_t D = (int64_t)((double)d + 1.5);
168 
169  /* Push out parameters */
170  *year_out= (uint32_t) Y;
171  *month_out= (uint32_t) M;
172  *day_out= (uint32_t) D;
173 }
174 
186  , uint32_t *year_out
187  , uint32_t *month_out
188  , uint32_t *day_out)
189 {
192  , year_out
193  , month_out
194  , day_out);
195 }
196 
218 inline uint32_t days_in_year(const uint32_t year, enum calendar calendar)
219 {
220  if (calendar == GREGORIAN)
221  return days_in_year_gregorian(year);
222  return days_in_year_julian(year);
223 }
224 
230 inline uint32_t days_in_year_julian(const uint32_t year)
231 {
232  /* Short-circuit. No odd years can be leap years... */
233  return (year & 3) == 0;
234 }
235 
241 inline uint32_t days_in_year_gregorian(const uint32_t year)
242 {
243  /* Short-circuit. No odd years can be leap years... */
244  if ((year & 1) == 1)
245  return 365;
246  return (
247  (year & 3) == 0
248  && (year % 100 || ((year % 400 == 0) && year))
249  ? 366
250  : 365
251  );
252 }
253 
279 uint32_t day_of_week(int64_t day_number
280  , bool sunday_is_first_day_of_week)
281 {
282  uint32_t tmp= (uint32_t) (day_number % 7);
283  /* 0 returned from above modulo is a Monday */
284  if (sunday_is_first_day_of_week)
285  tmp= (tmp == 6 ? 0 : tmp + 1);
286  return tmp;
287 }
288 
297 bool is_valid_gregorian_date(uint32_t year, uint32_t month, uint32_t day)
298 {
299  if (year < 1)
300  return false;
301  if (month != 2)
302  return (day <= __normal_days_in_month[month - 1]);
303  else
304  {
305  const uint32_t *p_months= days_in_month(year, (enum calendar) GREGORIAN);
306  return (day <= p_months[1]);
307  }
308 }
309 
317 uint32_t days_in_gregorian_year_month(uint32_t year, uint32_t month)
318 {
319  const uint32_t *p_months= days_in_month(year, GREGORIAN);
320  return p_months[month - 1];
321 }
322 
336 bool in_unix_epoch_range(uint32_t year,
337  uint32_t month,
338  uint32_t day,
339  uint32_t hour,
340  uint32_t minute,
341  uint32_t second)
342 {
343  if (month == 0 || day == 0)
344  return false;
345 
346  if (year < UNIX_EPOCH_MAX_YEARS
347  && year >= UNIX_EPOCH_MIN_YEARS)
348  return true;
349 
350  if (year < UNIX_EPOCH_MIN_YEARS)
351  return false;
352 
353  if (year == UNIX_EPOCH_MAX_YEARS)
354  {
355  if (month > 1)
356  {
357  return false;
358  }
359  if (day > 19)
360  {
361  return false;
362  }
363  else if (day < 19)
364  {
365  return true;
366  }
367  else
368  {
369  /* We are on the final day of UNIX Epoch */
370  uint32_t seconds= (hour * 60 * 60)
371  + (minute * 60)
372  + (second);
373  if (seconds <= ((3 * 60 * 60) + (14 * 60) + 7))
374  return true;
375  return false;
376  }
377  }
378  return false;
379 }
380 
394 uint32_t week_number_from_gregorian_date(uint32_t year
395  , uint32_t month
396  , uint32_t day
397  , bool sunday_is_first_day_of_week)
398 {
399  struct tm broken_time;
400 
401  broken_time.tm_year= year;
402  broken_time.tm_mon= month - 1; /* struct tm has non-ordinal months */
403  broken_time.tm_mday= day;
404 
405  /* fill out the rest of our tm fields. */
406  (void) mktime(&broken_time);
407 
408  char result[3]; /* 3 is enough space for a max 2-digit week number */
409  size_t result_len= strftime(result
410  , sizeof(result)
411  , (sunday_is_first_day_of_week ? "%U" : "%W")
412  , &broken_time);
413 
414  if (result_len != 0)
415  return (uint32_t) atoi(result);
416  return 0;
417 }
418 
438  , uint32_t month
439  , uint32_t day)
440 {
441  struct tm broken_time;
442 
443  broken_time.tm_year= year;
444  broken_time.tm_mon= month - 1; /* struct tm has non-ordinal months */
445  broken_time.tm_mday= day;
446 
447  /* fill out the rest of our tm fields. */
448  (void) mktime(&broken_time);
449 
450  char result[3]; /* 3 is enough space for a max 2-digit week number */
451  size_t result_len= strftime(result
452  , sizeof(result)
453  , "%V"
454  , &broken_time);
455 
456 
457  if (result_len == 0)
458  return 0; /* Not valid for ISO8601:1988 */
459 
460  uint32_t week_number= (uint32_t) atoi(result);
461 
462  return week_number;
463 }
464 
471 uint32_t year_month_to_months(uint32_t year_month)
472 {
473  if (year_month == 0)
474  return 0L;
475 
476  uint32_t years= year_month / 100;
477  if (years < CALENDAR_YY_PART_YEAR)
478  years+= 2000;
479  else if (years < 100)
480  years+= 1900;
481 
482  uint32_t months= year_month % 100;
483  return (years * 12) + (months - 1);
484 }
485 
492 uint32_t months_to_year_month(uint32_t months)
493 {
494  if (months == 0L)
495  return 0L;
496 
497  uint32_t years= (months / 12);
498 
499  if (years < 100)
500  years+= (years < CALENDAR_YY_PART_YEAR) ? 2000 : 1900;
501 
502  return (years * 100) + (months % 12) + 1;
503 }
504 
505 } /* namespace drizzled */
uint32_t days_in_gregorian_year_month(uint32_t year, uint32_t month)
Definition: calendar.cc:317
bool is_valid_gregorian_date(uint32_t year, uint32_t month, uint32_t day)
Definition: calendar.cc:297
static bool is_leap_year(uint32_t y, enum calendar c)
Definition: calendar.h:316
TODO: Rename this file - func.h is stupid.
uint32_t year_month_to_months(uint32_t year_month)
Definition: calendar.cc:471
int64_t julian_day_number_from_gregorian_date(uint32_t year, uint32_t month, uint32_t day)
Definition: calendar.cc:101
uint32_t days_in_year_gregorian(const uint32_t year)
Definition: calendar.cc:241
static const uint32_t __leap_days_in_month[12]
Definition: calendar.cc:47
uint32_t months_to_year_month(uint32_t months)
Definition: calendar.cc:492
uint32_t days_in_year_julian(const uint32_t year)
Definition: calendar.cc:230
uint32_t days_in_year(const uint32_t year, enum calendar calendar)
Definition: calendar.cc:218
void gregorian_date_from_absolute_day_number(int64_t absolute_day, uint32_t *year_out, uint32_t *month_out, uint32_t *day_out)
Definition: calendar.cc:185
void gregorian_date_from_julian_day_number(int64_t julian_day, uint32_t *year_out, uint32_t *month_out, uint32_t *day_out)
Definition: calendar.cc:148
bool in_unix_epoch_range(uint32_t year, uint32_t month, uint32_t day, uint32_t hour, uint32_t minute, uint32_t second)
Definition: calendar.cc:336
uint32_t iso_week_number_from_gregorian_date(uint32_t year, uint32_t month, uint32_t day)
Definition: calendar.cc:437
int64_t absolute_day_number_to_julian_day_number(int64_t absolute_day)
Definition: calendar.cc:119
uint32_t day_of_week(int64_t day_number, bool sunday_is_first_day_of_week)
Definition: calendar.cc:279
uint32_t week_number_from_gregorian_date(uint32_t year, uint32_t month, uint32_t day, bool sunday_is_first_day_of_week)
Definition: calendar.cc:394
int64_t julian_day_number_to_absolute_day_number(int64_t julian_day)
Definition: calendar.cc:131