Java UTC到本地时间不起作用

时间:2017-09-01 12:24:59

标签: java android date timezone simpledateformat

我正在尝试将UTC转换为本地时间,

以下是我正在使用的代码,

public static String utcToLocalDateFormat(String dateString) {

        Log.i("DateFormat", "utcToLocal:Before===>" + dateString);

        String formattedDate = null;
        if (dateString != null) {
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            dateFormat.setTimeZone(TimeZone.getDefault());
            Date date = null;
            try {

                Log.i("DateFormat", "getTimeZone===>" +dateFormat.getTimeZone());
                date = dateFormat.parse(dateString);
                System.out.println(date);
            } catch (ParseException e) {
                e.printStackTrace();
            }
            formattedDate = dateFormat.format(date);
            Log.i("DateFormat", "utcToLocal:After===>" + formattedDate);

        }
        return formattedDate;
    }

但问题是在时区转换时间相同之前和之后。它不会转换为UTC到本地时间。 任何帮助赞赏。

以下是我的意见: 1)2017-08-31 20:40:59 2)2017-09-01 11:16:24.024

以下是输出: 1)2017-08-31 20:40:59 2)2017-09-01 11:16:24

2 个答案:

答案 0 :(得分:2)

当你这样做时:

dateFormat.setTimeZone(TimeZone.getDefault());

然后解析String,你对格式化板说:“我要给你一个字符串,在这个时区里有一个日期和时间”。当您使用TimeZone.getDefault()时,它将使用JVM的默认时区。所以第一件事是告诉格式化程序在解析时使用UTC:

DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use UTC to parse
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
....
date = dateFormat.parse(dateString);

我正在测试dateString等于2017-08-01 10:00:00。因此,date将等同于2017-08-01 10:00:00 UTC。当您使用System.out.println打印日期时,它会调用toString()并将其转换为JVM的默认时区。

在我正在使用的JVM中,默认时区是America/Sao_Paulo,所以当我这样称呼时:

System.out.println(date);

打印:

  

Tue Aug 01 07:00:00 BRT 2017

因为在8月1日 st ,UTC的上午10点相当于圣保罗的上午7点。 此结果将根据您的JVM默认时区进行更改。

如果您要打印此日期,但日期和时间相当于另一个时区(UTC除外),则需要另一个设置了不同时区的格式化程序:

DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use my default timezone to format (America/Sao_Paulo)
dateFormat2.setTimeZone(TimeZone.getDefault());
formattedDate = dateFormat2.format(date);

这将打印:

  

2017-08-01 07:00:00

您可以使用您想要的任何时区(我使用America/New_York作为示例),而不是默认时区:

DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use New York timezone
dateFormat2.setTimeZone(TimeZone.getTimeZone("America/New_York"));
formattedDate = dateFormat2.format(date);

这会将日期/时间转换为纽约的时区:

  

2017-08-01 06:00:00

如果您想以UTC格式打印日期/时间,那么您不需要创建另一个格式化程序,只需使用第一个格式化程序(因为它已经设置为UTC)。

JVM的默认时区can be changed without notice, even at runtime,因此最好使用特定的时区,而不是仅使用getDefault()

更喜欢使用IANA timezones names(始终采用Region/City格式,例如America/Sao_PauloEurope/Berlin。 避免使用3个字母的缩写(例如CSTPST),因为它们是ambiguous and not standard

您可以致电TimeZone.getAvailableIDs()获取可用时区列表(并选择最适合您系统的时区)。

新日期/时间API

旧类(DateCalendarSimpleDateFormat)有lots of problemsdesign issues,它们将被新API取代。< / p>

在Android中,您可以使用ThreeTen Backport,这是Java 8新日期/时间类的绝佳后端。为了使其有效,您还需要ThreeTenABP(更多关于如何使用它here)。

此API更易于使用。首先,您创建一个org.threeten.bp.format.DateTimeFormatter并将输入String解析为org.threeten.bp.LocalDateTime

然后将其转换为UTC(创建org.threeten.bp.ZonedDateTime),然后转换为您想要的时区,并使用另一个格式化程序输出它:

// date/time with optional milliseconds
DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS]");
// parse to LocalDateTime
LocalDateTime dt = LocalDateTime.parse(dateString, parser);

// convert to UTC
ZonedDateTime z = dt.atZone(ZoneOffset.UTC);

// convert to another timezone
z = z.withZoneSameInstant(ZoneId.of("America/New_York"));
// format it
// date/time without milliseconds
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(fmt.format(z));

您还可以使用ZoneId.systemDefault()使用默认时区,并使用ZoneId.getAvailableZoneIds()获取所有可用的时区。

如果您希望以UTC格式显示日期/时间,则可以跳过对withZoneSameInstant()的调用。

要将其转换为java.util.Date,您可以使用org.threeten.bp.DateTimeUtils类:

// convert ZonedDateTime to java.util.Date
Date d = DateTimeUtils.toDate(z.toInstant());

答案 1 :(得分:0)

更改行

dateFormat.setTimeZone(TimeZone.getDefault());

dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));