将日期时间字符串从一个时区A转换为时区B,其中jvm在时区C中运行

时间:2014-11-17 18:53:28

标签: java date datetime

我有一个场景,我需要将日期时间字符串从时区A(UTC)转换为时区B(EST)

此处捕获的是发生此转换的JVM 时区C(HKT)日期对象

所以代码块如下:

String dateString="20141114213000";
dateString += " UTC";
String formatString ="yyyyMMddHHmmss";
SimpleDateFormat sdf = new SimpleDateFormat(formatString + " z");

 Date localDate = sdf.parse(dateString);
 System.out.println("Local Date::"+localDate); // Local Date::Sat Nov 15 05:30:00 HKT 2014

 Calendar localCal = Calendar.getInstance();
 localCal.setTime(localDate);

 TimeZone estTimeZone = TimeZone.getTimeZone("America/New_York");

 localCal.setTimeZone(estTimeZone);
 sdf.setTimeZone(estTimeZone);

 System.out.println(sdf.format(localCal.getTime()));//20141114163000 EST

 System.out.println(localCal.getTime());//Sat Nov 15 05:30:00 HKT 2014

我期待的输出是" 星期五11月14日16:30:00 EST 2014 "从最后一个陈述开始,即可用的最终日期对象应该在 EST 中。

如果有人有这方面的信息,请告知。


更新:
只是为了明确我的请求,输出应仅在日期对象中。

示例代码和我打印的输出仅用于更清楚的解释。

所以基本上是String" 20141114213000 "这是一个 UTC日期字符串需要转换为 EST日期对象,并且发生此转换的JVM位于 HKT

3 个答案:

答案 0 :(得分:1)

Java的日期和时间类似乎存在显着问题。

让我们使用流行的Joda-Time - Java date and time API。 只需下载最新的稳定版本并将jar文件添加到项目的构建路径中。

在逐行的基础上,我已经注释掉了你的代码,并重写了Joda Time的替代方案。这样,您就可以了解我如何将现有代码转换为Joda Time API。

import java.text.ParseException;

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class JodaTimeTransition {
    public static void main(String[] args) throws ParseException {
        String dateString="20141114213000";
        dateString += " UTC";

        /*new*/
        String formatString = "yyyyMMddHHmmss z";
//      String formatString ="yyyyMMddHHmmss";

        /*new*/ 
        DateTimeFormatter dtf = DateTimeFormat.forPattern(formatString);
//      SimpleDateFormat sdf = new SimpleDateFormat(formatString + " z");

        /* new - Create localDate using JodaTime DateTime class */
        DateTime localDate = DateTime.parse(dateString, dtf);
//      Date localDate = sdf.parse(dateString);

        /* new - convert time to MST, since it is currently UTC*/
        localDate = localDate.toDateTime(DateTimeZone.forID("America/Denver"));

        /* new - print out <local date> using specified format.*/
        System.out.println("Local Date::" + localDate.toString("EEE MMM dd HH:mm:ss z yyyy"));
        /* Where did you get the local date mentioned at comments of line below? */
//      System.out.println("Local Date::"+localDate); // Local Date::Sat Nov 15 05:30:00 HKT 2014


        /* new - Get reference to current date/time as <localCal> 
         * (This step can be omitted, and the previous localDate variable can be used)
        */
        DateTime localCal = DateTime.now();
//      Calendar localCal = Calendar.getInstance();

        /* new - Set <localCal> to <localDate> */
        localCal = localDate;
//      localCal.setTime(localDate);

        /* new - Create new EST time zone*/
        DateTimeZone estTimeZone= DateTimeZone.forID("America/New_York");
//      TimeZone estTimeZone = TimeZone.getTimeZone("America/New_York");

        /* new - set <localCal> time zone from MST to EST */
        localCal = localCal.toDateTime(estTimeZone);
//      localCal.setTimeZone(estTimeZone);
//      sdf.setTimeZone(estTimeZone);

        /* new - print <localCal> as new EST time zone */
        System.out.println(localCal.toString("yyyyMMddHHmmss z"));
//      System.out.println(sdf.format(localCal.getTime()));//20141114163000 EST

        /* new - print in desired format: Fri Nov 14 16:30:00 EST 2014 */
        System.out.println(localCal.toString("EEE MMM dd HH:mm:ss z yyyy"));
//      System.out.println(localCal.getTime());//Sat Nov 15 05:30:00 HKT 2014
    }
}

答案 1 :(得分:1)

这实际上非常简单(不需要Joda时间,不是它不是一个很棒的库),你只需要在SimpleDateFormat上设置TimeZone。在解析时使用源TimeZone,在格式化时使用目标TimeZone(并且您不需要中间日历)。

更新:

日期没有TimeZones。如果你想要一个带有TimeZone(除了字符串)的东西,那么你需要一个日历。除了在解析之前没有在SimpleDateFormat上设置源TimeZone之外,您当前的代码大多是正确的。

答案 2 :(得分:0)

<强>更新

在评论中进行了一些讨论之后,现在看来你应该完全依赖java.util.Date时区了。下面描述的技巧(我的原始答案)可能会有效,但这不是正确的做法。切换到支持时区的东西(例如java.util.Calendar),但最好使用JodaTime。


警告:这是一个技巧,可能(或可能不)适用于Sun的java.util.Date实现,其内部结构使用时区进行初始化。

首先尝试使用TimeZone.setDefault(...)设置默认时区。

你的最后一次电话:

System.out.println(localCal.getTime());

实际上是:

System.out.println(new Date(localCal.getTimeInMillis()).toString());

因此,在日历上设置任何时区信息毫无意义。

Date.toString(),但首先对日期进行内部规范化并使用静态TimeZone.getDefaultRef()。这应该为您提供默认时区 - 您可以(通常)通过TimeZone.setDefailt(...)设置。

一定要使用JodaTime。