我按照以下代码在指定的dateTime上使用指定的Timezone创建Date对象 注意:我没有为jvm设置任何时区;但是使用不同的Linux服务器时区测试此代码。
String date = "20121225 10:00:00";
String timeZoneId = "Asia/Calcutta";
TimeZone timeZone = TimeZone.getTimeZone(timeZoneId);
DateFormat dateFormatLocal = new SimpleDateFormat("yyyyMMdd HH:mm:ss z");
//This date object is given time and given timezone
java.util.Date parsedDate = dateFormatLocal.parse(date + " "
+ timeZone.getDisplayName(false, TimeZone.SHORT));
if (timeZone.inDaylightTime(parsedDate)) {
// We need to re-parse because we don't know if the date
// is DST until it is parsed...
parsedDate = dateFormatLocal.parse(date + " "
+ timeZone.getDisplayName(true, TimeZone.SHORT));
}
现在parsedDate对象的行为不同了
当我的jvm服务器在IST中运行时
parsedDate.getTime() - 1356409800000
parsedDate.toString() - 12月25日星期二10:00:00 IST 2012
在GMT --- 12/25/2012 04:30:00 GMT
当我的jvm服务器在EST中运行时
parsedDate.getTime() - 1356422400000
parsedDate.toString() - 2012年12月25日星期二03:00:00
在GMT --- 12/25/2012 08:00:00 GMT
我的两个系统时间都在同步中 2012年12月24日星期一10:30:04 2012年 2012年12月24日星期一21:00:48 我期待两台机器都能获得相同的GMT时间 这里出了什么问题?
答案 0 :(得分:4)
我认为问题在于你试图解析IST,它具有不同的含义,具体取决于你的默认值" location"是
Time Zone Abbreviation Zone Description Relative UTC
IST Irish Summer Time UTC+01
IST Israeli Standard Time UTC+02
IST Iran Standard Time UTC+0330
IST Indian Standard Time UTC+0530
如果您所在的位置是印度人,则会按照您的预期对待IST,但如果您使用美国,则会猜到不同的时区。
解决方案是不使用三个字母的时区并明确设置它们。
String date = "20121225 10:00:00";
String timeZoneId = "Asia/Calcutta";
TimeZone timeZone = TimeZone.getTimeZone(timeZoneId);
DateFormat dateFormatLocal = new SimpleDateFormat("yyyyMMdd HH:mm:ss");
dateFormatLocal.setTimeZone(timeZone);
Date parsedDate = dateFormatLocal.parse(date);
答案 1 :(得分:3)
短名称不是识别时区的好方法,因为它不是唯一的; the Javadoc for java.util.TimeZone
举例说明“'CST'可能是美国'中央标准时间'和'中国标准时间'”。
更一般。 。 。而不是将时区作为字符串传递,以便您的DateFormat
必须解析它,通过使用{{1}告诉您的DateFormat
时区是更有意义的你已经拥有的实例:
TimeZone
(这也将在可能的范围内自动处理夏令时。)
答案 2 :(得分:1)
这里有一个快速的Groovy脚本来演示如何使用缩写的时区名称是一个问题,结果将根据本地环境而有所不同,尤其是本地默认TimeZone
。
假设您要解析2015-02-20T17:21:17.190EST
,并且您认为美国东海岸意义上的EST = 东部标准时间,那么纽约时间。因此,您希望纪元时间准确为1424470877190
或GMT: Fri, 20 Feb 2015 22:21:17.190 GMT
,因为此EST
为GMT-0500
。这是一个测试脚本,显示当前默认TimeZone
如何影响EST
的解释。
import java.util.*
import java.text.*
SimpleDateFormat sdf
TimeZone.setDefault(TimeZone.getTimeZone("Australia/Sydney"))
printDefaultTimeZone()
sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSz")
checkTime(sdf.parse("2015-02-20T17:21:17.190EST").getTime())
checkTime(sdf.parse("2015-02-20T17:21:17.190-0500").getTime())
TimeZone.setDefault(TimeZone.getTimeZone("EST"))
printDefaultTimeZone()
// same SDF
checkTime(sdf.parse("2015-02-20T17:21:17.190EST").getTime())
checkTime(sdf.parse("2015-02-20T17:21:17.190-0500").getTime())
printDefaultTimeZone()
// new SDF
sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSz")
checkTime(sdf.parse("2015-02-20T17:21:17.190EST").getTime())
checkTime(sdf.parse("2015-02-20T17:21:17.190-0500").getTime())
void printDefaultTimeZone() {
println(TimeZone.getDefault().getDisplayName() + ":" + TimeZone.getDefault().getRawOffset() / 3600 / 1000)
}
void checkTime(long time) {
println(time + (time == 1424470877190L ? ": CORRECT" : ":"))
}
输出:
Eastern Standard Time (New South Wales):10
1424413277190:
1424470877190: CORRECT
Eastern Standard Time:-5
1424413277190:
1424470877190: CORRECT
Eastern Standard Time:-5
1424470877190: CORRECT
1424470877190: CORRECT
在上面的输出中,意外/不正确的日期时间为1424413277190 = GMT: Fri, 20 Feb 2015 06:21:17.190 GMT
,比解析的EST
时间 11 小时(在这种情况下为Australia/Sydney
变种EST
),因为夏令时适用于该日期。
因此,您可以看到EST
的解释取决于构建时的默认TimeZone
。在前两个转换批次中,默认TimeZone
为Australia/Sydney
,其本身缩写为EST
,因此Java将缩写解释为此。直到在默认TZ改变之后构造新的SDF之后,我们才看到缩写应用为预期。
作为设置默认时区的替代方法,您还可以在SDF上设置Calendar
实例:
sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSz")
sdf.setCalendar(Calendar.getInstance(TimeZone.getTimeZone("America/New_York"), new Locale("en_US")))
这会产生解释EST
的效果。