You should be using a date-time type for your database column to store date-time data rather than an integer of milliseconds. The SQL standard defines a few date-time types. But support for date-time varies widely, with Postgres being one of the best.
Since you tagged Java, read this Question and my Answer to learn about using Java to pinpoint the first moment of today and tomorrow. The Half-Open approach used there is common in date-time work. Half-Open means a span of time where the beginning is inclusive while the ending is exclusive. For SQL, it means not using the BETWEEN
operator.
java.time
The java.time framework is built into Java 8 and later, and back-ported to Java 6 & 7 and to Android. Read my other Answer for details.
Get the first moments of today and tomorrow. Be aware that time zone is crucial in determining dates and the meaning of “today”. For any given moment, the date varies around the world by time zone. A new day begins earlier in the east. For example, a few moments after midnight in Paris is still “yesterday” in Montréal.
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 );
Some day we may see JDBC drivers updated to directly handle java.time types. Indeed, JDBC 4.2 compliant drivers may work if you call getObject
and setObject
on your ResultSet
and PreparedStatement
respectively. But if not, fallback to using the java.sql types. Notice the new methods added to these old classes including java.sql.Timestamp
. The from
method takes an Instant
which we can extract from our ZonedDateTime
objects.
java.sql.Timestamp tsStart = java.sql.Timestamp.from( zdtStart.toInstant() );
java.sql.Timestamp tsStop = java.sql.Timestamp.from( zdtTomorrowStart.toInstant() );
Now set these two variables are arguments on your PreparedStatement
. Notice the comparison operators, testing for possible values that start on first moment of the day (>=
) and running up to but not including the first moment of the next day (<
).
String sql =
"SELECT * FROM event_" +
"WHERE when_ >= ? " +
"AND when_ < ? " +
";" ;
…
pstmt.setTimestamp( 1 , tsStart );
pstmt.setTimestamp( 2 , tsStop );
If you do indeed store integers instead of using date-time types, and you are storing milliseconds as a count from the epoch reference date-time of first moment of 1970 in UTC, then you can extract a number from each Instant
. Remember that the java.time classes use a finer resolution of nanoseconds as do some databases such as H2 Database, and some databases such as Postgres capture date-time with a resolution of microseconds. So truncating to milliseconds may mean a loss of data.
long millisStart = tsStart.toInstant().toEpochMilli();
long millisStop = tsStop.toInstant().toEpochMilli();
Call setLong
on your PreparedStatement
.
pstmt.setLong( 1 , millisStart );
pstmt.setLong( 2 , millisStop );
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.