Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: source/i18n/calendar.cpp

Issue 845603002: Update ICU to 54.1 step 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/deps/icu.git@master
Patch Set: remove unusued directories Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « source/i18n/bocsu.cpp ('k') | source/i18n/chnsecal.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 ******************************************************************************* 2 *******************************************************************************
3 * Copyright (C) 1997-2013, International Business Machines Corporation and * 3 * Copyright (C) 1997-2014, International Business Machines Corporation and *
4 * others. All Rights Reserved. * 4 * others. All Rights Reserved. *
5 ******************************************************************************* 5 *******************************************************************************
6 * 6 *
7 * File CALENDAR.CPP 7 * File CALENDAR.CPP
8 * 8 *
9 * Modification History: 9 * Modification History:
10 * 10 *
11 * Date Name Description 11 * Date Name Description
12 * 02/03/97 clhuang Creation. 12 * 02/03/97 clhuang Creation.
13 * 04/22/97 aliu Cleaned up, fixed memory leak, made 13 * 04/22/97 aliu Cleaned up, fixed memory leak, made
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 #include <stdio.h> 99 #include <stdio.h>
100 100
101 /** 101 /**
102 * convert a UCalendarDateFields into a string - for debugging 102 * convert a UCalendarDateFields into a string - for debugging
103 * @param f field enum 103 * @param f field enum
104 * @return static string to the field name 104 * @return static string to the field name
105 * @internal 105 * @internal
106 */ 106 */
107 107
108 const char* fldName(UCalendarDateFields f) { 108 const char* fldName(UCalendarDateFields f) {
109 » return udbg_enumName(UDBG_UCalendarDateFields, (int32_t)f); 109 return udbg_enumName(UDBG_UCalendarDateFields, (int32_t)f);
110 } 110 }
111 111
112 #if UCAL_DEBUG_DUMP 112 #if UCAL_DEBUG_DUMP
113 // from CalendarTest::calToStr - but doesn't modify contents. 113 // from CalendarTest::calToStr - but doesn't modify contents.
114 void ucal_dump(const Calendar &cal) { 114 void ucal_dump(const Calendar &cal) {
115 cal.dump(); 115 cal.dump();
116 } 116 }
117 117
118 void Calendar::dump() const { 118 void Calendar::dump() const {
119 int i; 119 int i;
(...skipping 553 matching lines...) Expand 10 before | Expand all | Expand 10 after
673 673
674 Calendar::Calendar(UErrorCode& success) 674 Calendar::Calendar(UErrorCode& success)
675 : UObject(), 675 : UObject(),
676 fIsTimeSet(FALSE), 676 fIsTimeSet(FALSE),
677 fAreFieldsSet(FALSE), 677 fAreFieldsSet(FALSE),
678 fAreAllFieldsSet(FALSE), 678 fAreAllFieldsSet(FALSE),
679 fAreFieldsVirtuallySet(FALSE), 679 fAreFieldsVirtuallySet(FALSE),
680 fNextStamp((int32_t)kMinimumUserStamp), 680 fNextStamp((int32_t)kMinimumUserStamp),
681 fTime(0), 681 fTime(0),
682 fLenient(TRUE), 682 fLenient(TRUE),
683 fZone(0), 683 fZone(NULL),
684 fRepeatedWallTime(UCAL_WALLTIME_LAST), 684 fRepeatedWallTime(UCAL_WALLTIME_LAST),
685 fSkippedWallTime(UCAL_WALLTIME_LAST) 685 fSkippedWallTime(UCAL_WALLTIME_LAST)
686 { 686 {
687 clear(); 687 clear();
688 if (U_FAILURE(success)) {
689 return;
690 }
688 fZone = TimeZone::createDefault(); 691 fZone = TimeZone::createDefault();
689 if (fZone == NULL) { 692 if (fZone == NULL) {
690 success = U_MEMORY_ALLOCATION_ERROR; 693 success = U_MEMORY_ALLOCATION_ERROR;
691 } 694 }
692 setWeekData(Locale::getDefault(), NULL, success); 695 setWeekData(Locale::getDefault(), NULL, success);
693 } 696 }
694 697
695 // ------------------------------------- 698 // -------------------------------------
696 699
697 Calendar::Calendar(TimeZone* zone, const Locale& aLocale, UErrorCode& success) 700 Calendar::Calendar(TimeZone* zone, const Locale& aLocale, UErrorCode& success)
698 : UObject(), 701 : UObject(),
699 fIsTimeSet(FALSE), 702 fIsTimeSet(FALSE),
700 fAreFieldsSet(FALSE), 703 fAreFieldsSet(FALSE),
701 fAreAllFieldsSet(FALSE), 704 fAreAllFieldsSet(FALSE),
702 fAreFieldsVirtuallySet(FALSE), 705 fAreFieldsVirtuallySet(FALSE),
703 fNextStamp((int32_t)kMinimumUserStamp), 706 fNextStamp((int32_t)kMinimumUserStamp),
704 fTime(0), 707 fTime(0),
705 fLenient(TRUE), 708 fLenient(TRUE),
706 fZone(0), 709 fZone(NULL),
707 fRepeatedWallTime(UCAL_WALLTIME_LAST), 710 fRepeatedWallTime(UCAL_WALLTIME_LAST),
708 fSkippedWallTime(UCAL_WALLTIME_LAST) 711 fSkippedWallTime(UCAL_WALLTIME_LAST)
709 { 712 {
713 if (U_FAILURE(success)) {
714 return;
715 }
710 if(zone == 0) { 716 if(zone == 0) {
711 #if defined (U_DEBUG_CAL) 717 #if defined (U_DEBUG_CAL)
712 fprintf(stderr, "%s:%d: ILLEGAL ARG because timezone cannot be 0\n", 718 fprintf(stderr, "%s:%d: ILLEGAL ARG because timezone cannot be 0\n",
713 __FILE__, __LINE__); 719 __FILE__, __LINE__);
714 #endif 720 #endif
715 success = U_ILLEGAL_ARGUMENT_ERROR; 721 success = U_ILLEGAL_ARGUMENT_ERROR;
716 return; 722 return;
717 } 723 }
718 724
719 clear(); 725 clear();
720 fZone = zone; 726 fZone = zone;
721
722 setWeekData(aLocale, NULL, success); 727 setWeekData(aLocale, NULL, success);
723 } 728 }
724 729
725 // ------------------------------------- 730 // -------------------------------------
726 731
727 Calendar::Calendar(const TimeZone& zone, const Locale& aLocale, UErrorCode& succ ess) 732 Calendar::Calendar(const TimeZone& zone, const Locale& aLocale, UErrorCode& succ ess)
728 : UObject(), 733 : UObject(),
729 fIsTimeSet(FALSE), 734 fIsTimeSet(FALSE),
730 fAreFieldsSet(FALSE), 735 fAreFieldsSet(FALSE),
731 fAreAllFieldsSet(FALSE), 736 fAreAllFieldsSet(FALSE),
732 fAreFieldsVirtuallySet(FALSE), 737 fAreFieldsVirtuallySet(FALSE),
733 fNextStamp((int32_t)kMinimumUserStamp), 738 fNextStamp((int32_t)kMinimumUserStamp),
734 fTime(0), 739 fTime(0),
735 fLenient(TRUE), 740 fLenient(TRUE),
736 fZone(0), 741 fZone(NULL),
737 fRepeatedWallTime(UCAL_WALLTIME_LAST), 742 fRepeatedWallTime(UCAL_WALLTIME_LAST),
738 fSkippedWallTime(UCAL_WALLTIME_LAST) 743 fSkippedWallTime(UCAL_WALLTIME_LAST)
739 { 744 {
745 if (U_FAILURE(success)) {
746 return;
747 }
740 clear(); 748 clear();
741 fZone = zone.clone(); 749 fZone = zone.clone();
742 if (fZone == NULL) { 750 if (fZone == NULL) {
743 » success = U_MEMORY_ALLOCATION_ERROR; 751 success = U_MEMORY_ALLOCATION_ERROR;
744 } 752 }
745 setWeekData(aLocale, NULL, success); 753 setWeekData(aLocale, NULL, success);
746 } 754 }
747 755
748 // ------------------------------------- 756 // -------------------------------------
749 757
750 Calendar::~Calendar() 758 Calendar::~Calendar()
751 { 759 {
752 delete fZone; 760 delete fZone;
753 } 761 }
754 762
755 // ------------------------------------- 763 // -------------------------------------
756 764
757 Calendar::Calendar(const Calendar &source) 765 Calendar::Calendar(const Calendar &source)
758 : UObject(source) 766 : UObject(source)
759 { 767 {
760 fZone = 0; 768 fZone = NULL;
761 *this = source; 769 *this = source;
762 } 770 }
763 771
764 // ------------------------------------- 772 // -------------------------------------
765 773
766 Calendar & 774 Calendar &
767 Calendar::operator=(const Calendar &right) 775 Calendar::operator=(const Calendar &right)
768 { 776 {
769 if (this != &right) { 777 if (this != &right) {
770 uprv_arrayCopy(right.fFields, fFields, UCAL_FIELD_COUNT); 778 uprv_arrayCopy(right.fFields, fFields, UCAL_FIELD_COUNT);
771 uprv_arrayCopy(right.fIsSet, fIsSet, UCAL_FIELD_COUNT); 779 uprv_arrayCopy(right.fIsSet, fIsSet, UCAL_FIELD_COUNT);
772 uprv_arrayCopy(right.fStamp, fStamp, UCAL_FIELD_COUNT); 780 uprv_arrayCopy(right.fStamp, fStamp, UCAL_FIELD_COUNT);
773 fTime = right.fTime; 781 fTime = right.fTime;
774 fIsTimeSet = right.fIsTimeSet; 782 fIsTimeSet = right.fIsTimeSet;
775 fAreAllFieldsSet = right.fAreAllFieldsSet; 783 fAreAllFieldsSet = right.fAreAllFieldsSet;
776 fAreFieldsSet = right.fAreFieldsSet; 784 fAreFieldsSet = right.fAreFieldsSet;
777 fAreFieldsVirtuallySet = right.fAreFieldsVirtuallySet; 785 fAreFieldsVirtuallySet = right.fAreFieldsVirtuallySet;
778 fLenient = right.fLenient; 786 fLenient = right.fLenient;
779 fRepeatedWallTime = right.fRepeatedWallTime; 787 fRepeatedWallTime = right.fRepeatedWallTime;
780 fSkippedWallTime = right.fSkippedWallTime; 788 fSkippedWallTime = right.fSkippedWallTime;
781 if (fZone != NULL) { 789 delete fZone;
782 delete fZone; 790 fZone = NULL;
783 }
784 if (right.fZone != NULL) { 791 if (right.fZone != NULL) {
785 fZone = right.fZone->clone(); 792 fZone = right.fZone->clone();
786 } 793 }
787 fFirstDayOfWeek = right.fFirstDayOfWeek; 794 fFirstDayOfWeek = right.fFirstDayOfWeek;
788 fMinimalDaysInFirstWeek = right.fMinimalDaysInFirstWeek; 795 fMinimalDaysInFirstWeek = right.fMinimalDaysInFirstWeek;
789 fWeekendOnset = right.fWeekendOnset; 796 fWeekendOnset = right.fWeekendOnset;
790 fWeekendOnsetMillis = right.fWeekendOnsetMillis; 797 fWeekendOnsetMillis = right.fWeekendOnsetMillis;
791 fWeekendCease = right.fWeekendCease; 798 fWeekendCease = right.fWeekendCease;
792 fWeekendCeaseMillis = right.fWeekendCeaseMillis; 799 fWeekendCeaseMillis = right.fWeekendCeaseMillis;
793 fNextStamp = right.fNextStamp; 800 fNextStamp = right.fNextStamp;
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
1157 { 1164 {
1158 set(UCAL_YEAR, year); 1165 set(UCAL_YEAR, year);
1159 set(UCAL_MONTH, month); 1166 set(UCAL_MONTH, month);
1160 set(UCAL_DATE, date); 1167 set(UCAL_DATE, date);
1161 set(UCAL_HOUR_OF_DAY, hour); 1168 set(UCAL_HOUR_OF_DAY, hour);
1162 set(UCAL_MINUTE, minute); 1169 set(UCAL_MINUTE, minute);
1163 set(UCAL_SECOND, second); 1170 set(UCAL_SECOND, second);
1164 } 1171 }
1165 1172
1166 // ------------------------------------- 1173 // -------------------------------------
1174 // For now the full getRelatedYear implementation is here;
1175 // per #10752 move the non-default implementation to subclasses
1176 // (default implementation will do no year adjustment)
1177
1178 static int32_t gregoYearFromIslamicStart(int32_t year) {
1179 // ad hoc conversion, improve under #10752
1180 // rough est for now, ok for grego 1846-2138,
1181 // otherwise occasionally wrong (for 3% of years)
1182 int cycle, offset, shift = 0;
1183 if (year >= 1397) {
1184 cycle = (year - 1397) / 67;
1185 offset = (year - 1397) % 67;
1186 shift = 2*cycle + ((offset >= 33)? 1: 0);
1187 } else {
1188 cycle = (year - 1396) / 67 - 1;
1189 offset = -(year - 1396) % 67;
1190 shift = 2*cycle + ((offset <= 33)? 1: 0);
1191 }
1192 return year + 579 - shift;
1193 }
1194
1195 int32_t Calendar::getRelatedYear(UErrorCode &status) const
1196 {
1197 if (U_FAILURE(status)) {
1198 return 0;
1199 }
1200 int32_t year = get(UCAL_EXTENDED_YEAR, status);
1201 if (U_FAILURE(status)) {
1202 return 0;
1203 }
1204 // modify for calendar type
1205 ECalType type = getCalendarType(getType());
1206 switch (type) {
1207 case CALTYPE_PERSIAN:
1208 year += 622; break;
1209 case CALTYPE_HEBREW:
1210 year -= 3760; break;
1211 case CALTYPE_CHINESE:
1212 year -= 2637; break;
1213 case CALTYPE_INDIAN:
1214 year += 79; break;
1215 case CALTYPE_COPTIC:
1216 year += 284; break;
1217 case CALTYPE_ETHIOPIC:
1218 year += 8; break;
1219 case CALTYPE_ETHIOPIC_AMETE_ALEM:
1220 year -=5492; break;
1221 case CALTYPE_DANGI:
1222 year -= 2333; break;
1223 case CALTYPE_ISLAMIC_CIVIL:
1224 case CALTYPE_ISLAMIC:
1225 case CALTYPE_ISLAMIC_UMALQURA:
1226 case CALTYPE_ISLAMIC_TBLA:
1227 case CALTYPE_ISLAMIC_RGSA:
1228 year = gregoYearFromIslamicStart(year); break;
1229 default:
1230 // CALTYPE_GREGORIAN
1231 // CALTYPE_JAPANESE
1232 // CALTYPE_BUDDHIST
1233 // CALTYPE_ROC
1234 // CALTYPE_ISO8601
1235 // do nothing, EXTENDED_YEAR same as Gregorian
1236 break;
1237 }
1238 return year;
1239 }
1240
1241 // -------------------------------------
1242 // For now the full setRelatedYear implementation is here;
1243 // per #10752 move the non-default implementation to subclasses
1244 // (default implementation will do no year adjustment)
1245
1246 static int32_t firstIslamicStartYearFromGrego(int32_t year) {
1247 // ad hoc conversion, improve under #10752
1248 // rough est for now, ok for grego 1846-2138,
1249 // otherwise occasionally wrong (for 3% of years)
1250 int cycle, offset, shift = 0;
1251 if (year >= 1977) {
1252 cycle = (year - 1977) / 65;
1253 offset = (year - 1977) % 65;
1254 shift = 2*cycle + ((offset >= 32)? 1: 0);
1255 } else {
1256 cycle = (year - 1976) / 65 - 1;
1257 offset = -(year - 1976) % 65;
1258 shift = 2*cycle + ((offset <= 32)? 1: 0);
1259 }
1260 return year - 579 + shift;
1261 }
1262 void Calendar::setRelatedYear(int32_t year)
1263 {
1264 // modify for calendar type
1265 ECalType type = getCalendarType(getType());
1266 switch (type) {
1267 case CALTYPE_PERSIAN:
1268 year -= 622; break;
1269 case CALTYPE_HEBREW:
1270 year += 3760; break;
1271 case CALTYPE_CHINESE:
1272 year += 2637; break;
1273 case CALTYPE_INDIAN:
1274 year -= 79; break;
1275 case CALTYPE_COPTIC:
1276 year -= 284; break;
1277 case CALTYPE_ETHIOPIC:
1278 year -= 8; break;
1279 case CALTYPE_ETHIOPIC_AMETE_ALEM:
1280 year +=5492; break;
1281 case CALTYPE_DANGI:
1282 year += 2333; break;
1283 case CALTYPE_ISLAMIC_CIVIL:
1284 case CALTYPE_ISLAMIC:
1285 case CALTYPE_ISLAMIC_UMALQURA:
1286 case CALTYPE_ISLAMIC_TBLA:
1287 case CALTYPE_ISLAMIC_RGSA:
1288 year = firstIslamicStartYearFromGrego(year); break;
1289 default:
1290 // CALTYPE_GREGORIAN
1291 // CALTYPE_JAPANESE
1292 // CALTYPE_BUDDHIST
1293 // CALTYPE_ROC
1294 // CALTYPE_ISO8601
1295 // do nothing, EXTENDED_YEAR same as Gregorian
1296 break;
1297 }
1298 // set extended year
1299 set(UCAL_EXTENDED_YEAR, year);
1300 }
1301
1302 // -------------------------------------
1167 1303
1168 void 1304 void
1169 Calendar::clear() 1305 Calendar::clear()
1170 { 1306 {
1171 for (int32_t i=0; i<UCAL_FIELD_COUNT; ++i) { 1307 for (int32_t i=0; i<UCAL_FIELD_COUNT; ++i) {
1172 fFields[i] = 0; // Must do this; other code depends on it 1308 fFields[i] = 0; // Must do this; other code depends on it
1173 fStamp[i] = kUnset; 1309 fStamp[i] = kUnset;
1174 fIsSet[i] = FALSE; // Remove later 1310 fIsSet[i] = FALSE; // Remove later
1175 } 1311 }
1176 fIsTimeSet = fAreFieldsSet = fAreAllFieldsSet = fAreFieldsVirtuallySet = FAL SE; 1312 fIsTimeSet = fAreFieldsSet = fAreAllFieldsSet = fAreFieldsVirtuallySet = FAL SE;
(...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after
1887 void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status ) 2023 void Calendar::add(UCalendarDateFields field, int32_t amount, UErrorCode& status )
1888 { 2024 {
1889 if (amount == 0) { 2025 if (amount == 0) {
1890 return; // Do nothing! 2026 return; // Do nothing!
1891 } 2027 }
1892 2028
1893 // We handle most fields in the same way. The algorithm is to add 2029 // We handle most fields in the same way. The algorithm is to add
1894 // a computed amount of millis to the current millis. The only 2030 // a computed amount of millis to the current millis. The only
1895 // wrinkle is with DST (and/or a change to the zone's UTC offset, which 2031 // wrinkle is with DST (and/or a change to the zone's UTC offset, which
1896 // we'll include with DST) -- for some fields, like the DAY_OF_MONTH, 2032 // we'll include with DST) -- for some fields, like the DAY_OF_MONTH,
1897 // we don't want the HOUR to shift due to changes in DST. If the 2033 // we don't want the wall time to shift due to changes in DST. If the
1898 // result of the add operation is to move from DST to Standard, or 2034 // result of the add operation is to move from DST to Standard, or
1899 // vice versa, we need to adjust by an hour forward or back, 2035 // vice versa, we need to adjust by an hour forward or back,
1900 // respectively. For such fields we set keepHourInvariant to TRUE. 2036 // respectively. For such fields we set keepWallTimeInvariant to TRUE.
1901 2037
1902 // We only adjust the DST for fields larger than an hour. For 2038 // We only adjust the DST for fields larger than an hour. For
1903 // fields smaller than an hour, we cannot adjust for DST without 2039 // fields smaller than an hour, we cannot adjust for DST without
1904 // causing problems. for instance, if you add one hour to April 5, 2040 // causing problems. for instance, if you add one hour to April 5,
1905 // 1998, 1:00 AM, in PST, the time becomes "2:00 AM PDT" (an 2041 // 1998, 1:00 AM, in PST, the time becomes "2:00 AM PDT" (an
1906 // illegal value), but then the adjustment sees the change and 2042 // illegal value), but then the adjustment sees the change and
1907 // compensates by subtracting an hour. As a result the time 2043 // compensates by subtracting an hour. As a result the time
1908 // doesn't advance at all. 2044 // doesn't advance at all.
1909 2045
1910 // For some fields larger than a day, such as a UCAL_MONTH, we pin the 2046 // For some fields larger than a day, such as a UCAL_MONTH, we pin the
1911 // UCAL_DAY_OF_MONTH. This allows <March 31>.add(UCAL_MONTH, 1) to be 2047 // UCAL_DAY_OF_MONTH. This allows <March 31>.add(UCAL_MONTH, 1) to be
1912 // <April 30>, rather than <April 31> => <May 1>. 2048 // <April 30>, rather than <April 31> => <May 1>.
1913 2049
1914 double delta = amount; // delta in ms 2050 double delta = amount; // delta in ms
1915 UBool keepHourInvariant = TRUE; 2051 UBool keepWallTimeInvariant = TRUE;
1916 2052
1917 switch (field) { 2053 switch (field) {
1918 case UCAL_ERA: 2054 case UCAL_ERA:
1919 set(field, get(field, status) + amount); 2055 set(field, get(field, status) + amount);
1920 pinField(UCAL_ERA, status); 2056 pinField(UCAL_ERA, status);
1921 return; 2057 return;
1922 2058
1923 case UCAL_YEAR: 2059 case UCAL_YEAR:
1924 case UCAL_YEAR_WOY: 2060 case UCAL_YEAR_WOY:
1925 { 2061 {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1967 case UCAL_DAY_OF_YEAR: 2103 case UCAL_DAY_OF_YEAR:
1968 case UCAL_DAY_OF_WEEK: 2104 case UCAL_DAY_OF_WEEK:
1969 case UCAL_DOW_LOCAL: 2105 case UCAL_DOW_LOCAL:
1970 case UCAL_JULIAN_DAY: 2106 case UCAL_JULIAN_DAY:
1971 delta *= kOneDay; 2107 delta *= kOneDay;
1972 break; 2108 break;
1973 2109
1974 case UCAL_HOUR_OF_DAY: 2110 case UCAL_HOUR_OF_DAY:
1975 case UCAL_HOUR: 2111 case UCAL_HOUR:
1976 delta *= kOneHour; 2112 delta *= kOneHour;
1977 keepHourInvariant = FALSE; 2113 keepWallTimeInvariant = FALSE;
1978 break; 2114 break;
1979 2115
1980 case UCAL_MINUTE: 2116 case UCAL_MINUTE:
1981 delta *= kOneMinute; 2117 delta *= kOneMinute;
1982 keepHourInvariant = FALSE; 2118 keepWallTimeInvariant = FALSE;
1983 break; 2119 break;
1984 2120
1985 case UCAL_SECOND: 2121 case UCAL_SECOND:
1986 delta *= kOneSecond; 2122 delta *= kOneSecond;
1987 keepHourInvariant = FALSE; 2123 keepWallTimeInvariant = FALSE;
1988 break; 2124 break;
1989 2125
1990 case UCAL_MILLISECOND: 2126 case UCAL_MILLISECOND:
1991 case UCAL_MILLISECONDS_IN_DAY: 2127 case UCAL_MILLISECONDS_IN_DAY:
1992 keepHourInvariant = FALSE; 2128 keepWallTimeInvariant = FALSE;
1993 break; 2129 break;
1994 2130
1995 default: 2131 default:
1996 #if defined (U_DEBUG_CAL) 2132 #if defined (U_DEBUG_CAL)
1997 fprintf(stderr, "%s:%d: ILLEGAL ARG because field %s not addable", 2133 fprintf(stderr, "%s:%d: ILLEGAL ARG because field %s not addable",
1998 __FILE__, __LINE__, fldName(field)); 2134 __FILE__, __LINE__, fldName(field));
1999 #endif 2135 #endif
2000 status = U_ILLEGAL_ARGUMENT_ERROR; 2136 status = U_ILLEGAL_ARGUMENT_ERROR;
2001 return; 2137 return;
2002 // throw new IllegalArgumentException("Calendar.add(" + fieldName(field ) + 2138 // throw new IllegalArgumentException("Calendar.add(" + fieldName(field ) +
2003 // ") not supported"); 2139 // ") not supported");
2004 } 2140 }
2005 2141
2006 // In order to keep the hour invariant (for fields where this is 2142 // In order to keep the wall time invariant (for fields where this is
2007 // appropriate), check the combined DST & ZONE offset before and 2143 // appropriate), check the combined DST & ZONE offset before and
2008 // after the add() operation. If it changes, then adjust the millis 2144 // after the add() operation. If it changes, then adjust the millis
2009 // to compensate. 2145 // to compensate.
2010 int32_t prevOffset = 0; 2146 int32_t prevOffset = 0;
2011 int32_t hour = 0; 2147 int32_t prevWallTime = 0;
2012 if (keepHourInvariant) { 2148 if (keepWallTimeInvariant) {
2013 prevOffset = get(UCAL_DST_OFFSET, status) + get(UCAL_ZONE_OFFSET, status ); 2149 prevOffset = get(UCAL_DST_OFFSET, status) + get(UCAL_ZONE_OFFSET, status );
2014 hour = internalGet(UCAL_HOUR_OF_DAY); 2150 prevWallTime = get(UCAL_MILLISECONDS_IN_DAY, status);
2015 } 2151 }
2016 2152
2017 setTimeInMillis(getTimeInMillis(status) + delta, status); 2153 setTimeInMillis(getTimeInMillis(status) + delta, status);
2018 2154
2019 if (keepHourInvariant) { 2155 if (keepWallTimeInvariant) {
2020 int32_t newOffset = get(UCAL_DST_OFFSET, status) + get(UCAL_ZONE_OFFSET, status); 2156 int32_t newWallTime = get(UCAL_MILLISECONDS_IN_DAY, status);
2021 if (newOffset != prevOffset) { 2157 if (newWallTime != prevWallTime) {
2022 // We have done an hour-invariant adjustment but the 2158 // There is at least one zone transition between the base
2023 // combined offset has changed. We adjust millis to keep 2159 // time and the result time. As the result, wall time has
2024 // the hour constant. In cases such as midnight after 2160 // changed.
2025 // a DST change which occurs at midnight, there is the 2161 UDate t = internalGetTime();
2026 // danger of adjusting into a different day. To avoid 2162 int32_t newOffset = get(UCAL_DST_OFFSET, status) + get(UCAL_ZONE_OFF SET, status);
2027 // this we make the adjustment only if it actually 2163 if (newOffset != prevOffset) {
2028 // maintains the hour. 2164 // When the difference of the previous UTC offset and
2029 2165 // the new UTC offset exceeds 1 full day, we do not want
2030 // When the difference of the previous UTC offset and 2166 // to roll over/back the date. For now, this only happens
2031 // the new UTC offset exceeds 1 full day, we do not want 2167 // in Samoa (Pacific/Apia) on Dec 30, 2011. See ticket:9452.
2032 // to roll over/back the date. For now, this only happens 2168 int32_t adjAmount = prevOffset - newOffset;
2033 // in Samoa (Pacific/Apia) on Dec 30, 2011. See ticket:9452. 2169 adjAmount = adjAmount >= 0 ? adjAmount % (int32_t)kOneDay : -(-a djAmount % (int32_t)kOneDay);
2034 int32_t adjAmount = prevOffset - newOffset; 2170 if (adjAmount != 0) {
2035 adjAmount = adjAmount >= 0 ? adjAmount % (int32_t)kOneDay : -(-adjAm ount % (int32_t)kOneDay); 2171 setTimeInMillis(t + adjAmount, status);
2036 if (adjAmount != 0) { 2172 newWallTime = get(UCAL_MILLISECONDS_IN_DAY, status);
2037 double t = internalGetTime(); 2173 }
2038 setTimeInMillis(t + adjAmount, status); 2174 if (newWallTime != prevWallTime) {
2039 if (get(UCAL_HOUR_OF_DAY, status) != hour) { 2175 // The result wall time or adjusted wall time was shifted be cause
2040 setTimeInMillis(t, status); 2176 // the target wall time does not exist on the result date.
2177 switch (fSkippedWallTime) {
2178 case UCAL_WALLTIME_FIRST:
2179 if (adjAmount > 0) {
2180 setTimeInMillis(t, status);
2181 }
2182 break;
2183 case UCAL_WALLTIME_LAST:
2184 if (adjAmount < 0) {
2185 setTimeInMillis(t, status);
2186 }
2187 break;
2188 case UCAL_WALLTIME_NEXT_VALID:
2189 UDate tmpT = adjAmount > 0 ? internalGetTime() : t;
2190 UDate immediatePrevTrans;
2191 UBool hasTransition = getImmediatePreviousZoneTransition (tmpT, &immediatePrevTrans, status);
2192 if (U_SUCCESS(status) && hasTransition) {
2193 setTimeInMillis(immediatePrevTrans, status);
2194 }
2195 break;
2196 }
2041 } 2197 }
2042 } 2198 }
2043 } 2199 }
2044 } 2200 }
2045 } 2201 }
2046 2202
2047 // ------------------------------------- 2203 // -------------------------------------
2048 int32_t Calendar::fieldDifference(UDate when, EDateFields field, UErrorCode& sta tus) { 2204 int32_t Calendar::fieldDifference(UDate when, EDateFields field, UErrorCode& sta tus) {
2049 return fieldDifference(when, (UCalendarDateFields) field, status); 2205 return fieldDifference(when, (UCalendarDateFields) field, status);
2050 } 2206 }
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
2151 2307
2152 // ------------------------------------- 2308 // -------------------------------------
2153 2309
2154 void 2310 void
2155 Calendar::adoptTimeZone(TimeZone* zone) 2311 Calendar::adoptTimeZone(TimeZone* zone)
2156 { 2312 {
2157 // Do nothing if passed-in zone is NULL 2313 // Do nothing if passed-in zone is NULL
2158 if (zone == NULL) return; 2314 if (zone == NULL) return;
2159 2315
2160 // fZone should always be non-null 2316 // fZone should always be non-null
2161 if (fZone != NULL) delete fZone; 2317 delete fZone;
2162 fZone = zone; 2318 fZone = zone;
2163 2319
2164 // if the zone changes, we need to recompute the time fields 2320 // if the zone changes, we need to recompute the time fields
2165 fAreFieldsSet = FALSE; 2321 fAreFieldsSet = FALSE;
2166 } 2322 }
2167 2323
2168 // ------------------------------------- 2324 // -------------------------------------
2169 void 2325 void
2170 Calendar::setTimeZone(const TimeZone& zone) 2326 Calendar::setTimeZone(const TimeZone& zone)
2171 { 2327 {
2172 adoptTimeZone(zone.clone()); 2328 adoptTimeZone(zone.clone());
2173 } 2329 }
2174 2330
2175 // ------------------------------------- 2331 // -------------------------------------
2176 2332
2177 const TimeZone& 2333 const TimeZone&
2178 Calendar::getTimeZone() const 2334 Calendar::getTimeZone() const
2179 { 2335 {
2336 U_ASSERT(fZone != NULL);
2180 return *fZone; 2337 return *fZone;
2181 } 2338 }
2182 2339
2183 // ------------------------------------- 2340 // -------------------------------------
2184 2341
2185 TimeZone* 2342 TimeZone*
2186 Calendar::orphanTimeZone() 2343 Calendar::orphanTimeZone()
2187 { 2344 {
2345 // we let go of the time zone; the new time zone is the system default time zone
2346 TimeZone *defaultZone = TimeZone::createDefault();
2347 if (defaultZone == NULL) {
2348 // No error handling available. Must keep fZone non-NULL, there are many unchecked uses.
2349 return NULL;
2350 }
2188 TimeZone *z = fZone; 2351 TimeZone *z = fZone;
2189 // we let go of the time zone; the new time zone is the system default time zone 2352 fZone = defaultZone;
2190 fZone = TimeZone::createDefault();
2191 return z; 2353 return z;
2192 } 2354 }
2193 2355
2194 // ------------------------------------- 2356 // -------------------------------------
2195 2357
2196 void 2358 void
2197 Calendar::setLenient(UBool lenient) 2359 Calendar::setLenient(UBool lenient)
2198 { 2360 {
2199 fLenient = lenient; 2361 fLenient = lenient;
2200 } 2362 }
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
2299 UCalendarWeekdayType 2461 UCalendarWeekdayType
2300 Calendar::getDayOfWeekType(UCalendarDaysOfWeek dayOfWeek, UErrorCode &status) co nst 2462 Calendar::getDayOfWeekType(UCalendarDaysOfWeek dayOfWeek, UErrorCode &status) co nst
2301 { 2463 {
2302 if (U_FAILURE(status)) { 2464 if (U_FAILURE(status)) {
2303 return UCAL_WEEKDAY; 2465 return UCAL_WEEKDAY;
2304 } 2466 }
2305 if (dayOfWeek < UCAL_SUNDAY || dayOfWeek > UCAL_SATURDAY) { 2467 if (dayOfWeek < UCAL_SUNDAY || dayOfWeek > UCAL_SATURDAY) {
2306 status = U_ILLEGAL_ARGUMENT_ERROR; 2468 status = U_ILLEGAL_ARGUMENT_ERROR;
2307 return UCAL_WEEKDAY; 2469 return UCAL_WEEKDAY;
2308 } 2470 }
2309 » if (fWeekendOnset == fWeekendCease) { 2471 if (fWeekendOnset == fWeekendCease) {
2310 » » if (dayOfWeek != fWeekendOnset) 2472 if (dayOfWeek != fWeekendOnset)
2311 » » » return UCAL_WEEKDAY; 2473 return UCAL_WEEKDAY;
2312 » » return (fWeekendOnsetMillis == 0) ? UCAL_WEEKEND : UCAL_WEEKEND_ ONSET; 2474 return (fWeekendOnsetMillis == 0) ? UCAL_WEEKEND : UCAL_WEEKEND_ONSET;
2313 » } 2475 }
2314 if (fWeekendOnset < fWeekendCease) { 2476 if (fWeekendOnset < fWeekendCease) {
2315 if (dayOfWeek < fWeekendOnset || dayOfWeek > fWeekendCease) { 2477 if (dayOfWeek < fWeekendOnset || dayOfWeek > fWeekendCease) {
2316 return UCAL_WEEKDAY; 2478 return UCAL_WEEKDAY;
2317 } 2479 }
2318 } else { 2480 } else {
2319 if (dayOfWeek > fWeekendCease && dayOfWeek < fWeekendOnset) { 2481 if (dayOfWeek > fWeekendCease && dayOfWeek < fWeekendOnset) {
2320 return UCAL_WEEKDAY; 2482 return UCAL_WEEKDAY;
2321 } 2483 }
2322 } 2484 }
2323 if (dayOfWeek == fWeekendOnset) { 2485 if (dayOfWeek == fWeekendOnset) {
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
2811 // zoneOffset != (raw + dst) only when the given wall time fall into 2973 // zoneOffset != (raw + dst) only when the given wall time fall into
2812 // a skipped wall time range caused by positive zone offset tran sition. 2974 // a skipped wall time range caused by positive zone offset tran sition.
2813 if (zoneOffset != (raw + dst)) { 2975 if (zoneOffset != (raw + dst)) {
2814 if (!isLenient()) { 2976 if (!isLenient()) {
2815 status = U_ILLEGAL_ARGUMENT_ERROR; 2977 status = U_ILLEGAL_ARGUMENT_ERROR;
2816 } else { 2978 } else {
2817 U_ASSERT(fSkippedWallTime == UCAL_WALLTIME_NEXT_VALID); 2979 U_ASSERT(fSkippedWallTime == UCAL_WALLTIME_NEXT_VALID);
2818 // Adjust time to the next valid wall clock time. 2980 // Adjust time to the next valid wall clock time.
2819 // At this point, tmpTime is on or after the zone offset transition causing 2981 // At this point, tmpTime is on or after the zone offset transition causing
2820 // the skipped time range. 2982 // the skipped time range.
2821 2983 UDate immediatePrevTransition;
2822 BasicTimeZone *btz = getBasicTimeZone(); 2984 UBool hasTransition = getImmediatePreviousZoneTransition (tmpTime, &immediatePrevTransition, status);
2823 if (btz) { 2985 if (U_SUCCESS(status) && hasTransition) {
2824 TimeZoneTransition transition; 2986 t = immediatePrevTransition;
2825 UBool hasTransition = btz->getPreviousTransition(tmp Time, TRUE, transition);
2826 if (hasTransition) {
2827 t = transition.getTime();
2828 } else {
2829 // Could not find any transitions.
2830 // Note: This should never happen.
2831 status = U_INTERNAL_PROGRAM_ERROR;
2832 }
2833 } else {
2834 // If not BasicTimeZone, return unsupported error fo r now.
2835 // TODO: We may support non-BasicTimeZone in future.
2836 status = U_UNSUPPORTED_ERROR;
2837 } 2987 }
2838 } 2988 }
2839 } else { 2989 } else {
2840 t = tmpTime; 2990 t = tmpTime;
2841 } 2991 }
2842 } 2992 }
2843 } else { 2993 } else {
2844 t = millis + millisInDay - computeZoneOffset(millis, millisInDay, st atus); 2994 t = millis + millisInDay - computeZoneOffset(millis, millisInDay, st atus);
2845 } 2995 }
2846 } 2996 }
2847 if (U_SUCCESS(status)) { 2997 if (U_SUCCESS(status)) {
2848 internalSetTime(t); 2998 internalSetTime(t);
2849 } 2999 }
2850 } 3000 }
2851 3001
2852 /** 3002 /**
3003 * Find the previous zone transtion near the given time.
3004 */
3005 UBool Calendar::getImmediatePreviousZoneTransition(UDate base, UDate *transition Time, UErrorCode& status) const {
3006 BasicTimeZone *btz = getBasicTimeZone();
3007 if (btz) {
3008 TimeZoneTransition trans;
3009 UBool hasTransition = btz->getPreviousTransition(base, TRUE, trans);
3010 if (hasTransition) {
3011 *transitionTime = trans.getTime();
3012 return TRUE;
3013 } else {
3014 // Could not find any transitions.
3015 // Note: This should never happen.
3016 status = U_INTERNAL_PROGRAM_ERROR;
3017 }
3018 } else {
3019 // If not BasicTimeZone, return unsupported error for now.
3020 // TODO: We may support non-BasicTimeZone in future.
3021 status = U_UNSUPPORTED_ERROR;
3022 }
3023 return FALSE;
3024 }
3025
3026 /**
2853 * Compute the milliseconds in the day from the fields. This is a 3027 * Compute the milliseconds in the day from the fields. This is a
2854 * value from 0 to 23:59:59.999 inclusive, unless fields are out of 3028 * value from 0 to 23:59:59.999 inclusive, unless fields are out of
2855 * range, in which case it can be an arbitrary value. This value 3029 * range, in which case it can be an arbitrary value. This value
2856 * reflects local zone wall time. 3030 * reflects local zone wall time.
2857 * @stable ICU 2.0 3031 * @stable ICU 2.0
2858 */ 3032 */
2859 int32_t Calendar::computeMillisInDay() { 3033 int32_t Calendar::computeMillisInDay() {
2860 // Do the time portion of the conversion. 3034 // Do the time portion of the conversion.
2861 3035
2862 int32_t millisInDay = 0; 3036 int32_t millisInDay = 0;
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
3229 // WEEK_OF_YEAR, which are similar, or the DAY_OF_WEEK_IN_MONTH. 3403 // WEEK_OF_YEAR, which are similar, or the DAY_OF_WEEK_IN_MONTH.
3230 // First, perform initial shared computations. These locate the 3404 // First, perform initial shared computations. These locate the
3231 // first week of the period. 3405 // first week of the period.
3232 3406
3233 // Get the 0-based localized DOW of day one of the month or year. 3407 // Get the 0-based localized DOW of day one of the month or year.
3234 // Valid range 0..6. 3408 // Valid range 0..6.
3235 int32_t first = julianDayToDayOfWeek(jan1Start + 1) - firstDayOfWeek; 3409 int32_t first = julianDayToDayOfWeek(jan1Start + 1) - firstDayOfWeek;
3236 if (first < 0) { 3410 if (first < 0) {
3237 first += 7; 3411 first += 7;
3238 } 3412 }
3239 int32_t nextFirst = julianDayToDayOfWeek(nextJan1Start + 1) - firstDayOfWeek ; 3413
3240 if (nextFirst < 0) { 3414 //// (nextFirst was not used below)
3241 nextFirst += 7; 3415 // int32_t nextFirst = julianDayToDayOfWeek(nextJan1Start + 1) - firstDayOfW eek;
3242 } 3416 // if (nextFirst < 0) {
3417 // nextFirst += 7;
3418 //}
3243 3419
3244 int32_t minDays = getMinimalDaysInFirstWeek(); 3420 int32_t minDays = getMinimalDaysInFirstWeek();
3245 UBool jan1InPrevYear = FALSE; // January 1st in the year of WOY is the 1st week? (i.e. first week is < minimal ) 3421 UBool jan1InPrevYear = FALSE; // January 1st in the year of WOY is the 1st week? (i.e. first week is < minimal )
3246 //UBool nextJan1InPrevYear = FALSE; // January 1st of Year of WOY + 1 is in the first week? 3422 //UBool nextJan1InPrevYear = FALSE; // January 1st of Year of WOY + 1 is in the first week?
3247 3423
3248 if((7 - first) < minDays) { 3424 if((7 - first) < minDays) {
3249 jan1InPrevYear = TRUE; 3425 jan1InPrevYear = TRUE;
3250 } 3426 }
3251 3427
3252 // if((7 - nextFirst) < minDays) { 3428 // if((7 - nextFirst) < minDays) {
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after
3690 return NULL; 3866 return NULL;
3691 } 3867 }
3692 3868
3693 U_NAMESPACE_END 3869 U_NAMESPACE_END
3694 3870
3695 #endif /* #if !UCONFIG_NO_FORMATTING */ 3871 #endif /* #if !UCONFIG_NO_FORMATTING */
3696 3872
3697 3873
3698 //eof 3874 //eof
3699 3875
OLDNEW
« no previous file with comments | « source/i18n/bocsu.cpp ('k') | source/i18n/chnsecal.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698