我遇到了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,这可能是相关的吗?
答案 0 :(得分:4)
使用now.getTime()
获取没有时区的Date
。
尝试使用
设置时区sdf.setTimeZone(now.getTimeZone());
答案 1 :(得分:2)
答案 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)
可怕的Calendar
类早在几年前就被JSR 310中定义的现代 java.time 类所取代。具体由ZonedDateTime
取代。没有必要花时间和精力来理解Calendar
— Sun,Oracle和JCP社区,他们都放弃了这个有缺陷的课程,我们也应该放弃。
您的目的使用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
java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
要了解更多信息,请参阅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类?