I am accessing Android MMS database to get the date of MMS message:
Uri mmsUri = Uri.parse("content://mms/");
ContentResolver contentResolver = getContentResolver();
String[] projection = {"_id", "date"};
Cursor cursor = contentResolver.query(mmsUri, projection, null, null, null);
long dateVal = cursor.getLong(cursor.getColumnIndex("date"));
//This date is always 1970
Date mmsDate = new Date(dateVal);
But the date I get is always 1970. Then, I found an answer for this. I need to set the projection to null (to return all columns) and then use the following code to get date value:
//A mystery column of index 2
long timestamp = cursor.getLong(2) * 1000;
//It works !
Date mmsDate = new Date(timestamp);
Everything until here is fine. But, now instead of geting all rows from MMS database, I need to select those rows which were sent after a certain date, which means I need to use selection & selection argument. Something like:
String selection = NAME_OF_MYSTERY_COLUMN_IDX_2 > minDate
Cursor cursor = contentResolver.query(mmsUri, projection, selection, null, null);
But I have no idea what is the name of the column with index 2, how could I achieve what I need ? Is there a workaround?
Your first code block is correct, except for the Date instantiation. That constructor expects the time in milliseconds, but the MMS table keeps dates in seconds. To correct this, simply multiply the value returned from the query by 1000.
Date mmsDate = new Date(dateVal * 1000);
For future reference, the Cursor#getColumnName() method will give you the String name for a given column index.
You can try this.
String selection = "date_sent" > minDate
https://developer.android.com/reference/android/provider/Telephony.BaseMmsColumns.html#DATE_SENT
Related
I'm struggling with the implementation of dates in SQLite3 (for android). According to the documentation (https://www.sqlite.org/datatype3.html and http://www.sqlite.org/lang_datefunc.html), SQLite doesn't have datatypes for date and time specifically and therefore it can be either stored as a TEXT or as an INTEGER. I've tried both, but they give the same erroneous results. After reading a lot on the internet and trying everything I can think of, I come here as a last resort.
So, now for the problem. The idea is actually very simple. I have a table containing items, with a date column. Now I want to select all items from this database that have a date of today, or before (i.e. today or in the past). In my current implementation I store dates as integers, since most people seem to agree that that is the way to go.
Below is the (simplified) code for inserting an item.
Calendar calendar = GregorianCalendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0); // Might not be necessary
calendar.add(Calendar.DAY_OF_YEAR, 4); // Today plus 4 days
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(COLUMN_DATE, calendar.getTimeInMillis()); // Today as integer/long
long id = db.insert(TABLE_ITEMS, null, values); // Add to db
And next I want to select the items where the date is equal to or lower than today:
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
String[] columns = new String[]{COLUMN_ID, COLUMN_TEXT, COLUMN_DATE};
String[] selectArg = new String[]{"date('now')"};
Cursor cItems = db.query(TABLE_ITEMS, columns, COLUMN_DATE + "<= ?", selectArg, null, null, null);
//Cursor cItems = db.query(TABLE_ITEMS, columns, "strftime('%Y-%m-%d'," + COLUMN_DATE + ")" + select, selectArg, null, null, null);
//Cursor cItems = db.query(TABLE_ITEMS, columns, "date(" + COLUMN_DATE + ")" + select, selectArg, null, null, null);
Now all rows are selected, also the rows with a date in the future. Could anyone tell me what I need to do differently?
Thanks in advance!
Edit
I found out that sqlite stores date integers in seconds (is that correct?). So that would mean that value I put in the database should be Math.round(calendar.getTimeInMillis()/1000, to get it in seconds right? But then it makes even less sence, since a date in milliseconds should always be larger than a date in seconds. Anyhow, I tried that, but it doesn't work either.
Thanks to the insights CL. gave me, I fixed some trivial errors I made.
Looking back at the SQLite documentation, I figured that there are two ways of storing a date without a time. A Julian day number or a date string YYYY-MM-DD. There is no readily available function to get a Julian day number in java/android, so therefore I chose to go back to the string format again.
A second, mistake I figured out just now is that the selectArgs are considered text and therefore, putting the date('now', 'localtime') in there won't work.
Below are the final scripts that do work.
Calendar calendar = GregorianCalendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 0); // Might not be necessary
calendar.add(Calendar.DAY_OF_YEAR, 4); // Today plus 4 days
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
ContentValues values = new ContentValues();
values.put(COLUMN_DATE, dateFormat.format(calendar.getTime())); // Date as string
SQLiteDatabase db = dbOpenHelper.getWritableDatabase();
long id = db.insert(TABLE_ITEMS, null, values); // Add to db
And to get the data back:
SQLiteDatabase db = dbOpenHelper.getReadableDatabase();
String[] columns = new String[]{COLUMN_ID, COLUMN_TEXT, COLUMN_DATE};
String[] selectArg = new String[]{};
Cursor cItems = db.query(TABLE_ITEMS, columns, COLUMN_DATE + "<= date('now', 'localtime')", selectArg, null, null, null);
CL., many thanks for your help! In the end it was so simple...
Neither date() nor strftime('%Y-%m-%d') returns a date in your format.
To convert a date into the seconds format, you would have to use strftime('%s', ...), and convert the resulting string into a number.
I am working on a project and now I have been stuck on a weird stage.
I know that we can execute any query that has to do anything with database we can write that using:
Cursor cursor = db.rawQuery("SELECT * FROM table_name", null);
But now I want to execute this query:
"SELECT strftime('%s','now','-2 day')"
Generally the above query returns unixepoch time of one day before yesterday.
Does anyone know how can I get this done?
You would handle this query like any other query:
Cursor cursor = db.rawQuery("SELECT strftime('%s','now','-2 day')", null);
try {
if (cursor.moveToFirst()) {
long seconds = cursor.getLong(0);
...
} else {
// cannot happen with this query
}
} finally {
cursor.close();
}
If you want to access the column by name (which is completely pointless if you have only a single column), you can give it an alias:
cursor = db.rawQuery("SELECT strftime(...) AS s", null);
cursor.getColumnIndexOrThrow("s"); // returns zero
...
Please note that for queries that return a single value, there is a helper function:
long seconds = DatabaseUtils.longForQuery(
db, "SELECT strftime('%s','now','-2 day')", null);
Date date = new Date();
will return the current day, if you then subtract X numbers of days, then parse that Date to String with the required format. You can do this with the method SimpleDateFormat:
String newDate = new SimpleDateFormat(pattern).format(date);
where pattern can be something like this "dd-MM-yyyy"
Then, you can add said date to your query.
I cant get any result if i put "date('now', 'localtime')" in the query.
My original code is:
Cursor record = db.query(RECORD_TABLE, null, date(UTC_DATETIME,'localtime') = ? ",
new String[]{"date('now', 'localtime')"},null,null,null);
It doesn't return any result.
But I can get result if I use:
Cursor record = db.query(RECORD_TABLE,null, date(UTC_DATETIME,'localtime') = ? ",
new String[]{"2014-05-13"},null,null,null);
Is there a way that I can use "date('now', 'localtime')" in my query?
The whole point of parameters is to prevent their values from being interpreted as SQL expressions.
To call an SQL function, you have to put it into the SQL string:
Cursor record = db.query(RECORD_TABLE, null,
"date(UTC_DATETIME,'localtime') = date('now', 'localtime')",
null,null,null,null);
Please note that the localtime conversion affects both values in the same way, so you can omit it:
Cursor record = db.query(RECORD_TABLE, null,
"date(UTC_DATETIME) = date('now')",
null,null,null,null);
or even omit the first date call if the UTC_DATETIME column alread is in the correct yyyy-MM-dd format:
Cursor record = db.query(RECORD_TABLE, null,
"UTC_DATETIME = date('now')",
null,null,null,null);
I have date stored in the form of TEXT in sqllite database. The format is "dd-mm-yyyy". I am making a query to select rows having dates in between two given dates. When I query the database with query dates belonging to the same month, I am getting the results. But, when the date range belong to different month, it returns no rows. For eg:
The problem arises when the dates are something like : 29-03-2013 to 05-04-2013. It returns rows successfully when the dates are between: 02-04-2013 and 05-04-2013. There are rows with entries made on all the dates.
Following are the ways I have tried:
// MySQLiteHelper.COLUMN_DATE_DATE stores column name which is 'date'
// startdate and end date are string in form of mm-dd-yyyy
// MySQLiteHelper.TABLE_NAMES contain table name string
// MySQLiteHelper.COLUMN_MOOD_LEVEL is another column that I wish to get in return
I have tried using the BETWEEN clause and the <= and >=, but no effect to the output. Here is how:
// Method 1:
String selection = MySQLiteHelper.COLUMN_DATE_DATE + " BETWEEN '"+startdate+"' AND '"+ enddate+"' ";
// Method 2:
String selection = MySQLiteHelper.COLUMN_DATE_DATE + " >= '"+startdate+"' AND "+MySQLiteHelper.COLUMN_DATE_DATE+" <= '"+ enddate+"' ";
String []colum = {MySQLiteHelper.COLUMN_MOOD_LEVEL};
Cursor cursor = database.query(MySQLiteHelper.TABLE_NAMES, colum, selection, null, null, null, null);
When I use
cursor.getCount()
to see the number of rows returned, it gives 0. Though there are entries existing in between those dates.
Is their some basic comparison issue that I am missing? I tried looking at some previous questions but didn't work out. I would really appreciate the help.
For string comparisons to work correctly, you must use a format where the most significant field comes first, i.e., yyyy-mm-dd. (This also is the only supported format for SQLite's built-in date functions.)
Before the query , i would like to highlight the correct Date format that is
yyyy-MM-dd
Make sure to save your date in this format.then further the query is following :
Cursor cursor = db.query(TABLE, null, COL_GAME_DATE + " BETWEEN ? AND ?", new String[]{
startDate, endDate},
null, null, null);
I'd suggest you rather fix your database first. Dates should be stored in DATE type, just because of simplicity of further use.
I have a database which has a column of dates in milliseconds. I'm trying to perform a query which allows me to retrieve only the dates that are greater than the current system time and in ascending order.
I've tried this query, but it causes my app to force close. I'm not sure whether the problem is the where clause part or the orderby clause part or both.
Here is what I done, your help would be most appreciative.
long lowestDate = 0;
long currentTime = System.currentTimeMillis();
String CT = Long.toString(currentTime);
String[]c = {CT};
mDb = mDbHelper.getReadableDatabase();
String[] dates = {KEY_DT};
Cursor getDate = mDb.query(DATABASE_TABLE, dates, dates + "> ?", c, null, null, dates + "ASC");
getDate.moveToFirst();
while(getDate.isAfterLast() == false)
{
lowestDate = getDate.getLong(0);
getDate.moveToNext();
}
It seems you are using query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy)
selection argument description:
A filter declaring which rows to return, formatted as an SQL WHERE clause (excluding the WHERE itself). Passing null will return all rows for the given table.
You should correct that. I think that's an issue, because you are calling toString() method on dates variable, which is an Array.