记录下本地时间转utc时间的方法,参考大神的帖子

般说来,UTC时间本地时间是比较方便的,可以根据当前时区来进行时间的转换。

然而从本地时间转为UTC时间会相对复杂一些。当然,如果本地时间没有冬夏令时时,这种转换也是非常简单的。本文就针对本地时间转UTC时间做一下探讨。

1.冬夏令时

1.1.简介

夏时制(Daylight Saving Time:DST),又称“日光节约时制”和“夏令时间”,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间提前一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏时制的国家具体规定不同。目前全世界有近110个国家每年要实行夏令时。

冬令时是在冬天使用的标准时间。在使用日光节约时制的地区,夏天时钟拨快一小时,冬天再拨回来。这时采用的是标准时间,也就是冬令时 。

 

1.2.利弊

高纬度地区由于夏季太阳升起时间明显比冬季早,夏令时确实起到节省照明时间的作用。 不少零售商对夏令时持肯定态度。美国的糖果商院集团已经游说美国国会将夏令时延长到11月,因为万圣节是糖果销售最旺的季节,而家长们不希望孩子们在天黑以后还在外面游逛。 有人认为夏令时对患有夜盲症的人大有好处。 除了节约了电,也让人们养成了早睡早起的好习惯。
对低纬度地区,夏令时作用不大。尤其这些地方在夏天十分湿热,夜晚降临时闷热无法入眠,而清晨正是睡眠的好时间。  当夏令时开始和结束时,人们必须将所有计时仪器调快或调慢;当夏令时结束时,某些时间会在当天出现两次,这些都容易构成混乱。  夏令时违背了设定时区的原意──尽量使中午贴近太阳上中天的时间。

2.本地时间和UTC时间

2.1.本地时间

全球分为24个时区,以英国伦敦格林威治这个地方为零度经线的起点(亦称为本初子午线),并以地球由西向东每24小时自转一周360°,每隔经度15°,时差1小时。而每15°的经线则称为该时区的中央经线,将全球划分为24个时区,其中包含23个整时区及180°经线左右两侧的2个半时区。

其中格林威治为我们所见的GMT时间,全球各个地区按照GMT时间作为标准来设定当地时间。

每个地区所在的时区都有自己的本地时间,例如北京时间所在为东八区,为GMT+8。

2.2.UTC时间

在本地时间中介绍到了GMT时间,另外还有一个UTC时间,Coordinated Universal Time- 世界协调时间(又称世界标准时间、世界统一时间)。经过平均太阳时(以格林威治时间GMT为准)、地轴运动修正后的新时标以及以「秒」为单位的国际原子时所综合精算而成的时间,计算过程相当严谨精密,因此若以「世界标准时间」的角度来说,UTC比GMT来得更加精准。其误差值必须保持在0.9秒以内,若大于0.9秒则由位于巴黎的国际地球自转事务中央局发布闰秒,使UTC与地球自转周期一致。

基本上UTC的本质强调的是比GMT更为精确的世界时间标准,不过对于现行表款来说,GMT与UTC的功能与精确度是没有差别的。

所以我们基本上将UTC与GMT等同来进行处理。

2.3.本地时间转UTC时间

在我们平时开发过程中,经常需要进行时间转换,这里主要介绍本地时间转UTC时间。

如果只是本地当前时间转UTC时间,如下方式即可:

1

2

3

4

5

6

7

8

9

10

11

//1、取得本地时间:

Calendar cal = Calendar.getInstance();

//2、取得时间偏移量:

int zoneOffset = cal.get(Calendar.ZONE_OFFSET);

//3、取得夏令时差:

int dstOffset = cal.get(Calendar.DST_OFFSET);

//4、从本地时间里扣除这些差量,即可以取得UTC时间:

cal.add(Calendar.MILLISECOND, -(zoneOffset + dstOffset));

//之后调用cal.get(int x)或cal.getTimeInMillis()方法

//所取得的时间即是UTC标准时间。

System.out.println("UTC:"+new Date(cal.getTimeInMillis()));

大家看到上面这一段,就有疑问,如果将上面的cal直接传入对应的时间,不是就可以直接转换任意时间点的本地时间了么,然而实际情况是什么样子的呢?
如果本地所在时区有冬夏令时切换,由于Calendar本身会根据冬夏令时的时间会做微调整,就可能会导致我们获得的时间跟我们的预想的时间提前或者延后一个小时,那么怎么来解决呢?

Apache Common Lang包中提供了方法:

1

2

3

4

5

6

7

//1、取得时间Calendar

Calendar cal = Calendar.getInstance();

//2、设定对应的时间

cal.setTime(strToDate(args[0], format));

//3、获得UTC时间

System.out.println(DateFormatUtils.formatUTC(cal.getTimeInMillis(),

                                             format));

还有一种做法是不管冬夏令时的切换,直接以当前时间所在的令时进行UTC时间的转换:

1

2

3

4

5

6

7

8

9

10

11

12

//1、获得当前所在的令时偏移量-(zoneOffset + dstOffset)

Calendar cal = Calendar.getInstance();

int zoneOffset = cal.get(Calendar.ZONE_OFFSET);

int dstOffset = cal.get(Calendar.DST_OFFSET);       

//2、生成Calendar,并传入对应的时间

//使用GMT时区进行时间计算,防止令时切换导致的微调整

Calendar cal1 = Calendar.getInstance();

cal1.setTimeZone(TimeZone.getTimeZone(TIMEZONE_GMT));

cal1.setTime(strToDate(args[0], FORMAT_1));

cal1.add(Calendar.MILLISECOND, -(zoneOffset + dstOffset));

//3、获取对应的UTC时间

System.out.println(dateToString(cal1.getTime(), FORMAT_1));

这样,就可以得到对应UTC时间。

3.其他

获得当前时区:

1

2

3

4

5

6

7

//方法1

Calendar calendar = Calendar.getInstance();

TimeZone tz = calendar.getTimeZone();

System.out.println(tz.getID());

//方法2

TimeZone my=TimeZone.getDefault();

System.out.println(my.getID());

获得支持的时区列表:

1

2

3

//取得java所支持的所有时区ID

String[] ids=TimeZone.getAvailableIDs();

System.out.println(Arrays.toString(ids));

先到这里,有其他再补充。

 

 

前面都是copy人家的防止原帖看不了 

下面附上原帖链接

http://zhihao.info/sd/programm-language/java/local-time-to-utc-time/

转载于:https://my.oschina.net/u/2539375/blog/796029

unit uTimeZonesMgr; interface uses Windows, SysUtils, Classes, Registry, DateUtils; type {* 用于读取时区注册表TZI(长度为44)的属性值,存储时区信息 *} PRegTZIInfo = ^TRegTZIInfo; TRegTZIInfo = record Bias: Longint; StandardBias: Longint; DaylightBias: Longint; StandardDate: TSystemTime; DaylightDate: TSystemTime; end; {* 单个时区管理对象 *} TTimeZone = class private FTimeZoneName: string; //时区的显示名 FDisplay: string; //夏令时的名字 FDlt: string; //时区标准名字 FStd: string; //是Time zone information的缩写,描述时区的一些重要信息 FTZI: PRegTZIInfo; function GetSelfTimeZoneInformation: TTimeZoneInformation; public constructor Create; destructor Destroy; override; function UTCToLocalDateTime(const AUTC: TDateTime; var ALocalDateTime: TDateTime): Boolean; function LocalDateTimeToUTC(const ALocalDateTime: TDateTime; var AUTC: TDateTime): Boolean; public property TimeZoneName: string read FTimeZoneName write FTimeZoneName; property Display: string read FDisplay write FDisplay; property Dlt: string read FDlt write FDlt; property Std: string read FStd write FStd; property TZI: PRegTZIInfo read FTZI write FTZI; end; {* 所有时区管理对象 *} TTimeZones = class private FTimeZoneKeyPath: string; FTimeZoneList: TStringList; FDefaultTimeZone: TTimeZone; procedure CollectTimeZone; procedure DestoryTimeZones; procedure CheckISDefaultTimeZone(ATimeZone: TTimeZone); public constructor Create; destructor Destroy; override; function FindTimeZone(const ADisplay: string): TTimeZone; public property TimeZoneList: TStringList read FTimeZoneList; property DefaultTimeZone: TTimeZone read FDefaultTimeZone; end; implementation { TTimeZones } procedure TTimeZones.CheckISDefaultTimeZone(ATimeZone: TTimeZone); var DefaultTimeZone: TTimeZoneInformation; begin GetTimeZoneInformation(DefaultTimeZone); if (ATimeZone.TZI.Bias = DefaultTimeZone.Bias) and (ATimeZone.Std = DefaultTimeZone.StandardName) then FDefaultTimeZone := ATimeZone; end; procedure TTimeZones.CollectTimeZone; var reg, tempReg: TRegistry; tempKeyPath: string; tempTimeZoneStrings: TStrings; iCir: Integer; tempTimeZone: TTimeZone; begin reg := TRegistry.Create; try reg.RootKey := HKEY_LOCAL_MACHINE; reg.OpenKey(FTimeZoneKeyPath, False); tempTimeZoneStrings := TStringList.Create; try reg.GetKeyNames(tempTimeZoneStrings); for iCir := 0 to tempTimeZoneStrings.Count - 1 do begin tempKeyPath := FTimeZoneKeyPath + '\' + tempTimeZoneStrings.Strings[iCir]; tempReg := TRegistry.Create; try tempReg.RootKey := HKEY_LOCAL_MACHINE; tempReg.OpenKey(tempKeyPath, False); tempTimeZone := TTimeZone.Create; tempTimeZone.TimeZoneName := tempTimeZoneStrings.Strings[iCir]; tempTimeZone.Display := tempReg.ReadString('Display'); tempTimeZone.Std := tempReg.ReadString('Std'); tempTimeZone.Dlt := tempReg.ReadString('Dlt'); tempReg.ReadBinaryData('TZI', tempTimeZone.TZI^, SizeOf(TRegTZIInfo)); FTimeZoneList.AddObject(tempTimeZone.Display, tempTimeZone); if FDefaultTimeZone = nil then CheckISDefaultTimeZone(tempTimeZone); finally tempReg.CloseKey; tempReg.Free; end; end; finally tempTimeZoneStrings.Free; end; finally reg.CloseKey; reg.Free; end; end; constructor TTimeZones.Create; begin FTimeZoneKeyPath := '\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones'; FTimeZoneList := TStringList.Create; FTimeZoneList.Sorted := True; FDefaultTimeZone := nil; CollectTimeZone; end; procedure TTimeZones.DestoryTimeZones; var iCir: Integer; tempTimeZone: TTimeZone; begin for iCir := 0 to FTimeZoneList.Count - 1 do begin tempTimeZone := TTimeZone(FTimeZoneList.Objects[iCir]); tempTimeZone.Free; end; FTimeZoneList.Clear; FTimeZoneList.Free; end; destructor TTimeZones.Destroy; begin DestoryTimeZones(); inherited; end; function TTimeZones.FindTimeZone(const ADisplay: string): TTimeZone; var iIndex: Integer; begin Result := nil; FTimeZoneList.Sort; if FTimeZoneList.Find(ADisplay, iIndex) then begin Result := TTimeZone(FTimeZoneList.Objects[iIndex]); end; end; { TTimeZone } constructor TTimeZone.Create; begin FTZI := GetMemory(SizeOf(TRegTZIInfo)); FillMemory(FTZI, SizeOf(TRegTZIInfo), 0); end; destructor TTimeZone.Destroy; begin FreeMemory(FTZI); inherited; end; function TTimeZone.GetSelfTimeZoneInformation: TTimeZoneInformation; begin GetTimeZoneInformation(Result); Result.Bias := TZI^.Bias; Result.StandardBias := TZI^.StandardBias; Result.StandardDate := TZI^.StandardDate; Result.DaylightBias := TZI^.DaylightBias; Result.DaylightDate := TZI^.DaylightDate; end; function TTimeZone.LocalDateTimeToUTC(const ALocalDateTime: TDateTime; var AUTC: TDateTime): Boolean; var tempLocalToLocal: TDateTime; iMilliSecond: Int64; begin Result := UTCToLocalDateTime(ALocalDateTime, tempLocalToLocal); if Result then begin if tempLocalToLocal > ALocalDateTime then begin iMilliSecond := MilliSecondsBetween(tempLocalToLocal, ALocalDateTime); AUTC := IncMilliSecond(ALocalDateTime, iMilliSecond * -1); end else begin iMilliSecond := MilliSecondsBetween(ALocalDateTime, tempLocalToLocal); AUTC := IncMilliSecond(ALocalDateTime, iMilliSecond); end; Result := True; end; end; function TTimeZone.UTCToLocalDateTime(const AUTC: TDateTime; var ALocalDateTime: TDateTime): Boolean; var TimeZone: TTimeZoneInformation; stUTC, stLC: SYSTEMTIME; begin Result := False; TimeZone := GetSelfTimeZoneInformation; DateTimeToSystemTime(AUTC, stUTC); if SystemTimeToTzSpecificLocalTime(@TimeZone, stUTC, stLC) then begin ALocalDateTime := SystemTimeToDateTime(stLC); Result := True; end; end; end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值