intl/icu/source/i18n/gregoimp.h

changeset 0
6474c204b198
     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

mercurial