我在一些java代码中发现了一条注释,指出需要调用getTime()
来更新Calendar
对象。这是真的?我找不到任何说这是必要的东西。
以下是代码:
Calendar cal = new GregorianCalendar();
cal.setFirstDayOfWeek(Calendar.SUNDAY);
cal.set(2009, 9 - 1, 10, 2, 30);
// Get Time needs to be called to update the Calendar object
cal.getTime();
答案 0 :(得分:9)
cal.getTime()
来重新计算其内部结构。这是一种非常奇怪的API行为,但Calendar javadocs明确说明了这一点:
获取和设置日历字段值
可以通过调用set方法来设置日历字段值。任何 在需要之前,不会解释在日历中设置的字段值 计算其时间值(距离纪元的毫秒数)或值 日历字段。调用get,getTimeInMillis,getTime,添加 和滚动涉及这样的计算。
...
Field Manipulation
可以使用三种方法更改日历字段:set(),add(), 和roll()。 set(f,value)将日历字段f更改为值。在 另外,它设置一个内部成员变量来表示 日历字段f已更改。虽然日历字段f是 立即更改,日历的时间值(以毫秒为单位)不是 重新计算,直到下一次调用get(),getTime(),getTimeInMillis(), 制作了add()或roll()。因此,不会触发多次调用set() 多次,不必要的计算。由于更改日历 使用set()的字段,其他日历字段也可能会更改,具体取决于 日历字段,日历字段值和日历系统。 另外,get(f)不一定返回调用设置的值 重新计算日历字段后的set方法。该 细节由具体的日历类确定。
行为是意外的,并不总是发生,但以下单元测试应该举例说明这种行为并且总是发生。
/**
* Fails the assertion due to missing getTime()
* @throws ParseException
*/
public class DateTest {
@Test
public void testNoGetTime() throws ParseException {
DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
Date testDate = df.parse("04/15/2013");
Calendar testCal = Calendar.getInstance();
testCal.setTime(testDate);
Date expectedDate = df.parse("04/04/2013");
Date actualDate = null;
testCal.set(Calendar.DAY_OF_MONTH, testCal.getMinimum(Calendar.DAY_OF_MONTH));
//testCal.getTime();
testCal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
testCal.add(Calendar.DAY_OF_MONTH, -1);
actualDate = testCal.getTime();
assertEquals("Dates should be equal", expectedDate.toString(), actualDate.toString());
}
@Test
public void testWithGetTime() throws ParseException {
DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
Date testDate = df.parse("04/15/2013");
Calendar testCal = Calendar.getInstance();
testCal.setTime(testDate);
Date expectedDate = df.parse("04/04/2013");
Date actualDate = null;
testCal.set(Calendar.DAY_OF_MONTH, testCal.getMinimum(Calendar.DAY_OF_MONTH));
testCal.getTime();
testCal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
testCal.add(Calendar.DAY_OF_MONTH, -1);
actualDate = testCal.getTime();
assertEquals("Dates should be equal", expectedDate.toString(), actualDate.toString());
}
}
答案 1 :(得分:2)
你可能正在点击Bug ID 4851640
在Calendar实例上调用get(...)/ getTime()会使isSet(...)无效!
答案 2 :(得分:2)
@skaffman答案 NOT CORRECT 。
这是一个证明我在说什么的例子。
//Create an Calendar object set to todays date & time
Calendar calendar = Calendar.getInstance();
Log.d(Tag, "Now : "+ calendar.toString());
//Set the Calendar to the first day of Month
calendar.set(Calendar.DAY_OF_MONTH,1);
Log.d(Tag, "Calendar.DAY_OF_MONTH,1: "+ calendar.toString());
这是Log.d输出:
Now : java.util.GregorianCalendar[time=1478834995641,areFieldsSet=true,lenient=true,zone=America/Chicago,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=10,WEEK_OF_YEAR=46,WEEK_OF_MONTH=2,DAY_OF_MONTH=10,DAY_OF_YEAR=315,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=29,SECOND=55,MILLISECOND=641,ZONE_OFFSET=-21600000,DST_OFFSET=0] Calendar.DAY_OF_MONTH,1:
Calendar.DAY_OF_MONTH,1: java.util.GregorianCalendar[time=?,areFieldsSet=false,lenient=true,zone=America/Chicago,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=10,WEEK_OF_YEAR=46,WEEK_OF_MONTH=2,DAY_OF_MONTH=1,DAY_OF_YEAR=315,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=29,SECOND=55,MILLISECOND=641,ZONE_OFFSET=-21600000,DST_OFFSET=0]
如果你花时间检查它: 开头的日历显示:
time=1478834995641
DAY_OF_MONTH=10
DAY_OF_YEAR=315
但是,当您将其设置为该月的第一天时:
time=?
DAY_OF_MONTH=1
DAY_OF_YEAR=315
是的,它改变了我们想要的月份的第一天,但有些属性保持不变。例如,我们如何将日历设置为DAY_OF_MONTH=1
,但我们仍然在DAY_OF_YEAR=315
。
如果我们使用以下任何功能,它将强制更新日历。
调用get,getTimeInMillis,getTime,add和roll。
来自Javadocs中的日历类检查:Getting and Setting Calendar Field Values
要解决此问题,我们添加以下代码calendar.getTimeInMillis();
,强制日历更新其属性。
//Create an Calendar object set to todays date & time
Calendar calendar = Calendar.getInstance();
Log.d(Tag, "Now : "+ calendar.toString());
//Set the Calendar to the first day of Month
calendar.set(Calendar.DAY_OF_MONTH,1);
//UPDATE BY CALLING getTimeInMillis() or any of the previously mentioned functions
calendar.getTimeInMillis();
Log.d(Tag, "Calendar.DAY_OF_MONTH,1: "+ calendar.toString());
现在,让我们检查结果:
Now : java.util.GregorianCalendar[time=1478836452183,areFieldsSet=true,lenient=true,zone=America/Chicago,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=10,WEEK_OF_YEAR=46,WEEK_OF_MONTH=2,DAY_OF_MONTH=10,DAY_OF_YEAR=315,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=54,SECOND=12,MILLISECOND=183,ZONE_OFFSET=-21600000,DST_OFFSET=0]
Calendar.DAY_OF_MONTH,1: java.util.GregorianCalendar[time=1478055252183,areFieldsSet=true,lenient=true,zone=America/Chicago,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=10,WEEK_OF_YEAR=45,WEEK_OF_MONTH=1,DAY_OF_MONTH=1,DAY_OF_YEAR=306,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=54,SECOND=12,MILLISECOND=183,ZONE_OFFSET=-21600000,DST_OFFSET=3600000]
因此,@skaffman答案是不正确的,至于你的问题Calendar.getTime();
确实需要,如果你不想在某个时候得到奇怪的值。
答案 3 :(得分:0)
不,这不是真的。
答案 4 :(得分:0)
不,没有必要。
之后日历是否立即序列化?
我遇到了旧版jvms中日历序列化的错误。
在序列化之前调用getTime可能足以解决这个问题,虽然我没有安装足够旧的JVM来确认这一点。