intl/icu/source/i18n/gregoimp.h

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /*
     2  **********************************************************************
     3  * Copyright (c) 2003-2008, 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  */
    12 #ifndef GREGOIMP_H
    13 #define GREGOIMP_H
    14 #include "unicode/utypes.h"
    15 #if !UCONFIG_NO_FORMATTING
    17 #include "unicode/ures.h"
    18 #include "unicode/locid.h"
    19 #include "putilimp.h"
    21 U_NAMESPACE_BEGIN
    23 /**
    24  * A utility class providing mathematical functions used by time zone
    25  * and calendar code.  Do not instantiate.  Formerly just named 'Math'.
    26  * @internal
    27  */
    28 class ClockMath {
    29  public:
    30     /**
    31      * Divide two integers, returning the floor of the quotient.
    32      * Unlike the built-in division, this is mathematically
    33      * well-behaved.  E.g., <code>-1/4</code> => 0 but
    34      * <code>floorDivide(-1,4)</code> => -1.
    35      * @param numerator the numerator
    36      * @param denominator a divisor which must be != 0
    37      * @return the floor of the quotient
    38      */
    39     static int32_t floorDivide(int32_t numerator, int32_t denominator);
    41     /**
    42      * Divide two numbers, returning the floor of the quotient.
    43      * Unlike the built-in division, this is mathematically
    44      * well-behaved.  E.g., <code>-1/4</code> => 0 but
    45      * <code>floorDivide(-1,4)</code> => -1.
    46      * @param numerator the numerator
    47      * @param denominator a divisor which must be != 0
    48      * @return the floor of the quotient
    49      */
    50     static inline double floorDivide(double numerator, double denominator);
    52     /**
    53      * Divide two numbers, returning the floor of the quotient and
    54      * the modulus remainder.  Unlike the built-in division, this is
    55      * mathematically well-behaved.  E.g., <code>-1/4</code> => 0 and
    56      * <code>-1%4</code> => -1, but <code>floorDivide(-1,4)</code> =>
    57      * -1 with <code>remainder</code> => 3.  NOTE: If numerator is
    58      * too large, the returned quotient may overflow.
    59      * @param numerator the numerator
    60      * @param denominator a divisor which must be != 0
    61      * @param remainder output parameter to receive the
    62      * remainder. Unlike <code>numerator % denominator</code>, this
    63      * will always be non-negative, in the half-open range <code>[0,
    64      * |denominator|)</code>.
    65      * @return the floor of the quotient
    66      */
    67     static int32_t floorDivide(double numerator, int32_t denominator,
    68                                int32_t& remainder);
    70     /**
    71      * For a positive divisor, return the quotient and remainder
    72      * such that dividend = quotient*divisor + remainder and
    73      * 0 <= remainder < divisor.
    74      *
    75      * Works around edge-case bugs.  Handles pathological input
    76      * (divident >> divisor) reasonably.
    77      *
    78      * Calling with a divisor <= 0 is disallowed.
    79      */
    80     static double floorDivide(double dividend, double divisor,
    81                               double& remainder);
    82 };
    84 // Useful millisecond constants
    85 #define kOneDay    (1.0 * U_MILLIS_PER_DAY)       //  86,400,000
    86 #define kOneHour   (60*60*1000)
    87 #define kOneMinute 60000
    88 #define kOneSecond 1000
    89 #define kOneMillisecond  1
    90 #define kOneWeek   (7.0 * kOneDay) // 604,800,000
    92 // Epoch constants
    93 #define kJan1_1JulianDay  1721426 // January 1, year 1 (Gregorian)
    95 #define kEpochStartAsJulianDay  2440588 // January 1, 1970 (Gregorian)
    97 #define kEpochYear              1970
   100 #define kEarliestViableMillis  -185331720384000000.0  // minimum representable by julian day  -1e17
   102 #define kLatestViableMillis     185753453990400000.0  // max representable by julian day      +1e17
   104 /**
   105  * The minimum supported Julian day.  This value is equivalent to
   106  * MIN_MILLIS.
   107  */
   108 #define MIN_JULIAN (-0x7F000000)
   110 /**
   111  * The minimum supported epoch milliseconds.  This value is equivalent
   112  * to MIN_JULIAN.
   113  */
   114 #define MIN_MILLIS ((MIN_JULIAN - kEpochStartAsJulianDay) * kOneDay)
   116 /**
   117  * The maximum supported Julian day.  This value is equivalent to
   118  * MAX_MILLIS.
   119  */
   120 #define MAX_JULIAN (+0x7F000000)
   122 /**
   123  * The maximum supported epoch milliseconds.  This value is equivalent
   124  * to MAX_JULIAN.
   125  */
   126 #define MAX_MILLIS ((MAX_JULIAN - kEpochStartAsJulianDay) * kOneDay)
   128 /**
   129  * A utility class providing proleptic Gregorian calendar functions
   130  * used by time zone and calendar code.  Do not instantiate.
   131  *
   132  * Note:  Unlike GregorianCalendar, all computations performed by this
   133  * class occur in the pure proleptic GregorianCalendar.
   134  */
   135 class Grego {
   136  public:
   137     /**
   138      * Return TRUE if the given year is a leap year.
   139      * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
   140      * @return TRUE if the year is a leap year
   141      */
   142     static inline UBool isLeapYear(int32_t year);
   144     /**
   145      * Return the number of days in the given month.
   146      * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
   147      * @param month 0-based month, with 0==Jan
   148      * @return the number of days in the given month
   149      */
   150     static inline int8_t monthLength(int32_t year, int32_t month);
   152     /**
   153      * Return the length of a previous month of the Gregorian calendar.
   154      * @param y the extended year
   155      * @param m the 0-based month number
   156      * @return the number of days in the month previous to the given month
   157      */
   158     static inline int8_t previousMonthLength(int y, int m);
   160     /**
   161      * Convert a year, month, and day-of-month, given in the proleptic
   162      * Gregorian calendar, to 1970 epoch days.
   163      * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
   164      * @param month 0-based month, with 0==Jan
   165      * @param dom 1-based day of month
   166      * @return the day number, with day 0 == Jan 1 1970
   167      */
   168     static double fieldsToDay(int32_t year, int32_t month, int32_t dom);
   170     /**
   171      * Convert a 1970-epoch day number to proleptic Gregorian year,
   172      * month, day-of-month, and day-of-week.
   173      * @param day 1970-epoch day (integral value)
   174      * @param year output parameter to receive year
   175      * @param month output parameter to receive month (0-based, 0==Jan)
   176      * @param dom output parameter to receive day-of-month (1-based)
   177      * @param dow output parameter to receive day-of-week (1-based, 1==Sun)
   178      * @param doy output parameter to receive day-of-year (1-based)
   179      */
   180     static void dayToFields(double day, int32_t& year, int32_t& month,
   181                             int32_t& dom, int32_t& dow, int32_t& doy);
   183     /**
   184      * Convert a 1970-epoch day number to proleptic Gregorian year,
   185      * month, day-of-month, and day-of-week.
   186      * @param day 1970-epoch day (integral value)
   187      * @param year output parameter to receive year
   188      * @param month output parameter to receive month (0-based, 0==Jan)
   189      * @param dom output parameter to receive day-of-month (1-based)
   190      * @param dow output parameter to receive day-of-week (1-based, 1==Sun)
   191      */
   192     static inline void dayToFields(double day, int32_t& year, int32_t& month,
   193                                    int32_t& dom, int32_t& dow);
   195     /**
   196      * Convert a 1970-epoch milliseconds to proleptic Gregorian year,
   197      * month, day-of-month, and day-of-week, day of year and millis-in-day.
   198      * @param time 1970-epoch milliseconds
   199      * @param year output parameter to receive year
   200      * @param month output parameter to receive month (0-based, 0==Jan)
   201      * @param dom output parameter to receive day-of-month (1-based)
   202      * @param dow output parameter to receive day-of-week (1-based, 1==Sun)
   203      * @param doy output parameter to receive day-of-year (1-based)
   204      * @param mid output parameter to recieve millis-in-day
   205      */
   206     static void timeToFields(UDate time, int32_t& year, int32_t& month,
   207                             int32_t& dom, int32_t& dow, int32_t& doy, int32_t& mid);
   209     /**
   210      * Return the day of week on the 1970-epoch day
   211      * @param day the 1970-epoch day (integral value)
   212      * @return the day of week
   213      */
   214     static int32_t dayOfWeek(double day);
   216     /**
   217      * Returns the ordinal number for the specified day of week within the month.
   218      * The valid return value is 1, 2, 3, 4 or -1.
   219      * @param year Gregorian year, with 0 == 1 BCE, -1 == 2 BCE, etc.
   220      * @param month 0-based month, with 0==Jan
   221      * @param dom 1-based day of month
   222      * @return The ordinal number for the specified day of week within the month
   223      */
   224     static int32_t dayOfWeekInMonth(int32_t year, int32_t month, int32_t dom);
   226     /**
   227      * Converts Julian day to time as milliseconds.
   228      * @param julian the given Julian day number.
   229      * @return time as milliseconds.
   230      * @internal
   231      */
   232     static inline double julianDayToMillis(int32_t julian);
   234     /**
   235      * Converts time as milliseconds to Julian day.
   236      * @param millis the given milliseconds.
   237      * @return the Julian day number.
   238      * @internal
   239      */
   240     static inline int32_t millisToJulianDay(double millis);
   242     /** 
   243      * Calculates the Gregorian day shift value for an extended year.
   244      * @param eyear Extended year 
   245      * @returns number of days to ADD to Julian in order to convert from J->G
   246      */
   247     static inline int32_t gregorianShift(int32_t eyear);
   249  private:
   250     static const int16_t DAYS_BEFORE[24];
   251     static const int8_t MONTH_LENGTH[24];
   252 };
   254 inline double ClockMath::floorDivide(double numerator, double denominator) {
   255     return uprv_floor(numerator / denominator);
   256 }
   258 inline UBool Grego::isLeapYear(int32_t year) {
   259     // year&0x3 == year%4
   260     return ((year&0x3) == 0) && ((year%100 != 0) || (year%400 == 0));
   261 }
   263 inline int8_t
   264 Grego::monthLength(int32_t year, int32_t month) {
   265     return MONTH_LENGTH[month + (isLeapYear(year) ? 12 : 0)];
   266 }
   268 inline int8_t
   269 Grego::previousMonthLength(int y, int m) {
   270   return (m > 0) ? monthLength(y, m-1) : 31;
   271 }
   273 inline void Grego::dayToFields(double day, int32_t& year, int32_t& month,
   274                                int32_t& dom, int32_t& dow) {
   275   int32_t doy_unused;
   276   dayToFields(day,year,month,dom,dow,doy_unused);
   277 }
   279 inline double Grego::julianDayToMillis(int32_t julian)
   280 {
   281   return (julian - kEpochStartAsJulianDay) * kOneDay;
   282 }
   284 inline int32_t Grego::millisToJulianDay(double millis) {
   285   return (int32_t) (kEpochStartAsJulianDay + ClockMath::floorDivide(millis, (double)kOneDay));
   286 }
   288 inline int32_t Grego::gregorianShift(int32_t eyear) {
   289   int32_t y = eyear-1;
   290   int32_t gregShift = ClockMath::floorDivide(y, 400) - ClockMath::floorDivide(y, 100) + 2;
   291   return gregShift;
   292 }
   294 /**
   295  * This utility class provides convenient access to the data needed for a calendar. 
   296  * @internal ICU 3.0
   297  */
   298 class CalendarData : public UMemory {
   299 public: 
   300     /**
   301      * Construct a CalendarData from the given locale.
   302      * @param loc locale to use. The 'calendar' keyword will be ignored.
   303      * @param type calendar type. NULL indicates the gregorian calendar. 
   304      * No default lookup is done.
   305      * @param status error code
   306      */
   307     CalendarData(const Locale& loc, const char *type, UErrorCode& status);
   309     /**
   310      * Load data for calendar. Note, this object owns the resources, do NOT call ures_close()!
   311      * The ResourceBundle C++ API should NOT be used because it is too slow for a low level API.
   312      *
   313      * @param key Resource key to data
   314      * @param status Error Status
   315      * @internal
   316      */
   317     UResourceBundle* getByKey(const char *key, UErrorCode& status);
   319     /**
   320      * Load data for calendar. Note, this object owns the resources, do NOT call ures_close()!
   321      * There is an implicit key of 'format'
   322      * data is located in:   "calendar/key/format/subKey"
   323      * for example,  calendar/dayNames/format/abbreviated
   324      * The ResourceBundle C++ API should NOT be used because it is too slow for a low level API.
   325      *
   326      * @param key Resource key to data
   327      * @param subKey Resource key to data
   328      * @param status Error Status
   329      * @internal
   330      */
   331     UResourceBundle* getByKey2(const char *key, const char *subKey, UErrorCode& status);
   333     /**
   334      * Load data for calendar. Note, this object owns the resources, do NOT call ures_close()!
   335      * data is located in:   "calendar/key/contextKey/subKey"
   336      * for example,  calendar/dayNames/standalone/narrow
   337      * The ResourceBundle C++ API should NOT be used because it is too slow for a low level API.
   338      *
   339      * @param key Resource key to data
   340      * @param contextKey Resource key to data
   341      * @param subKey Resource key to data
   342      * @param status Error Status
   343      * @internal
   344      */
   345     UResourceBundle* getByKey3(const char *key, const char *contextKey, const char *subKey, UErrorCode& status);
   347     ~CalendarData();
   349 private:
   350     void initData(const char *locale, const char *type, UErrorCode& status);
   352     UResourceBundle *fFillin;
   353     UResourceBundle *fOtherFillin;
   354     UResourceBundle *fBundle;
   355     UResourceBundle *fFallback;
   356     CalendarData(); // Not implemented.
   357 };
   359 U_NAMESPACE_END
   361 #endif // !UCONFIG_NO_FORMATTING
   362 #endif // GREGOIMP_H
   364 //eof

mercurial