简体   繁体   English

Calendar,SimpleDateFormat和Date的异常行为

[英]Unexpected behavior with Calendar, SimpleDateFormat and Date

Given a date D, I am trying to create two Calendar instances for that day at the following UTC times: 00:00:00 and 23:59:59. 给定日期D,我试图在以下UTC时间创建当天的两个Calendar实例:00:00:00和23:59:59。 My algorithm should work regardless of my timezone (mine is UTC+1) and, given the day of D, for that D the time has to be set. 无论我的时区是什么(我的时间是UTC + 1),我的算法都应该工作,并且在D的给定日期,必须为该D设置时间。

This is my code: 这是我的代码:

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);

//...

Then, I am trying to transform them into a UTC string with this code: 然后,我尝试使用以下代码将它们转换为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);
}

After this, the console prints 11:00:13 for c1 and 22:59:13 for c2. 此后,控制台将为c1打印11:00:13,为c2打印22:59:13。 JDK7. JDK7。 The test main is trivial: 测试主要是微不足道的:

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

Why? 为什么?

I'm not sure what is your intention, but below code gives what you expect as the output. 我不确定您的意图是什么,但是下面的代码给出了您期望的输出。

    ...
    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);

Output: 输出:

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

There is a Z at the end because of the format you have used. 由于您使用的格式,结尾处会有一个Z But actually the output is not in UTC. 但是实际上输出不是采用UTC。

Update: 更新:

With your code: 使用您的代码:

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

With your code + -Duser.timezone=GMT adding to JVM: 将您的代码+ -Duser.timezone=GMT添加到JVM:

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

I assume you are not in UTC, so you're creating a time for timezone X and convert it to UTC afterwards. 我认为您不在UTC中,因此您要为时区X创建一个时间,然后将其转换为UTC。 The solution is to create the Calendar objects in UTC: 解决方案是 UTC中创建Calendar对象:

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

respectively 分别

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

Complete Sample Program 完整的样例程序

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);
    }
}

leads to 导致

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM