欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Java時(shí)區(qū)處理之Date,Calendar,TimeZone,SimpleDateFormat

 更新時(shí)間:2020年07月17日 16:51:59   作者:Josh_Persistence  
這篇文章主要介紹了Java時(shí)區(qū)處理之Date,Calendar,TimeZone,SimpleDateFormat的區(qū)別于用法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

一、概述

1、問(wèn)題描述

使用Java處理時(shí)間時(shí),我們可能會(huì)經(jīng)常發(fā)現(xiàn)時(shí)間不對(duì),比如相差8個(gè)小時(shí)等等,其真實(shí)原因便是TimeZone。只有正確合理的運(yùn)用TimeZone,才能保證系統(tǒng)時(shí)間無(wú)論何時(shí)都是準(zhǔn)確的。由于我在外企工作,服務(wù)器在美國(guó),美國(guó)也有很多時(shí)區(qū),經(jīng)常會(huì)碰到向處于不同時(shí)區(qū)的服務(wù)器發(fā)請(qǐng)求時(shí)需要考慮時(shí)區(qū)轉(zhuǎn)換的問(wèn)題。譬如,服務(wù)器位于西八區(qū)(GMT-8:00),而身處東八區(qū)的用戶(hù)想要查詢(xún)當(dāng)天的銷(xiāo)售記錄。則需把東八區(qū)的“今天”這個(gè)時(shí)間范圍轉(zhuǎn)換為服務(wù)器所在時(shí)區(qū)的時(shí)間范圍。

2、時(shí)區(qū)認(rèn)識(shí)

GMT時(shí)間:即格林威治平時(shí)(Greenwich Mean Time)。平太陽(yáng)時(shí)是與視太陽(yáng)時(shí)對(duì)應(yīng)的,由于地球軌道非圓形,運(yùn)行速度隨地球與太陽(yáng)距離改變而出現(xiàn)變化,因此視太陽(yáng)時(shí)欠缺均勻性。為了糾正這種不均勻 性,天文學(xué)家就計(jì)算地球非圓形軌跡與極軸傾斜對(duì)視太陽(yáng)時(shí)的效應(yīng),而平太陽(yáng)時(shí)就是指經(jīng)修訂之后的視太陽(yáng)時(shí)。在格林威治子午線上的平太陽(yáng)時(shí)稱(chēng)為世界時(shí)(UTC), 又叫格林威治平時(shí)(GMT)。

3、Java 時(shí)間和時(shí)區(qū)API

3.1、Date

類(lèi)Date表示特定的瞬間,精確到毫秒。獲得一個(gè)表示當(dāng)前時(shí)間的Date對(duì)象有兩種方式:

Date date = new Date(); 
Date date = Calendar.getInstance().getTime(); 

Date對(duì)象本身所存儲(chǔ)的毫秒數(shù)可以通過(guò)date.getTime()方法得到;該函數(shù)返回自1970年1月1日 00:00:00 GMT以來(lái)此對(duì)象表示的毫秒數(shù)。它與時(shí)區(qū)和地域沒(méi)有關(guān)系(其實(shí)可以認(rèn)為是GMT時(shí)間),而且還會(huì)告訴我們這個(gè)時(shí)區(qū)是否使用夏令時(shí)。有個(gè)這個(gè)信息,我們就能夠繼續(xù)將時(shí)區(qū)對(duì)象和日期格式化器結(jié)合在一起在其它的時(shí)區(qū)和其它的語(yǔ)言顯示時(shí)間了。

3.2、 Calendar

Calendar的getInstance()方法有參數(shù)為T(mén)imeZone和Locale的重載,可以使用指定時(shí)區(qū)和語(yǔ)言環(huán)境獲得一個(gè)日歷。無(wú)參則使用默認(rèn)時(shí)區(qū)和語(yǔ)言環(huán)境獲得日歷。

3.3、TimeZone

TimeZone對(duì)象給我們的是原始的偏移量,也就是與GMT相差的微秒數(shù),即TimeZone表示時(shí)區(qū)偏移量,本質(zhì)上以毫秒數(shù)保存與GMT的差值。

獲取TimeZone可以通過(guò)時(shí)區(qū)ID,如"America/New_York",也可以通過(guò)GMT+/-hh:mm來(lái)設(shè)定。例如北京時(shí)間可以表示為GMT+8:00。

TimeZone.getRawOffset()方法可以用來(lái)得到當(dāng)前時(shí)區(qū)的標(biāo)準(zhǔn)時(shí)間到GMT的偏移量。上段提到的"America/New_York"和"GMT+8:00"兩個(gè)時(shí)區(qū)的偏移量分別為-18000000和28800000。

4、影響TimeZone的因素

1. 操作系統(tǒng)的時(shí)區(qū)設(shè)置。

2. 數(shù)據(jù)傳輸時(shí)時(shí)區(qū)設(shè)置。

第一個(gè)原因其實(shí)是根本原因,當(dāng)數(shù)據(jù)在不同操作系統(tǒng)間流轉(zhuǎn)時(shí),就有可能因?yàn)椴僮飨到y(tǒng)的差異造成時(shí)間偏差,而JVM默認(rèn)情況下獲取的就是操作系統(tǒng)的時(shí)區(qū)設(shè)置。因此在項(xiàng)目中最好事先設(shè)置好時(shí)區(qū),例如:

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

5、解決的方法:

從以上的分析可以看出,解決時(shí)區(qū)問(wèn)題就簡(jiǎn)單了,在時(shí)區(qū)間轉(zhuǎn)換時(shí)間時(shí),首先用原時(shí)間減掉原時(shí)間所在時(shí)區(qū)相對(duì)于GMT的偏移量,得到原時(shí)間相對(duì)于GMT的值,然后再加上目標(biāo)時(shí)區(qū)相對(duì)GMT的偏移量即可。需要注意的是這樣得到的結(jié)果依然是毫秒數(shù),所以我們要按照指定日期格式重新轉(zhuǎn)換成Date對(duì)象即可。

6、實(shí)例:

在實(shí)例之前,假設(shè)當(dāng)前的時(shí)區(qū)為中國(guó)的東八區(qū)。即GMT+8:00

package com.wsheng.aggregator.timezone;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

/**
 * @author Josh Wang(Sheng)
 * 
 * @email swang6@ebay.com
 * 
 */
public class TimeZone1 {
	
	public static void main(String[] args) {
	 Date date = new Date(1391174450000L); // 2014-1-31 21:20:50 
	 String dateStr = "2014-1-31 21:20:50 "; 
	 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
	 dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); 
	 try { 
	  Date dateTmp = dateFormat.parse(dateStr); 
	  System.out.println(dateTmp); 
	  } catch (ParseException e) { 
	  e.printStackTrace(); 
	 } 
	 String dateStrTmp = dateFormat.format(date); 
	 System.out.println(dateStrTmp); 
	}
	

}

執(zhí)行結(jié)果:

Sat Feb 01 05:20:50 CST 2014
2014-01-31 13:20:50

我們發(fā)現(xiàn)同一時(shí)間,字符串和日期運(yùn)行出來(lái)的結(jié)果并不相同,那么我們應(yīng)該怎么理解呢?

一切都要以根本原因, 即當(dāng)前操作系統(tǒng)的時(shí)間為基準(zhǔn)。

我的操作系統(tǒng) 是"Asia/Shanghai",即GMT+8的北京時(shí)間,那么執(zhí)行日期轉(zhuǎn)字符串的format方法時(shí),由于日期生成時(shí)默認(rèn)是操作系統(tǒng)時(shí)區(qū),因此 2014-1-31 21:20:50是北京時(shí)間,那么推算到GMT時(shí)區(qū),自然是要減8個(gè)小時(shí)的,即結(jié)果(2014-01-31 13:20:50);而執(zhí)行字符串轉(zhuǎn)日期的parse方法時(shí),由于字符串本身沒(méi)有時(shí)區(qū)的概念,因此 2013-1-31 22:17:14就是指GMT(UTC)時(shí)間【ps:所有字符串都看做是GMT時(shí)間】,那么當(dāng)轉(zhuǎn)化為日期時(shí)要加上默認(rèn)時(shí)區(qū), 即"Asia/Shanghai",因此要加上8個(gè)小時(shí)。

用Calendar的話,如下:

package com.wsheng.aggregator.timezone;

import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 * @author Josh Wang(Sheng)
 * 
 * @email swang6@ebay.com
 * 
 */
public class TimeZone2 {
	
 public static void main(String[] args) { 
 	Date date = new Date(1391174450000L); // 2014-1-31 21:20:50 
  System.out.println(date); 
  Calendar calendar = Calendar.getInstance(); 
  calendar.setTimeZone(TimeZone.getTimeZone("GMT")); 
  // 或者可以 Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); 
  calendar.setTime(date); 
  System.out.println(calendar.get(Calendar.HOUR_OF_DAY) + ":" + calendar.get(Calendar.MINUTE)); 
 } 

}

執(zhí)行結(jié)果:

Fri Jan 31 21:20:50 CST 2014
13:20

Calendar不涉及到日期與字符串的轉(zhuǎn)化,因此不像SimpleDateFormat那么復(fù)雜,與日期轉(zhuǎn)字符串的思路類(lèi)似。但是需要注意的是,設(shè)置完時(shí)區(qū)后,我們不能用calendar.getTime()來(lái)直接獲取Date日期,因?yàn)榇藭r(shí)的日期與一開(kāi)始setTime時(shí)是相同值,要想獲取某時(shí)區(qū)的時(shí)間,正確的做法是用calendar.get()方法,那么我們?cè)趺传@得Date類(lèi)型的日期呢?

正確的做法如下:

package com.wsheng.aggregator.timezone;

import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;

/**
 * @author Josh Wang(Sheng)
 * 
 * @email swang6@ebay.com
 * 
 */
public class TimeZone3 {
	
 public static void main(String[] args) { 
 	Date date = new Date(1391174450000L); // 2014-1-31 21:20:50 
  System.out.println(date); 
  Calendar calendar = Calendar.getInstance(); 
  calendar.setTimeZone(TimeZone.getTimeZone("GMT")); 
  // 或者可以 Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); 
  calendar.setTime(date); 
  Calendar calendar2 = Calendar.getInstance(); 
  calendar2.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND)); 
  System.out.println(calendar2.getTime()); 
 } 

}

執(zhí)行結(jié)果:

Fri Jan 31 21:20:50 CST 2014
Fri Jan 31 13:20:50 CST 2014

完美通用轉(zhuǎn)換方法

其實(shí)上面兩個(gè)轉(zhuǎn)換方法都要受到操作系統(tǒng)的時(shí)區(qū)設(shè)置影響,如果軟件在不同操作系統(tǒng)運(yùn)行,仍然會(huì)有時(shí)間誤差,那么怎么才能統(tǒng)一呢?

/**
 * 
 */
package com.wsheng.aggregator.timezone;

import java.util.Date;
import java.util.TimeZone;

/**
 * @author Josh Wang(Sheng)
 * 
 * @email swang6@ebay.com
 * 
 */
public class TimeZone4 {
	
 public static void main(String[] args) { 
 	Date date = new Date(1391174450000L); // 2014-1-31 21:20:50 
  System.out.println(date); 
  date = changeTimeZone(date, TimeZone.getTimeZone("Asia/Shanghai"), TimeZone.getTimeZone("GMT")); 
  System.out.println(date); 
 } 
  
 /** 
  * 獲取更改時(shí)區(qū)后的日期 
  * @param date 日期 
  * @param oldZone 舊時(shí)區(qū)對(duì)象 
  * @param newZone 新時(shí)區(qū)對(duì)象 
  * @return 日期 
  */ 
 public static Date changeTimeZone(Date date, TimeZone oldZone, TimeZone newZone) { 
  Date dateTmp = null; 
  if (date != null) { 
   int timeOffset = oldZone.getRawOffset() - newZone.getRawOffset(); 
   dateTmp = new Date(date.getTime() - timeOffset); 
  } 
  return dateTmp; 
 } 

}

運(yùn)行結(jié)果:

Fri Jan 31 21:20:50 CST 2014
Fri Jan 31 13:20:50 CST 2014

更通用的,我們可以寫(xiě)一個(gè)支持類(lèi)型轉(zhuǎn)換的類(lèi):

package com.wsheng.aggregator.timezone;
import java.text.*; 
import java.util.*; 
 
/**
 * 
 * @author Josh Wang(Sheng)
 * 
 * @email swang6@ebay.com
 *
 */
public class DateTransformer { 
 public static final String DATE_FORMAT = "MM/dd/yyyy HH:mm:ss"; 
   
 public static String dateTransformBetweenTimeZone(Date sourceDate, DateFormat formatter, 
  TimeZone sourceTimeZone, TimeZone targetTimeZone) { 
  Long targetTime = sourceDate.getTime() - sourceTimeZone.getRawOffset() + targetTimeZone.getRawOffset(); 
  return DateTransformer.getTime(new Date(targetTime), formatter); 
 } 
   
 public static String getTime(Date date, DateFormat formatter){ 
  return formatter.format(date); 
 } 
   
 public static void main(String[] args){ 
  DateFormat formatter = new SimpleDateFormat(DATE_FORMAT); 
  Date date = Calendar.getInstance().getTime(); 
  System.out.println(" date: " + date);
  
  TimeZone srcTimeZone = TimeZone.getTimeZone("EST"); 
  TimeZone destTimeZone = TimeZone.getTimeZone("GMT+8"); 
  System.out.println(DateTransformer.dateTransformBetweenTimeZone(date, formatter, srcTimeZone, destTimeZone)); 
 } 
} 

DateFormat是日期/時(shí)間格式化子類(lèi)的抽象類(lèi),它以與語(yǔ)言無(wú)關(guān)的方式格式化并解析日期或時(shí)間。日期/時(shí)間格式化子類(lèi)(如 SimpleDateFormat)允許進(jìn)行格式化(也就是日期 -> 文本)、解析(文本-> 日期)和標(biāo)準(zhǔn)化。將日期表示為 Date 對(duì)象,或者表示為從 GMT(格林尼治標(biāo)準(zhǔn)時(shí)間)1970 年 1 月 1 日 00:00:00 這一刻開(kāi)始的毫秒數(shù)。SimpleDateFormat則是一個(gè)以與語(yǔ)言環(huán)境有關(guān)的方式來(lái)格式化和解析日期的具體類(lèi),可以以“日期和時(shí)間模式”字符串指定日期和時(shí)間格式。我們函數(shù)中所用模式字符串為"MM/dd/yyyy HH:mm:ss",則輸出日期:"07/16/2013 04:00:00"

其他常見(jiàn)的模式字母定義如下:

字母  日期或時(shí)間元素  表示  示例
G Era 標(biāo)志符 Text AD
y   年 Year 1996; 96 
M 年中的月份 Month July; Jul; 07 
w 年中的周數(shù) Number 27
W 月份中的周數(shù) Number 2
D 年中的天數(shù) Number 189
d 月份中的天數(shù) Number 10
F 月份中的星期 Number 2
E 星期中的天數(shù) Text Tuesday; Tue 
a Am/pm 標(biāo)記 Text PM
H 一天中的小時(shí)數(shù)(0-23) Number 0
k 一天中的小時(shí)數(shù)(1-24) Number 24
K am/pm 中的小時(shí)數(shù)(0-11) Number 0
h am/pm 中的小時(shí)數(shù)(1-12) Number 12
m 小時(shí)中的分鐘數(shù) Number 30
s 分鐘中的秒數(shù) Number 55
S 毫秒數(shù) Number 978
z 時(shí)區(qū) General time zone Pacific Standard Time; PST; GMT-08:00 
Z 時(shí)區(qū) RFC 822 time zone -0800

由上面的分析和事例說(shuō)明可知:

1. 計(jì)算機(jī)內(nèi)部記錄的時(shí)間(Date date = new Date()), 為格林威治標(biāo)準(zhǔn)時(shí)(GMT). 即java.util.Date代表一個(gè)時(shí)間點(diǎn),其值為距公元1970年1月1日 00:00:00的毫秒數(shù)。所以它可以認(rèn)為是沒(méi)有時(shí)區(qū)和Locale概念的。

2. 日期格式化類(lèi)DateFormat, 對(duì)于不同地區(qū)的配置一般有兩個(gè)點(diǎn), 一個(gè)是Locale , 一個(gè)是TimeZone
     前者(Locale)使DateFormat按所配置的地區(qū)特性來(lái)輸出文字(例如中國(guó),美國(guó),法國(guó)不同地區(qū)對(duì)日期的表示格式不一樣,中國(guó)可能是2001年10月5日)
     后者(TimeZone)讓DateFormat知道怎么去轉(zhuǎn)換,去調(diào)整時(shí)間偏移度,從而得到符合配置的時(shí)區(qū)的時(shí)間.
(即假設(shè)取得當(dāng)前時(shí)間(假設(shè)當(dāng)前時(shí)區(qū)為GMT+0,即與new Date()最后轉(zhuǎn)換的時(shí)間毫秒數(shù)一致)為2:00, 那么如果你配置DateFormat.setTimeZome("GMT+8"), 即北京時(shí)間的時(shí)區(qū), 那么這時(shí)候格式化輸出的就是10:00了, 因?yàn)橄到y(tǒng)對(duì)原始毫秒數(shù)進(jìn)行了時(shí)間偏移調(diào)整(調(diào)到你設(shè)置的時(shí)區(qū)),即加多8小時(shí),之后再格式化輸出日期的字符串形式)

3. GMT與UTC的時(shí)區(qū)是一樣的,都是以倫敦時(shí)間為基準(zhǔn). 而GMT+8時(shí)區(qū)就是北京時(shí)間所在時(shí)區(qū).同一時(shí)刻的時(shí)間比GMT快8小時(shí)。

到此這篇關(guān)于Java時(shí)區(qū)處理之Date,Calendar,TimeZone,SimpleDateFormat的區(qū)別于用法的文章就介紹到這了,更多相關(guān)Java時(shí)區(qū)處理 Date,Calendar,TimeZone,SimpleDateFormat內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java根據(jù)圖片中綠色像素點(diǎn)的多少進(jìn)行排序

    java根據(jù)圖片中綠色像素點(diǎn)的多少進(jìn)行排序

    這篇文章主要介紹了java根據(jù)圖片中綠色像素點(diǎn)的多少進(jìn)行排序,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • 分析JVM的執(zhí)行子系統(tǒng)

    分析JVM的執(zhí)行子系統(tǒng)

    本文主要介紹了JVM執(zhí)行子系統(tǒng)。了解虛擬機(jī)是如何執(zhí)行程序的, 虛擬機(jī)怎樣運(yùn)行一個(gè)Class文件的概念模型, 可以更好的理解怎樣寫(xiě)出優(yōu)秀的代碼
    2021-06-06
  • java讀取csv文件和寫(xiě)csv示例分享

    java讀取csv文件和寫(xiě)csv示例分享

    這篇文章主要介紹了JAVA對(duì)CSV格式文本數(shù)據(jù)處理后再保存成新CSV格式文本的模板,可以學(xué)習(xí)到j(luò)ava讀取csv文件和寫(xiě)csv的方法,需要的朋友可以參考下
    2014-03-03
  • IDEA生成標(biāo)準(zhǔn)JavaBean的幾種方法總結(jié)

    IDEA生成標(biāo)準(zhǔn)JavaBean的幾種方法總結(jié)

    標(biāo)準(zhǔn)javaBean是定義一個(gè)類(lèi)的標(biāo)準(zhǔn)結(jié)構(gòu),下面這篇文章主要給大家總結(jié)介紹了關(guān)于IDEA生成標(biāo)準(zhǔn)JavaBean的幾種方法,文中通過(guò)圖文以及代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • Java實(shí)現(xiàn)字符數(shù)組全排列的方法

    Java實(shí)現(xiàn)字符數(shù)組全排列的方法

    這篇文章主要介紹了Java實(shí)現(xiàn)字符數(shù)組全排列的方法,涉及Java針對(duì)字符數(shù)組的遍歷及排序算法的實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2015-12-12
  • JAVA中的Launcher類(lèi)解析

    JAVA中的Launcher類(lèi)解析

    這篇文章主要介紹了JAVA中的Launcher類(lèi)解析,Launcher作為JAVA應(yīng)用的入口,根據(jù)雙親委派模型,Laucher是由JVM創(chuàng)建的,它類(lèi)加載器應(yīng)該是BootStrapClassLoader, 這是一個(gè)C++編寫(xiě)的類(lèi)加載器,是java應(yīng)用體系中最頂層的類(lèi)加載器,需要的朋友可以參考下
    2023-09-09
  • Java實(shí)現(xiàn)的圖像查看器完整實(shí)例

    Java實(shí)現(xiàn)的圖像查看器完整實(shí)例

    這篇文章主要介紹了Java實(shí)現(xiàn)的圖像查看器,以完整實(shí)例形式較為詳細(xì)的分析了java處理圖片的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • springboot?publish?event?事件機(jī)制demo分享

    springboot?publish?event?事件機(jī)制demo分享

    這篇文章主要介紹了springboot?publish?event?事件機(jī)制demo,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • 淺談spring aop的五種通知類(lèi)型

    淺談spring aop的五種通知類(lèi)型

    這篇文章主要介紹了淺談spring aop的五種通知類(lèi)型,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-12-12
  • Java排序算法中的選擇排序算法實(shí)現(xiàn)

    Java排序算法中的選擇排序算法實(shí)現(xiàn)

    這篇文章主要介紹了Java排序算法中的選擇排序算法實(shí)現(xiàn),選擇排序算法的實(shí)現(xiàn)思路類(lèi)似插入排序,分已排序區(qū)間和未排序區(qū)間,選擇排序每次會(huì)從未排序區(qū)間中找到最小(大)的元素,將其放到已排序區(qū)間的末尾,需要的朋友可以參考下
    2023-12-12

最新評(píng)論