Java使用Joda将UTC日期转换为本地日期

时间:2018-04-11 11:33:57

标签: java jodatime utc localtime

此代码正常运行,但我想使用Joda-Time

public static Date dateFromUTC(Date date){
        return new DateTime(date).withZone(DateTimeZone.getDefault()).toDate();
    }

我尝试了这个,但它没有用 - 这有什么问题?

{{1}}

3 个答案:

答案 0 :(得分:1)

试试这个:

new DateTime(date, DateTimeZone.UTC)
    .toLocalDateTime() // value without timezone
    .toDateTime() // convert to default timezone
    .toDate();

您的代码实际上对日期没有任何作用,因为new DateTime(date)使用默认时区创建DateTime对象。然后你只需将它转换回java.util.Date

答案 1 :(得分:1)

首先,请阅读评论中链接的文章:https://codeblog.jonskeet.uk/2017/04/23/all-about-java-util-date/

java.util.Date没有时区。它实际上代表了一个时间点:自unix时代(1970年1月1日,午夜,UTC)以来的毫秒数。

当您打印Date时,使用 JVM默认时区将Date转换为日期/时间值,但Date本身没有时区。

这就是将Date对象转换为另一个时区的原因没有意义。

如果您想知道与特定时区中的Date对应的日期(日,月,年)和时间(小时,分钟,秒,毫秒),那么您可以使用Joda-Time:

// java.util.Date
Date date = new Date();

// the Date converted to UTC
DateTime utc = new DateTime(date, DateTimeZone.UTC);

// the Date converted to JVM default timezone
DateTime convertedToDefaultTz= new DateTime(date, DateTimeZone.getDefault());

转换也可以使用其他DateTime

进行
DateTime convertedToDefaultTz = utc.withZone(DateTimeZone.getDefault());

Joda的DateTime附加了一个时区,所以现在转换到另一个时区是有意义的。但是它返回的Date对象将始终是相同的,因为它们都代表同一时刻(时间轴中的相同点):

Date d1 = utc.toDate();
Date d2 = convertedToDefaultTz.toDate();
System.out.println(d1.equals(d2)); // true

所有因为 - 再次 - Date没有时区。

答案 2 :(得分:1)

TL;博士

改为使用 java.time 类。

Instant.now()        // Capture current moment in UTC. Always in UTC, by definition.

...和...

ZonedDateTime.now()  // Capture current moment as seen through the wall-clock time of the people in the region of the time zone used by default in this JVM.

详细

正如其他人所说,你误解了这些课程中涉及的概念。 java.util.Date代表UTC的时刻,始终在UTC ,从不在其他时区。因此,问题中看到的代码是非感性的。你工作太辛苦了!

java.time

Joda-Time项目现在位于maintenance mode,团队建议迁移到java.time课程。许多概念在Joda-Time和java.time之间是相似的,因为这两个项目都由同一个人Stephen Colebourne领导。

准备好迁移后,请使用Instant代替java.util.Date

Instant instant = Instant.now() ;  // Capture the current moment in UTC.
  

instant.toString():2018-01-23T12:34:56.123456789Z

而不是java.util.Calendar,使用ZonedDateTime来表示在特定区域(时区)的挂钟时间内看到的时刻。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;  // Same moment, same point on the timeline, different wall-clock time.

作为一种快捷方式,如果您只想要分区时间,可以跳过Instant

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Capture the current moment as seen by people in a certain time zone.

您可以通过提取Instant对象从那里获取UTC。

Instant instant = zdt.toInstant() ;  // Same moment, same point on the timeline, but viewed with the wall-clock time of UTC.

实际上,java.util.Date内深度分配的时区,但与我们在此讨论无关。混乱?是。其中一个很多原因可以避免旧的Date / Calendar以及相关的旧日期时间类的可怕混乱。

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore