时区计算,冬夏令时, 计算历史某一刻的某地区的时区
首先来聊聊冬夏令时
冬令时和夏令时是为了节约能源和充分利用光照资源而设立的时间制度。在夏季,许多国家和地区会将时钟拨快一小时,称为夏令时,以便让人们早起早睡,减少照明用电。而在冬季,时钟会拨回标准时间,称为冬令时。
历史背景和实施国家
夏令时的概念最早由新西兰昆虫学家George Vernon Hudson在1895年提出,但未得到广泛响应。1907年,英国建筑师威廉·维莱特向英国议会提出了夏令时的构思,但未被采纳。德国于1916年首次正式使用夏令时,随后英国、法国和俄罗斯也开始执行。目前,全世界有近110个国家每年实行夏令时。
中国的实施情况
中国在1986年至1991年间曾实行夏令时制度。具体做法是每年从4月中旬的第一个星期日起将时钟拨快一小时,称为夏令时开始;到9月中旬的第一个星期日再拨回一小时,称为夏令时结束。然而,自1992年起,中国暂停实行夏令时
java 中获取时区的方式
1指定时区,这种就会忽略夏令时 因为指定了 -4
TimeZone tz = TimeZone.getTimeZone("GMT-04:00");
2指定地点城市,会自动计算夏令时
TimeZone tz = TimeZone.getTimeZone("America/New_York");
以new york为例
2024年 11 月 3 号调整了冬令时, 时区由-4 调整为 -5
参考网站:
我们来实际计算下 纽约 在2024-11-02 13:00:00这个时刻的当时时间下的时区是夏令时还是冬令时
public static void main(String[] args) throws ParseException {
//1指定时区为纽约
ZoneId newYorkZoneId = ZoneId.of("America/New_York");
TimeZone tz = TimeZone.getTimeZone(newYorkZoneId);
//初始化一个时间格式化,并指定纽约时区
FastDateFormat format = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss", tz);
//使用纽约时区,反序列化一个时间
Date date = format.parse("2024-11-02 13:00:00");
//获取时区
ZonedDateTime pastTimeInNewYork = ZonedDateTime.ofInstant(date.toInstant(), newYorkZoneId);
System.out.println("过去时间点的时区信息: " + pastTimeInNewYork.getOffset());
}
上面结果输出为
可以看到,2024-11-02时间点的纽约时区信息: -04:00
当我们将历史时间 修改为 11月3号,
可以看到这里同样是纽约, 11月3号的时区已经变为-5, 因为调整了冬令时
夏令时和冬令时调整的时间是不固定的, 例如纽约冬令时开始时间是每年11月的第一个星期日, 2024年就是 11月3号, 具体时间为2点调整为1点
如果遇到闰年冬令时会推迟一天
闰年是为了弥补因人为历法规定的年度天数365日和地球实际公转周期(大约365.24219日)的时间差而设立的。具体来说,闰年的规则如下:
能被4整除的年份通常是闰年,这意味着每四年,我们会增加一天,即2月29日,使得该年有366天。
经过上面的内容我们可以得到结论
这样得到某个城市,某个时刻的 具体时区,这样就可以 准确的进行时间转换
拓展:
介绍下时间转换方法
/**
* 将sourceDate转换成指定时区的时间
*
* @param sourceDate
* @param sourceTimezone sourceDate所在的时区
* @param targetTimezone 转化成目标时间所在的时区
* @return
*/
public static Date convertTimezone(Date sourceDate, TimeZone sourceTimezone, TimeZone targetTimezone) {
Calendar calendar = Calendar.getInstance();
//原时间
long sourceTime = sourceDate.getTime();
calendar.setTimeZone(sourceTimezone);
calendar.setTimeInMillis(sourceTime);
//获取源时区的到UTC的时区差
int sourceZoneOffset = calendar.get(Calendar.ZONE_OFFSET);
//目标时区
calendar.setTimeZone(targetTimezone);
calendar.setTimeInMillis(sourceTime);
//获取目标时区的到UTC的时区差
int targetZoneOffset = calendar.get(Calendar.ZONE_OFFSET);
long targetTime = sourceTime + targetZoneOffset - sourceZoneOffset;
return new Date(targetTime);
}
请注意,如果想考虑冬夏令时,上面的targetTimezonetimeZone一定要是 根据城市获取的,而不是固定偏移量的
TimeZone.getTimeZone("America/New_York")