`
刘方然
  • 浏览: 30100 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

Calendar的clear的陷阱

阅读更多
今天在写一个流量控制的模块,要做一个根据输入的时间,获得下一天0点0分0秒的时间戳。

	public long caculateResetTimestamp(long currentTimestamp) {
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(currentTimestamp);
		cal.clear(Calendar.MILLISECOND);
		cal.clear(Calendar.SECOND);
		cal.clear(Calendar.MINUTE);
		cal.clear(Calendar.HOUR);
		cal.clear(Calendar.HOUR_OF_DAY);
		cal.roll(Calendar.DATE, true);
		
		return cal.getTimeInMillis();
	}


程序非常简单,习惯性地做了个单元测试。尽然没有通过
	DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
	DailyResetPolicy resetPolicy = new DailyResetPolicy();
	
	@Test
	public void testCaculateResetTimestamp() throws ParseException {
		
		long input = toMillis("2010-01-12 12:12:23.234");
		long expected = toMillis("2010-01-13 00:00:00.000");
		long result = resetPolicy.caculateResetTimestamp(input);

		assertEquals(expected, result);
	}

	long toMillis(String source) throws ParseException {
		return format.parse(source).getTime();
	}


这怎么可能!!明明应该是对的啊。后来打出时间来,看了下。输出的结果是

2010-01-13 12:00:00.000

是小时域有问题。仔细阅读了JavaDoc后发现,不能使用clear(Calendar.HOUR_OF_DAY)来清除小时域;clear(Calendar.HOUR)也不行。

还是老老实实用set(Calendar.HOUR_OF_DAY,0)来清除小时域。最后干脆全部用set方法了。

正确的版本是这样的:

	public long caculateResetTimestamp(long currentTimestamp) {
		Calendar cal = Calendar.getInstance();
		cal.setTimeInMillis(currentTimestamp);
		cal.set(Calendar.MILLISECOND, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MINUTE, 0);
		
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.roll(Calendar.DATE, true);
		
		return cal.getTimeInMillis();
	}
0
0
分享到:
评论
2 楼 yunye 2013-04-19  
清空小时的确不能用clear(field), 需要用set(Calendar.HOUR_OF_DAY, 0)

 /**
     * Sets the given calendar field value and the time value
     * (millisecond offset from the <a href="#Epoch">Epoch</a>) of
     * this <code>Calendar</code> undefined. This means that {@link
     * #isSet(int) isSet(field)} will return <code>false</code>, and
     * the date and time calculations will treat the field as if it
     * had never been set. A <code>Calendar</code> implementation
     * class may use the field's specific default value for date and
     * time calculations.
     *
     * <p>The {@link #HOUR_OF_DAY}, {@link #HOUR} and {@link #AM_PM}
     * fields are handled independently and the <a
     * href="#time_resolution">the resolution rule for the time of
     * day</a> is applied. Clearing one of the fields doesn't reset
     * the hour of day value of this <code>Calendar</code>. Use {@link
     * #set(int,int) set(Calendar.HOUR_OF_DAY, 0)} to reset the hour
     * value.
     *
     * @param field the calendar field to be cleared.
     * @see #clear()
     */
    public final void clear(int field)
    {
	fields[field] = 0;
	stamp[field] = UNSET;
	isSet[field] = false;

	areAllFieldsSet = areFieldsSet = false;
	isTimeSet = false;
    }
1 楼 hanjk1234 2010-01-30  
Api 文档都告诉你怎么用了,你还在这里发牢骚,说什么陷阱.
I F le you

相关推荐

Global site tag (gtag.js) - Google Analytics