/src/icu/icu4c/source/i18n/cecal.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 272 | : Calendar(TimeZone::forLocaleOrDefault(aLocale), aLocale, success) |
55 | 272 | { |
56 | 272 | } |
57 | | |
58 | | CECalendar::CECalendar (const CECalendar& other) |
59 | 4.79k | : Calendar(other) |
60 | 4.79k | { |
61 | 4.79k | } |
62 | | |
63 | | CECalendar::~CECalendar() |
64 | 4.96k | { |
65 | 4.96k | } |
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 | 51.4k | { |
74 | 51.4k | int64_t year64 = eyear; |
75 | | // handle month > 12, < 0 (e.g. from add/set) |
76 | 51.4k | if ( emonth >= 0 ) { |
77 | 50.0k | year64 += emonth/13; |
78 | 50.0k | emonth %= 13; |
79 | 50.0k | } else { |
80 | 1.42k | ++emonth; |
81 | 1.42k | year64 += emonth/13 - 1; |
82 | 1.42k | emonth = emonth%13 + 12; |
83 | 1.42k | } |
84 | | |
85 | 51.4k | return ( |
86 | 51.4k | getJDEpochOffset() // difference from Julian epoch to 1,1,1 |
87 | 51.4k | + 365LL * year64 // number of days from years |
88 | 51.4k | + ClockMath::floorDivideInt64(year64, 4LL) // extra day of leap year |
89 | 51.4k | + 30 * emonth // number of days from months (months are 0-based) |
90 | 51.4k | - 1 // number of days for present month (1 based) |
91 | 51.4k | ); |
92 | 51.4k | } |
93 | | |
94 | | int32_t |
95 | | CECalendar::handleGetLimit(UCalendarDateFields field, ELimitType limitType) const |
96 | 14.5k | { |
97 | 14.5k | return LIMITS[field][limitType]; |
98 | 14.5k | } |
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 | 16.6k | { |
107 | 16.6k | int32_t c4; // number of 4 year cycle (1461 days) |
108 | 16.6k | int32_t r4; // remainder of 4 year cycle, always positive |
109 | | |
110 | 16.6k | if (uprv_add32_overflow(julianDay, -jdEpochOffset, &julianDay)) { |
111 | 23 | status = U_ILLEGAL_ARGUMENT_ERROR; |
112 | 23 | return; |
113 | 23 | } |
114 | 16.6k | c4 = ClockMath::floorDivide(julianDay, 1461, &r4); |
115 | | |
116 | 16.6k | year = 4 * c4 + (r4/365 - r4/1460); // 4 * <number of 4year cycle> + <years within the last cycle> |
117 | | |
118 | 16.6k | doy = (r4 == 1460) ? 365 : (r4 % 365); // days in present year |
119 | | |
120 | 16.6k | month = doy / 30; // 30 -> Coptic/Ethiopic month length up to 12th month |
121 | 16.6k | day = (doy % 30) + 1; // 1-based days in a month |
122 | 16.6k | doy++; // 1-based days in a year. |
123 | 16.6k | } |
124 | | } // namespace |
125 | | |
126 | | void |
127 | | CECalendar::handleComputeFields(int32_t julianDay, UErrorCode& status) |
128 | 16.6k | { |
129 | 16.6k | int32_t eyear, month, day, doy; |
130 | 16.6k | jdToCE(julianDay, getJDEpochOffset(), eyear, month, day, doy, status); |
131 | 16.6k | if (U_FAILURE(status)) return; |
132 | 16.6k | int32_t era = extendedYearToEra(eyear); |
133 | 16.6k | int32_t year = extendedYearToYear(eyear); |
134 | | |
135 | 16.6k | internalSet(UCAL_EXTENDED_YEAR, eyear); |
136 | 16.6k | internalSet(UCAL_ERA, era); |
137 | 16.6k | internalSet(UCAL_YEAR, year); |
138 | 16.6k | internalSet(UCAL_MONTH, month); |
139 | 16.6k | internalSet(UCAL_ORDINAL_MONTH, month); |
140 | 16.6k | internalSet(UCAL_DATE, day); |
141 | 16.6k | internalSet(UCAL_DAY_OF_YEAR, doy); |
142 | 16.6k | } |
143 | | |
144 | | static const char* kMonthCode13 = "M13"; |
145 | | |
146 | 0 | const char* CECalendar::getTemporalMonthCode(UErrorCode& status) const { |
147 | 0 | if (get(UCAL_MONTH, status) == 12) { |
148 | 0 | return kMonthCode13; |
149 | 0 | } |
150 | 0 | return Calendar::getTemporalMonthCode(status); |
151 | 0 | } |
152 | | |
153 | | void |
154 | 0 | CECalendar::setTemporalMonthCode(const char* code, UErrorCode& status) { |
155 | 0 | if (U_FAILURE(status)) { |
156 | 0 | return; |
157 | 0 | } |
158 | 0 | if (uprv_strcmp(code, kMonthCode13) == 0) { |
159 | 0 | set(UCAL_MONTH, 12); |
160 | 0 | set(UCAL_IS_LEAP_MONTH, 0); |
161 | 0 | return; |
162 | 0 | } |
163 | 0 | Calendar::setTemporalMonthCode(code, status); |
164 | 0 | } |
165 | | |
166 | | U_NAMESPACE_END |
167 | | |
168 | | #endif /* #if !UCONFIG_NO_FORMATTING */ |
169 | | //eof |