Calendar,SimpleDateFormat和Date的意外行为

时间:2015-01-21 13:55:39

标签: java

给定日期D,我试图在接下来的UTC时间创建当天的两个日历实例:00:00:00和23:59:59。无论我的时区(我的是UTC + 1),我的算法应该都能正常工作,并且在D的日期,对于那个D,必须设置时间。

这是我的代码:

import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

private static void f(Date date) {
Calendar c1 = Calendar.getInstance();
c1.setTime(date);
c1.set(Calendar.HOUR_OF_DAY, 0);
c1.set(Calendar.MINUTE, 0);
c1.set(Calendar.SECOND, 0);

Calendar c2 = Calendar.getInstance();
c2.setTime(date);
c2.set(Calendar.HOUR_OF_DAY, 23);
c2.set(Calendar.MINUTE, 59);
c2.set(Calendar.SECOND, 59);

//...

然后,我尝试使用以下代码将它们转换为UTC字符串:

//...
String sc1 = fromDateToUTCString(c1.getTime());
String sc2 = fromDateToUTCString(c2.getTime());

System.out.println(sc1);
System.out.println(sc2);
}

public static String fromDateToUTCString(final Date date) {
    final String ISO_FORMAT = "yyy-MM-dd'T'HH:mm:ss'Z'";
    final SimpleDateFormat sdf = new SimpleDateFormat(ISO_FORMAT);
    final TimeZone utc = TimeZone.getTimeZone("UTC");
    sdf.setTimeZone(utc);
    return sdf.format(date);
}

此后,控制台为c1打印11:00:13,为c2打印22:59:13。 JDK7。 测试主要是微不足道的:

public static void main(String[] args) {
    f(new Date());
}

为什么?

2 个答案:

答案 0 :(得分:1)

我不确定你的意图是什么,但是下面的代码给出了你期望的输出结果。

    ...
    Calendar c1 = Calendar.getInstance();
    c1.setTimeInMillis(date.getTime());
    c1.add(Calendar.HOUR_OF_DAY, -1*c1.get(Calendar.HOUR_OF_DAY));
    c1.add(Calendar.MINUTE, -1*c1.get(Calendar.MINUTE));
    c1.add(Calendar.SECOND, -1*c1.get(Calendar.SECOND));

    Calendar c2 = Calendar.getInstance();
    c2.setTimeInMillis(date.getTime());
    c2.add(Calendar.HOUR, -1*c2.get(Calendar.HOUR_OF_DAY) + 23);
    c2.add(Calendar.MINUTE, -1*c2.get(Calendar.MINUTE) + 59);
    c2.add(Calendar.SECOND, -1*c2.get(Calendar.SECOND) + 59); 
    ....

    //comment the time zone setting
    //sdf.setTimeZone(utc);

输出:

    2015-01-21T 00:00:00Z
    2015-01-21T 23:59:59Z

由于您使用的格式,最后会有Z。但实际上输出不是UTC。

<强>更新

使用您的代码:

2015-01-20T16:30:00Z
2015-01-21T16:29:59Z

将代码+ -Duser.timezone=GMT添加到JVM:

2015-01-21T00:00:00Z
2015-01-21T23:59:59Z

答案 1 :(得分:-1)

我假设您不是UTC,因此您正在为时区X创建时间并在之后将其转换为UTC。解决方案是在 UTC中创建Calendar个对象

c1.setTimeZone(TimeZone.getTimeZone("UTC"));
分别

c2.setTimeZone(TimeZone.getTimeZone("UTC"));

完成示例程序

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;


public class CalendarTest {

    public static void main(String[] args) {
        f(new Date());
    }

    private static void f(Date date) {
        Calendar c1 = Calendar.getInstance();
        c1.setTime(date);
        c1.set(Calendar.HOUR_OF_DAY, 0);
        c1.set(Calendar.MINUTE, 0);
        c1.set(Calendar.SECOND, 0);
        c1.setTimeZone(TimeZone.getTimeZone("UTC"));

        Calendar c2 = Calendar.getInstance();
        c2.setTime(date);
        c2.set(Calendar.HOUR_OF_DAY, 23);
        c2.set(Calendar.MINUTE, 59);
        c2.set(Calendar.SECOND, 59);
        c2.setTimeZone(TimeZone.getTimeZone("UTC"));

        String sc1 = fromDateToUTCString(c1.getTime());
        String sc2 = fromDateToUTCString(c2.getTime());

        System.out.println(sc1);
        System.out.println(sc2);
    }

    public static String fromDateToUTCString(final Date date) {
        final String ISO_FORMAT = "yyy-MM-dd'T'HH:mm:ss'Z'";
        final SimpleDateFormat sdf = new SimpleDateFormat(ISO_FORMAT);
        final TimeZone utc = TimeZone.getTimeZone("UTC");
        sdf.setTimeZone(utc);
        return sdf.format(date);
    }
}

导致

2015-01-21T00:00:00Z
2015-01-21T23:59:59Z