2013-08-29 212 views
4

请看看你是否可以告诉我如何处理我的情况下的DST问题。夏令时在java

第一,我的应用程序是一个物流系统,这是全球用户,所以它涉及时区的问题,我将处理它集预订的用户本地日期时,以下几点:

1.当用户登录应用,我们可以根据登录IP获取用户的时区,但这只是一个偏移量(我不记得这个东西的时间),例如“GMT + 08”(北京)或“GMT-06”(芝加哥)。

2.before用户保存预订时,我们需要设置预订本地日期,因为我不能得到用户本地日期直接.so我会得到服务器日期第一(在我的情况下,这是北京时间),然后根据服务器日期和用户时区计算本地日期,例如,如果用户时区为“GMT-08”,则服务器日期为2013-08-29 17:45:00。服务器时区为“GMT + 08”,那么我将使用服务器日期-8-8,结果将为2013-08-29 01:45:00。但由于我不考虑DST,计算出的本地日期将会与实际的日期有所不同,现在在旧金山,实际的本地日期将比我以这种方式计算的结果早一个小时,

我发现java TimeZone已经考虑了DST问题,但是我在构建TimeZone时需要提供“位置”名称(例如US/Alaska,Pacific/Apia)。而在我的情况下,我能得到的只是offset.so你能告诉我如何解决我的案例中的DST问题吗?

回答

3

这是头痛

  1. 以我的经验的常见来源,通过IP地址的位置并不总是可靠的,例如当人们使用企业VPN时。
  2. 你是正确的,基于地区的时区(“欧洲/巴黎”,“CET”)更适合正确处理DST。

我用下面的方法解决了一个类似的问题: 您将精确的时区与服务器端数据库中的每个用户相关联。当用户填写预订表单时,您将显示一个TZ选择器,预先填入其默认TZ。因此,他可以仔细检查它(恕我直言,比IP猜测更安全),并且在服务器端,日期可以安全地从本地服务器转换为服务器时间并返回。

5

是的,您应该使用Joda-Time或Java 8中新的java.time包(受Joda-Time的启发)。

偏移量是由某个日期时间值表示的从UTC(GMT)开始的小时和分钟数。西海岸是-08:00(忽略夏令时的废话),意思是8小时UTC以后。

请注意,它的初始版本中的java.time有一个小错误,它无法处理只有几小时的偏移量(例如+08)而没有分钟(如+08:00)。

A time zone是偏移量有关夏令时(DST),DST更改历史和其他异常信息的规则。

正确使用time zone names(主要是大陆斜线城市)。避免使用3或4个字母代码,如EST,它既不标准也不唯一。

java.util.Date没有时区,而Joda-Time DateTime

要获得网络浏览器的时区,请参阅this question。但通常情况下,这并不好。正如您可能已经看到的,许多网站要求用户选择一个时区。

您的确切用例令人困惑。通常最好的方法是使用UTC的日期时间值,然后根据需要调整到用户的当地时间。通常最适合您的软件工作并将日期时间存储为UTC。然后呈现调整为适合用户的本地日期时间。换句话说,全球考虑(UTC),本地出现(本地时区调整)。

通常系统管理员将他们的服务器计算机设置为UTC(无时区偏移量)。如果您的操作系统(如Mac OS X)不提供UTC,则使用Reykjavik,因为冰岛全年使用UTC而无夏令时。同样,数据库引擎几乎总是将日期时间值转换为UTC以存储。

Joda-Time的确提供了LocalDate类,当你真的不关心时区或时间时。但通常最好使用日期时间(DateTime实例),并根据需要格式化为仅限日期的字符串。

Joda-Time中的示例代码2.3。

DateTimeZone timeZoneChina = DateTimeZone.forID("Asia/Shanghai"); 
DateTime dateTimeChina = new DateTime(2013, 8, 29, 17, 45, 00, timeZoneChina); 
DateTime dateTimeUtc = dateTimeChina.withZone(DateTimeZone.UTC); 
DateTime dateTimeParis = dateTimeChina.withZone(DateTimeZone.forID("Europe/Paris")); 

DateTimeZone timeZoneUsWestCoast = DateTimeZone.forID("America/Los_Angeles"); 
DateTime dateTimeUnitedStatesWestCoast = dateTimeChina.withZone(timeZoneUsWestCoast); 

DateTimeFormatter formatter = ISODateTimeFormat.date(); 
String outputDateOnlyForUnitedStatesWestCoast = formatter.withZone(timeZoneUsWestCoast).print(dateTimeUtc); 

转储到控制台...

System.out.println("dateTimeChina: " + dateTimeChina); 
System.out.println("dateTimeUtc: " + dateTimeUtc); 
System.out.println("dateTimeParis: " + dateTimeParis); 
System.out.println("dateTimeUnitedStatesWestCoast: " + dateTimeUnitedStatesWestCoast); 
System.out.println("outputDateOnlyForUnitedStatesWestCoast: " + outputDateOnlyForUnitedStatesWestCoast); 

运行时...

dateTimeChina: 2013-08-29T17:45:00.000+08:00 
dateTimeUtc: 2013-08-29T09:45:00.000Z 
dateTimeParis: 2013-08-29T11:45:00.000+02:00 
dateTimeUnitedStatesWestCoast: 2013-08-29T02:45:00.000-07:00 
outputDateOnlyForUnitedStatesWestCoast: 2013-08-29