@@ -128,7 +128,7 @@ public class ChineseCalendar extends Calendar {
128
128
* 1813 and 2033, the leap month is after the Winter Solstice of that year. So
129
129
* this value could be false for a date prior to the Winter Solstice of that
130
130
* year but that year still has a leap month and therefor is a leap year.
131
- * @see #computeChineseFields
131
+ * @see #computeMonthInfo
132
132
*/
133
133
private transient boolean hasLeapMonthBetweenWinterSolstices ;
134
134
@@ -823,31 +823,62 @@ private boolean isLeapMonthBetween(int newMoon1, int newMoon2) {
823
823
* @stable ICU 2.8
824
824
*/
825
825
protected void handleComputeFields (int julianDay ) {
826
+ int days = julianDay - EPOCH_JULIAN_DAY ; // local days
827
+ int gyear = getGregorianYear ();
828
+ int gmonth = getGregorianMonth ();
829
+ MonthInfo info = computeMonthInfo (days , gyear );
830
+
831
+ // Extended year and cycle year is based on the epoch year
832
+ int extended_year = gyear - epochYear ;
833
+ int cycle_year = gyear - CHINESE_EPOCH_YEAR ;
834
+ if (info .month < 10 ||
835
+ gmonth >= JULY ) {
836
+ extended_year ++;
837
+ cycle_year ++;
838
+ }
839
+ int dayOfMonth = days - info .thisMoon + 1 ;
840
+
841
+ // 0->0,60 1->1,1 60->1,60 61->2,1 etc.
842
+ int [] yearOfCycle = new int [1 ];
843
+ int cycle = floorDivide (cycle_year -1 , 60 , yearOfCycle );
844
+
845
+ // Days will be before the first new year we compute if this
846
+ // date is in month 11, leap 11, 12. There is never a leap 12.
847
+ // New year computations are cached so this should be cheap in
848
+ // the long run.
849
+ int newYear = newYear (gyear );
850
+ if (days < newYear ) {
851
+ newYear = newYear (gyear -1 );
852
+ }
826
853
827
- computeChineseFields (julianDay - EPOCH_JULIAN_DAY , // local days
828
- getGregorianYear (), getGregorianMonth (),
829
- true ); // set all fields
854
+ hasLeapMonthBetweenWinterSolstices = info .hasLeapMonthBetweenWinterSolstices ;
855
+ internalSet (EXTENDED_YEAR , extended_year );
856
+ internalSet (ERA , cycle +1 );
857
+ internalSet (YEAR , yearOfCycle [0 ]+1 );
858
+ internalSet (MONTH , info .month ); // Convert from 1-based to 0-based
859
+ internalSet (ORDINAL_MONTH , info .ordinalMonth );
860
+ internalSet (DAY_OF_MONTH , dayOfMonth );
861
+ internalSet (IS_LEAP_MONTH , info .isLeapMonth ?1 :0 );
862
+ internalSet (DAY_OF_YEAR , days - newYear + 1 );
830
863
}
831
864
832
- /**
833
- * Compute fields for the Chinese calendar system. This method can
834
- * either set all relevant fields, as required by
835
- * <code>handleComputeFields()</code>, or it can just set the MONTH and
836
- * IS_LEAP_MONTH fields, as required by
837
- * <code>handleComputeMonthStart()</code>.
838
- *
839
- * <p>As a side effect, this method sets {@link #hasLeapMonthBetweenWinterSolstices}.
840
- * @param days days after January 1, 1970 0:00 astronomical base zone of the
841
- * date to compute fields for
842
- * @param gyear the Gregorian year of the given date
843
- * @param gmonth the Gregorian month of the given date
844
- * @param setAllFields if true, set the EXTENDED_YEAR, ERA, YEAR,
845
- * DAY_OF_MONTH, and DAY_OF_YEAR fields. In either case set the MONTH
846
- * and IS_LEAP_MONTH fields.
847
- */
848
- private void computeChineseFields (int days , int gyear , int gmonth ,
849
- boolean setAllFields ) {
865
+ class MonthInfo {
866
+ int month ;
867
+ int ordinalMonth ;
868
+ int thisMoon ;
869
+ boolean isLeapMonth ;
870
+ boolean hasLeapMonthBetweenWinterSolstices ;
871
+ MonthInfo (int month , int ordinalMonth , int thisMoon , boolean isLeapMonth ,
872
+ boolean hasLeapMonthBetweenWinterSolstices ) {
873
+ this .month = month ;
874
+ this .ordinalMonth = ordinalMonth ;
875
+ this .thisMoon = thisMoon ;
876
+ this .isLeapMonth = isLeapMonth ;
877
+ this .hasLeapMonthBetweenWinterSolstices = hasLeapMonthBetweenWinterSolstices ;
878
+ }
879
+ };
850
880
881
+ private MonthInfo computeMonthInfo (int days , int gyear ) {
851
882
// Find the winter solstices before and after the target date.
852
883
// These define the boundaries of this Chinese year, specifically,
853
884
// the position of month 11, which always contains the solstice.
@@ -867,8 +898,8 @@ private void computeChineseFields(int days, int gyear, int gmonth,
867
898
int firstMoon = newMoonNear (solsticeBefore + 1 , true );
868
899
int lastMoon = newMoonNear (solsticeAfter + 1 , false );
869
900
int thisMoon = newMoonNear (days + 1 , false ); // Start of this month
870
- // Note: hasLeapMonthBetweenWinterSolstices is a member variable
871
- hasLeapMonthBetweenWinterSolstices = synodicMonthsBetween (firstMoon , lastMoon ) == 12 ;
901
+
902
+ boolean hasLeapMonthBetweenWinterSolstices = synodicMonthsBetween (firstMoon , lastMoon ) == 12 ;
872
903
873
904
int month = synodicMonthsBetween (firstMoon , thisMoon );
874
905
int theNewYear = newYear (gyear );
@@ -890,42 +921,7 @@ private void computeChineseFields(int days, int gyear, int gmonth,
890
921
hasNoMajorSolarTerm (thisMoon ) &&
891
922
!isLeapMonthBetween (firstMoon , newMoonNear (thisMoon - SYNODIC_GAP , false ));
892
923
893
- internalSet (MONTH , month -1 ); // Convert from 1-based to 0-based
894
- internalSet (ORDINAL_MONTH , ordinalMonth );
895
- internalSet (IS_LEAP_MONTH , isLeapMonth ?1 :0 );
896
-
897
- if (setAllFields ) {
898
-
899
- // Extended year and cycle year is based on the epoch year
900
- int extended_year = gyear - epochYear ;
901
- int cycle_year = gyear - CHINESE_EPOCH_YEAR ;
902
- if (month < 11 ||
903
- gmonth >= JULY ) {
904
- extended_year ++;
905
- cycle_year ++;
906
- }
907
- int dayOfMonth = days - thisMoon + 1 ;
908
-
909
- internalSet (EXTENDED_YEAR , extended_year );
910
-
911
- // 0->0,60 1->1,1 60->1,60 61->2,1 etc.
912
- int [] yearOfCycle = new int [1 ];
913
- int cycle = floorDivide (cycle_year -1 , 60 , yearOfCycle );
914
- internalSet (ERA , cycle +1 );
915
- internalSet (YEAR , yearOfCycle [0 ]+1 );
916
-
917
- internalSet (DAY_OF_MONTH , dayOfMonth );
918
-
919
- // Days will be before the first new year we compute if this
920
- // date is in month 11, leap 11, 12. There is never a leap 12.
921
- // New year computations are cached so this should be cheap in
922
- // the long run.
923
- int newYear = newYear (gyear );
924
- if (days < newYear ) {
925
- newYear = newYear (gyear -1 );
926
- }
927
- internalSet (DAY_OF_YEAR , days - newYear + 1 );
928
- }
924
+ return new MonthInfo (month -1 , ordinalMonth , thisMoon , isLeapMonth , hasLeapMonthBetweenWinterSolstices );
929
925
}
930
926
931
927
//------------------------------------------------------------------
@@ -999,27 +995,17 @@ private int handleComputeMonthStartWithLeap(int eyear, int month, int isLeapMont
999
995
1000
996
int julianDay = newMoon + EPOCH_JULIAN_DAY ;
1001
997
1002
- // Save fields for later restoration
1003
- int saveMonth = internalGet (MONTH );
1004
- int saveOrdinalMonth = internalGet (ORDINAL_MONTH );
1005
- int saveIsLeapMonth = internalGet (IS_LEAP_MONTH );
1006
-
1007
998
computeGregorianFields (julianDay );
1008
999
1009
1000
// This will modify the MONTH and IS_LEAP_MONTH fields (only)
1010
- computeChineseFields (newMoon , getGregorianYear (),
1011
- getGregorianMonth (), false );
1001
+ MonthInfo info = computeMonthInfo (newMoon , getGregorianYear ());
1012
1002
1013
- if (month != internalGet ( MONTH ) ||
1014
- isLeapMonth != internalGet ( IS_LEAP_MONTH ) ) {
1003
+ if (month != info . month ||
1004
+ info . isLeapMonth != ( isLeapMonth != 0 ) ) {
1015
1005
newMoon = newMoonNear (newMoon + SYNODIC_GAP , true );
1016
1006
julianDay = newMoon + EPOCH_JULIAN_DAY ;
1017
1007
}
1018
1008
1019
- internalSet (MONTH , saveMonth );
1020
- internalSet (ORDINAL_MONTH , saveOrdinalMonth );
1021
- internalSet (IS_LEAP_MONTH , saveIsLeapMonth );
1022
-
1023
1009
return julianDay - 1 ;
1024
1010
}
1025
1011
0 commit comments