冬令时 java_java处理 夏令时、冬令时问题

博客介绍了如何在Java中处理美国洛杉矶时区的夏令时和冬令时问题。通过示例代码展示了由于夏令时导致的一天可能出现23或25小时的情况,并提出了解决方案——在转换时间时设置正确的时区。
摘要由CSDN通过智能技术生成

最近接到一个需求:

给一个在美国洛杉矶时区(America/Los_Angeles)的机器上生成的long的时间,要在中国时区的机器上,把这个时间转换成美国时间?

业务方提醒,需要特别主要夏令时、冬令时问题。

于是就研究了下夏令时、冬令时问题:

1,首先搜索到这篇问题,知道了java中已经自带处理了这个问题,Java中不是每天都是标准的24个小时,可能是23,也可能是25。23小时和25小时就是夏令时、冬令时引起的。

package com.mike.test;

import java.text.SimpleDateFormat;

import java.util.Calendar;

import java.util.Date;

import java.util.TimeZone;

public class WhatTime {

/**

* Dates those have not EXACTLY 24 hours ?

**/

public static void testDayTime(TimeZone timeZone) {

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

System.out.println("Time Zone is " + timeZone.getDisplayName() + " " + timeZone.getID());

Calendar start = Calendar.getInstance(timeZone);

start.setTime(new Date(0));// UTC 1970-01-01

System.out.println("start=" + fmt.format(start.getTime()));

long now = Calendar.getInstance(timeZone).getTimeInMillis();

long year = 1000l * 3600 * 24 * 365;

long end = now + year * 5;//

// System.out.println("now=" + now + "\tend" + end);

System.out.println(new Date(end));

// time

boolean find = false;

for (long i = start.getTimeInMillis(); i < end; i = start.getTimeInMillis()) {

start.add(Calendar.DATE, 1); // add one day

if ((start.getTimeInMillis() - i) % (24 * 3600 * 1000L) != 0) {

find = true;

System.out.println("from " + fmt.format(new Date(i)) + "to " + fmt.format(start.getTime()) + " has "

+ (start.getTimeInMillis() - i) + "ms" + "[" + (start.getTimeInMillis() - i) / (3600 * 1000L)

+ "hours]");

}

}

if (!find) {

System.out.println("Every day is ok.");

}

}

public static void main(String argv[]) throws Exception {

TimeZone timeZone = TimeZone.getDefault();

WhatTime.testDayTime(timeZone);

System.out.println("----------------------------------------------------------------");

timeZone = TimeZone.getTimeZone("GMT");

WhatTime.testDayTime(timeZone);

System.out.println("----------------------------------------------------------------");

timeZone = TimeZone.getTimeZone("America/Los_Angeles");

WhatTime.testDayTime(timeZone);

}

}

输出:

Time Zone is 中国标准时间 Asia/Shanghai

start=1970-01-01 08:00:00

Mon Sep 02 20:46:37 CST 2019

from 1986-05-03 08:00:00to 1986-05-04 08:00:00 has 82800000ms[23hours]

from 1986-09-13 08:00:00to 1986-09-14 08:00:00 has 90000000ms[25hours]

from 1987-04-11 08:00:00to 1987-04-12 08:00:00 has 82800000ms[23hours]

from 1987-09-12 08:00:00to 1987-09-13 08:00:00 has 90000000ms[25hours]

from 1988-04-09 08:00:00to 1988-04-10 08:00:00 has 82800000ms[23hours]

from 1988-09-10 08:00:00to 1988-09-11 08:00:00 has 90000000ms[25hours]

from 1989-04-15 08:00:00to 1989-04-16 08:00:00 has 82800000ms[23hours]

from 1989-09-16 08:00:00to 1989-09-17 08:00:00 has 90000000ms[25hours]

from 1990-04-14 08:00:00to 1990-04-15 08:00:00 has 82800000ms[23hours]

from 1990-09-15 08:00:00to 1990-09-16 08:00:00 has 90000000ms[25hours]

from 1991-04-13 08:00:00to 1991-04-14 08:00:00 has 82800000ms[23hours]

from 1991-09-14 08:00:00to 1991-09-15 08:00:00 has 90000000ms[25hours]

----------------------------------------------------------------

Time Zone is 格林威治时间 GMT

start=1970-01-01 08:00:00

Mon Sep 02 20:46:37 CST 2019

Every day is ok.

----------------------------------------------------------------

Time Zone is 太平洋标准时间 America/Los_Angeles

start=1970-01-01 08:00:00

Mon Sep 02 20:46:37 CST 2019

from 1970-04-26 08:00:00to 1970-04-27 07:00:00 has 82800000ms[23hours]

from 1970-10-25 07:00:00to 1970-10-26 08:00:00 has 90000000ms[25hours]

from 1971-04-25 08:00:00to 1971-04-26 07:00:00 has 82800000ms[23hours]

from 1971-10-31 07:00:00to 1971-11-01 08:00:00 has 90000000ms[25hours]

from 1972-04-30 08:00:00to 1972-05-01 07:00:00 has 82800000ms[23hours]

from 1972-10-29 07:00:00to 1972-10-30 08:00:00 has 90000000ms[25hours]

from 1973-04-29 08:00:00to 1973-04-30 07:00:00 has 82800000ms[23hours]

from 1973-10-28 07:00:00to 1973-10-29 08:00:00 has 90000000ms[25hours]

from 1974-01-06 08:00:00to 1974-01-07 07:00:00 has 82800000ms[23hours]

from 1974-10-27 07:00:00to 1974-10-28 08:00:00 has 90000000ms[25hours]

from 1975-02-23 08:00:00to 1975-02-24 07:00:00 has 82800000ms[23hours]

from 1975-10-26 07:00:00to 1975-10-27 08:00:00 has 90000000ms[25hours]

from 1976-04-25 08:00:00to 1976-04-26 07:00:00 has 82800000ms[23hours]

from 1976-10-31 07:00:00to 1976-11-01 08:00:00 has 90000000ms[25hours]

from 1977-04-24 08:00:00to 1977-04-25 07:00:00 has 82800000ms[23hours]

from 1977-10-30 07:00:00to 1977-10-31 08:00:00 has 90000000ms[25hours]

from 1978-04-30 08:00:00to 1978-05-01 07:00:00 has 82800000ms[23hours]

from 1978-10-29 07:00:00to 1978-10-30 08:00:00 has 90000000ms[25hours]

from 1979-04-29 08:00:00to 1979-04-30 07:00:00 has 82800000ms[23hours]

from 1979-10-28 07:00:00to 1979-10-29 08:00:00 has 90000000ms[25hours]

from 1980-04-27 08:00:00to 1980-04-28 07:00:00 has 82800000ms[23hours]

from 1980-10-26 07:00:00to 1980-10-27 08:00:00 has 90000000ms[25hours]

from 1981-04-26 08:00:00to 1981-04-27 07:00:00 has 82800000ms[23hours]

from 1981-10-25 07:00:00to 1981-10-26 08:00:00 has 90000000ms[25hours]

from 1982-04-25 08:00:00to 1982-04-26 07:00:00 has 82800000ms[23hours]

from 1982-10-31 07:00:00to 1982-11-01 08:00:00 has 90000000ms[25hours]

from 1983-04-24 08:00:00to 1983-04-25 07:00:00 has 82800000ms[23hours]

from 1983-10-30 07:00:00to 1983-10-31 08:00:00 has 90000000ms[25hours]

from 1984-04-29 08:00:00to 1984-04-30 07:00:00 has 82800000ms[23hours]

from 1984-10-28 07:00:00to 1984-10-29 08:00:00 has 90000000ms[25hours]

from 1985-04-28 08:00:00to 1985-04-29 07:00:00 has 82800000ms[23hours]

from 1985-10-27 07:00:00to 1985-10-28 08:00:00 has 90000000ms[25hours]

from 1986-04-27 08:00:00to 1986-04-28 07:00:00 has 82800000ms[23hours]

from 1986-10-26 07:00:00to 1986-10-27 08:00:00 has 90000000ms[25hours]

from 1987-04-05 08:00:00to 1987-04-06 07:00:00 has 82800000ms[23hours]

from 1987-10-25 07:00:00to 1987-10-26 08:00:00 has 90000000ms[25hours]

from 1988-04-03 08:00:00to 1988-04-04 07:00:00 has 82800000ms[23hours]

from 1988-10-30 07:00:00to 1988-10-31 08:00:00 has 90000000ms[25hours]

from 1989-04-02 08:00:00to 1989-04-03 07:00:00 has 82800000ms[23hours]

from 1989-10-29 07:00:00to 1989-10-30 08:00:00 has 90000000ms[25hours]

from 1990-04-01 08:00:00to 1990-04-02 07:00:00 has 82800000ms[23hours]

from 1990-10-28 07:00:00to 1990-10-29 08:00:00 has 90000000ms[25hours]

from 1991-04-07 08:00:00to 1991-04-08 07:00:00 has 82800000ms[23hours]

from 1991-10-27 07:00:00to 1991-10-28 08:00:00 has 90000000ms[25hours]

from 1992-04-05 08:00:00to 1992-04-06 07:00:00 has 82800000ms[23hours]

from 1992-10-25 07:00:00to 1992-10-26 08:00:00 has 90000000ms[25hours]

from 1993-04-04 08:00:00to 1993-04-05 07:00:00 has 82800000ms[23hours]

from 1993-10-31 07:00:00to 1993-11-01 08:00:00 has 90000000ms[25hours]

from 1994-04-03 08:00:00to 1994-04-04 07:00:00 has 82800000ms[23hours]

from 1994-10-30 07:00:00to 1994-10-31 08:00:00 has 90000000ms[25hours]

from 1995-04-02 08:00:00to 1995-04-03 07:00:00 has 82800000ms[23hours]

from 1995-10-29 07:00:00to 1995-10-30 08:00:00 has 90000000ms[25hours]

from 1996-04-07 08:00:00to 1996-04-08 07:00:00 has 82800000ms[23hours]

from 1996-10-27 07:00:00to 1996-10-28 08:00:00 has 90000000ms[25hours]

from 1997-04-06 08:00:00to 1997-04-07 07:00:00 has 82800000ms[23hours]

from 1997-10-26 07:00:00to 1997-10-27 08:00:00 has 90000000ms[25hours]

from 1998-04-05 08:00:00to 1998-04-06 07:00:00 has 82800000ms[23hours]

from 1998-10-25 07:00:00to 1998-10-26 08:00:00 has 90000000ms[25hours]

from 1999-04-04 08:00:00to 1999-04-05 07:00:00 has 82800000ms[23hours]

from 1999-10-31 07:00:00to 1999-11-01 08:00:00 has 90000000ms[25hours]

from 2000-04-02 08:00:00to 2000-04-03 07:00:00 has 82800000ms[23hours]

from 2000-10-29 07:00:00to 2000-10-30 08:00:00 has 90000000ms[25hours]

from 2001-04-01 08:00:00to 2001-04-02 07:00:00 has 82800000ms[23hours]

from 2001-10-28 07:00:00to 2001-10-29 08:00:00 has 90000000ms[25hours]

from 2002-04-07 08:00:00to 2002-04-08 07:00:00 has 82800000ms[23hours]

from 2002-10-27 07:00:00to 2002-10-28 08:00:00 has 90000000ms[25hours]

from 2003-04-06 08:00:00to 2003-04-07 07:00:00 has 82800000ms[23hours]

from 2003-10-26 07:00:00to 2003-10-27 08:00:00 has 90000000ms[25hours]

from 2004-04-04 08:00:00to 2004-04-05 07:00:00 has 82800000ms[23hours]

from 2004-10-31 07:00:00to 2004-11-01 08:00:00 has 90000000ms[25hours]

from 2005-04-03 08:00:00to 2005-04-04 07:00:00 has 82800000ms[23hours]

from 2005-10-30 07:00:00to 2005-10-31 08:00:00 has 90000000ms[25hours]

from 2006-04-02 08:00:00to 2006-04-03 07:00:00 has 82800000ms[23hours]

from 2006-10-29 07:00:00to 2006-10-30 08:00:00 has 90000000ms[25hours]

from 2007-03-11 08:00:00to 2007-03-12 07:00:00 has 82800000ms[23hours]

from 2007-11-04 07:00:00to 2007-11-05 08:00:00 has 90000000ms[25hours]

from 2008-03-09 08:00:00to 2008-03-10 07:00:00 has 82800000ms[23hours]

from 2008-11-02 07:00:00to 2008-11-03 08:00:00 has 90000000ms[25hours]

from 2009-03-08 08:00:00to 2009-03-09 07:00:00 has 82800000ms[23hours]

from 2009-11-01 07:00:00to 2009-11-02 08:00:00 has 90000000ms[25hours]

from 2010-03-14 08:00:00to 2010-03-15 07:00:00 has 82800000ms[23hours]

from 2010-11-07 07:00:00to 2010-11-08 08:00:00 has 90000000ms[25hours]

from 2011-03-13 08:00:00to 2011-03-14 07:00:00 has 82800000ms[23hours]

from 2011-11-06 07:00:00to 2011-11-07 08:00:00 has 90000000ms[25hours]

from 2012-03-11 08:00:00to 2012-03-12 07:00:00 has 82800000ms[23hours]

from 2012-11-04 07:00:00to 2012-11-05 08:00:00 has 90000000ms[25hours]

from 2013-03-10 08:00:00to 2013-03-11 07:00:00 has 82800000ms[23hours]

from 2013-11-03 07:00:00to 2013-11-04 08:00:00 has 90000000ms[25hours]

from 2014-03-09 08:00:00to 2014-03-10 07:00:00 has 82800000ms[23hours]

from 2014-11-02 07:00:00to 2014-11-03 08:00:00 has 90000000ms[25hours]

from 2015-03-08 08:00:00to 2015-03-09 07:00:00 has 82800000ms[23hours]

from 2015-11-01 07:00:00to 2015-11-02 08:00:00 has 90000000ms[25hours]

from 2016-03-13 08:00:00to 2016-03-14 07:00:00 has 82800000ms[23hours]

from 2016-11-06 07:00:00to 2016-11-07 08:00:00 has 90000000ms[25hours]

from 2017-03-12 08:00:00to 2017-03-13 07:00:00 has 82800000ms[23hours]

from 2017-11-05 07:00:00to 2017-11-06 08:00:00 has 90000000ms[25hours]

from 2018-03-11 08:00:00to 2018-03-12 07:00:00 has 82800000ms[23hours]

from 2018-11-04 07:00:00to 2018-11-05 08:00:00 has 90000000ms[25hours]

from 2019-03-10 08:00:00to 2019-03-11 07:00:00 has 82800000ms[23hours]

可以发现中国时区在1992年后就废除了夏令时、冬令时,GMT时区是不存在夏令时、冬令时,美国洛杉矶一直在用夏令时、冬令时。

2,好奇一天怎么会变23,25小时,继续试验。

package com.mike.test;

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.TimeZone;

public class GetAmericaLosTime {

private static SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

/**

* @param args

* @throws ParseException

*/

public static void main(String[] args) throws ParseException {

//

// // 相差15小时

// String dateString = "2014-08-31 07:00:00";

//

// Date summer = fmt.parse(dateString);

// printDate(summer.getTime());

//

// // 相差16小时

// dateString = "2014-12-02 07:00:00";

// Date winter = fmt.parse(dateString);

// printDate(winter.getTime());

// 特殊时间点1

long abc = 1414918799000l;

printDate(abc);

abc = 1414918800000l;

printDate(abc);

// 特殊时间点2

// long bcd = 1394359199000l;

// printDate(bcd);

// bcd = 1394359200000l;

// printDate(bcd);

// printSameTime();

// 例如: long值: 1414918799000l 对应的中国时间:2014-11-2 16:59:59

// 用 return new Date(time).toLocaleString(), 返回 美国时间 2014-11-2 1:59:59

// 用 return new Date(time).toString(); 返回美国实际 ,Sun Nov 02 01:59:59 PDT

// 2014

}

private static void printDate(long now) {

// 中国时间

// TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

// System.out.println(new Date(now).toString());

// System.out.println(new Date(now).toLocaleString());

// 美国时间

TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));

System.out.println(new Date(now));

System.out.println(new Date(now).toLocaleString());

System.out.println("============================================================");

}

private static String conventTime(long time) {

// 中国时间

// TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

// 美国时间

TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));

return new Date(time).toLocaleString();

}

private static void printSameTime() throws ParseException {

TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

// 展示不同long,显示相同date

String dateString = "2014-03-10 00:00:00";

Date special = fmt.parse(dateString);

long specialTime = special.getTime();

System.out.println(specialTime);

TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));

long oneHour = 3600 * 1000l;

for (int i = -26; i < 26; i++) {

System.out.println("date long:" + (specialTime + oneHour * i) + " \tdate"

+ new Date(specialTime + oneHour * i));

}

}

private static void printTestDate() {

long start = System.currentTimeMillis();

System.out.println("start " + new Date(start));

System.out.println("start+one hour " + new Date(start + 3600 * 1000));

System.out.println("start+one day " + new Date(start + 3600 * 1000 * 24));

System.out.println("start+one year " + new Date(start + 3600l * 1000 * 24 * 365));

System.out.println("start+ten year " + new Date(start + 3600l * 1000 * 24 * 365 * 10));

System.out.println("now " + new Date(0));

}

}

输出:

Sun Nov 02 01:59:59 PDT 2014

2014-11-2 1:59:59

============================================================

Sun Nov 02 01:00:00 PST 2014

2014-11-2 1:00:00

============================================================

发现long值为1414918799000l,美国时间是2014-11-2 1:59:59;增加一秒1414918800000l,美国时间是2014-11-2 1:00:00,嘿嘿,是不是很神奇!!

不过仔细观察下你会发现,1414918799000l是夏令时PDT的Sun Nov 02 01:59:59 PDT 2014;而1414918800000l是冬令时PST的Sun Nov 02 01:00:00 PST 2014。

至此问题问题就明白了!!!

3,回到需求

想到Date和时区有关系,那只要转换前设置下时区就解决问题了。

private static String conventTime(long time) {

// 中国时间

// TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

// 美国时间

TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));

return new Date(time).toLocaleString();

}

over

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值