日历小时设置为0,但显示1,为什么?

时间:2012-09-10 12:00:56

标签: java datetime calendar timezone

我遇到了Java Calendar的一个奇怪问题。

以下代码从午夜开始的日期开始连续增加3小时。

public static void main(String[] args) {

    Calendar now = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));

    // Setting to January 29th, 1920 at 00:00:00
    // now.setTimeZone(TimeZone.getTimeZone("GMT+0"));
    now.set(Calendar.YEAR, 1920);
    now.set(Calendar.MONTH, 0);
    now.set(Calendar.DAY_OF_MONTH, 29);
    now.set(Calendar.HOUR_OF_DAY, 0);
    now.set(Calendar.MINUTE, 0);
    now.set(Calendar.SECOND, 0);
    now.set(Calendar.MILLISECOND, 0);       

    now.setLenient(false);

    int threeHours = 1000 * 60 * 60 * 3;

    SimpleDateFormat sdf
        = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");

    for (int i=0;i<25;i++) {

        System.out.println(sdf.format(now.getTime()));
        now.add(Calendar.MILLISECOND, threeHours);

    }

}

然而,显示的结果是:

1920-01-29 01:00:00 000
1920-01-29 04:00:00 000
1920-01-29 07:00:00 000
1920-01-29 10:00:00 000
1920-01-29 13:00:00 000
1920-01-29 16:00:00 000
1920-01-29 19:00:00 000
1920-01-29 22:00:00 000
1920-01-30 01:00:00 000
1920-01-30 04:00:00 000
1920-01-30 07:00:00 000
1920-01-30 10:00:00 000
1920-01-30 13:00:00 000
1920-01-30 16:00:00 000
1920-01-30 19:00:00 000
1920-01-30 22:00:00 000
1920-01-31 01:00:00 000
1920-01-31 04:00:00 000
1920-01-31 07:00:00 000
1920-01-31 10:00:00 000
1920-01-31 13:00:00 000
1920-01-31 16:00:00 000
1920-01-31 19:00:00 000
1920-01-31 22:00:00 000
1920-02-01 01:00:00 000

为什么第一个小时1而不是0?我位于GMT + 1,这可能是相关的吗?

4 个答案:

答案 0 :(得分:4)

使用now.getTime()获取没有时区的Date

尝试使用

设置时区
sdf.setTimeZone(now.getTimeZone());

答案 1 :(得分:2)

我猜你应该用 now.set(Calendar.HOUR,0);而是now.set(Calendar.HOUR_OF_DAY,0);

答案 2 :(得分:1)

现在它应该可以正常工作

        Calendar now = Calendar.getInstance();
        TimeZone timezone = TimeZone.getTimeZone("GMT+0");
        now.set(Calendar.YEAR, 1920);
        now.set(Calendar.MONTH, 0);
        now.set(Calendar.DAY_OF_MONTH, 29);
        now.set(Calendar.HOUR_OF_DAY, 0);
        now.set(Calendar.MINUTE, 0);
        now.set(Calendar.SECOND, 0);
        now.set(Calendar.MILLISECOND, 0);       
        now.setLenient(false);
        int threeHours = 1000 * 60 * 60 * 3;
        SimpleDateFormat sdf
            = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
        sdf.setTimeZone(timezone);
        for (int i=0;i<25;i++) {
            System.out.println(sdf.format(now.getTime()));
            now.add(Calendar.MILLISECOND, threeHours);
        }

答案 3 :(得分:1)

java.time

可怕的Calendar类早在几年前就被JSR 310中定义的现代 java.time 类所取代。具体由ZonedDateTime取代。没有必要花时间和精力来理解CalendarSunOracleJCP社区,他们都放弃了这个有缺陷的课程,我们也应该放弃。

您的目的使用UTC而不是特定的时区。因此,OffsetDateTime是合适的。

// Setting to January 29th, 1920 at 00:00:00 in UTC.
LocalDate ld = LocalDate.of( 1920 , Month.JANUARY , 29 ) ;
LocalTime lt = LocalTime.MIN ;
ZoneOffset offset = ZoneOffset.UTC ;
OffsetDateTime odt = OffsetDateTime.of( ld , lt , offset ) ;

一次添加3小时,共25次。使用Duration以小时-分钟-秒为单位来表示时间跨度。将Duration对象作为OffsetDatetime::plus传递到TemporalAmount

Duration d = Duration.ofHours( 3 ) ;
for( int i = 0 ; i < 25 ; i ++ )
{
    System.out.println( odt ) ; 
    // Set up the next loop.
    odt = odt.plus( d ) ;
}

请参阅此code run live at IdeOne.com

odt.toString(): 1920-01-29T00:00Z
1920-01-29T00:00Z
1920-01-29T03:00Z
1920-01-29T06:00Z
1920-01-29T09:00Z
1920-01-29T12:00Z
1920-01-29T15:00Z
1920-01-29T18:00Z
1920-01-29T21:00Z
1920-01-30T00:00Z
1920-01-30T03:00Z
1920-01-30T06:00Z
1920-01-30T09:00Z
1920-01-30T12:00Z
1920-01-30T15:00Z
1920-01-30T18:00Z
1920-01-30T21:00Z
1920-01-31T00:00Z
1920-01-31T03:00Z
1920-01-31T06:00Z
1920-01-31T09:00Z
1920-01-31T12:00Z
1920-01-31T15:00Z
1920-01-31T18:00Z
1920-01-31T21:00Z
1920-02-01T00:00Z

Table of all date-time types in Java, both modern and legacy


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规范为JSR 310

Joda-Time项目(现在位于maintenance mode中)建议迁移到java.time类。

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。 Hibernate 5和JPA 2.2支持 java.time

在哪里获取java.time类?