Java UTC到当地时间不起作用



我正在尝试将UTC转换为local,

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

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

但是问题是在时区转换时间相同之前和之后。任何帮助都赞赏。

以下是我的输入:1)2017-08-31 20:40:592)2017-09-01 11:16:24.024

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

当您做:

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

它打印:

星期二8月1日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的默认时间区域,而无需通知,因此最好使用特定的时区,而不仅仅是使用getDefault()

更喜欢使用IANA时区名称(始终以Region/City格式,例如America/Sao_PauloEurope/Berlin)。避免使用3个字母的缩写(例如CSTPST),因为它们是模棱两可的,而不是标准的。

您可以通过调用TimeZone.getAvailableIDs()


新日期/时间API

旧类(DateCalendarSimpleDateFormat)有很多问题和设计问题,它们被新的API替换。

在Android中,您可以使用Threeten Backport,这是Java 8的新日期/时间课程的绝佳备份。为了使它起作用,您还需要三个threetenabp(有关如何在此处使用它的更多信息)。

此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());

更改行

dateFormat.setTimeZone(TimeZone.getDefault());

to

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

相关内容

  • 没有找到相关文章

最新更新