1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
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.
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.
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
24
* Structures and functions for:
26
* Calculating day number in Gregorian and Julian proleptic calendars.
27
* Converting between day numbers and dates in the calendars.
28
* Converting between different calendars.
29
* Calculating differences between dates.
31
* Works used in research:
33
* @cite "Calendrical Calculations", Dershowitz and Reingold
34
* @cite ISO 8601 http://en.wikipedia.org/wiki/ISO_8601
35
* @cite http://www.ddj.com/hpc-high-performance-computing/197006254
36
* @cite http://en.wikipedia.org/wiki/Julian_day#Calculation
39
#ifndef DRIZZLED_CALENDAR_H
40
#define DRIZZLED_CALENDAR_H
42
#define JULIAN_DAY_NUMBER_AT_ABSOLUTE_DAY_ONE INT64_C(1721425)
44
#define DAYS_IN_NORMAL_YEAR INT32_C(365)
45
#define DAYS_IN_LEAP_YEAR INT32_C(366)
47
#define GREGORIAN_START_YEAR 1582
48
#define GREGORIAN_START_MONTH 10
49
#define GREGORIAN_START_DAY 15
51
#define UNIX_EPOCH_MAX_YEARS 2038
52
#define UNIX_EPOCH_MIN_YEARS 1970
55
* The following constants define the system of calculating the number
56
* of days in various periods of time in the Gregorian calendar.
58
* Leap years (years containing 366 days) occur:
60
* - When the year is evenly divisible by 4
61
* - If the year is evenly divisible by 100, it must also
62
* be evenly divisible by 400.
64
#define GREGORIAN_DAYS_IN_400_YEARS UINT32_C(146097)
65
#define GREGORIAN_DAYS_IN_100_YEARS UINT32_C(36524)
66
#define GREGORIAN_DAYS_IN_4_YEARS UINT32_C(1461)
69
* Simple macro returning whether the supplied year
70
* is a leap year in the supplied calendar.
72
* @param Year to evaluate
73
* @param Calendar to use
75
#define IS_LEAP_YEAR(y, c) (days_in_year((y),(c)) == 366)
78
* Simple macro returning whether the supplied year
79
* is a leap year in the Gregorian proleptic calendar.
81
#define IS_GREGORIAN_LEAP_YEAR(y) (days_in_year_gregorian((y)) == 366)
84
* Simple macro returning whether the supplied year
85
* is a leap year in the Julian proleptic calendar.
87
#define IS_JULIAN_LEAP_YEAR(y) (days_in_year_julian((y)) == 366)
94
* Different calendars supported by the temporal library
105
* Calculates the Julian Day Number from the year, month
106
* and day supplied for a Gregorian Proleptic calendar date.
110
* Year month and day values are assumed to be valid. This
111
* method does no bounds checking or validation.
113
* @param Year of date
114
* @param Month of date
117
int64_t julian_day_number_from_gregorian_date(uint32_t year, uint32_t month, uint32_t day);
120
* Translates an absolute day number to a
123
* @param The absolute day number
125
int64_t absolute_day_number_to_julian_day_number(int64_t absolute_day);
128
* Translates a Julian day number to an
129
* absolute day number.
131
* @param The Julian day number
133
int64_t julian_day_number_to_absolute_day_number(int64_t julian_day);
136
* Given a supplied Julian Day Number, populates a year, month, and day
137
* with the date in the Gregorian Proleptic calendar which corresponds to
138
* the given Julian Day Number.
140
* @param Julian Day Number
141
* @param Pointer to year to populate
142
* @param Pointer to month to populate
143
* @param Pointer to the day to populate
145
void gregorian_date_from_julian_day_number(int64_t julian_day
147
, uint32_t *month_out
148
, uint32_t *day_out);
151
* Given a supplied Absolute Day Number, populates a year, month, and day
152
* with the date in the Gregorian Proleptic calendar which corresponds to
153
* the given Absolute Day Number.
155
* @param Absolute Day Number
156
* @param Pointer to year to populate
157
* @param Pointer to month to populate
158
* @param Pointer to the day to populate
160
void gregorian_date_from_absolute_day_number(int64_t absolute_day
162
, uint32_t *month_out
163
, uint32_t *day_out);
166
* Returns the number of days in a particular year.
168
* @param year to evaluate
169
* @param calendar to use
171
uint32_t days_in_year(uint32_t year, enum calendar calendar);
174
* Returns the number of days in a particular Gregorian Proleptic calendar year.
176
* @param year to evaluate
178
uint32_t days_in_year_gregorian(uint32_t year);
181
* Returns the number of days in a particular Julian Proleptic calendar year.
183
* @param year to evaluate
185
uint32_t days_in_year_julian(uint32_t year);
187
#define NUM_LEAP_YEARS(y, c) ((c) == GREGORIAN \
188
? number_of_leap_years_gregorian((y)) \
189
: number_of_leap_years_julian((y)))
192
* Returns the number of leap years that have
193
* occurred in the Julian Proleptic calendar
194
* up to the supplied year.
196
* @param year to evaluate (1 - 9999)
198
int32_t number_of_leap_years_julian(uint32_t year);
201
* Returns the number of leap years that have
202
* occurred in the Gregorian Proleptic calendar
203
* up to the supplied year.
205
* @param year to evaluate (1 - 9999)
207
int32_t number_of_leap_years_gregorian(uint32_t year);
210
* Returns the number of days in a month, given
211
* a year and a month in the Gregorian calendar.
213
* @param Year in Gregorian Proleptic calendar
214
* @param Month in date
216
uint32_t days_in_gregorian_year_month(uint32_t year, uint32_t month);
219
* Returns the number of the day in a week.
221
* @see temporal_to_number_days()
225
* Day Day Number Sunday first day?
226
* -------------- ----------- -----------------
242
* @param Number of days since start of Gregorian calendar.
243
* @param Consider Sunday the first day of the week?
245
uint32_t day_of_week(int64_t day_number, bool sunday_is_first_day_of_week);
248
* Given a year, month, and day, returns whether the date is
249
* valid for the Gregorian proleptic calendar.
255
bool is_valid_gregorian_date(uint32_t year, uint32_t month, uint32_t day);
258
* Returns whether the supplied date components are within the
259
* range of the UNIX epoch.
261
* Times in the range of 1970-01-01T00:00:00 to 2038-01-19T03:14:07
270
bool in_unix_epoch_range(uint32_t year
278
* I don't like using these defines, but probably good to keep in sync
279
* with MySQL's week mode stuff..
281
#define DRIZZLE_WEEK_MODE_MONDAY_FIRST_DAY 1
282
#define DRIZZLE_WEEK_MODE_USE_ISO_8601_1988 2
283
#define DRIZZLE_WEEK_MODE_WEEK_RANGE_IS_ORDINAL 4
286
* Returns the number of the week from a supplied year, month, and
287
* date in the Gregorian proleptic calendar.
289
* The week number returned will depend on the values of the
290
* various boolean flags passed to the function.
292
* The flags influence returned values in the following ways:
294
* sunday_is_first_day_of_week
296
* If TRUE, Sunday is first day of week
297
* If FALSE, Monday is first day of week
299
* week_range_is_ordinal
301
* If FALSE, the week is in range 0-53
303
* Week 0 is returned for the the last week of the previous year (for
304
* a date at start of january) In this case one can get 53 for the
305
* first week of next year. This flag ensures that the week is
306
* relevant for the given year.
308
* If TRUE, the week is in range 1-53.
310
* In this case one may get week 53 for a date in January (when
311
* the week is that last week of previous year) and week 1 for a
316
* If TRUE, the weeks are numbered according to ISO 8601:1988
318
* ISO 8601:1988 means that if the week containing January 1 has
319
* four or more days in the new year, then it is week 1;
320
* Otherwise it is the last week of the previous year, and the
321
* next week is week 1.
323
* If FALSE, the week that contains the first 'first-day-of-week' is week 1.
325
* @param Subject year
326
* @param Subject month
328
* @param Is sunday the first day of the week?
329
* @param Is the week range ordinal?
330
* @param Should we use ISO 8601:1988 rules?
331
* @param Pointer to a uint32_t to hold the resulting year, which
332
* may be incremented or decremented depending on flags
334
uint32_t week_number_from_gregorian_date(uint32_t year
337
, bool sunday_is_first_day_of_week
338
, bool week_range_is_ordinal
339
, bool use_iso_8601_1988
340
, uint32_t *year_out);
346
#endif /* DRIZZLED_CALENDAR_H */