【问题标题】:Timezone conversion for a specific datetime in javajava中特定日期时间的时区转换
【发布时间】:2012-03-30 09:09:11
【问题描述】:

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

这是我的方法。

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;
    }
}

【问题讨论】:

    标签: java timezone


    【解决方案1】:

    您不应该在日历中添加任何代表特定时刻的内容。事实上,你根本不需要日历。

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

    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。

    【讨论】:

      【解决方案2】:

      java.time

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

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

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

      使用现代日期时间 API java.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 了解有关现代日期时间 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

      【讨论】:

        猜你喜欢
        • 2011-12-01
        • 2020-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-29
        • 1970-01-01
        相关资源
        最近更新 更多