Generally, the add method is used when calendar is used for date processing:
Calendar calendar = calendar. getinstance ();
Calendar. settime (date );
Calendar.Add(Calendar. Second, 1 );
When the latest code review, we can see that someone uses the Set Method for date processing:
Calendar calendar = calendar. getinstance ();
Calendar. settime (date );
Calendar. Set (calendar. Month, calendar. Get (calendar. month) + month );
As a result, he jumped out immediately and told him that he was wrong. Unfortunately, BS was immediately returned because he could see the following test code:
Calendar Cal = calendar. getinstance ();
Cal. Set (2009, 02, 15 );
Date testdate = Cal. gettime ();
System. Out. println (testdate );
Calendar calendar = calendar. getinstance ();
Calendar. settime (testdate );
Calendar. Set (calendar. Month, calendar. Get (calendar. month) + 1 );
Date testdate2 = calendar. gettime ();
System. Out. println (testdate2 );
Output result:
Sun Mar 11:21:18 CST 2009
Wed Apr 15 11:21:18 CST 2009
That is to say, the set method can also be used for field operations !!
Fortunately, I am a person who has the courage to admit mistakes. After apologizing, I was forgiven by the other party, but I still cannot accept this fact. JDK is also too earthy, is there no difference in designing these two methods? So what is the add method?
With the above problem in mind, I started code review again today. The more I think about it, the more I can't think of it. It's unreasonable. Forget it. Check the JDK documentation. Below is a comment on the calendar class in JDK:
You can change the calendar field in three ways:set()
,add()
Androll()
.
set(f, value)
Set the calendar Fieldf
Changevalue
. In addition, it sets an internal member variable to indicate the calendar Fieldf
It has been changed. Despite calendar Fieldsf
Is changed immediately, but is not called until the next time.get()
,getTime()
,getTimeInMillis()
,add()
Orroll()
The time value of the calendar (in milliseconds) is recalculated ). Therefore, multiple callsset()
Does not trigger unnecessary computing multiple times. Useset()
The result of changing the calendar field is that other calendar fields may also be changed, depending on the calendar field, calendar field value, and calendar system. In addition, after recalculating the calendar field,get(f)
No need to callset
Method returnvalue
Set. The specific details are determined by the specific calendar class.
Example: AssumeGregorianCalendar
It was initially set to August 31, 1999. Callset(Calendar.MONTH, Calendar.SEPTEMBER)
Set this date to January 1, September 31, 1999. If you callgetTime()
, So this is a temporary internal representation for parsing in October 1, 1999. HowevergetTime()
Previously calledset(Calendar.DAY_OF_MONTH, 30)
This date is set to September 30, 1999, becauseset()
No re-calculation occurred.
add(f, delta)
Setdelta
Addf
Field. This is equivalent to callingset(f, get(f) + delta)
But it must include the following two adjustments:
Add Rule 1. After the callf
Field Value minus before callf
The field value is equaldelta
, With Fieldsf
Any overflow occurs as a model. Overflow occurs when the field value exceeds its range. As a result, the next larger field will increase or decrease progressively, and the field value will be adjusted back to its range.
Add Rule 2. It is impossible to expect a smaller field to remain unchanged but make it equal to the previous value, becausef
After the change, or after other constraints, such as the time zone offset, the maximum and minimum values are also changed, then its value is adjusted to be as close as possible to the expected value. A smaller field indicates a smaller unit of time.HOUR
Is a ratioDAY_OF_MONTH
Small field. For smaller fields that do not expect to be unchanged, no adjustment is required. The calendar system determines the expected fields.
In additionset()
Different,add()
Force the calendar system to re-calculate the calendar's millisecond count and all fields immediately.
Example: AssumeGregorianCalendar
It was initially set to August 31, 1999. Calladd(Calendar.MONTH, 13)
Set the calendar to September 30, 2000.Add Rule 1SetMONTH
The field is set to September, because the next year's September is obtained by adding 13 months to August. Because inGregorianCalendar
Medium,DAY_OF_MONTH
It cannot be September 31, soAdd Rule 2SetDAY_OF_MONTH
Set to 30, which is the most likely value. Although it is a smaller field, it cannot be adjusted according to Rule 2.DAY_OF_WEEK
Because inGregorianCalendar
When the month in changes, the value also needs to change.
roll(f, delta)
Setdelta
Addf
Field, but do not change the larger field. This is equivalent to callingadd(f, delta)
But with the following adjustments:
Roll rule. After the call is completed, the larger field remains unchanged. A larger field indicates a larger unit of time.DAY_OF_MONTH
Is a ratioHOUR
Large field.
Example: SeeGregorianCalendar.roll(int, int)
.
Use Model. To help understandadd()
Androll()
Assume that there is a user interface component withGregorianCalendar
. If the date read from the interface is January 1, January 31, 1999, and you press the incremental button of the month, what should you get? If the underlying implementation usesset()
You can set the date to March 3, 1999. The better result is February 28, 1999. In addition, if you re-Press the incremental button of the month, the date should be read as January 1, March 31, 1999, rather than January 1, March 28, 1999. By saving the original date and usingadd()
Orroll()
, Depending on whether it will affect more fields, the user interface can run as expected by most users.
After carefully studying the above annotations, I finally found a trace of clues. The add method is different from the set method. It should be different in the natural day processing, so I have the following code:
Calendar Cal = calendar. getinstance ();
Cal. Set (2009, 02, 31 );
Date testdate = Cal. gettime ();
System. Out. println (testdate );
Calendar cal1 = calendar. getinstance ();
Cal1.settime (testdate );
Cal1.add (calendar. month, 1 );
Date testdate1 = cal1.gettime ();
System. Out. println (testdate1 );
The output is as follows:
Tue Mar 31 11:27:41 CST 2009
Thu Apr 30 11:27:41 CST 2009
OK. The conclusion is that the add method will process the increase or decrease of the calendar month to process the date part, but the set method will only be treated as 30 days. Facts have proved that the original feeling is correct. I hope that similar errors will not be encountered in the future !!