时区转换期间的奇怪行为

时间:2014-03-11 15:13:47

标签: java datetime timezone

我正在尝试将在EST时区打印的日期转换为以GMT / UTC打印的日期

package com.stefano;

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


public class MainEntry {

/**
 * @param args
 * @throws ParseException 
 */


public static void main(String[] args) throws ParseException {


    String dateTime = "1307011200"; //12:00PM 01 July 2013
    System.out.println("Input -> " + dateTime);
    SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmm");
    format.setTimeZone(TimeZone.getTimeZone("EST"));
    Date date = format.parse(dateTime);
    System.out.println("Intermediate -> " + date);
    format.setTimeZone(TimeZone.getTimeZone("GMT"));
    System.out.println("Output -> " + format.format(date));


    }

}

它给出的输出是:

Input -> 1307011200
Intermediate -> Mon Jul 01 17:00:00 BST 2013
Output -> 1307011600

即使EST和GMT之间的时差总是5,但它还是以某种方式参与了BST。

我无法使用Joda-Time

2 个答案:

答案 0 :(得分:2)

SimpleDateFormat.parse(String)方法的javadoc引用了parse(String,ParsePosition)方法,它说:

  

此解析操作使用日历生成日期。因此,日历的日期时间字段和TimeZone值可能已被覆盖,具体取决于子类实现。之前通过调用setTimeZone设置的任何TimeZone值可能需要恢复以进行进一步操作。

根据这个,您无法使用此方法告诉SimpleDateFormat哪个时区 给定的日期是。 您可以像这样修复此方法:

String dateTime = "1307011200"; // 12:00PM 01 July 2013
dateTime += " EST"; // append the timezone information to the input string
System.out.println("Input -> " + dateTime);
SimpleDateFormat format = new SimpleDateFormat("yyMMddHHmm z"); // tell the formatter to look for the timezone info
Date date = format.parse(dateTime);
System.out.println("Intermediate -> " + date);
format.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println("Output -> " + format.format(date));

这也将使用您的本地时区打印Date对象,但它显示了使用给定时区解析dateTime字符串的方法。

答案 1 :(得分:2)

answer by zovits是正确的。

美国东海岸抵消

如果EST表示美国东海岸(以及加拿大的部分地区),则您的声明the time difference between EST and GMT is always 5不正确。使用夏令时(DST),偏移量可能是-05:00 -04:00。实际上,您指定的日期时间确实有DST生效。

避免3-4个字母时区代码

这三个或四个字母的时区代码既不标准也不唯一。避免他们。使用proper time zone names,其中大部分是大陆+城市。

与Joda-Time的比较

为了比较,这里有一些Joda-Time示例代码。 java.util.Date&与Java捆绑在一起的日历类是非常麻烦的,每个Java程序员都应该转移到Joda-Time或新的Java 8 java.time package(受Joda-Time启发,由JSR 310定义)。

虽然java.util.Date似乎有时区但实际上没有,但请注意Joda-Time DateTime确实知道自己指定的时区。

Joda-Time使用ISO 8601标准作为默认值。您也可以使用其他格式,如下面的蒙特利尔示例所示。

示例代码

String input = "1307011200"; //12:00PM 01 July 2013
DateTimeFormatter formatterSmooshed = DateTimeFormat.forPattern( "yyMMddHHmm" );
DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" );
DateTime dateTimeNewYork = formatterSmooshed.withZone( timeZoneNewYork ).parseDateTime( input );
DateTime dateTimeUtc = dateTimeNewYork.withZone( DateTimeZone.UTC );
String outputMontréal = DateTimeFormat.forStyle( "FF" ).withLocale( Locale.CANADA_FRENCH ).print( dateTimeNewYork );
String outputSmooshed = formatterSmooshed.print( dateTimeNewYork ); // Expect same as input.

转储到控制台...

System.out.println( "input: " + input );
System.out.println( "dateTimeNewYork: " + dateTimeNewYork );
System.out.println( "dateTimeUtc: " + dateTimeUtc );
System.out.println( "outputMontréal: " + outputMontréal );
System.out.println( "outputSmooshed: " + outputSmooshed );

跑步时......

input: 1307011200
dateTimeNewYork: 2013-07-01T12:00:00.000-04:00
dateTimeUtc: 2013-07-01T16:00:00.000Z
outputMontréal: lundi 1 juillet 2013 12 h 00 EDT
outputSmooshed: 1307011200