Java:如何将UTC时间戳转换为本地时间?

2022-09-01 00:25:42

我有一个 UTC 时间戳,我想将其转换为本地时间,而不使用 API 调用,如 .你到底应该如何做到这一点?我一直在使用以下代码,但没有取得多大成功:TimeZone.getTimeZone("PST")

private static final SimpleDateFormat mSegmentStartTimeFormatter = new        SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");

Calendar calendar = Calendar.getInstance();

    try {
        calendar.setTime(mSegmentStartTimeFormatter.parse(startTime));
    }
    catch (ParseException e) {
        e.printStackTrace();
    }

    return calendar.getTimeInMillis();

示例输入值:[2012-08-15T22:56:02.038Z]

应返回等效值[2012-08-15T15:56:02.038Z]


答案 1

Date没有时区,内部存储在 UTC 中。仅当设置日期格式时,才会应用时区更正。使用 时,它默认为运行它的 JVM 的时区。用于根据需要更改它。DateFormatsetTimeZone

DateFormat utcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
utcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));

Date date = utcFormat.parse("2012-08-15T22:56:02.038Z");

DateFormat pstFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
pstFormat.setTimeZone(TimeZone.getTimeZone("PST"));

System.out.println(pstFormat.format(date));

这打印2012-08-15T15:56:02.038

请注意,我省略了 PST 格式中的 ,因为它表示 UTC。如果你只是去,那么输出将是'Z'Z2012-08-15T15:56:02.038-0700


答案 2

使用现代Java日期和时间API,这很简单:

    String inputValue = "2012-08-15T22:56:02.038Z";
    Instant timestamp = Instant.parse(inputValue);
    ZonedDateTime losAngelesTime = timestamp.atZone(ZoneId.of("America/Los_Angeles"));
    System.out.println(losAngelesTime);

这打印

2012-08-15T15:56:02.038-07:00[America/Los_Angeles]

注意事项:

  • 你的期望中有一个小错误。时间戳中的表示 UTC,也称为祖鲁时间。因此,在本地时间值中,不应该存在。相反,您需要一个返回值,例如,因为偏移量现在是-7小时而不是Z。ZZ2012-08-15T15:56:02.038-07:00
  • 避免使用三个字母的时区缩写。它们不是标准化的,因此通常是模棱两可的。例如,PST可能意味着Philppine Standard Time,Pacific Standard Time或Pitcairn Standard Time(尽管缩写中的S通常表示夏季时间(意思是DST))。如果您打算使用太平洋标准时间,则它甚至不是时区,因为在夏季(您的示例时间戳所在的位置),而是使用太平洋夏令时。而不是缩写使用时区ID格式的区域/城市,如我的代码中。
  • 时间戳通常最好作为对象处理。仅在您有需要时才转换为,例如用于演示。InstantZonedDateTime

问:我可以在 Java 版本中使用现代 API 吗?

如果至少使用Java 6,则可以。

  • 在Java 8及更高版本中,新的API是内置的。
  • 在Java 6和7中,获得ThreeTen Backport,即新类的向后移植(这是JSR-310的ThreeTen,其中首先定义了现代API)。
  • 在 Android 上,使用 Android 版本的 ThreeTen Backport。它被称为ThreeTenABP,我认为这个问题有一个很好的解释:如何在Android项目中使用ThreeTenABP