【问题标题】:Convert datatime and insert in MySQL转换日期时间并在 MySQL 中插入
【发布时间】:2018-06-05 22:55:14
【问题描述】:

我必须导入一个包含 120k 行的 CVS 文件。前 6 列分别包含日期和时间,即:年、月、日、小时、分钟、秒。

我将它们导入 Java:

int year = 2016
int month = 5
int day = 23
int hour = 15
int minutes = 57
int seconds = 22 

如何将此格式转换为与 MySQL (DATETIME) 兼容的格式?

我还有一个 GMT 列,即“GMT +0200”。我也可以在 DATETIME 内转换这些数据吗?

【问题讨论】:

  • 专栏的data type 是什么? DATETIME? TIMESTAMP?

标签: java mysql database datetime type-conversion


【解决方案1】:

您可以这样做的一种方法是以这种格式构建您的字符串:

yyyy-MM-DD HH:mm:ss

然后插入它。

INSERT INTO yourtable VALUES('2016-05-23 15:57:22')

【讨论】:

    【解决方案2】:
    String datetime = String.format("%s-%s-%s %s:%s:%s", year, month, day, hour, minutes, seconds);
    

    这将为您生成DATETIME

    【讨论】:

      【解决方案3】:

      tl;博士

      myPreparedStatement.setObject( 
          … , 
          ZonedDateTime.of( 2016 , 5 , 23 , 15 , 57 , 22 , 0 , ZoneId.of( "Africa/Casablanca" ) )
      ) ;
      

      详情

      使用 java.time 类和 driver 支持 JDBC 4.2 或更高版本的 MySQL 5.7 TIMESTAMP 列...

      时区

      确定适用于该日期时间的时区。 没有时区,日期时间没有确切的含义。例如,法国巴黎的中午比魁北克蒙特利尔的中午要早得多。

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

      ZoneId z = ZoneId.of( "America/Montreal" );
      

      ZonedDateTime & Instant

      使用您的输入和时区来实例化 ZonedDateTime 以表示时间轴上的某个时刻。

      ZonedDateTime zdt = ZonedDateTime.of( 2016 , 5 , 23 , 15 , 57 , 22 , 0 , z ) ;
      

      提取与 UTC 值相同的时刻。

      Instant instant = zdt.toInstant() ;
      

      发送到数据库。

      myPreparedStatement.setObject( … , instant ) ;
      

      然后检索。

      Instant instant = myResultSet.getObject( … , Instant.class ) ;
      ZonedDateTime zdt = instant.atZone( z ) ;
      

      关于java.time

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

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

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

      从哪里获得 java.time 类?

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

      【讨论】:

      • 这在各方面都是首选方式。使用数据时间类型而不是字符串可以告诉读者您正在处理什么,并且可以免费为您提供数据验证。优势不容小觑。最重要的是,代码更易于阅读。
      • 感谢您的详细回答。我现在才看到我在 csv 中有一个列,其中存储了一个“GMT”值,即“GMT +0200”。这是转换后的时区吗?还是不行?
      • 是的,或者更准确地说,是时区偏移量(在许多时区中,偏移量在一年中发生变化和/或在历史上已经改变,并且将来可能会再次发生)。您可能应该找到一种解析它的方法。
      • @Simon, ZoneOffset.from(DateTimeFormatter.ofPattern("'GMT' xx").parse("GMT +0200")) 给你一个ZoneOffset 对象,你可以用它来构造一个OffsetDateTime
      • @Simon 编辑您的问题以包含所有相关详细信息,我将更新我的答案以显示OffsetDateTime 类的使用。并且,在未来,请尝试更彻底、更好地准备好所有详细信息在此处发布之前,因为 Stack Overflow 意味着更正式,更像 Wikipedia,而不是随意的讨论板。并通过编辑您的问题以记录您的列的数据类型来回应我对您问题的评论。
      【解决方案4】:

      我(也)建议您为此使用java.time。由于您与 UTC 有一个偏移量(为了我们的目的,UTC 和 GMT 可以被认为是等效的),声明一个格式化程序来解析它:

      private static final DateTimeFormatter gmtOffsetFormatter 
              = DateTimeFormatter.ofPattern("'GMT' xx");
      

      然后创建一个OffsetDateTime 对象:

          ZoneOffset offset = ZoneOffset.from(gmtOffsetFormatter.parse(gmtOffsetString));
          OffsetDateTime dateTime 
                  = OffsetDateTime.of(year, month, day, hour, minutes, seconds, 0, offset);
          System.out.println(dateTime);
      

      也许这并不奇怪

      2016-05-23T15:57:22+02:00
      

      据我了解,您的数据库列的数据类型为 datetime,它不允许存储偏移量。您可能需要考虑使用timestamp 列。对于datetime,您至少需要知道(或决定)在哪个偏移量或哪个时区来解释数据库值。要将您的日期时间转换为您决定的数据库偏移量:

          LocalDateTime dateTimeWithoutOffset = dateTime
                  .withOffsetSameInstant(ZoneOffset.UTC)
                  .toLocalDateTime();
      

      我以 UTC 作为典型和推荐的例子。我正在转换为LocalDateTime,因为我认为这是存储到datetime 列中的合适类型,但这不是我的家乡,我可能弄错了。 sn-p 结果为2016-05-23T13:57:22,这是我们的日期时间的 UTC 等价物。要存储到数据库中,请关注Basil Bourque’s answerPreparedStatement.setObject() 很高兴接受LocalDateTime

      如果您可以将列类型更改为 timestamp,请将 Instant 存储到其中,如 Basil Bourque 的回答中所示。

          Instant inst = dateTime.toInstant();
      

      结果是2016-05-23T13:57:22Z,因为Instant.toString() 生成一个UTC 字符串。 timestampInstant 的优点是它们表示时间线上的明确点,因此您和维护代码的人员都无需再担心时区或偏移量。

      【讨论】:

        猜你喜欢
        • 2017-07-08
        • 1970-01-01
        • 2018-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-05
        相关资源
        最近更新 更多