1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/intl/icu/source/i18n/gregoimp.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,364 @@ 1.4 +/* 1.5 + ********************************************************************** 1.6 + * Copyright (c) 2003-2008, International Business Machines 1.7 + * Corporation and others. All Rights Reserved. 1.8 + ********************************************************************** 1.9 + * Author: Alan Liu 1.10 + * Created: September 2 2003 1.11 + * Since: ICU 2.8 1.12 + ********************************************************************** 1.13 + */ 1.14 + 1.15 +#ifndef GREGOIMP_H 1.16 +#define GREGOIMP_H 1.17 +#include "unicode/utypes.h" 1.18 +#if !UCONFIG_NO_FORMATTING 1.19 + 1.20 +#include "unicode/ures.h" 1.21 +#include "unicode/locid.h" 1.22 +#include "putilimp.h" 1.23 + 1.24 +U_NAMESPACE_BEGIN 1.25 + 1.26 +/** 1.27 + * A utility class providing mathematical functions used by time zone 1.28 + * and calendar code. Do not instantiate. Formerly just named 'Math'. 1.29 + * @internal 1.30 + */ 1.31 +class ClockMath { 1.32 + public: 1.33 + /** 1.34 + * Divide two integers, returning the floor of the quotient. 1.35 + * Unlike the built-in division, this is mathematically 1.36 + * well-behaved. E.g., <code>-1/4</code> => 0 but 1.37 + * <code>floorDivide(-1,4)</code> => -1. 1.38 + * @param numerator the numerator 1.39 + * @param denominator a divisor which must be != 0 1.40 + * @return the floor of the quotient 1.41 + */ 1.42 + static int32_t floorDivide(int32_t numerator, int32_t denominator); 1.43 + 1.44 + /** 1.45 + * Divide two numbers, returning the floor of the quotient. 1.46 + * Unlike the built-in division, this is mathematically 1.47 + * well-behaved. E.g., <code>-1/4</code> => 0 but 1.48 + * <code>floorDivide(-1,4)</code> => -1. 1.49 + * @param numerator the numerator 1.50 + * @param denominator a divisor which must be != 0 1.51 + * @return the floor of the quotient 1.52 + */ 1.53 + static inline double floorDivide(double numerator, double denominator); 1.54 + 1.55 + /** 1.56 + * Divide two numbers, returning the floor of the quotient and 1.57 + * the modulus remainder. Unlike the built-in division, this is 1.58 + * mathematically well-behaved. E.g., <code>-1/4</code> => 0 and 1.59 + * <code>-1%4</code> => -1, but <code>floorDivide(-1,4)</code> => 1.60 + * -1 with <code>remainder</code> => 3. NOTE: If numerator is 1.61 + * too large, the returned quotient may overflow. 1.62 + * @param numerator the numerator 1.63 + * @param denominator a divisor which must be != 0 1.64 + * @param remainder output parameter to receive the 1.65 + * remainder. Unlike <code>numerator % denominator</code>, this 1.66 + * will always be non-negative, in the half-open range <code>[0, 1.67 + * |denominator|)</code>. 1.68 + * @return the floor of the quotient 1.69 + */ 1.70 + static int32_t floorDivide(double numerator, int32_t denominator, 1.71 + int32_t& remainder); 1.72 + 1.73 + /** 1.74 + * For a positive divisor, return the quotient and remainder 1.75 + * such that dividend = quotient*divisor + remainder and 1.76 + * 0 <= remainder < divisor. 1.77 + * 1.78 + * Works around edge-case bugs. Handles pathological input 1.79 + * (divident >> divisor) reasonably. 1.80 + * 1.81 + * Calling with a divisor <= 0 is disallowed. 1.82 + */ 1.83 + static double floorDivide(double dividend, double divisor, 1.84 + double& remainder); 1.85 +}; 1.86 + 1.87 +// Useful millisecond constants 1.88 +#define kOneDay (1.0 * U_MILLIS_PER_DAY) // 86,400,000 1.89 +#define kOneHour (60*60*1000) 1.90 +#define kOneMinute 60000 1.91 +#define kOneSecond 1000 1.92 +#define kOneMillisecond 1 1.93 +#define kOneWeek (7.0 * kOneDay) // 604,800,000 1.94 + 1.95 +// Epoch constants 1.96 +#define kJan1_1JulianDay 1721426 // January 1, year 1 (Gregorian) 1.97 + 1.98 +#define kEpochStartAsJulianDay 2440588 // January 1, 1970 (Gregorian) 1.99 + 1.100 +#define kEpochYear 1970 1.101 + 1.102 + 1.103 +#define kEarliestViableMillis -185331720384000000.0 // minimum representable by julian day -1e17 1.104 + 1.105 +#define kLatestViableMillis 185753453990400000.0 // max representable by julian day +1e17 1.106 + 1.107 +/** 1.108 + * The minimum supported Julian day. This value is equivalent to 1.109 + * MIN_MILLIS. 1.110 + */ 1.111 +#define MIN_JULIAN (-0x7F000000) 1.112 + 1.113 +/** 1.114 + * The minimum supported epoch milliseconds. This value is equivalent 1.115 + * to MIN_JULIAN. 1.116 + */ 1.117 +#define MIN_MILLIS ((MIN_JULIAN - kEpochStartAsJulianDay) * kOneDay) 1.118 + 1.119 +/** 1.120 + * The maximum supported Julian day. This value is equivalent to 1.121 + * MAX_MILLIS. 1.122 + */ 1.123 +#define MAX_JULIAN (+0x7F000000) 1.124 + 1.125 +/** 1.126 + * The maximum supported epoch milliseconds. This value is equivalent 1.127 + * to MAX_JULIAN. 1.128 + */ 1.129 +#define MAX_MILLIS ((MAX_JULIAN - kEpochStartAsJulianDay) * kOneDay) 1.130 + 1.131 +/** 1.132 + * A utility class providing proleptic Gregorian calendar functions 1.133 + * used by time zone and calendar code. Do not instantiate. 1.134 + * 1.135 + * Note: Unlike GregorianCalendar, all computations performed by this 1.136 + * class occur in the pure proleptic GregorianCalendar. 1.137 + */ 1.138 +class Grego { 1.139 + public: 1.140 + /** 1.141 + * Return TRUE if the given year is a leap year. 1.142 + * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc. 1.143 + * @return TRUE if the year is a leap year 1.144 + */ 1.145 + static inline UBool isLeapYear(int32_t year); 1.146 + 1.147 + /** 1.148 + * Return the number of days in the given month. 1.149 + * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc. 1.150 + * @param month 0-based month, with 0==Jan 1.151 + * @return the number of days in the given month 1.152 + */ 1.153 + static inline int8_t monthLength(int32_t year, int32_t month); 1.154 + 1.155 + /** 1.156 + * Return the length of a previous month of the Gregorian calendar. 1.157 + * @param y the extended year 1.158 + * @param m the 0-based month number 1.159 + * @return the number of days in the month previous to the given month 1.160 + */ 1.161 + static inline int8_t previousMonthLength(int y, int m); 1.162 + 1.163 + /** 1.164 + * Convert a year, month, and day-of-month, given in the proleptic 1.165 + * Gregorian calendar, to 1970 epoch days. 1.166 + * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc. 1.167 + * @param month 0-based month, with 0==Jan 1.168 + * @param dom 1-based day of month 1.169 + * @return the day number, with day 0 == Jan 1 1970 1.170 + */ 1.171 + static double fieldsToDay(int32_t year, int32_t month, int32_t dom); 1.172 + 1.173 + /** 1.174 + * Convert a 1970-epoch day number to proleptic Gregorian year, 1.175 + * month, day-of-month, and day-of-week. 1.176 + * @param day 1970-epoch day (integral value) 1.177 + * @param year output parameter to receive year 1.178 + * @param month output parameter to receive month (0-based, 0==Jan) 1.179 + * @param dom output parameter to receive day-of-month (1-based) 1.180 + * @param dow output parameter to receive day-of-week (1-based, 1==Sun) 1.181 + * @param doy output parameter to receive day-of-year (1-based) 1.182 + */ 1.183 + static void dayToFields(double day, int32_t& year, int32_t& month, 1.184 + int32_t& dom, int32_t& dow, int32_t& doy); 1.185 + 1.186 + /** 1.187 + * Convert a 1970-epoch day number to proleptic Gregorian year, 1.188 + * month, day-of-month, and day-of-week. 1.189 + * @param day 1970-epoch day (integral value) 1.190 + * @param year output parameter to receive year 1.191 + * @param month output parameter to receive month (0-based, 0==Jan) 1.192 + * @param dom output parameter to receive day-of-month (1-based) 1.193 + * @param dow output parameter to receive day-of-week (1-based, 1==Sun) 1.194 + */ 1.195 + static inline void dayToFields(double day, int32_t& year, int32_t& month, 1.196 + int32_t& dom, int32_t& dow); 1.197 + 1.198 + /** 1.199 + * Convert a 1970-epoch milliseconds to proleptic Gregorian year, 1.200 + * month, day-of-month, and day-of-week, day of year and millis-in-day. 1.201 + * @param time 1970-epoch milliseconds 1.202 + * @param year output parameter to receive year 1.203 + * @param month output parameter to receive month (0-based, 0==Jan) 1.204 + * @param dom output parameter to receive day-of-month (1-based) 1.205 + * @param dow output parameter to receive day-of-week (1-based, 1==Sun) 1.206 + * @param doy output parameter to receive day-of-year (1-based) 1.207 + * @param mid output parameter to recieve millis-in-day 1.208 + */ 1.209 + static void timeToFields(UDate time, int32_t& year, int32_t& month, 1.210 + int32_t& dom, int32_t& dow, int32_t& doy, int32_t& mid); 1.211 + 1.212 + /** 1.213 + * Return the day of week on the 1970-epoch day 1.214 + * @param day the 1970-epoch day (integral value) 1.215 + * @return the day of week 1.216 + */ 1.217 + static int32_t dayOfWeek(double day); 1.218 + 1.219 + /** 1.220 + * Returns the ordinal number for the specified day of week within the month. 1.221 + * The valid return value is 1, 2, 3, 4 or -1. 1.222 + * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc. 1.223 + * @param month 0-based month, with 0==Jan 1.224 + * @param dom 1-based day of month 1.225 + * @return The ordinal number for the specified day of week within the month 1.226 + */ 1.227 + static int32_t dayOfWeekInMonth(int32_t year, int32_t month, int32_t dom); 1.228 + 1.229 + /** 1.230 + * Converts Julian day to time as milliseconds. 1.231 + * @param julian the given Julian day number. 1.232 + * @return time as milliseconds. 1.233 + * @internal 1.234 + */ 1.235 + static inline double julianDayToMillis(int32_t julian); 1.236 + 1.237 + /** 1.238 + * Converts time as milliseconds to Julian day. 1.239 + * @param millis the given milliseconds. 1.240 + * @return the Julian day number. 1.241 + * @internal 1.242 + */ 1.243 + static inline int32_t millisToJulianDay(double millis); 1.244 + 1.245 + /** 1.246 + * Calculates the Gregorian day shift value for an extended year. 1.247 + * @param eyear Extended year 1.248 + * @returns number of days to ADD to Julian in order to convert from J->G 1.249 + */ 1.250 + static inline int32_t gregorianShift(int32_t eyear); 1.251 + 1.252 + private: 1.253 + static const int16_t DAYS_BEFORE[24]; 1.254 + static const int8_t MONTH_LENGTH[24]; 1.255 +}; 1.256 + 1.257 +inline double ClockMath::floorDivide(double numerator, double denominator) { 1.258 + return uprv_floor(numerator / denominator); 1.259 +} 1.260 + 1.261 +inline UBool Grego::isLeapYear(int32_t year) { 1.262 + // year&0x3 == year%4 1.263 + return ((year&0x3) == 0) && ((year%100 != 0) || (year%400 == 0)); 1.264 +} 1.265 + 1.266 +inline int8_t 1.267 +Grego::monthLength(int32_t year, int32_t month) { 1.268 + return MONTH_LENGTH[month + (isLeapYear(year) ? 12 : 0)]; 1.269 +} 1.270 + 1.271 +inline int8_t 1.272 +Grego::previousMonthLength(int y, int m) { 1.273 + return (m > 0) ? monthLength(y, m-1) : 31; 1.274 +} 1.275 + 1.276 +inline void Grego::dayToFields(double day, int32_t& year, int32_t& month, 1.277 + int32_t& dom, int32_t& dow) { 1.278 + int32_t doy_unused; 1.279 + dayToFields(day,year,month,dom,dow,doy_unused); 1.280 +} 1.281 + 1.282 +inline double Grego::julianDayToMillis(int32_t julian) 1.283 +{ 1.284 + return (julian - kEpochStartAsJulianDay) * kOneDay; 1.285 +} 1.286 + 1.287 +inline int32_t Grego::millisToJulianDay(double millis) { 1.288 + return (int32_t) (kEpochStartAsJulianDay + ClockMath::floorDivide(millis, (double)kOneDay)); 1.289 +} 1.290 + 1.291 +inline int32_t Grego::gregorianShift(int32_t eyear) { 1.292 + int32_t y = eyear-1; 1.293 + int32_t gregShift = ClockMath::floorDivide(y, 400) - ClockMath::floorDivide(y, 100) + 2; 1.294 + return gregShift; 1.295 +} 1.296 + 1.297 +/** 1.298 + * This utility class provides convenient access to the data needed for a calendar. 1.299 + * @internal ICU 3.0 1.300 + */ 1.301 +class CalendarData : public UMemory { 1.302 +public: 1.303 + /** 1.304 + * Construct a CalendarData from the given locale. 1.305 + * @param loc locale to use. The 'calendar' keyword will be ignored. 1.306 + * @param type calendar type. NULL indicates the gregorian calendar. 1.307 + * No default lookup is done. 1.308 + * @param status error code 1.309 + */ 1.310 + CalendarData(const Locale& loc, const char *type, UErrorCode& status); 1.311 + 1.312 + /** 1.313 + * Load data for calendar. Note, this object owns the resources, do NOT call ures_close()! 1.314 + * The ResourceBundle C++ API should NOT be used because it is too slow for a low level API. 1.315 + * 1.316 + * @param key Resource key to data 1.317 + * @param status Error Status 1.318 + * @internal 1.319 + */ 1.320 + UResourceBundle* getByKey(const char *key, UErrorCode& status); 1.321 + 1.322 + /** 1.323 + * Load data for calendar. Note, this object owns the resources, do NOT call ures_close()! 1.324 + * There is an implicit key of 'format' 1.325 + * data is located in: "calendar/key/format/subKey" 1.326 + * for example, calendar/dayNames/format/abbreviated 1.327 + * The ResourceBundle C++ API should NOT be used because it is too slow for a low level API. 1.328 + * 1.329 + * @param key Resource key to data 1.330 + * @param subKey Resource key to data 1.331 + * @param status Error Status 1.332 + * @internal 1.333 + */ 1.334 + UResourceBundle* getByKey2(const char *key, const char *subKey, UErrorCode& status); 1.335 + 1.336 + /** 1.337 + * Load data for calendar. Note, this object owns the resources, do NOT call ures_close()! 1.338 + * data is located in: "calendar/key/contextKey/subKey" 1.339 + * for example, calendar/dayNames/standalone/narrow 1.340 + * The ResourceBundle C++ API should NOT be used because it is too slow for a low level API. 1.341 + * 1.342 + * @param key Resource key to data 1.343 + * @param contextKey Resource key to data 1.344 + * @param subKey Resource key to data 1.345 + * @param status Error Status 1.346 + * @internal 1.347 + */ 1.348 + UResourceBundle* getByKey3(const char *key, const char *contextKey, const char *subKey, UErrorCode& status); 1.349 + 1.350 + ~CalendarData(); 1.351 + 1.352 +private: 1.353 + void initData(const char *locale, const char *type, UErrorCode& status); 1.354 + 1.355 + UResourceBundle *fFillin; 1.356 + UResourceBundle *fOtherFillin; 1.357 + UResourceBundle *fBundle; 1.358 + UResourceBundle *fFallback; 1.359 + CalendarData(); // Not implemented. 1.360 +}; 1.361 + 1.362 +U_NAMESPACE_END 1.363 + 1.364 +#endif // !UCONFIG_NO_FORMATTING 1.365 +#endif // GREGOIMP_H 1.366 + 1.367 +//eof