UTC
Generally, the best practice for storing or exchanging date-time values is to adjust them into UTC.
Programmers and sysadmins should learn to think in UTC rather than their own parochial time zone. Consider UTC as The One True Time, with all other offsets and zones being mere variations on that theme.
Adjust your OffsetDateTime
into UTC.
OffsetDateTime odtUtc = myOdt.withOffsetSameInstant( ZoneOffset.UTC ) ;
odtUtc.toString(): 2007-12-03T10:15:30.783Z
Simplest approach is to convert to Instant
, which is always in UTC.
Instant instant = myOdt.toInstant() ;
String instantText = instant.toString() ; // Generate text in standard ISO 8601 format.
…
myPreparedStatement.setString( instantText ) ;
ISO 8601
Given the limitations of SQLite, I suggest storing the values as text, in a format that when sorted alphabetically is also chronological.
You need not invent such a format. The ISO 8601 standard has already defined such formats. The standard formats are sensible, practical, easy to parse by machine, and easy to read by humans across various cultures.
Conveniently, the java.time classes use ISO 8601 formats by default when parsing or generating strings.
If your JDBC driver complies with JDBC 4.2 or later, you can exchange the java.time objects directly to the database via setObject
and getObject
.
myPreparedStatement.setObject( … , odtUtc ) ;
Resolution
You mentioned milliseconds. Know that java.time classes use a resolution of nanoseconds, for up to nine decimal digits of fractional second.
Calculating days
simple arithmetic like "how many days passed since some event".
Actually that is not so simple. Do you mean calendar days? If so, specify a time zone to determine the dates. Or do you mean periods of 24-hours?
// Count of generic 24-hour days
String fromDatabase = myResultSet.getString( … ) ;
Instant instant = Instant.parse( fromDatabase ) ;
Instant now = Instant.now() ;
long days = ChronoUnit.DAYS.between( instant , now ) ;
// Count of calendar days.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
ZonedDateTime zdtNow = now.atZone( z ) ;
long days = ChronoUnit.DAYS.between( zdt.toLocalDate() , zdtNow.toLocalDate() ).
Half-Open
Do not use BETWEEN
predicate for date-time range searching. Generally the best practice is to use the Half-Open approach where the beginning is inclusive and the ending is exclusive. In contrast, BETWEEN
is inclusive on both ends, also known as "fully closed".
Consider another database
Your database needs may be exceeding the limited purpose of SQLite. Consider moving up to a serious database engine if you need features such as extensive date-time handling or high performance.
Richard Hipp, the creator of SQLite, intended that product to be an alternative to plain text files, not be a competitor in the database arena. See What I learned about SQLite…at a PostgreSQL conference.
H2 Database
For Android, H2 Database is another possibility. For more info, see:
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.
Where to obtain the java.time classes?