]> git.saurik.com Git - apple/icu.git/blame - icuSources/i18n/gregoimp.h
ICU-6.2.14.tar.gz
[apple/icu.git] / icuSources / i18n / gregoimp.h
CommitLineData
374ca955
A
1/*
2**********************************************************************
3* Copyright (c) 2003-2004, International Business Machines
4* Corporation and others. All Rights Reserved.
5**********************************************************************
6* Author: Alan Liu
7* Created: September 2 2003
8* Since: ICU 2.8
9**********************************************************************
10*/
11#ifndef GREGOIMP_H
12#define GREGOIMP_H
13#include "unicode/utypes.h"
14#if !UCONFIG_NO_FORMATTING
15
16#include "unicode/ures.h"
17#include "unicode/locid.h"
18#include "putilimp.h"
19
20U_NAMESPACE_BEGIN
21
22/**
23 * A utility class providing mathematical functions used by time zone
24 * and calendar code. Do not instantiate.
25 */
26class U_I18N_API Math {
27 public:
28 /**
29 * Divide two integers, returning the floor of the quotient.
30 * Unlike the built-in division, this is mathematically
31 * well-behaved. E.g., <code>-1/4</code> => 0 but
32 * <code>floorDivide(-1,4)</code> => -1.
33 * @param numerator the numerator
34 * @param denominator a divisor which must be != 0
35 * @return the floor of the quotient
36 */
37 static int32_t floorDivide(int32_t numerator, int32_t denominator);
38
39 /**
40 * Divide two numbers, returning the floor of the quotient.
41 * Unlike the built-in division, this is mathematically
42 * well-behaved. E.g., <code>-1/4</code> => 0 but
43 * <code>floorDivide(-1,4)</code> => -1.
44 * @param numerator the numerator
45 * @param denominator a divisor which must be != 0
46 * @return the floor of the quotient
47 */
48 static inline double floorDivide(double numerator, double denominator);
49
50 /**
51 * Divide two numbers, returning the floor of the quotient and
52 * the modulus remainder. Unlike the built-in division, this is
53 * mathematically well-behaved. E.g., <code>-1/4</code> => 0 and
54 * <code>-1%4</code> => -1, but <code>floorDivide(-1,4)</code> =>
55 * -1 with <code>remainder</code> => 3. NOTE: If numerator is
56 * too large, the returned quotient may overflow.
57 * @param numerator the numerator
58 * @param denominator a divisor which must be != 0
59 * @param remainder output parameter to receive the
60 * remainder. Unlike <code>numerator % denominator</code>, this
61 * will always be non-negative, in the half-open range <code>[0,
62 * |denominator|)</code>.
63 * @return the floor of the quotient
64 */
65 static int32_t floorDivide(double numerator, int32_t denominator,
66 int32_t& remainder);
67
68 /**
69 * For a positive divisor, return the quotient and remainder
70 * such that dividend = quotient*divisor + remainder and
71 * 0 <= remainder < divisor.
72 *
73 * Works around edge-case bugs. Handles pathological input
74 * (divident >> divisor) reasonably.
75 *
76 * Calling with a divisor <= 0 is disallowed.
77 */
78 static double floorDivide(double dividend, double divisor,
79 double& remainder);
80};
81
82// Useful millisecond constants
83#define kOneDay (1.0 * U_MILLIS_PER_DAY) // 86,400,000
84#define kOneHour (60*60*1000)
85#define kOneMinute 60000
86#define kOneSecond 1000
87#define kOneMillisecond 1
88#define kOneWeek (7.0 * kOneDay) // 604,800,000
89
90// Epoch constants
91#define kJan1_1JulianDay 1721426 // January 1, year 1 (Gregorian)
92
93#define kEpochStartAsJulianDay 2440588 // January 1, 1970 (Gregorian)
94
95#define kEpochYear 1970
96
97
98#define kEarliestViableMillis -185331720384000000.0 // minimum representable by julian day -1e17
99
100#define kLatestViableMillis 185753453990400000.0 // max representable by julian day +1e17
101
102/**
103 * The minimum supported Julian day. This value is equivalent to
104 * MIN_MILLIS.
105 */
106#define MIN_JULIAN (-0x7F000000)
107
108/**
109 * The minimum supported epoch milliseconds. This value is equivalent
110 * to MIN_JULIAN.
111 */
112#define MIN_MILLIS ((MIN_JULIAN - kEpochStartAsJulianDay) * kOneDay)
113
114/**
115 * The maximum supported Julian day. This value is equivalent to
116 * MAX_MILLIS.
117 */
118#define MAX_JULIAN (+0x7F000000)
119
120/**
121 * The maximum supported epoch milliseconds. This value is equivalent
122 * to MAX_JULIAN.
123 */
124#define MAX_MILLIS ((MAX_JULIAN - kEpochStartAsJulianDay) * kOneDay)
125
126/**
127 * A utility class providing proleptic Gregorian calendar functions
128 * used by time zone and calendar code. Do not instantiate.
129 *
130 * Note: Unlike GregorianCalendar, all computations performed by this
131 * class occur in the pure proleptic GregorianCalendar.
132 */
133class U_I18N_API Grego {
134 public:
135 /**
136 * Return TRUE if the given year is a leap year.
137 * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
138 * @return TRUE if the year is a leap year
139 */
140 static inline UBool isLeapYear(int32_t year);
141
142 /**
143 * Return the number of days in the given month.
144 * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
145 * @param month 0-based month, with 0==Jan
146 * @return the number of days in the given month
147 */
148 static inline int8_t monthLength(int32_t year, int32_t month);
149
150 /**
151 * Return the length of a previous month of the Gregorian calendar.
152 * @param y the extended year
153 * @param m the 0-based month number
154 * @return the number of days in the month previous to the given month
155 */
156 static inline int8_t previousMonthLength(int y, int m);
157
158 /**
159 * Convert a year, month, and day-of-month, given in the proleptic
160 * Gregorian calendar, to 1970 epoch days.
161 * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
162 * @param month 0-based month, with 0==Jan
163 * @param dom 1-based day of month
164 * @return the day number, with day 0 == Jan 1 1970
165 */
166 static double fieldsToDay(int32_t year, int32_t month, int32_t dom);
167
168 /**
169 * Convert a 1970-epoch day number to proleptic Gregorian year,
170 * month, day-of-month, and day-of-week.
171 * @param day 1970-epoch day (integral value)
172 * @param year output parameter to receive year
173 * @param month output parameter to receive month (0-based, 0==Jan)
174 * @param dom output parameter to receive day-of-month (1-based)
175 * @param dow output parameter to receive day-of-week (1-based, 1==Sun)
176 * @param doy output parameter to receive day-of-year (1-based)
177 */
178 static void dayToFields(double day, int32_t& year, int32_t& month,
179 int32_t& dom, int32_t& dow, int32_t& doy);
180
181 /**
182 * Convert a 1970-epoch day number to proleptic Gregorian year,
183 * month, day-of-month, and day-of-week.
184 * @param day 1970-epoch day (integral value)
185 * @param year output parameter to receive year
186 * @param month output parameter to receive month (0-based, 0==Jan)
187 * @param dom output parameter to receive day-of-month (1-based)
188 * @param dow output parameter to receive day-of-week (1-based, 1==Sun)
189 */
190 static inline void dayToFields(double day, int32_t& year, int32_t& month,
191 int32_t& dom, int32_t& dow);
192
193 /**
194 * Converts Julian day to time as milliseconds.
195 * @param julian the given Julian day number.
196 * @return time as milliseconds.
197 * @internal
198 */
199 static inline double julianDayToMillis(int32_t julian);
200
201 /**
202 * Converts time as milliseconds to Julian day.
203 * @param millis the given milliseconds.
204 * @return the Julian day number.
205 * @internal
206 */
207 static inline int32_t millisToJulianDay(double millis);
208
209 /**
210 * Calculates the Gregorian day shift value for an extended year.
211 * @param eyear Extended year
212 * @returns number of days to ADD to Julian in order to convert from J->G
213 */
214 static inline int32_t gregorianShift(int32_t eyear);
215
216 private:
217 static const int16_t DAYS_BEFORE[24];
218 static const int8_t MONTH_LENGTH[24];
219};
220
221inline double Math::floorDivide(double numerator, double denominator) {
222 return uprv_floor(numerator / denominator);
223}
224
225inline UBool Grego::isLeapYear(int32_t year) {
226 // year&0x3 == year%4
227 return ((year&0x3) == 0) && ((year%100 != 0) || (year%400 == 0));
228}
229
230inline int8_t
231Grego::monthLength(int32_t year, int32_t month) {
232 return MONTH_LENGTH[month + isLeapYear(year)?12:0];
233}
234
235inline int8_t
236Grego::previousMonthLength(int y, int m) {
237 return (m > 0) ? monthLength(y, m-1) : 31;
238}
239
240inline void Grego::dayToFields(double day, int32_t& year, int32_t& month,
241 int32_t& dom, int32_t& dow) {
242 int32_t doy_unused;
243 dayToFields(day,year,month,dom,dow,doy_unused);
244}
245
246inline double Grego::julianDayToMillis(int32_t julian)
247{
248 return (julian - kEpochStartAsJulianDay) * kOneDay;
249}
250
251inline int32_t Grego::millisToJulianDay(double millis) {
252 return (int32_t) (kEpochStartAsJulianDay + Math::floorDivide(millis, (double)kOneDay));
253}
254
255inline int32_t Grego::gregorianShift(int32_t eyear) {
256 int32_t y = eyear-1;
257 int32_t gregShift = Math::floorDivide(y, 400) - Math::floorDivide(y, 100) + 2;
258 return gregShift;
259}
260
261/**
262 * This class provides convenient access to the data needed for a calendar.
263 * @internal ICU 3.0
264 */
265class U_I18N_API CalendarData : public UObject {
266public:
267 /**
268 * Construct a CalendarData from the given locale.
269 * @param loc locale to use. The 'calendar' keyword will be ignored.
270 * @param type calendar type. NULL indicates the gregorian calendar.
271 * No default lookup is done.
272 * @param status error code
273 */
274 CalendarData(const Locale& loc, const char *type, UErrorCode& status);
275
276 /**
277 * Load data for calendar. Note, this object owns the resources, do NOT call ures_close()!
278 * The ResourceBundle C++ API should NOT be used because it is too slow for a low level API.
279 *
280 * @param key Resource key to data
281 * @param status Error Status
282 * @internal
283 */
284 UResourceBundle* getByKey(const char *key, UErrorCode& status);
285
286 /**
287 * Load data for calendar. Note, this object owns the resources, do NOT call ures_close()!
288 * There is an implicit key of 'format'
289 * data is located in: "calendar/key/format/subKey"
290 * for example, calendar/dayNames/format/abbreviated
291 * The ResourceBundle C++ API should NOT be used because it is too slow for a low level API.
292 *
293 * @param key Resource key to data
294 * @param subKey Resource key to data
295 * @param status Error Status
296 * @internal
297 */
298 UResourceBundle* getByKey2(const char *key, const char *subKey, UErrorCode& status);
299
300 ~CalendarData();
301
302 /**
303 * Override Calendar Returns a unique class ID POLYMORPHICALLY. Pure virtual
304 * override. This method is to implement a simple version of RTTI, since not all C++
305 * compilers support genuine RTTI. Polymorphic operator==() and clone() methods call
306 * this method.
307 *
308 * @return The class ID for this object. All objects of a given class have the
309 * same class ID. Objects of other classes have different class IDs.
310 * @stable ICU 2.0
311 */
312 virtual UClassID getDynamicClassID(void) const;
313
314 /**
315 * Return the class ID for this class. This is useful only for comparing to a return
316 * value from getDynamicClassID(). For example:
317 *
318 * Base* polymorphic_pointer = createPolymorphicObject();
319 * if (polymorphic_pointer->getDynamicClassID() ==
320 * Derived::getStaticClassID()) ...
321 *
322 * @return The class ID for all objects of this class.
323 * @stable ICU 2.0
324 */
325 static UClassID U_EXPORT2 getStaticClassID(void);
326
327private:
328 void initData(const char *locale, const char *type, UErrorCode& status);
329
330 UResourceBundle *fFillin;
331 UResourceBundle *fOtherFillin;
332 UResourceBundle *fBundle;
333 UResourceBundle *fFallback;
334 CalendarData(); // Not implemented.
335};
336
337U_NAMESPACE_END
338
339#endif // !UCONFIG_NO_FORMATTING
340#endif // GREGOIMP_H
341
342//eof