Android UTC日期字符串到本地日期

时间:2018-04-17 16:10:25

标签: java android timezone utc datetime-conversion

我在Android中将UTC日期字符串转换为本地日期字符串时遇到问题。例子是, 我已将UTC日期字符串输入为2018-02-28T02:42:41Z

我在PST时区,但当我尝试转换为本地时区时,它并没有改变。我得到February 28, 2018 02:42 AM这是不正确的。

public static String convertUTCtoLocalTime(String utcDateString) throws Exception{

    SimpleDateFormat dateFormatter;

    //create a new Date object using the UTC timezone
    Log.v(TAG, "Input utc date:" + utcDateString);
    dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
    dateFormatter.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date utcDate = dateFormatter.parse(utcDateString);

    //Convert the UTC date to Local timezone
    dateFormatter = new SimpleDateFormat("MMMM dd, yyyy hh:mm a");
    dateFormatter.setTimeZone(TimeZone.getDefault());
    String formattedDate = dateFormatter.format(utcDate);
    Log.v(TAG, "convertUTCtoLocalTime: local time:" + formattedDate);

    return lv_dateFormateInLocalTimeZone;
}

我并不完全理解其中的差异,但类似的转换工作在" swift"如下图所示,

    static func utcDateToLocal(utcdate: String) -> String {
      let dateFormatter = DateFormatter()

      dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ" //Input Format 2018-02-28T02:42:41Z
      dateFormatter.timeZone = NSTimeZone(name: "UTC")! as TimeZone
      let UTCDate = dateFormatter.date(from: utcdate)

      dateFormatter.dateFormat = "MMMM dd, yyyy hh:mm a" // Output Format
      dateFormatter.timeZone = TimeZone.current
      let UTCToCurrentFormat = dateFormatter.string(from: UTCDate!)
      return UTCToCurrentFormat
  }

Swift的例子让我" 2018年2月27日06:42 PM"这是正确的。

Swift正在使用v3.x和

Android是Studio 3.1.1 Build#AI-173.4697961,建于2018年4月3日 JRE:1.8.0_152-release-1024-b01 x86_64 JVM:JetBrains s.r.o的OpenJDK 64位服务器VM Mac OS X 10.13.4

我在同一台机器上运行这两个示例。 任何在Android上解决问题的提示都非常有用。

1 个答案:

答案 0 :(得分:1)

static DateTimeFormatter formatter = DateTimeFormatter
        .ofLocalizedDateTime(FormatStyle.LONG, FormatStyle.SHORT)
        .withLocale(Locale.US);

public static String convertUTCtoLocalTime(String utcDateString) {

    Log.v(TAG, "Input utc date:" + utcDateString);

    String formattedDateTime = Instant.parse(utcDateString)
            .atZone(ZoneId.systemDefault())
            .format(formatter);

    Log.v(TAG, "convertUTCtoLocalTime: local time:" + formattedDateTime);

    return formattedDateTime;
}

试一试:

    System.out.println(convertUTCtoLocalTime("2018-02-28T02:42:41Z"));

输出:

  

2018年2月27日,下午6:42

使用内置的本地化格式,而不是构建自己的格式模式字符串。它可以确保格式适合所讨论的语言环境,它也适用于其他语言环境,它可以使您免于编写正确格式模式字符串的容易出错的任务。在美国语言环境中,长日期格式为您提供完整的月份名称(不仅仅是“2月”),短时间格式为您提供没有秒数的时间。结合我理解你想要的字符串。

Instant类在没有任何显式格式化程序的情况下解析您的UTC字符串,这再次使您无法构建格式模式字符串。格式为ISO 8601. Instant类和我使用的其他日期时间类是java.time(现代Java日期和时间API)的一部分。这些类将ISO 8601解析为默认值。通常,现代API可以更好地使用。

您的代码出了什么问题?

您的转换是正确的。当我在计算机上运行它时,它将以下字符串传递给Log.v()convertUTCtoLocalTime: local time:February 27, 2018 06:42 PM。我相信这就是你的期望。我只能看到两个潜在的问题:

  1. 如果您的默认时区(从TimeZone.getDefault()获得 - 不是您认为的那样),您将得到错误的结果。但是,在这种情况下,您的Swift代码可能会产生相同的错误结果,而我上面的代码肯定会。
  2. 您的退货声明是:

         return lv_dateFormateInLocalTimeZone;
    

    您之前未触及名为lv_dateFormateInLocalTimeZone的变量,因此此变量无法保存您的格式化日期时间。要返回它,你需要

         return formattedDate;
    
  3. 问题:我可以在Android上使用java.time吗?

    是的,java.time适用于较旧和较新的Android设备。它只需要至少Java 6

    • 在Java 8及更高版本和更新的Android设备上(来自API级别26,我被告知)现代API内置。
    • 在Java 6和7中获取ThreeTen Backport,新类的后端端口(适用于JSR 310的ThreeTen;请参阅底部的链接)。
    • On(较旧)Android使用Android版的ThreeTen Backport。它被称为ThreeTenABP。并确保使用子包从org.threeten.bp导入日期和时间类。

    链接