在Java中将ZoneId应用于日期对象

在Java中将ZoneId应用于日期对象,java,datetime,java-time,timezone-offset,Java,Datetime,Java Time,Timezone Offset,我有以下日期对象2017年11月1日星期三00:00:00 GMT。这显然是在格林尼治时间,但是,我想认为它是在一个不同的时区。 作为一个例子,我想在下面的时区美国/山峰< /代码>中考虑上述日期,然后将其转换为UTC,导致 No.07:07:00:UTC/ 我试图找到一种方法来改变日期的时区,同时保留时间,但失败了 感谢使用java time API,您可以: 将字符串解析为ZoneDateTime 使用ZoneDateTime.WithZoneMaleLocal和ZoneDateTime.W

我有以下日期对象
2017年11月1日星期三00:00:00 GMT
。这显然是在格林尼治时间,但是,我想认为它是在一个不同的时区。

作为一个例子,我想在下面的时区<代码>美国/山峰< /代码>中考虑上述日期,然后将其转换为UTC,导致<代码> No.07:07:00:UTC/<代码> 我试图找到一种方法来改变日期的时区,同时保留时间,但失败了


感谢使用java time API,您可以:

  • 将字符串解析为
    ZoneDateTime
  • 使用
    ZoneDateTime.WithZoneMaleLocal
    ZoneDateTime.WithZoneMaiInstant
    转换结果
  • 大概是这样的:

    DateTimeFormatter fmt = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z uuuu");
    
    ZonedDateTime gmt = ZonedDateTime.parse("Wed Nov 01 00:00:00 GMT 2017", fmt);
    ZonedDateTime mountain = gmt.withZoneSameLocal(ZoneId.of("US/Mountain"));
    ZonedDateTime utc = mountain.withZoneSameInstant(ZoneOffset.UTC);
    
    System.out.println(utc.format(fmt));
    

    顺便说一下,它输出:
    Wed Nov 01 06:00:00 Z 2017
    (DST将仅在11月3日生效)。

    我从您的评论中了解到您有一个
    java.util.Date
    实例。它打印为(例如)
    2017年11月1日星期三00:00:00 GMT
    。这就是它的
    toString
    方法产生的结果。
    日期
    中没有时区。通常
    Date.toString()
    会获取JVM的时区设置并呈现该时区中的日期。看来你在运行格林尼治时间时区?您可以在中阅读更多内容

    如果可以,请避免使用
    日期
    。无论是在一般情况下,还是在像你这样的时区魔术中,与之合作都是非常好的。然后使用

    对于这个答案,我假设您从一些遗留API获得了一个
    日期
    ,您无法更改(或者现在无法更改)。我仍然推荐使用现代API来实现您想要的更改。我在代码中以注释的形式给出以下代码段的输出

        System.out.println(oldFashionedDateObject); // Wed Nov 01 00:00:00 GMT 2017
        // first thing, convert the Date to an instance of a modern class, Instant
        Instant pointInTime = oldFashionedDateObject.toInstant();
        // convert to same hour and minute in US/Mountain and then back into UTC
        ZonedDateTime convertedDateTime = pointInTime.atOffset(ZoneOffset.UTC)
                .atZoneSimilarLocal(ZoneId.of("US/Mountain"))
                .withZoneSameInstant(ZoneOffset.UTC);
        System.out.println(convertedDateTime); // 2017-11-01T06:00Z
    
        // only assuming you absolutely and indispensably need an old-fashioned Date object back
        oldFashionedDateObject = Date.from(convertedDateTime.toInstant());
        System.out.println(oldFashionedDateObject); // Wed Nov 01 06:00:00 GMT 2017
    

    作为亚西莉亚,我得到了
    11月1日星期三06:00:00
    。根据今年11月5日结束的夏季时间(DST)。

    您使用java.util.Date还是java.time.LocalDate?我使用java.util。Date@AdrianDanielCulea,那就别再那样做了。对不起,我无法抗拒。说真的,现代的Java日期和时间API非常好用,我建议更改.BTW,
    Java.util.date
    对象不是GMT格式的。它没有时区,也没有偏移量,它只是时间线上的一个点。正是它的
    toString
    方法愚弄了你(和许多其他人)让你相信里面有一个区域。顺便说一句,java时间标签指的是
    java.time
    API,所以如果你不是有意的,标签的用法是不正确的。您可能需要添加java.util.date标记。不过,我还是建议您开始使用
    java.time