我在DB中存储了一些行,其中包含该时刻的时间戳,以毫秒为单位。 现在,如果我需要检索给定日期的所有行,就像今天一样,如何正确创建当天的开始和结束毫秒?
我简单地了解了SimpleDateFormat和Calendar.getInstance(),但是我需要进行字符串操作(我想避免)才能获得今天的日期,添加小时部分然后将其转换回毫秒,或者是有更好的方法吗?
答案 0 :(得分:1)
由于您未在问题中提供任何代码,请允许我在回复时给您一般答案。
您要查找的是两个日期/时间today
和tomorrow
,均指定为“0小时0分0秒”。
today <= date AND date < tomorrow
请注意两种不同的比较。
答案 1 :(得分:0)
最简单的方法是使用DateFormat
:
String input = "Sat Feb 17 2013";
Date date = new SimpleDateFormat("EEE MMM dd yyyy", Locale.ENGLISH).parse(input);
long milliseconds = date.getTime();
String input1="Sun Feb 18 2013"
Date inputNextDay = new SimpleDateFormat("EEE MMM dd yyyy", Locale.ENGLISH).parse(input);
long millisecondsForNextDay=inputNextDay.getTime();
要获取特定日期的行,只需找到时间戳为milliseconds
和millisecondsForNextDay
的毫秒值的行:
if(rowsTimestampSeconds>milliseconds && rowsTimestampSeconds<millisecondsForNextDay){
//get the row
}
答案 2 :(得分:0)
您可以使用GregorianCalendar类执行此操作而无需任何字符串。
Calendar calendar = new GregorianCalendar(year, month, day); long start_of_day_millis = calendar.getTimeInMillis(); calendar.add(Calendar.DAY_OF_MONTH, 1); long next_day_millis = calendar.getTimeInMillis();
使用calendar.add(Calendar.DAY_OF_MONTH);
而不是仅将(24 * 60 * 60 * 1000)添加到第一个毫秒值的原因是为了实现飞跃。除了众所周知的闰年之外,还有闰秒的发生。请看这个链接:http://www.timeanddate.com/time/leapseconds.html
确保您的表达式包含start_of_day_millis
(大于或等于)和next_day_millis
(小于)的外观。
即:if(test_time >= start_of_day_millis && test_time < next_day_millis)
<强>更新强>
如果你想要今天的日期,你可以省略日历构造函数中的所有参数,只需调用new GregorianCalendar()
,但是你需要确保通过调用{{1}来清空小时,分钟,秒和毫秒字段。之后,在使用日历之前,因为它会被初始化为创建对象的确切时刻。
答案 3 :(得分:0)
您应该使用数据库列的日期时间类型来存储日期时间数据,而不是整数毫秒。 SQL标准定义了few date-time types。但是对日期时间的支持差别很大,Postgres是最好的之一。
由于您标记了Java,请阅读this Question和my Answer以了解如何使用Java来确定今天和明天的第一时刻。使用的半开放方法在日期时间工作中很常见。半开是指一段时间,其中开头是包含,而结尾是独占。对于SQL,它意味着不使用BETWEEN
运算符。
java.time框架内置于Java 8及更高版本中,并后端移植到Java 6&amp; 7和Android。请阅读my other Answer了解详情。
获取今天和明天的第一时间。请注意,时区对于确定日期和“今天”的含义至关重要。对于任何特定时刻,日期因时区而异。新的一天在东部开始。例如,巴黎午夜过后的一段时间仍然在蒙特利尔“昨天”。
Instant instant = Instant.now();
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
ZonedDateTime zdtStart = zdt.toLocalDate().atStartOfDay( zoneId );
ZonedDateTime zdtTomorrowStart = zdtStart.plusDays( 1 );
有一天,我们可能会看到更新的JDBC驱动程序直接处理java.time类型。实际上,如果您分别在getObject
和setObject
上拨打ResultSet
和PreparedStatement
,则JDBC 4.2兼容的驱动程序可能会有效。但如果没有,则回退到使用java.sql类型。请注意添加到这些旧类的新方法,包括java.sql.Timestamp
。 from
方法需要Instant
我们可以从ZonedDateTime
个对象中提取。
java.sql.Timestamp tsStart = java.sql.Timestamp.from( zdtStart.toInstant() );
java.sql.Timestamp tsStop = java.sql.Timestamp.from( zdtTomorrowStart.toInstant() );
现在设置这两个变量为arguments on your PreparedStatement
。请注意比较运算符,测试在一天中的第一时刻开始的可能值(>=
)并在第二天的第一时刻运行但不包括({{1} })。
<
如果你确实存储了整数而不是使用日期时间类型,并且你在epoch reference date-time中存储了1970年第一时刻的UTC作为计数的毫秒数,那么你可以{{3 }}。请记住,java.time类使用更精细的纳秒分辨率,如某些数据库(如extract a number from each Instant
),而某些数据库(如Postgres)捕获日期时间,分辨率为微秒。因此截断到毫秒可能意味着数据丢失。
String sql =
"SELECT * FROM event_" +
"WHERE when_ >= ? " +
"AND when_ < ? " +
";" ;
…
pstmt.setTimestamp( 1 , tsStart );
pstmt.setTimestamp( 2 , tsStop );
在long millisStart = tsStart.toInstant().toEpochMilli();
long millisStop = tsStop.toInstant().toEpochMilli();
上致电H2 Database。
PreparedStatement
setLong
框架内置于Java 8及更高版本中。这些类取代了麻烦的旧java.time日期时间类,例如legacy,java.util.Date
和&amp; Calendar
现在位于SimpleDateFormat
的Joda-Time项目建议迁移到maintenance mode类。
要了解详情,请参阅java.time。并搜索Stack Overflow以获取许多示例和解释。规范是Oracle Tutorial。
您可以直接与数据库交换 java.time 对象。使用符合JSR 310或更高版本的JDBC driver。不需要字符串,不需要pstmt.setLong( 1 , millisStart );
pstmt.setLong( 2 , millisStop );
类。
从哪里获取java.time类?
How to use ThreeTenABP…项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如ThreeTen-Extra,Interval
,YearWeek
和YearQuarter
。