1

尝试使用 JSR 310 在时区之间转换毫秒日期时间值。需要处理毫秒值,才能使用旧版 API。就我而言,它介于本地和 UTC/GMT 之间,但我希望它是完全相同的代码,而与所涉及的源时区和目标时区无关。这是我的小测试程序。它被配置为在最后一次本地 DST 更改前后的几个小时内进行迭代。输出是错误的,所以我认为 UTCtoLocalMillis 是错误的,但我的测试方法也可能存在问题。我所说的错误输出的意思是,对于我的时区,应该减去小时以获得 UTC,但代码实际上增加了小时。其次,夏令时的时间点也相差一小时。

我首先获取本地时区,然后将其重置为 UTC,这样 Date().toString() 在创建输出时不会执行任何转换。

我想要的是创建一个以毫秒为单位的方法,一个源 ZoneID 和一个目标 ZoneID,并使用新的 JSR 310 API 返回转换后的毫秒数。

public class Test {
static int DAYS_OFFSET_TO_BE_BEFORE_DST_CHANGE = -16;

static TimeZone UTC_TZ = TimeZone.getTimeZone("UTC");

static TimeZone LOCAL_TZ = TimeZone.getDefault();

static ZoneId UTC_ID = ZoneId.of(UTC_TZ.getID());

static ZoneId LOCAL_ZONE_ID = ZoneId.of(LOCAL_TZ.getID());

static long UTCtoLocalMillis(final long utcMillis) {
    final Instant instant = Instant.ofEpochMilli(utcMillis);
    final ZonedDateTime before
        = ZonedDateTime.ofInstant(instant, UTC_ID);
    final ZonedDateTime after
        = before.withZoneSameLocal(LOCAL_ZONE_ID);
    return after.toInstant().toEpochMilli();
}

public static void main(final String[] args) {
    TimeZone.setDefault(UTC_TZ);
    System.out.println("LOCAL_TZ: " + LOCAL_TZ.getDisplayName());
    final Calendar cal = Calendar.getInstance(LOCAL_TZ);
    cal.add(Calendar.DATE, DAYS_OFFSET_TO_BE_BEFORE_DST_CHANGE);
    final Date start = cal.getTime();
    // DST Change: Sunday, 31 March 2013 01:59:59 (local time)
    final long oneHour = 3600000L;
    for (int i = 0; i < 12; i++) {
        final Date date = new Date(start.getTime() + i * oneHour);
        System.out.println("UTC: " + date + "   toLocal: "
                + new Date(UTCtoLocalMillis(date.getTime())));
    }
}
}
4

2 回答 2

3

我想要的是创建一个以毫秒为单位的方法,一个源 ZoneID 和一个目标 ZoneID,并使用新的 JSR 310 API 返回转换后的毫秒数。

您的要求似乎很混乱。时间 APIs 中一般提到的“毫秒”值是 epoch-millis,即从 1970-01-01T00:00Z 开始的毫秒数。毫秒值始终与 UTC 相关。虽然有“本地毫秒”的概念,但它从未真正使用过。特别是,java.util.Date 构造函数采用 epoch-millis。

因此,代码new Date(UTCtoLocalMillis(date.getTime()))基本上没有意义。

于 2013-04-16T09:48:48.513 回答
2
于 2018-09-30T22:41:00.237 回答