将 UTC 日期转换为 Android 中的本地时间?

Convert UTC date to Local Time in Android?

我有一个日期 String,类似于 2017-09-16T05:06:18.157,我想将其转换为当地时间 (IST)。在印度标准时间大约是 2017-09-16 10:36:18.

使用 Joda-Time,我尝试将其转换为本地,但我无法做到。

下面是我的代码:

private String getConvertDate(String date_server) {
    DateTimeFormatter inputFormatter = DateTimeFormat
            .forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
            .withLocale(Locale.US);

    DateTime parsed = inputFormatter.parseDateTime(date_server);

    DateTimeFormatter outputFormatter = DateTimeFormat
            .forPattern("yyyy-MM-dd HH:mm:ss")
            .withLocale(Locale.US)
            .withZone(DateTimeZone.getDefault());

    return outputFormatter.print(parsed);
}
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
TimeZone utcZone = TimeZone.getTimeZone("UTC");
simpleDateFormat.setTimeZone(utcZone);
Date myDate =simpleDateFormat.parse(rawQuestion.getString("Asia/Kolkata"));

simpleDateFormat.setTimeZone(TimeZone.getDefault());
String formattedDate = simpleDateFormat.format(myDate);

试试这个代码:

   String serverdateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'";

  public String convertServerDateToUserTimeZone(String serverDate) {
    String ourdate;
    try {
        SimpleDateFormat formatter = new SimpleDateFormat(serverdateFormat, Locale.UK);
        formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date value = formatter.parse(serverDate);
        TimeZone timeZone = TimeZone.getTimeZone("Asia/Kolkata");
        SimpleDateFormat dateFormatter = new SimpleDateFormat(serverdateFormat, Locale.UK); //this format changeable
        dateFormatter.setTimeZone(timeZone);
        ourdate = dateFormatter.format(value);

        //Log.d("OurDate", OurDate);
    } catch (Exception e) {
        ourdate = "0000-00-00 00:00:00";
    }
    return ourdate;
}

很好,您找到了 SimpleDateFormat 的解决方案。我只想添加更多关于它的见解(主要是因为旧的 classes(DateCalendarSimpleDateFormat)有 lots of problems and design issues,他们正在被新的 APIs 取代)。

输入String2017-09-16T05:06:18.157)仅包含日期(year/month/day)和时间(hour/minute/second/millisecond),但没有时区信息。因此,当调用 parseDateTime 时,Joda-Time 只是假定它处于 JVM 默认时区。

如果你知道输入是UTC,但输入本身没有关于它的信息,你必须告诉它。一种方法是在格式化程序中设置:

// set the formatter to UTC
DateTimeFormatter inputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
    .withZone(DateTimeZone.UTC);

// DateTime will be in UTC
DateTime parsed = inputFormatter.parseDateTime("2017-09-16T05:06:18.157");

另一种方法是首先将输入解析为 org.joda.time.LocalDateTime(表示没有时区的日期和时间的 class),然后将其转换为 DateTime协调世界时:

// parse to LocalDateTime
DateTime = parsed = LocalDateTime.parse("2017-09-16T05:06:18.157")
    // convert to a DateTime in UTC
    .toDateTime(DateTimeZone.UTC);

两者产生相同的 DateTime,对应于 UTC 2017-09-16T05:06:18.157Z

要将其格式化为 "IST timezone"(这实际上不是时区 - 更多内容见下文),您还可以在格式化程序中设置时区:

// convert to Asia/Kolkata
DateTimeFormatter outputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
    .withZone(DateTimeZone.forID("Asia/Kolkata"));
System.out.println(outputFormatter.print(parsed));

或者您可以将 DateTime 转换为另一个时区,使用 withZone() method:

DateTimeFormatter outputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
// convert to Asia/Kolkata
System.out.println(outputFormatter.print(parsed.withZone(DateTimeZone.forID("Asia/Kolkata"))));

两者都将打印:

2017-09-16 10:36:18

在您的代码中,您使用的是 DateTimeZone.getDefault(),它获取 JVM 默认时区(有一些 ). But the default timezone ,因此最好指定您要使用的时区。

此外,请记住像 IST 这样的短名称不是真正的时区。始终喜欢使用 IANA timezones names(始终采用 Region/City 格式,如 Asia/KolkataEurope/Berlin)。

避免使用 3 个字母的缩写(如 ISTPST),因为它们 ambiguous and not standard. Just check in this list IST 可以是 "India Standard Time"、"Israel Standard Time" 和"Irish Standard Time".

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

获取可用时区列表(并选择最适合您的系统的时区)

Java 新 Date/Time API

Joda-Time 处于维护模式,正在被新的 APIs 取代,所以我不建议用它开始一个新项目。即使在 joda's website 它说:"Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. If using Java SE 8, please migrate to java.time (JSR-310).".

如果您不能(或不想)从 Joda-Time 迁移到新的 API,您可以忽略此部分。

在 Android 中你可以使用 ThreeTen Backport, a great backport for Java 8's new date/time classes. To make it work, you'll also need the ThreeTenABP (more on how to use it ).

这个新的 API 每个情况都有 lots of different date/time types

首先,您可以将输入解析为 org.threeten.bp.LocalDateTime,然后我使用 org.threeten.bp.ZoneOffset 将其转换为 UTC,结果为 org.threeten.bp.OffsetDateTime.

然后,我使用 org.threeten.bp.ZoneId 将其转换为另一个时区,并使用 org.threeten.bp.format.DateTimeFormatter 对其进行格式化(这基本上是 的建议 - 只是为了展示如何很简单,因为没有什么不同可做):

// parse to LocalDateTime
OffsetDateTime parsed = LocalDateTime.parse("2017-09-16T05:06:18.157")
    // convert to UTC
    .atOffset(ZoneOffset.UTC);

// convert to Asia/Kolkata
ZoneId zone = ZoneId.of("Asia/Kolkata");
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(outputFormatter.format(parsed.atZoneSameInstant(zone)));

输出为:

2017-09-16 10:36:18