Java中的时区

Java中的时区,java,calendar,Java,Calendar,我正在用java编写一个安全签名,它还可以验证调用的日期和时间。POST call到达时带有如下内容 String date = "Sat, 27 Apr 2013 01:11:30 GMT" SimpleDateFormat RFC1123Format = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z", Locale.US); 我能解析它 Calendar gmtTime = new GregorianCalendar(TimeZon

我正在用java编写一个安全签名,它还可以验证调用的日期和时间。POST call到达时带有如下内容

String date = "Sat, 27 Apr 2013 01:11:30 GMT"
SimpleDateFormat RFC1123Format = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z", Locale.US);
我能解析它

Calendar gmtTime = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
Date dateHeader = RFC1123Format.parse(date);
gmtTime.setTime(dateHeader);

System.out.println("Date Header (GMT TIME): " + gmtTime.getTimeInMillis() + " ms");
System.out.println("Hour of day (GMT TIME): " + gmtTime.get(Calendar.HOUR_OF_DAY));

Calendar currentTime = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
currentTime.setTimeInMillis(System.currentTimeMillis());

System.out.println("System Date (LA TIME): " + currentTime.getTimeInMillis() + " ms");
System.out.println("Hour of day (LA TIME): " + currentTime.get(Calendar.HOUR_OF_DAY));

currentTime.setTimeZone(TimeZone.getTimeZone("GMT"));

System.out.println("System Date (GMT TIME): " + currentTime.getTimeInMillis() + " ms");
System.out.println("Hour of day (GMT TIME): " + currentTime.get(Calendar.HOUR_OF_DAY));

System.out.println("Diff: " + Math.abs(gmtTime.getTimeInMillis() - currentTime.getTimeInMillis()));
然而,我得到的打印结果相差整整一个小时

Date Header (GMT TIME): 1367025090000 ms
Hour of day (GMT TIME): 1
System Date (LA TIME): 1367022298441 ms
Hour of day (LA TIME): 0
System Date (GMT TIME): 1367022298441 ms
Hour of day (GMT TIME): 0
Diff: 2791559

有什么想法吗?

您可以使用比Java日历更高效地实现时区计算的JodaTime>通过添加额外的验证来检查是否遵守了夏令时,我自己修复了它。这是最终代码:

Calendar gmtTime = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
Date dateHeader = RFC1123Format.parse(date);
gmtTime.setTime(dateHeader);

Calendar currentTime = Calendar.getInstance();
currentTime.setTimeInMillis(System.currentTimeMillis());
boolean DST = false;
if(currentTime.getTimeZone().inDaylightTime(currentTime.getTime())) {
    DST = true; 
}
currentTime.setTimeZone(TimeZone.getTimeZone("GMT"));
if(DST) { 
    currentTime.set(Calendar.HOUR_OF_DAY, currentTime.get(Calendar.HOUR_OF_DAY) + 1); 
    .
    .
    .
    <code to handle last day of month and month change as a result of the hour adjustment>
}
日历gmtTime=new GregorianCalendar(TimeZone.getTimeZone(“GMT”); Date dateHeader=RFC1123Format.parse(日期); gmtTime.setTime(日期头); Calendar currentTime=Calendar.getInstance(); currentTime.setTimeInMillis(System.currentTimeMillis()); 布尔DST=false; if(currentTime.getTimeZone().inDaylightTime(currentTime.getTime())){ DST=真; } currentTime.setTimeZone(TimeZone.getTimeZone(“GMT”)); 如果(DST){ currentTime.set(Calendar.HOUR\u OF_DAY,currentTime.get(Calendar.HOUR\u OF_DAY)+1); . . . <处理月份最后一天和因小时调整而发生的月份变化的代码> }
谢谢@gangqinlaohu的建议。

您没有将用于表示时间戳的日历交给格式化程序

在这种情况下,您的日历设置为以GMT表示时间戳。GMT是UTC的同义词,UTC从不观察DST的任何调整。但是,默认情况下,格式化程序必须以系统默认日历为基础转换提供的字符串,这可能会遵守DST

如果是这种情况,您可以通过确保格式化程序使用与表示日期/时间相同的日历来获得一致的报告。试试这个:

SimpleDateFormat RFC1123Format = new SimpleDateFormat();
GregorianCalendar gc - new GregorianCalendar(TimeZone.getTimeZone("GMT"));

RFC1123Format.setCalendar(gc);
RFC1123Format.applyPattern("EEE, dd MMM yyyyy HH:mm:ss z");

gc.setTime(RFC1123Format.parse(yourDateString));

夏令时?是的,但我怎么解释。。。?如何验证是否观察到DST…?Java日期/时间API包含奥尔森时区数据库,能够提供从UTC到本地时间的历史准确转换,即使考虑到DST。如果您从UTC映射并得到意外结果,很可能是因为您得到了对不同时区的意外更正。在您的情况下,您的日历似乎设置为UTC。Java日期对象始终在内部使用UTC。但是,您的格式化程序没有日历,因此使用的是系统默认时区规则。尝试将格式化程序设置为UTC日历。我与Joda Time一起解决了一个DST问题,但最终它也出现了同样的问题。这是由于pc(或服务器)时区配置造成的。