【问题标题】:How to Convert String(2017-08-01T15:15:03.313000000+02:00) to TimeStamp如何将字符串(2017-08-01T15:15:03.313000000+02:00)转换为时间戳
【发布时间】:2018-01-24 10:42:39
【问题描述】:
 String str = "2017-08-01T15:15:03.313456768+02:00";
 // The following statement gives IllegalArgumentExceptionTimestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
 Timestamp timeStamp = Timestamp.valueOf(str);
 ZonedDateTime zoneddate = ZonedDateTime.parse(str);
 System.out.println("ZonedDate: "+zoneddate);// prints 2017-08-01T15:15:03.313456768+02:00
 Instant inst = zoneddate.toInstant();
 Timestamp newTime = Timestamp.from(inst);
 System.out.println("Timestamp: "+newTime);// prints 2017-08-01 15:15:03.313456768 without Zone

我在转换期间缺少区域。谁能建议我如何在TimeStamp 中获得区域?

【问题讨论】:

  • 我已经红了,但 SimpleDateFormat 不接受 9 位毫秒。
  • SimpleDateFormat 具有毫秒精度(小数点后只有 3 位)。对于 3 位以上的数字,您必须使用 Java 8 新的java.time API:stackoverflow.com/questions/30135025/…
  • 该区域没有丢失。 Timestamp 只是保持自 1970-01-01T00:00Z 以来的纳秒数,它没有时区。当你打印它时,toString() 方法被隐式调用,并且这个方法将值调整为 JVM 默认时区(检查TimeZone.getDefault() 的值,你可能在当前偏移量为+02:00 的区域中) .您所做的转换是正确的,您可以使用zoneddate.toInstant().equals(newTime.toInstant())(它将是true)进行检查。而且也可以认为是this的复制品
  • 每个数据库对时间戳/日期类型的工作方式不同,您必须在各自的文档中查看如何操作、如何保留时区信息、如何不丢失精度等。而且您还误认为 value(自 1970-01-01T00:00Z 以来的纳秒数)与 representation(显示日/月/年/小时/分钟/等的值一些特定的区域)。存储的 通常是相同的(纳秒数)。在向用户显示此时,您选择一种格式(此值的表示)。而且这种格式可以有也可以没有。
  • 我推荐this article - 它谈到java.util.Date,但Timestamp 是相似的(实际上它扩展了Date),所以所有概念都适用于两者。

标签: java timestamp datetime-parsing


【解决方案1】:

这个问题的最新版本是这样的:

谁能建议我如何获得时间戳中的区域

简单的答案是你不能。 Timestamp 不包含区域作为其表示的一部分。当您从 ZonedDateTime 转换生成 Timestamp 时,您丢弃时区偏移量。

您可以通过查看Timestamp 类的源代码来验证这一点。没有允许您传入时区信息的构造函数,并且日期/时间表示为 UTC。 (getTimezoneOffset() 方法返回不同的东西......无论如何该方法已被弃用。)

...但我必须在数据库中保留时间戳,它必须显示区域。

然后你需要使用不同的 SQL 类型(或类型)来表示时间戳,以及 Java 端的相应类型。请注意,某些 SQL 方言不会将时区信息存储在标准 DATE / TIME / TIMESTAMP 类型中。

【讨论】:

    【解决方案2】:

    Stephen C 的答案是正确的。

    避免使用麻烦的旧日期时间类,例如java.sql.Timestamp。现在被 java.time 类所取代。

    您有一个标准 ISO 8601 格式的字符串,表示一个与 UTC 有偏移但没有时区指示的日期时间。所以解析为OffsetDateTime。以 Instant 的形式移入 UTC 进行存储。

    检索后,指定您希望的任何时区。

    String input = "2017-08-01T15:15:03.313456768+02:00";
    OffsetDateTime odt = OffsetDateTime.parse( input ) ;
    Instant instant = odt.toInstant() ;  // Adjust into UTC for storage. 
    myPreparedStatement.setObject( … , instant ) ;
    

    检索。

    Instant instant = myResultSet.getObject( … , Instant.class ) ;
    ZoneId z = ZoneId.of( "America/Montreal" ) ;  // or "Europe/Berlin",  "Asia/Kolkata", whatever. 
    ZonedDateTime zdt = instant.atZone( z ) ;  // Move from UTC to a time zone.
    

    关于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
      • 2016-08-03
      • 2016-09-10
      • 2019-09-27
      • 1970-01-01
      • 1970-01-01
      • 2018-02-06
      • 2018-02-17
      • 1970-01-01
      相关资源
      最近更新 更多