今天在处理日期的时候,用到了java的Calendar类

日期类型如下:

几天前,几小时前,几分钟前,几秒前

思路就是直接用当前时间根据时间刻度进行加减即可,代码如下

   /**

     * 取得差距i小时的时间

     * 

     * @param i

     *            小时数(可以正负表示)

     * @return 日期(Date)

     */

    public static Date getPastHour(int i) {

        CALENDAR.roll(Calendar.HOUR, i);

        return CALENDAR.getTime();

    }

这是处理小时的方法,分钟和秒的处理方法省略,接下来是判断

        /**

     * 处理几秒,几分钟,几小时前这种格式的时间

     * 

     * @param date

     * @return

     */

    public static String formatBeforeDate(String date) {

        Integer time = Integer.parseInt(new RegexExtractor("\\d+")

                .extract(date));

        if (date.indexOf("小时") != -1) {

            date = DateUtils.getDate2LStr(DateUtils.getPastHour(-time));

        }

        if (date.indexOf("分钟") != -1) {

            ...

        }

        if (date.indexOf("秒") != -1) {

            ...

        }

        return date;

    }

代码貌似没有问题,但是在处理一个时间的时候发现,怎么差了一天呢,

时间:10小时前,当前时间:09:10

当前时间减去10小时,已经是昨天的时间了,但是roll方法并没有智能的处理为昨天的日期,我们看下roll方法的描述

public void roll(int field,

                 int amount)

向指定日历字段添加有符号的时间量,不更改更大的字段。负的波动量表示从字段减去时间量,不更改更大的字段。如果指定的量为 0,则此方法不执行任何操作。 

此方法在添加时间量前调用 Calendar.complete(),使得所有的日历字段都标准化。如果任何日历字段在 non-lenient 模式下具有超出范围的值,则抛出 IllegalArgumentException。 

示例:考虑原来设置为 1999 年 8 月 31 日的 GregorianCalendar 。现在调用 roll(Calendar.MONTH, 8) 将该日历设置为 1999 年 4 月 30 日。如果使用 GregorianCalendar,则 4 月份的 DAY_OF_MONTH 字段不可能为 31。将 DAY_OF_MONTH 设置为最可能接近的值 30。YEAR 字段保持为值 1999,因为它是一个比 MONTH 更大的字段。 

示例:考虑原来设置为 1999 年 6 月 6 日星期日的 GregorianCalendar 。现在调用 roll(Calendar.WEEK_OF_MONTH, -1) 将该日历设置为 1999 年 6 月 1 日星期二,而调用 add(Calendar.WEEK_OF_MONTH, -1) 则将日历设置为 1999 年 5 月 30 日星期日。这是因为上升和下降规则施加了其他的约束:WEEK_OF_MONTH 改变时 MONTH 必须不变。根据添加规则 1,所得日期必定在 6 月 1 日星期二和 6 月 5 日星期六之间。根据添加规则 2,DAY_OF_WEEK(在改变 WEEK_OF_MONTH 时它是一个不变量)被设置为 Tuesday,是最接近 Sunday 的可能值(其中星期日是一个星期的第一天)

这么长一段是什么意思呢。。简单的说,如果你更改的是小时字段,那么大于它的字段不会改变,也就是日期不会改变

再看add方法

public void add(int field,

                int amount)

根据日历规则,将指定的(有符号的)时间量添加到给定的日历字段中。 

添加规则 1。调用之后的 field 字段的值减去调用之前的 field 字段的值等于 amount,以 field 中发生的任何溢出为模。溢出发生在字段值超出其范围时,结果,下一个更大的字段会递增或递减,字段值被调整回其范围内。 

添加规则 2。如果期望某一个更小的字段是无变化的,但让它等于以前的值是不可能的,因为在字段 field 发生更改之后,它的最大值和最小值也在发生更改,然后它的值被调整为尽量接近于所期望的值。更小的字段表示一个更小的时间单元。HOUR 是一个比 DAY_OF_MONTH 更小的字段。对于不期望是无变化字段的更小字段,无需进行任何调整。日历系统确定期望是无变化字段的那些字段。 

和roll方法不同,它会改变比更改字段更大的字段属性。所以如果想自动处理日期,我们还是要使用add方法

我们把相应的方法改为调用add即可

    /**

     * 取得差距i小时的时间

     * 

     * @param i

     *            小时数(可以正负表示)

     * @return 日期(Date)

     */

    public static Date getPastHour(int i) {

        CALENDAR.add(Calendar.HOUR, i);

        return CALENDAR.getTime();

    }

还有一篇文章说的比较清楚:http://www.blogjava.net/vincent/archive/2007/10/12/152411.html

Comments
Write a Comment