【问题标题】:Add some hours/mins to current datetime and get the future datetime将一些小时/分钟添加到当前日期时间并获取未来的日期时间
【发布时间】:2019-09-18 17:05:43
【问题描述】:

我需要获取特定时间的未来时间戳值。我必须在当前日期时间时间戳中添加一个字符串值并获取未来的时间戳值。

我正在获取当前时间戳,如下所示:

Timestamp timestamp = new Timestamp(System.currentTimeMillis());

我有一个字符串值为"02:00:00",所以基本上我需要在这个时间上加上2小时,得到需要插入的未来时间戳值。

例如,如果当前时间戳是:2019-04-29 16:59:21.43 和字符串是"02:00:00"
我需要输出为2019-04-29 18:59:21.43

有人可以帮忙

【问题讨论】:

  • java.sql.Timestamp 类在几年前被 java.time.OffsetDateTime 类取代,从 JDBC 4.2 开始。
  • 使用诸如"02:00:00"之类的时间字符串格式来表示时间跨度是一种糟糕的方法,令人困惑(模棱两可)并且容易出错。了解日期时间工作的标准 ISO 8601 格式。两个小时是PT2H

标签: java mysql string date datetime


【解决方案1】:

你可以这样做

    Instant now = Instant.now();
    Duration diff = Duration.between(
            LocalTime.MIN,
            LocalTime.parse("02:00:00")
    );
    Instant res = now.plus(diff);

    System.out.println("res = " + Timestamp.from(res));

【讨论】:

  • 请不要使用LocalTime 作为持续时间。它不是一个,因此如果添加的数量为 24:00:00 或更大,它会导致混乱并崩溃。我知道在不使用LocalTime 的情况下将02:00:00 转换为Duration 需要更多时间,但这仍然是正确的做法。
  • 除了使用现代 Java 日期和时间 API java.time 中的 InstantDuration 之外,这是一个很好的建议。
【解决方案2】:

您可以使用 MySQL 函数 TIMESTAMP 将给定的时间字符串添加到您的时间戳值:

TIMESTAMP(expr), TIMESTAMP(expr1,expr2)

使用单个参数,此函数返回日期或日期时间 表达式 expr 作为日期时间值。有两个参数,它添加了 时间表达式 expr2 到日期或日期时间表达式 expr1 和 将结果作为日期时间值返回。

mysql> SELECT TIMESTAMP('2003-12-31 12:00:00','12:00:00');
-> '2004-01-01 00:00:00'

Reference

【讨论】:

    【解决方案3】:

    tl;博士

    插入两个小时后的时刻。

    myPreparedStatement                     // Use a `PreparedStatement` to exchange data with your database, to avoid SQL-injection risk. Use JDBC 4.2 or later for *java.time* support.
    .setObject(                             // Fill a placeholder `?` in your SQL statement.
        … ,                                 // Specify which placeholder. 
        OffsetDateTime                      // Use `OffsetDateTime` to specify a moment in JDBC 4.2. Optionally, your JDBC might support `Instant` or `ZonedDateTime` types, while support for `OffsetDateTime` is required.
        .now(                               // Capture the current moment.
            ZoneOffset.UTC                  // Set the offset-from-UTC to zero. We do not need to account for any time zone in this particular business scenario.
        )                                   // Returns an `OffsetDateTime` object.
        .plus(                              // Adds a span-of-time to the moment held in the `OffsetDateTime` object.
            Duration.parse( "PT2H" )        // Specify the span-of-time using standard ISO 8601 format for a duration.
        )                                   // Per Immutable Objects pattern, returns a new `OffsetDateTime` rather than changing ("mutating") the original.
    )                          
    

    详情

    我有一个字符串值为“02:00:00”,所以基本上我需要在这个时间上加上2小时,得到需要插入的未来时间戳值

    这是传达未附加到时间线的时间跨度的糟糕方式。

    standard wayPnYnMnDTnHnMnS,其中P 标志着开始,T 将年-月-日与小时-分钟-秒分开。所以 2 小时是PT2H

    要解析这样的字符串,请使用 Duration 类表示小时-分钟-秒(或 Period 表示年-月-日)。

    String input = "PT2H" ;
    Duration d = Duration.parse( input ) ;
    

    你可以生成这样的字符串。

    String output = Duration.ofHours( 2 ).toString() ;  // Yields "PT2H" string.
    

    捕捉UTC中的当前时刻。

    OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
    

    使用标准 ISO 8601 notation 添加两个小时的持续时间。

    Duration d = Duration.parse( "PT2H" ) ;
    ZonedDateTime odtLater = odt.plus( d ) ;  // Add 2 hours to the current moment.
    

    使用 JDBC 4.2 或更高版本将其提交到您的数据库。

    myPreparedStatement.setObject( … , odtLater ) ;
    

    检索。

    OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
    

    关于java.time

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

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

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

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

    从哪里获得 java.time 类?

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

    【讨论】:

      【解决方案4】:

      我喜欢将我的时间戳视为无符号整数。修改它们变得非常简单:在您的情况下,尝试获取一个 uint 表示并将2 * 3600 * 1000 添加到时间戳,然后将其格式化为您想要的输出。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-02-01
        • 1970-01-01
        • 2012-08-03
        • 1970-01-01
        • 2021-12-03
        • 1970-01-01
        • 2016-02-19
        • 2011-05-23
        相关资源
        最近更新 更多