如何获得一天中的所有毫秒



我在数据库中存储了许多行,该时刻的时间戳以毫秒为单位。现在,如果我需要检索给定日期的所有行,例如今天,如何正确创建当天的开始和结束毫秒?

我简要地了解 SimpleDateFormat 和 Calendar.getInstance((,但我是否需要进行字符串操作(我想避免(来仅获取今天的日期,添加小时部分,然后将其转换回毫秒,或者有更好的方法可以做到这一点?

由于您在问题中没有提供任何代码,请允许我给您一个一般性的回答作为回应。

您要查找的是两个日期/时间,todaytomorrow,都指定了"0小时,0分钟,0秒"。

today <= date AND date < tomorrow

请注意两种不同的比较。

最简单的技术是使用 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();

要获取落在特定日期的行,只需查找时间戳的毫秒值介于 millisecondsmillisecondsForNextDay 之间的行:

if(rowsTimestampSeconds>milliseconds && rowsTimestampSeconds<millisecondsForNextDay){
    //get the row
}

您可以使用 GregorianCalendar 类来执行此操作,而无需任何字符串。

   日历日历=新的公历(年,月,日(;    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(),但你需要确保在使用日历之前,小时、分钟、秒和毫秒字段通过调用calendar.set(Calendar._FIELD_NAME_, 0);将其清零,因为它将被初始化到创建对象的确切时刻。

您应该为数据库列使用日期时间类型来存储日期时间数据,而不是毫秒整数。SQL 标准定义了几种日期时间类型。但是对日期时间的支持差异很大,Postgres是最好的之一。

既然你标记了 Java,请阅读这个问题和我的答案,了解如何使用 Java 来确定今天和明天的第一个时刻。那里使用的半开放方法在日期时间工作中很常见。半开放是指开始是包容性的,而结尾是排他性的时间段。对于 SQL,这意味着不使用 BETWEEN 运算符。

java.time

java.time 框架内置于 Java 8 及更高版本中,并向后移植到 Java 6 和 7 以及 Android。有关详细信息,请阅读我的另一个答案。

获得今天和明天的第一个时刻。请注意,时区对于确定日期和"今天"的含义至关重要。对于任何给定时刻,日期因时区而异。新的一天在东方开始得更早。例如,巴黎午夜过后不久,蒙特利尔仍然是"昨天"。

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类型。事实上,如果您分别在ResultSetPreparedStatement上调用getObjectsetObject,则符合 JDBC 4.2 的驱动程序可能会起作用。但如果没有,请回退到使用 java.sql 类型。请注意添加到这些旧类的新方法,包括 java.sql.Timestampfrom方法采用一个Instant,我们可以从ZonedDateTime对象中提取该。

java.sql.Timestamp tsStart =  java.sql.Timestamp.from( zdtStart.toInstant() );
java.sql.Timestamp tsStop =  java.sql.Timestamp.from( zdtTomorrowStart.toInstant() );

现在将这两个变量设置为PreparedStatement上的参数。请注意比较运算符,测试从一天的第一个时刻(>=(开始并运行到但不包括第二天的第一个时刻(<(的可能值。

 String sql =
    "SELECT * FROM event_" +
    "WHERE when_ >= ? " +
    "AND when_ < ? " + 
    ";" ;
…
pstmt.setTimestamp( 1 , tsStart );
pstmt.setTimestamp( 2 , tsStop );

如果您确实存储整数而不是使用日期时间类型,并且您将毫秒存储为 UTC 中 1970 年第一个时刻的纪元参考日期时间的计数,那么您可以从每个Instant中提取一个数字。请记住,java.time 类使用更精细的纳秒分辨率,某些数据库(如 H2 数据库(和某些数据库(如 Postgres(以微秒的分辨率捕获日期时间。因此,截断到毫秒可能意味着数据丢失

long millisStart = tsStart.toInstant().toEpochMilli();
long millisStop = tsStop.toInstant().toEpochMilli();

拨打setLong PreparedStatement

pstmt.setLong( 1 , millisStart );
pstmt.setLong( 2 , millisStop );

关于 java.time

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

Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。

要了解更多信息,请参阅 Oracle 教程。并搜索堆栈溢出以获取许多示例和解释。规范为 JSR 310。

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

从哪里获得java.time类?

    Java SE 8、Java SE 9、Java SE
  • 10、Java SE 11 及更高版本 - 标准 Java API 的一部分,具有捆绑实现。
    • Java 9添加了一些小功能和修复。
  • Java SE
  • 6Java SE 7
    • 大多数java.time功能在ThreeTen-Backport中向后移植到Java 6和7。
  • 人造人
    • java.time 类的 Android 捆绑包实现的更高版本。
    • 对于早期的Android(<26(,ThreeTenABP项目适应了ThreeTen-Backport(如上所述(。请参阅如何使用ThreeTenABP...

ThreeTen-Extra项目通过额外的类扩展了java.time。这个项目是未来可能添加到java.time的试验场。你可以在这里找到一些有用的类,如IntervalYearWeekYearQuarter等。

最新更新