I have a database in room database Android Studio in which I need to find the records that match a date that comes to me through an http query
The problem I see is that since I am using a data converter (ZoneDateTimeConverter) when trying to make queries with "LIKE" or with "=" it returns a null object ... how could I make the queries?
Query 1:
@Query("select * from Operation where date =:arg0")
Operation getOperationConsult(String arg0);
Query 2:
@Query("select * from Operation where date LIKE :arg0")
Operation getOperationConsult(String arg0);
Operation Entity date:
@ColumnInfo(name = "date")
ZonedDateTime date;
Converter:
public class ZonedDateTimeTypeConverter {
@TypeConverter
public static ZonedDateTime toZonedDateTime(Long value) {
return value == null ? null : ZonedDateTime.ofInstant(Instant.ofEpochMilli(value), ZoneOffset.UTC);
}
@TypeConverter
public static Long toString(ZonedDateTime value) {
return value == null ? null : value.toInstant().toEpochMilli();
}
}
CodePudding user response:
In short you need to compare like for like and the data is stored as long down to milliseconds.
So you could have:-
@Query("SELECT * FROM operation WHERE date=:arg0")
List<Operation> getOperationConsult(long arg0);
Where long could be determined by using a ZonedDateTime converted to long using the TypeConverter that you've provided Room with (more on this later).
However, you are dealing with milli-seconds so the above query would likely not be at all useful due to the high precision.
Perhaps consider the following:-
@Query("SELECT * FROM operation WHERE date / (1000 * 60 * 60 * 24)= (:arg0 / (1000 * 60 * 60 * 24))")
List<Operation> getOperationsConsultPerDate(long arg0);
This strips off the the time (millis, seconds, minutes and hours) to just leave the date (for both sides of the argument) so would retrieve all operations that have the same date as the passed long.
To ascertain the long then this can be achieved using a ZDT and then using the toString
TypeConverter.
Consider the following working example, that uses your Operation Entity (at least the date column) and the above dao's (run on main thread for brevity and convenience):-
public class MainActivity extends AppCompatActivity {
private final static String TAG = "DBINFO";
TheDatabase db;
AllDao dao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
db = TheDatabase.getInstance(this);
dao = db.getAllDao();
/* Add some data */
for (int i=0;i<48;i ) {
ZonedDateTime zdt = ZonedDateTime.now().minusHours(i).plusHours(24);
dao.insert(new Operation(zdt));
}
/* extract Operations based upon the current time */
logOperations(dao.getOperationConsult(ZonedDateTimeTypeConverter.toString(ZonedDateTime.now())));
logOperations(dao.getOperationsConsultPerDate(ZonedDateTimeTypeConverter.toString(ZonedDateTime.now())));
}
void logOperations(List<Operation> operationList) {
for(Operation o: operationList) {
Log.d(TAG,"Operation ID is " o.id " date is " o.date.toString());
}
}
}
Running the above results in :-
- NOTHING extracted by the first query due to the precision factor.
- The following from the second query
:-
2021-12-15 10:49:16.451 D/DBINFOEXAMPLE2: Operation ID is 25 date is 2021-12-14T23:49:16.398Z
2021-12-15 10:49:16.451 D/DBINFOEXAMPLE2: Operation ID is 26 date is 2021-12-14T22:49:16.400Z
2021-12-15 10:49:16.452 D/DBINFOEXAMPLE2: Operation ID is 27 date is 2021-12-14T21:49:16.401Z
2021-12-15 10:49:16.452 D/DBINFOEXAMPLE2: Operation ID is 28 date is 2021-12-14T20:49:16.403Z
2021-12-15 10:49:16.452 D/DBINFOEXAMPLE2: Operation ID is 29 date is 2021-12-14T19:49:16.404Z
2021-12-15 10:49:16.452 D/DBINFOEXAMPLE2: Operation ID is 30 date is 2021-12-14T18:49:16.407Z
2021-12-15 10:49:16.452 D/DBINFOEXAMPLE2: Operation ID is 31 date is 2021-12-14T17:49:16.408Z
2021-12-15 10:49:16.453 D/DBINFOEXAMPLE2: Operation ID is 32 date is 2021-12-14T16:49:16.410Z
2021-12-15 10:49:16.453 D/DBINFOEXAMPLE2: Operation ID is 33 date is 2021-12-14T15:49:16.412Z
2021-12-15 10:49:16.453 D/DBINFOEXAMPLE2: Operation ID is 34 date is 2021-12-14T14:49:16.414Z
2021-12-15 10:49:16.453 D/DBINFOEXAMPLE2: Operation ID is 35 date is 2021-12-14T13:49:16.416Z
2021-12-15 10:49:16.453 D/DBINFOEXAMPLE2: Operation ID is 36 date is 2021-12-14T12:49:16.417Z
2021-12-15 10:49:16.454 D/DBINFOEXAMPLE2: Operation ID is 37 date is 2021-12-14T11:49:16.420Z
2021-12-15 10:49:16.454 D/DBINFOEXAMPLE2: Operation ID is 38 date is 2021-12-14T10:49:16.422Z
2021-12-15 10:49:16.454 D/DBINFOEXAMPLE2: Operation ID is 39 date is 2021-12-14T09:49:16.424Z
2021-12-15 10:49:16.454 D/DBINFOEXAMPLE2: Operation ID is 40 date is 2021-12-14T08:49:16.426Z
2021-12-15 10:49:16.454 D/DBINFOEXAMPLE2: Operation ID is 41 date is 2021-12-14T07:49:16.427Z
2021-12-15 10:49:16.454 D/DBINFOEXAMPLE2: Operation ID is 42 date is 2021-12-14T06:49:16.430Z
2021-12-15 10:49:16.454 D/DBINFOEXAMPLE2: Operation ID is 43 date is 2021-12-14T05:49:16.432Z
2021-12-15 10:49:16.455 D/DBINFOEXAMPLE2: Operation ID is 44 date is 2021-12-14T04:49:16.434Z
2021-12-15 10:49:16.455 D/DBINFOEXAMPLE2: Operation ID is 45 date is 2021-12-14T03:49:16.435Z
2021-12-15 10:49:16.455 D/DBINFOEXAMPLE2: Operation ID is 46 date is 2021-12-14T02:49:16.436Z
2021-12-15 10:49:16.455 D/DBINFOEXAMPLE2: Operation ID is 47 date is 2021-12-14T01:49:16.438Z
2021-12-15 10:49:16.455 D/DBINFOEXAMPLE2: Operation ID is 48 date is 2021-12-14T00:49:16.439Z
Extra
As the stored date (if divided by 1000) is a format (format 12) that the SQLite date and time functions recognises, then you can use SQlite date functions.
- note that storing the data as a long is, as far as the database is concerned, the most efficient format taking up up to 8 bytes rather than over double that to store the same information as a string/text format.
As an example the datetime function returns the datetime in the format yyyy-mm-dd hh:mm:ss, so to demonstrate consider the following query:-
@Query("SELECT datetime(date / 1000,'unixepoch') FROM operation WHERE date(date / 1000,'unixepoch') = date('now')")
List<String> getDatesFromOperations();
This will return the date and time per selected operation e.g. 2021-12-15 00:20:18. The operations selected are those who's date is the date when the query is invoked/used (i.e. 'now'). The query doesn't return a room object BUT as there is only a single output column then Room can handle a List of the common types, String in this case.
- unixepoch inidicates that the value is in the unix format for format 12 rather than being a Julian day number.
So using :-
for (String s: dao.getDatesFromOperations()) {
Log.d(TAG "EXAMPLE3","DateTime is " s);
}
Would result in :-
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 00:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 01:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 02:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 03:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 04:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 05:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 06:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 07:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 08:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 09:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 10:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 11:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 12:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 13:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 14:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 15:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 16:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 17:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 18:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 19:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 20:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 21:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 22:20:18
D/DBINFOEXAMPLE3: DateTime is 2021-12-15 23:20:18