【问题标题】:How to compare if a timestamp falls in range of a given time period in Java如何比较时间戳是否在Java中的给定时间段范围内
【发布时间】:2018-07-28 04:14:06
【问题描述】:

在我的Java Spring MVC Web Application 中,我正在尝试编写一个程序来保存一些带有时间戳的数据。但我有一个特定的时间段,我必须排除。

例如,我有以下时间戳:Sat Jul 28 17:03:00 IST 2018,它是一个 Java Date 对象。在保存到数据库之前,我必须检查这个时间是否在指定范围内,如果那么我必须在时间范围结束后获得下一分钟。

但时间范围是如下格式的字符串:

String startTime =  "5:03 PM";
String endTime = "5:10 PM";

所以如果我的 timeStamp 介于这个时间之间,我的时间戳应该更新为Sat Jul 28 17:11:00 IST 2018

我现在正在寻找比较两个时间值的方法,因为一个是字符串,另一个是时间戳。

有什么办法可以转换String endTime = "5:10 PM";到Sat Jul 28 17:11:00 IST 2018 或只是比较时间部分,计算分钟差并将其添加到时间戳。

【问题讨论】:

  • 您从哪里获得 startTimeendTime 的值?是用户输入吗?
  • 您是否已经知道“新”(从 java 8 开始)时间 API?参见例如ZonedDateTimePeriod
  • @Lino ,这些是用户输入,我只能将它们收集为字符串
  • @Hulk,我使用 java 7。我通常使用 joda 进行与日期时间相关的操作
  • 用于计算DateTimes之间的DurationRelated question

标签: java calendar jodatime


【解决方案1】:

避免使用旧的日期时间类

避免使用麻烦的旧日期时间类,例如 java.util.Date。仅使用 java.time 类。同样,Joda-Time 项目现在也被 java.time 类所取代,这两个类都是由同一个人 Stephen Colebourne 创建的。

Instant

将您的Date 转换为Instant。这两个类都代表UTC 中的一个时刻,总是在UTC 中,尽管Date::toString 方法对你撒谎。

使用添加到旧类的新方法进行转换。

Instant instant = myJavaUtilDate.toInstant() ;

ZonedDateTime

将时区或与 UTC 的偏移量应用于您的一对时间字符串预期的挂钟时间。你是说纽约的下午 5 点,突尼斯的下午 5 点,还是印度的下午 5 点?

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

ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;  // Or "Pacific/Auckland" etc. 
ZonedDateTime zdt = instant.atZone( z ) ;

提取没有日期和区域的时间。

LocalTime lt = zdt.toLocalTime() ;

LocalTime

将您的限制解析为LocalTime 对象。

DateTimeFormatter f = DateTimeFormatter.ofPattern( "h:mm a" , Locale.US ) ;

LocalTime start = LocalTime.parse( "5:03 PM" , f ) ;
LocalTime stop = LocalTime.parse( "5:11 PM" , f ) ;

半开

通常最好使用半开方法来定义时间跨度。这意味着开头是inclusive,而结尾是exclusive。因此,如果您想排除第 10 分钟的所有内容,请测试“五点后不到十一点”。

提示:“等于或在之后”的更简短的说法是“不在之前”。

if ( ( ! lt.isBefore( start ) ) && lt.isBefore( stop ) ) {
    zdt = zdt.with( stop ) ;  // Change to a different time-of-day. 
}

如果该区域中该日期的时间无效,ZonedDateTime 类会根据需要进行调整。

数据库

为了在TIMESTAMP WITH TIME ZONE 类型的列中保存到数据库,让我们通过提取Instant 将时刻调整为UTC。

Instant instantForDatabase = zdt.toInstant() ;
…
myPreparedStatement.setObject( … , instantForDatabase ) ;

从数据库中检索。

Instant instantFromDatabase = myResultSet.getObject( … , Instant.class ) ;
ZoneId zMontreal = ZoneId.of( "America/Montreal" ) ;  // Or "Asia/Kolkata" etc.
ZondDateTime zdtMontreal = instantFromDatabase.atZone( zMontreal ) ;  

关于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

【讨论】:

    【解决方案2】:

    您有很多选择,其中一个更简单的是:

    1)- 您可以将 TimeStamp 转换为 LocalDateTime/Calendar 对象,然后获取小时和分钟。

    LocalDateTime localdt = sqlTimestamp.toLocalDateTime();
    int hour = localdt.getHour();
    int minute = localdt.getMinute();
    

    2)-然后就可以解析字符串并比较结果了。

    - 您还可以将字符串转换为时间戳,因为您需要一天的开始和结束并解析字符串。

    - 不过,听起来你选择的数据类型以后会带来麻烦。

    【讨论】:

    • 这个答案没有解决时区的关键问题。
    猜你喜欢
    • 1970-01-01
    • 2017-01-11
    • 2018-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-24
    • 1970-01-01
    • 2017-07-13
    相关资源
    最近更新 更多