日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java夏令时问题呈现

發布時間:2023/12/20 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java夏令时问题呈现 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一,先看看中國的夏令時

?1986年至1991年,中華人民共和國在全國范圍實行了六年夏令時,每年從4月中旬的第一個星期日2時整(北京時間)到9月中旬第一個星期日的凌晨2時整;
? 十日為旬。 上旬 每月第一日至第十日的十天,為上旬。 中旬 每月十一日到二十日的十天,為中旬,下旬同理

可以通過如下代碼找出這6的異常點

?

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-01System.out.println("start=" + fmt.format(start.getTime()));long end = Calendar.getInstance(timeZone).getTimeInMillis();//current timeboolean find = false;for(long i = start.getTimeInMillis(); i < end; i= start.getTimeInMillis() ){start.add(Calendar.DATE, 1); //add one dayif((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);} 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] ----------------------------------------------------------------

然后我們再準確的找下是那幾個時間點有問題

?

?

// // 比如1986年的夏令時時間,從代碼來看,是從1986-05-04 00:00:00到1986-09-13 22:59:59 // 但是java也不一定對,需要看老人或者看當年的報紙才能知道準確的夏令時時間@Testpublic void test4() throws Exception {SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");TimeZone zone = TimeZone.getDefault();Date d12=sf.parse("1986-05-03 23:59:00");//Date d13=sf.parse("1986-05-04 00:00:00");//Date d14=sf.parse("1986-06-04 00:00:00");//Date d15=sf.parse("1986-09-13 22:59:59");// Date d16=sf.parse("1986-09-13 23:00:00");// //突變點System.out.println("===1986-05-04 00:00:00實際時間====="+sf.parse("1986-05-04 00:00:00").toLocaleString());System.out.println("===1986-09-13 22:59:59實際時間====="+sf.parse("1986-09-13 22:59:59").toLocaleString());System.out.println("===1986-09-13 23:00:00實際時間====="+sf.parse("1986-09-13 23:00:00").toLocaleString());System.out.println("===1986-09-13 23:59:59實際時間====="+sf.parse("1986-09-13 23:59:59").toLocaleString());Date d21=sf.parse("1987-04-11 23:59:00");//Date d22=sf.parse("1987-04-12 00:00:00");//Date d23=sf.parse("1987-09-12 22:59:59");//Date d24=sf.parse("1987-09-12 23:00:00");//Date d31=sf.parse("1988-04-09 23:59:59");//Date d32=sf.parse("1988-04-10 00:00:00");//Date d33=sf.parse("1988-09-10 22:59:59");//Date d34=sf.parse("1988-09-10 23:00:00");//System.out.println("===============");Date d41=sf.parse("1989-04-15 23:59:59");//Date d42=sf.parse("1989-04-16 00:00:00");//Date d43=sf.parse("1989-09-16 22:59:59");//Date d44=sf.parse("1989-09-16 23:00:00");//System.out.println("===============");Date d51=sf.parse("1990-04-14 23:59:59");//Date d52=sf.parse("1990-04-15 00:00:00");//Date d53=sf.parse("1990-09-15 22:59:59");//Date d54=sf.parse("1990-09-15 23:00:00");//System.out.println("===============");Date d61=sf.parse("1991-04-13 23:59:59");//Date d62=sf.parse("1991-04-14 00:00:00");//Date d63=sf.parse("1991-09-14 22:59:59");//Date d64=sf.parse("1991-09-14 23:00:00");//System.out.println("=========1986=======");System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d12));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d13));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d14));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d15));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d16));System.out.println("=========1987=======");System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d21));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d22));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d23));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d24));System.out.println("=========1988=======");System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d31));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d32));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d33));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d34));System.out.println("=========1989=======");System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d41));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d42));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d43));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d44));System.out.println("=========1990=======");System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d51));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d52));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d53));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d54));System.out.println("======1991==========");System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d61));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d62));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d63));System.out.println("目標時區是否使用了夏令時:"+isDaylight(zone, d64));//6個突變點如下,只在開始實行的時候變化System.out.println("===1986-05-04 00:00:00實際時間====="+sf.parse("1986-05-04 00:00:00").toLocaleString());System.out.println("===1987-04-12 00:00:00實際時間====="+sf.parse("1987-04-12 00:00:00").toLocaleString());System.out.println("===1988-04-10 00:00:00實際時間====="+sf.parse("1988-04-10 00:00:00").toLocaleString());System.out.println("===1990-04-15 00:00:00實際時間====="+sf.parse("1990-04-15 00:00:00").toLocaleString());System.out.println("===1991-04-14 00:00:00實際時間====="+sf.parse("1991-04-14 00:00:00").toLocaleString());}//判斷是否在夏令時private boolean isDaylight(TimeZone zone,Date date) {//正常邏輯是:時區使用了夏令時再判斷時間,這里因為中國取消了if (zone.getID().equals("Asia/Shanghai")) {return zone.inDaylightTime(date);}return zone.useDaylightTime()&&zone.inDaylightTime(date);}


通過上面,找到了6個突變點:

?

1986-05-04 00:00:00
1987-04-12 00:00:00

1988-04-10 00:00:00

1989-04-16 00:00:00

1990-04-15 00:00:00

1991-04-14 00:00:00


?/**
? ? ? * 說明:這6個夏令時日期會導致實際存入數據庫的date日期發生變化,比如寫的是1986-05-04,實際存入的是1986-05-04 01:00:00
? ? ? * 如果之后在數據庫里面進行日期匹配的時候會出現問題,你需要trunc(date)來比較
? ? ? *?
? ? ? *?
? ? ? * 這里有2個問題,
? ? ? * 1.為什么夏令時結束的時候不會突變呢,比如:1986-09-13 23:00:00這個時候結束了夏令時
? ? ? * 按理實際的時間應該是變為:1986-09-13 22:00:00, 結果沒有變,那么減少的那一個小時去哪里了呢?怎么體現?(待琢磨。。。)
? ? ? * 2.上面得到的夏令時時間范圍跟實際規定的真的一樣嗎?
? ? ? *?
? ? ? * 下面我們看看美國的夏令時是不是也是這種情況
? ? ? */

//美國的夏令時從三月的第二個周日開始到十一月的第一個周日結束//已知官方2016年:America/New_York的夏令時時間是: 2016-3-13 02:00:00 到 2016-11-06 01:59:59 @Testpublic void test5() throws Exception {// 轉換為0時區時間作為參照點SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// sf.setTimeZone(TimeZone.getTimeZone("GMT+0"));TimeZone york = TimeZone.getTimeZone("America/New_York"); // GMT-5sf.setTimeZone(york);Date d1 = sf.parse("2016-03-13 01:59:59");// falseDate d2 = sf.parse("2016-03-13 02:00:00");// trueDate d3 = sf.parse("2016-11-06 00:59:59");// trueDate d3_1 = sf.parse("2016-11-06 01:00:00");// falseDate d3_2 = sf.parse("2016-11-06 01:59:59");// false預計是夏令時時間,實際不是Date d4 = sf.parse("2016-11-06 02:00:00");// false//可以發現,對于夏令時開始的時間判斷確實沒問題,但是對于夏令時的結束時間判斷錯誤,準確說,提前了一個小時判斷了System.out.println("目標時區是否使用了夏令時:" + isDaylight(york, d1));System.out.println("目標時區是否使用了夏令時:" + isDaylight(york, d2));System.out.println("目標時區是否使用了夏令時:" + isDaylight(york, d3));System.out.println("目標時區是否使用了夏令時:" + isDaylight(york, d3_1));System.out.println("目標時區是否使用了夏令時:" + isDaylight(york, d3_2));System.out.println("目標時區是否使用了夏令時:" + isDaylight(york, d4));}

?

//再來看下美國夏令時的突變時間@Testpublic void test6() throws Exception {//中間相隔13個小時 中國+8 紐約-5ChangeZone("2016-3-13 14:59:59", "PRC","America/New_York", "yyyy-MM-dd HH:mm:ss");//2016-03-13 01:59:59ChangeZone("2016-3-13 15:00:00", "PRC","America/New_York", "yyyy-MM-dd HH:mm:ss");//2016-03-13 03:00:00ChangeZone("2016-11-6 13:59:59", "PRC","America/New_York", "yyyy-MM-dd HH:mm:ss");//2016-11-06 01:59:59//這個結果是不對的,應該02:00:00,結果還是01:00:00ChangeZone("2016-11-6 14:00:00", "PRC","America/New_York", "yyyy-MM-dd HH:mm:ss");//2016-11-06 01:00:00}/***通過以上測試可以發現:無論是中國還是美國的夏令時*依然存在上面的2個問題:*1.夏令時在結束的時間點是不會突變的,具體原因待查*2.通過代碼判斷的夏令時時間段比 實際宣傳的少一個小時*/public static void ChangeZone(String time, String srcID, String destID,String pattern) throws ParseException {// 設置默認時區TimeZone zone = TimeZone.getTimeZone(srcID);TimeZone.setDefault(zone);Date date = new SimpleDateFormat(pattern).parse(time);// 設置目標時區TimeZone destzone = TimeZone.getTimeZone(destID);SimpleDateFormat sdf = new SimpleDateFormat(pattern);// 設置要格式化的時區sdf.setTimeZone(destzone);String changTime = sdf.format(date);// 獲取目標時區System.out.println("修改時區后" + destzone.getID() + "的時間:" + changTime);}

?

?

?

?

?

小結:

雖然存在這2個問題,但是時間并不影響我們代碼邏輯,

唯一要注意的是夏令時開始時那6個突變點,是真實的會影響日期的準確性,在數據庫進行date比較時,必須要截取日期來比較

*1.夏令時在結束的時間點是不會突變的,具體原因待查*2.通過代碼判斷的夏令時時間段比 實際宣傳的少一個小時

如果你想解決第一個問題,即在夏令時結束的時候,也讓其時間突變,

參考我的另外一篇文章:

http://blog.csdn.net/u011165335/article/details/76636296

?

?

?

總結

以上是生活随笔為你收集整理的java夏令时问题呈现的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。