java 1900年,仅在1900年的Java日期计算中出现30分钟错误

这篇博客探讨了Java中日期处理时遇到的一个历史问题,即在1900年时会出现30分钟的时间差。问题源于历史上的格林尼治标准时间(GMT)偏移变化。通过示例代码展示了这个问题,并提供了解决方案,即使用`TimeZone`类获取特定日期的正确时区偏移。文章强调了在处理日期和时间时考虑时区和历史变化的重要性。
摘要由CSDN通过智能技术生成

package check;

import java.util.Calendar;

public class Test {

public static void main(String[] args) {

// length of a day

long DAY_MILLIS = 1000 * 60 * 60 * 24;

Calendar cal = Calendar.getInstance();

cal.set(1900, 0, 1, 0, 0, 0);

System.out.println(cal.getTime());

cal.setTimeInMillis(cal.getTimeInMillis() + DAY_MILLIS);

System.out.println(cal.getTime());

}

}

And it's result is:

Mon Jan 01 00:00:00 KST 1900

Mon Jan 01 23:30:00 KST 1900 // Where is 30 minutes here?

Most funny and important clue is that this problem happens when year is 1900 only.

解决方案

This is because of historical GMT offset changes. See an example here http://www.timeanddate.com/worldclock/timezone.html?n=101&syear=1900. These changes are different for different time zones. For instance in my time zone (EET) the result of your test is different:

Mon Jan 01 00:00:00 EET 1900

Mon Jan 01 23:39:52 EET 1900

because (according to Java) clocks were turned forward 0:20:08 hours on 1 Jan 1900 in EET. TimeZone has methods to determine offset for a particular date, TimeZone.getOffset(long date) API

This method returns a historically correct offset value if an underlying TimeZone implementation subclass supports historical Daylight Saving Time schedule and GMT offset changes.

Note that if you set Calendar to GMT and print the result in GMT there will be no error.

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

df.setTimeZone(TimeZone.getTimeZone("GMT"));

Calendar cal = Calendar.getInstance();

cal.setTimeZone(TimeZone.getTimeZone("GMT"));

cal.set(1900, 0, 1, 0, 0, 0);

System.out.println(df.format(cal.getTime()));

cal.setTimeInMillis(cal.getTimeInMillis() + 1000 * 60 * 60 * 24);

System.out.println(df.format(cal.getTime()));

output

1900-01-01 00:00:00

1900-01-02 00:00:00

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值