java中特定日期时间的时区转换

时间:2012-03-30 09:09:11

标签: java timezone

我将给出时区的输入日期时间和输入日期时间的时区,我们希望相关的日期时间在预期的时区。

这是我的方法。 convertToTimezone(“03/08/2010 20:19:00 PM”,“Asia / Shanghai”,“US / Central”); 以上时间是亚洲/上海的时间。我们想知道美国/中部的相应时间。

它工作正常,但我与实际时间相差1小时。 我能知道我哪里出错吗?

这是代码。

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

public class DateUtil 
{

    private static String format_date="MM/dd/yyyy HH:mm:ss a";

    public static void main(String a[])
    {
        try
        {
            String sourceTimezone="Asia/Shanghai";
            String destTimezone="US/Central";           
            String outputExpectedTimezone=convertToTimezone("03/08/2010 20:19:00 PM",sourceTimezone,destTimezone);
            System.out.println("outputExpectedTimezone :"+outputExpectedTimezone);
        }
        catch(Exception ex)
        {
            ex.printStackTrace();
        }
    }
    public static String convertToTimezone(String inputDate,String inputDateTimezone,String destinationDateTimezone)throws Exception
    {
        String outputDate=null;

        SimpleDateFormat format = new SimpleDateFormat(format_date);
        format.setTimeZone(TimeZone.getTimeZone(inputDateTimezone));

        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(inputDateTimezone));  
        calendar.setTime(format.parse(inputDate));
        calendar.add(Calendar.MILLISECOND,-(calendar.getTimeZone().getRawOffset()));        
        calendar.add(Calendar.MILLISECOND, - calendar.getTimeZone().getDSTSavings());
        calendar.add(Calendar.MILLISECOND, TimeZone.getTimeZone(destinationDateTimezone).getRawOffset());

        outputDate=format.format(calendar.getTime());
        return outputDate;
    }

    }

2 个答案:

答案 0 :(得分:2)

您不应该在日历中添加任何内容 - 这代表特定的即时时间。实际上,您根本不需要日历。

相反,有两种不同的格式,每个时区一个:

public static String convertToTimezone(String inputDate,
     String inputDateTimezone,
     String destinationDateTimezone)
     throws Exception
{
    SimpleDateFormat parser = new SimpleDateFormat(format_date);
    parser.setTimeZone(TimeZone.getTimeZone(inputDateTimezone));

    Date date = parser.parse(inputDate);

    SimpleDateFormat formatter = new SimpleDateFormat(format_date);
    formatter.setTimeZone(TimeZone.getTimeZone(outputDateTimezone));
    return formatter.format(date);
}

另外,我彻底建议使用Joda Time而不是内置的日期/时间API。

答案 1 :(得分:0)

java.time

java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用它们并切换到 modern Date-Time API*

另外,下面引用的是来自 home page of Joda-Time 的通知:

<块引用>

请注意,从 Java SE 8 开始,要求用户迁移到 java.time (JSR-310) - JDK 的核心部分,取代了该项目。

使用 java.time(现代日期时间 API)的解决方案:

  • 由于您输入的 Date-Time 没有时区信息,请将其解析为 LocalDateTime
    • 将输入日期时间的时区附加到它以获取 ZonedDateTime

演示:

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        // Tests
        System.out.println(convertToTimezone("03/08/2010 20:19:00 PM", "Asia/Shanghai", "US/Central"));
        System.out.println(convertToTimezone("03/08/2010 20:19:00 PM", "Asia/Shanghai", "America/Mexico_City"));
    }

    static String convertToTimezone(String inputDate, String inputDateTimezone, String destinationDateTimezone) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM/dd/uuuu HH:mm:ss a", Locale.ENGLISH);
        LocalDateTime ldt = LocalDateTime.parse(inputDate, dtf);
        ZonedDateTime zdtInput = ldt.atZone(ZoneId.of(inputDateTimezone));
        ZonedDateTime zdtDestination = zdtInput.withZoneSameInstant(ZoneId.of(destinationDateTimezone));
        return zdtDestination.format(dtf);
    }
}

输出:

03/08/2010 06:19:00 AM
03/08/2010 06:19:00 AM

ONLINE DEMO

注意:避免使用已弃用的 ID US/Central。使用标准 ID America/Mexico_City 其中 Mexico City is the largest city in this timezone

Trail: Date Time 了解有关现代 Date-Time API 的更多信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project