【问题标题】:Conversion to java.sql.Date转换为 java.sql.Date
【发布时间】:2017-09-18 09:41:35
【问题描述】:

我有一个String如下,需要转换成java.sql.Date格式:

2017-08-31 01:40:00+00:00

我使用下面的代码,我可以看到日期只被解析为2017-08-31,而不是上面的整个字符串。有人可以推荐吗?

java.util.Date utilDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(dateTimeStamp);

java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());

根据答案中的建议,我在下面实现:

String dateTimeStamp = "2017-08-31 01:40:00+00:00";
java.text.DateFormat format = new java.text.SimpleDateFormat("yyyy-MM-dd hh:mm:ssZZ");
java.util.Date date = format.parse(dateTimeStamp);
java.sql.Timestamp timestamp = new java.sql.Timestamp(date.getTime());
System.out.println("timestamp - " + timestamp);

但是,出现以下错误:

java.text.ParseException: Unparseable date: "2017-08-31 01:40:00+00:00"
        at java.text.DateFormat.parse(DateFormat.java:366)
        at com.eneco.mysqlsink.WeatherForecastSink.WeatherForecastTask.put(WeatherForecastTask.java:94)
        at org.apache.kafka.connect.runtime.WorkerSinkTask.deliverMessages(WorkerSinkTask.java:435)
        at org.apache.kafka.connect.runtime.WorkerSinkTask.poll(WorkerSinkTask.java:251)
        at org.apache.kafka.connect.runtime.WorkerSinkTask.iteration(WorkerSinkTask.java:180)
        at org.apache.kafka.connect.runtime.WorkerSinkTask.execute(WorkerSinkTask.java:148)
        at org.apache.kafka.connect.runtime.WorkerTask.doRun(WorkerTask.java:146)
        at org.apache.kafka.connect.runtime.WorkerTask.run(WorkerTask.java:190)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)

【问题讨论】:

  • 您需要java.sql.Date 做什么?如果它用于您的数据库,请注意您可能会获得(或已经拥有)一个更新的 JDBC 驱动程序,它可以让您从数据库中检索 java.time.LocalDate 对象并将相同的类型存储到其中。如果是这样,我建议你废弃 java.sql 中的过时类,而改用 java.time 中的现代类。

标签: java simpledateformat date-parsing date


【解决方案1】:

java.sql.Date 只提供日期。您需要使用java.sql.Timestamp 来获取日期和时间。

java.text.DateFormat format = new java.text.SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
java.util.Date date = format.parse("2017-08-31 01:40:00+00:00");
java.sql.Timestamp timestamp = new java.sql.Timestamp(date.getTime());
System.out.println(timestamp);

【讨论】:

    【解决方案2】:

    您正在使用hh 模式,它对应于hour-of-am-pm field(值从1 到12)。由于输入没有 AM/PM 指示符,因此这不会总是按预期工作。您必须将其更改为 HHhour-of-day,值从 0 到 23)。

    另外,要解析偏移量+00:00,您需要使用X 模式:

    String input = "2017-08-31 01:40:00+00:00";
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssX");
    // java.util.Date
    Date date = sdf.parse(input);
    

    X 模式是在 Java 7 中引入的。如果您使用的是旧版本,您还可以在格式化程序中设置 UTC 时区:

    // "X" is not supported
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    // set UTC in the formatter
    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
    // java.util.Date
    Date date = sdf.parse(input);
    

    这更糟糕,因为您需要知道输入的偏移量并将其设置在格式化程序中。所以如果支持的话最好使用X

    然后你可以从java.util.Date创建sql日期:

    java.sql.Date sqlDate = new java.sql.Date(date.getTime());
    java.sql.Timestamp timestamp = new Timestamp(date.getTime());
    

    但请注意,如果您只是System.out.println sql 日期或时间戳,它们将被转换为 JVM 默认时区(给您的印象是错误的:请参阅this article 了解更多详细信息)。

    另外,请记住 java.sql.Date 只是 keeps the date fields(日/月/年),将小时数设置为零(因此 01:40 丢失)。另一方面,java.sql.Timestamp 保留了 whole UTC millis value


    Java 新的日期/时间 API

    旧的类(DateCalendarSimpleDateFormat)有 lots of problemsdesign issues,它们正在被新的 API 取代。

    如果您使用的是 Java 8,请考虑使用 new java.time API。更简单,less bugged and less error-prone than the old APIs

    如果您使用的是 Java 6 或 7,则可以使用 ThreeTen Backport,这是 Java 8 新日期/时间类的一个很好的向后移植。对于Android,您还需要ThreeTenABP(更多关于如何使用它here)。

    下面的代码适用于两者。 唯一的区别是包名(在 Java 8 中是 java.time,在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp),但类和方法 names 是相同的。

    首先您将输入解析为OffsetDateTime,使用DateTimeFormatter 指定格式:

    String input = "2017-08-31 01:40:00+00:00";
    
    DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssXXX");
    OffsetDateTime odt = OffsetDateTime.parse(input, fmt);
    

    然后就可以转换成sql类型了。在 Java 8 中,有内置的方法可以做到这一点:

    java.sql.Date sqlDate = java.sql.Date.valueOf(odt.toLocalDate());
    java.sql.Timestamp sqlTimestamp = java.sql.Timestamp.from(odt.toInstant());
    

    在 Java 7 中,ThreeTen Backport 具有 org.threeten.bp.DateTimeUtils 类:

    java.sql.Date sqlDate = DateTimeUtils.toSqlDate(odt.toLocalDate());
    java.sql.Timestamp sqlTimestamp = DateTimeUtils.toSqlTimestamp(odt.toInstant());
    

    【讨论】:

      【解决方案3】:

      您需要在格式中包含时区标识符

      java.util.Date utilDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ssZZ").parse(dateTimeStamp);
      java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime()); 
      

      【讨论】:

        【解决方案4】:

        要获得timestamp,只需使用java.sql.Timestamp 而不是java.sql.Date

        java.sql.Timestamp 对象的toString() 方法应该根据需要返回字符串。

        【讨论】:

          【解决方案5】:

          您使用的格式很好,但您丢失了时区偏移量。

          如果您想考虑时区偏移,请使用以下格式。

          java.util.Date utilDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").parse(dateTimeStamp);
          

          结果:

          utilDate = 2017 年 8 月 31 日星期四 01:40:00 IST

          java.util.Date utilDate = new SimpleDateFormat("yyyy-MM-dd hh:mm:ssX").parse(dateTimeStamp);
          

          结果:

          utilDate = 2017 年 8 月 31 日星期四 07:10:00 IST。

          我正在从印度运行此代码,时区有 05:30 小时的偏移量。

          【讨论】:

            猜你喜欢
            • 2011-08-29
            • 2017-07-13
            • 2013-01-27
            • 2021-05-27
            • 2016-02-14
            • 1970-01-01
            • 1970-01-01
            • 2018-08-22
            • 2013-04-17
            相关资源
            最近更新 更多