cecal.cpp (5975B)
1 // © 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /* 4 ******************************************************************************* 5 * Copyright (C) 2003 - 2009, International Business Machines Corporation and * 6 * others. All Rights Reserved. * 7 ******************************************************************************* 8 */ 9 10 #include "unicode/utypes.h" 11 12 #if !UCONFIG_NO_FORMATTING 13 14 #include "cecal.h" 15 #include "gregoimp.h" //Math 16 #include "cstring.h" 17 18 U_NAMESPACE_BEGIN 19 20 static const int32_t LIMITS[UCAL_FIELD_COUNT][4] = { 21 // Minimum Greatest Least Maximum 22 // Minimum Maximum 23 { 0, 0, 1, 1}, // ERA 24 { 1, 1, 5000000, 5000000}, // YEAR 25 { 0, 0, 12, 12}, // MONTH 26 { 1, 1, 52, 53}, // WEEK_OF_YEAR 27 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // WEEK_OF_MONTH 28 { 1, 1, 5, 30}, // DAY_OF_MONTH 29 { 1, 1, 365, 366}, // DAY_OF_YEAR 30 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DAY_OF_WEEK 31 { -1, -1, 1, 5}, // DAY_OF_WEEK_IN_MONTH 32 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // AM_PM 33 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR 34 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // HOUR_OF_DAY 35 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MINUTE 36 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // SECOND 37 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECOND 38 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // ZONE_OFFSET 39 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DST_OFFSET 40 { -5000000, -5000000, 5000000, 5000000}, // YEAR_WOY 41 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // DOW_LOCAL 42 { -5000000, -5000000, 5000000, 5000000}, // EXTENDED_YEAR 43 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // JULIAN_DAY 44 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // MILLISECONDS_IN_DAY 45 {/*N/A*/-1,/*N/A*/-1,/*N/A*/-1,/*N/A*/-1}, // IS_LEAP_MONTH 46 { 0, 0, 12, 12}, // ORDINAL_MONTH 47 }; 48 49 //------------------------------------------------------------------------- 50 // Constructors... 51 //------------------------------------------------------------------------- 52 53 CECalendar::CECalendar(const Locale& aLocale, UErrorCode& success) 54 : Calendar(TimeZone::forLocaleOrDefault(aLocale), aLocale, success) 55 { 56 } 57 58 CECalendar::CECalendar (const CECalendar& other) 59 : Calendar(other) 60 { 61 } 62 63 CECalendar::~CECalendar() 64 { 65 } 66 67 //------------------------------------------------------------------------- 68 // Calendar framework 69 //------------------------------------------------------------------------- 70 71 int64_t 72 CECalendar::handleComputeMonthStart(int32_t eyear,int32_t emonth, UBool /*useMonth*/, UErrorCode& /*status*/) const 73 { 74 int64_t year64 = eyear; 75 // handle month > 12, < 0 (e.g. from add/set) 76 if ( emonth >= 0 ) { 77 year64 += emonth/13; 78 emonth %= 13; 79 } else { 80 ++emonth; 81 year64 += emonth/13 - 1; 82 emonth = emonth%13 + 12; 83 } 84 85 return ( 86 getJDEpochOffset() // difference from Julian epoch to 1,1,1 87 + 365LL * year64 // number of days from years 88 + ClockMath::floorDivideInt64(year64, 4LL) // extra day of leap year 89 + 30 * emonth // number of days from months (months are 0-based) 90 - 1 // number of days for present month (1 based) 91 ); 92 } 93 94 int32_t 95 CECalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const 96 { 97 return LIMITS[field][limitType]; 98 } 99 100 //------------------------------------------------------------------------- 101 // Calendar system Conversion methods... 102 //------------------------------------------------------------------------- 103 104 namespace { 105 void jdToCE(int32_t julianDay, int32_t jdEpochOffset, int32_t& year, int32_t& month, int32_t& day, int32_t& doy, UErrorCode& status) 106 { 107 int32_t c4; // number of 4 year cycle (1461 days) 108 int32_t r4; // remainder of 4 year cycle, always positive 109 110 if (uprv_add32_overflow(julianDay, -jdEpochOffset, &julianDay)) { 111 status = U_ILLEGAL_ARGUMENT_ERROR; 112 return; 113 } 114 c4 = ClockMath::floorDivide(julianDay, 1461, &r4); 115 116 year = 4 * c4 + (r4/365 - r4/1460); // 4 * <number of 4year cycle> + <years within the last cycle> 117 118 doy = (r4 == 1460) ? 365 : (r4 % 365); // days in present year 119 120 month = doy / 30; // 30 -> Coptic/Ethiopic month length up to 12th month 121 day = (doy % 30) + 1; // 1-based days in a month 122 doy++; // 1-based days in a year. 123 } 124 } // namespace 125 126 void 127 CECalendar::handleComputeFields(int32_t julianDay, UErrorCode& status) 128 { 129 int32_t eyear, month, day, doy; 130 jdToCE(julianDay, getJDEpochOffset(), eyear, month, day, doy, status); 131 if (U_FAILURE(status)) return; 132 int32_t era = extendedYearToEra(eyear); 133 int32_t year = extendedYearToYear(eyear); 134 135 internalSet(UCAL_EXTENDED_YEAR, eyear); 136 internalSet(UCAL_ERA, era); 137 internalSet(UCAL_YEAR, year); 138 internalSet(UCAL_MONTH, month); 139 internalSet(UCAL_ORDINAL_MONTH, month); 140 internalSet(UCAL_DATE, day); 141 internalSet(UCAL_DAY_OF_YEAR, doy); 142 } 143 144 static const char* kMonthCode13 = "M13"; 145 146 const char* CECalendar::getTemporalMonthCode(UErrorCode& status) const { 147 if (get(UCAL_MONTH, status) == 12) { 148 return kMonthCode13; 149 } 150 return Calendar::getTemporalMonthCode(status); 151 } 152 153 void 154 CECalendar::setTemporalMonthCode(const char* code, UErrorCode& status) { 155 if (U_FAILURE(status)) { 156 return; 157 } 158 if (uprv_strcmp(code, kMonthCode13) == 0) { 159 set(UCAL_MONTH, 12); 160 set(UCAL_IS_LEAP_MONTH, 0); 161 return; 162 } 163 Calendar::setTemporalMonthCode(code, status); 164 } 165 166 U_NAMESPACE_END 167 168 #endif /* #if !UCONFIG_NO_FORMATTING */ 169 //eof