【问题标题】:Java Convert UTC Date to local Date with JodaJava 使用 Joda 将 UTC 日期转换为本地日期
【发布时间】:2018-09-21 06:41:18
【问题描述】:

此代码有效,但我想使用 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();
    }

【问题讨论】:

标签: java jodatime utc localtime


【解决方案1】:

试试这个:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      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

      使用ZonedDateTime 代替java.util.Calendar 来表示通过特定区域(时区)的挂钟时间看到的时刻。

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

      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.DateCalendarSimpleDateFormat

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

      要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

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

      从哪里获得 java.time 类?

      ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多