繁体   English   中英

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

[英]Java Convert UTC Date to local Date with Joda

这段代码有效,但是我想使用Joda-Time

public static Date dateFromUTC(Date date){
        return new Date(date.getTime() + Calendar.getInstance().getTimeZone().getOffset(date.getTime()));
    }

我试过了,但是没有用-这是什么问题?

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

尝试这个:

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

您的代码实际上对日期不执行任何操作,因为new DateTime(date)创建具有默认时区的DateTime对象。 然后将其转换回java.util.Date

首先,请阅读注释中链接的文章: 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没有时区。

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 †表示 ,从未在其他时区中表示。 因此,在Question中看到的代码是荒谬的。 你太辛苦了!

java.time

Joda-Time项目现在处于维护模式 ,团队建议迁移到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的格式指定正确的时区名称 ,例如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及更高版本中。 这些类取代了麻烦的旧的旧式日期时间类,例如java.util.DateCalendarSimpleDateFormat

现在处于维护模式Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参见Oracle教程 并在Stack Overflow中搜索许多示例和说明。 规格为JSR 310

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

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。 该项目为将来可能在java.time中添加内容提供了一个试验场。 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM