How get data by month using DBFlow? - android

I'm facing some problems trying get a list of months and a list of data by month from my database in my app. Now I'm using strftime() function from SQLite but apparently the strftime() doesn't work.
For building and managing the database I'm using DBFlow ORM and the query of the first list looks like that.
List<ExpenseAndIncome> expenseAndIncomes = new Select("strftime('%Y-%m-%d', date").from(ExpenseAndIncome.class).queryList();
SELECT `strftime('%Y-%m-%d', date)` FROM `expense_and_income`
In this case it shows up an exception
android.database.sqlite.SQLiteException: no such column: strftime('%Y-%m-%d', date) (code 1): , while compiling: SELECT `strftime('%Y-%m-%d', date)` FROM `expense_and_income`
The other problem occurs when I'm trying to get a list of data by month. In this case the query looks like that.
List<ExpenseAndIncome> expenseAndIncomes = new Select().from(ExpenseAndIncome.class).where("strftime('%m', date) = ?", calendar.get(Calendar.MONTH)).groupBy("date").queryList();
SELECT * FROM `expense_and_income` WHERE strftime('%m', date) = 7 GROUP BY date
But the result always is a empty array.
Can someone helpe me?

strftime is just a function that formats a Date variable as a string. For example, strftime('%Y-%m-%d', date) might return '2015-08-17'.
Your query, then, is being evaluated as:
SELECT 2015-08-17 FROM expense_and_income
That's not really what you want. I imagine you want something more like:
SELECT UNIQUE month FROM expense_and_income
Assuming you have a field called month, that is.
Your second query is being evaluated as
SELECT * FROM expense_and_income WHERE 08 = 7 GROUP BY date
Obviously, 8 != 7, so while this is a valid query, it never returns anything. You probably want something more like
SELECT * FROM expense_and_income WHERE month = 08

I figured out how to solve one of the problems, getting a list of data by months.
When Android executes the following line in SQLite
List<ExpenseAndIncome> expenseAndIncomes = new Select().from(ExpenseAndIncome.class).where("strftime('%m', date) = ?", calendar.get(Calendar.MONTH)).groupBy("date").queryList();
Query representation
SELECT * FROM `expense_and_income` WHERE strftime('%m', date) = 7 GROUP BY date
They compare something like that
SELECT * FROM `expense_and_income` WHERE '08' = 7 GROUP BY date
And this occurs because my date table save the dates as string and calendar.get(Calendar.MONTH) returns an int as month representation and that int starts from 0. So, august is represented by the int 7 not 8 nor string '08'. SQLite query compares '08' with int 7 and because of this that array always are returned empty.
To solve this problem I created a method that returns a correct string representation to use in query comparison. The final code looks something like this:
List<ExpenseAndIncome> expenseAndIncomes = new Select().from(ExpenseAndIncome.class).where("strftime('%m', date) = ?", getMonthAsString(calendar.get(Calendar.MONTH))).groupBy("date").queryList();
private String getMonthAsString(int month) {
if (month > 0 && month < Constants.OCTOBER)
return Constants.ZERO + (Integer.toString(month) + 1);
return Integer.toString((month + 1));
}

Related

Android Room : Return Rows by custom date i.e -7day etc

I have overhauled my room database from String Dates to Date which is stored as a Long using type converters. I am unable to filter my results for specific times like -7 days or 3 months etc. Here is my configuration:
QUERY
SELECT *
FROM moodBeforetable
WHERE moodBeforetable.workoutDate >= datetime('now', '-1 year')
ORDER BY moodBeforetable.workoutDate DESC
LiveData<List<WorkoutLogsAllPojo>> getAllMoodLogs();
The query works fine when the WHERE clause is commented out, however if I include that line above no data is returned.
This moodBeforetable.workoutDate variable is a DATE but its stored in the database as Long :1590705660000
Type Converter
#TypeConverter
public static Date toDate(Long timestamp){
return timestamp == null ? null : new Date(timestamp);
}
#TypeConverter
public static Long toTimestamp(Date date){
return date == null ? null : date.getTime();
}
Any assistance on the root cause of why the WHERE clause is not returning any data or the specified amount of rows would be greatly appreciated.
Function datetime('now', '-1 year') returns timestamp as '%Y-%m-%d %H:%M:%S', for example 2019-05-28 23:29:42 (docs). To get the number of milliseconds since epoch, use 1000 * strftime('%s', datetime('now', '-1 year')) instead.

Using ROOM Dao - How I can get data of a table by comparing current date with date stored in table?

I'm working on an activity which have 6 radio buttons which are(1-All, 2-Today, 3-Yesterday, 4-Last Week, 5-This Month, 6-Last Month) <=These are the names of the radio buttons.
So when I check the Today's radio button and press OK button, it should show me all entries which are inserted in database in today's date, and the reset of radio buttons should give me the result as there names are, as if I check Yesterday, it should give me the data that was stored yesterday.
The problem is I don't know the exact queries for this scenario which will give me the desired data.
I'm using ROOM database and in Dao class I've to write the queries which will give me data according to radio buttons.
There is a Date and Time column which stores the current date and time when the data is store in this table, so I have to match the date of table with the date of Today, Yesterday and so on, and according to that matching the data will be filter.
This is my Entity class(Table) from where I want to get data according to date.
#Entity
public class IncomeExpense {
#PrimaryKey(autoGenerate = true)
private int id =0;
private String type;
private int amount;
private String category;
private String date;
private String time;
private String mode;
private String note;
I just want someone who can write me Dao queries & functions which will give me filter data according to radio buttons.
I have achieved this by using dates in string format. Like Standard format of dates 08-12-2015. In Dao Class I used the following query to get the record for date. note that in my entity class date was also in String format.
#Query("SELECT * from scan_data where sqlDate = date('now') ")
List<Data> getTodayRecord();
For YesterDay Record
#Query("SELECT * from scan_data where sqlDate = date('now','-1 day')")
List<Data> getYesterDayRecord();
For Last Week Record
#Query("SELECT * FROM scan_data WHERE DATE(sqlDate) >= DATE('now', 'weekday 0', '-7 days') AND DATE(sqlDate) != DATE('now') AND DATE(sqlDate) != DATE('now','-1 day')")
List<Data> getLastWeekRecord();
For Month Record
#Query("SELECT * FROM scan_data WHERE strftime('%W',sqlDate) != strftime('%W',date('now')) AND strftime('%Y',sqlDate) = strftime('%Y',date('now')) AND strftime('%m',sqlDate) = strftime('%m',date('now')) AND DATE(sqlDate) != DATE('now', 'weekday 0', '-7 days') AND DATE(sqlDate) != DATE('now') AND DATE(sqlDate) != DATE('now','-1 day')")
List<Data> getLastMonthRecord();
In the beginning, I do private String date instead of private Date date later because of this I can't do the date filter as I want. So use Date data type java.util.Date

Room Query BETWEEN dates doesnt return result

I am working on an application where i practice working with Room Persistence Library.
I have a class called expence based on which is the database with fields int amount and Date dob and other.
My goal is to use query below to return the sum of all entries between these dates.
#Query("SELECT SUM(amount) FROM expence WHERE dob BETWEEN date( :start ) AND date( :end ) ")
int newallexpensesFromTo(String start,String end);//
But at the curent state the query doesnt return anything and the textview i want to display the result = 0;
I have used guidance from http://androidkt.com/datetime-datatype-sqlite-using-room/ - to be able to convert from strings to Date and revese.
I have checked maybe its due to different format of the stored date and its the same the one stored in database and the one passed to query.
This is where i try to get the sum of the entries
value2 =db.expenceDao().newallexpensesFromTo(firstdayofmonth,lastdayofmonth);
I have a similar query where without the dates and it returns all entries.
When i add an expense i use DatePicker to add the Date to the dob in database.
Expected result is to receive the sum of entries added between these dates when the query receives the strings with the dates.
Try converting and inserting your startDate and endDate as a long timestamp value into your expense table instead of storing it in some another format.
Now while querying the data, use the timestamp values of your query dates.
For e.g., if you want SUM(amount) between 01-05-2019 and 31-05-2019 than your query would be like:
#Query("SELECT SUM(amount) FROM expense WHERE dob BETWEEN :startDate AND :endDate")
int newAllExpensesFromTo(Long startDate,Long endDate);
Where your startDate and endDate values will be something like 1556668800 & 1559260800 respectively.
For now you can use type converters.
As described in docs for Date your converter in Java should looks like below
public class Converters {
#TypeConverter
public static Date fromTimestamp(Long value) {
return value == null ? null : new Date(value);
}
#TypeConverter
public static Long dateToTimestamp(Date date) {
return date == null ? null : date.getTime();
}
}
To apply them, add below code above the class inheriting from RoomDatabase()
#TypeConverters({Converters.class})
Finally you will be able to use it like that
#Query("SELECT SUM(amount) FROM expence WHERE dob BETWEEN :from AND :to")
int newallexpensesFromTo(from: Date, to: Date)

Android SQlite: Querying table rows by date range from today backwards?

I get a date from the server in "MM/dd/yyy" form, then I convert it into milliseconds using the following function:
public static long getSimpleDateToMillis(String simpleDate) throws ParseException {
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
Date date = formatter.parse(simpleDate);
return date.getTime();
}
Then afterwards I save the result into the database as int.
Right now I'm stucked in what seems like a dead-end for me. I can't find a way through searching and from my stock knowledge on how I would be able to filter my cursorloader by project_date column which is saved as integer in the database.
In what way would I be able to query such that it would:
Select all row from projects table where the project_date is today and backwards (yesterday and so on).
I tried this one but seems to be really not the answer.
String [] projection = new String []{};
String selection = "datetime("+ ProjectsEntry.COLUMN_PROJECT_DATE + "/1000, 'unixepoch') =? ";
String [] selectionArgs = new String[]{" date('now')"};
return new CursorLoader(this,
JobsContract.JobsEntry.CONTENT_URI,
projection,
selection,
selectionArgs,
null);
I haven't found any other reference that would point me, so I'm hoping someone might also have encountered this perhaps.
This is how I do something quite similar, but using full timesteamp i.e. long rather than int.
First I have this method to get the TimeStamp, to get today's date/time as of midnight (bar 1 millisecond):-
/**
*
* #return 1 millsecond before midnight today
*/
private long getDateTimeOfAllofToday() {
Calendar cal = Calendar.getInstance();
cal.add(Calendar.DAY_OF_MONTH,1); // tomorrow
cal.set(Calendar.MILLISECOND,0);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.MINUTE,0);
cal.set(Calendar.HOUR_OF_DAY,0);
cal.add(Calendar.MILLISECOND,-1);
return cal.getTimeInMillis();
}
Then I create the respective where clause e.g. :-
filter = DBRulesTableConstants.RULES_ACTON_COL +
" <= " +
Long.toString(getDateTimeOfAllofToday());
This is used via a rawQuery so not exactly what you want but easy enough to to change " <= " to " <=?" and then use
String [] selectionArgs = new String[]{Long.toString(getDateTimeOfAllofToday())}; or a modified version to get integer.

How to fetch data between 2 dates in greenDao database

I have two dates . One is the current date and the other is 30 days back date. So I need to fetch the data between these 2 dates in Green Dao. But I am not getting the result.
MyCode:
Date startRangeDate = new Date();
Date endRangeDate = dateBefore30Days;
QueryBuilder<StructSamePage> qb = UserDao.queryBuilder();
qb.where(UserDao.Properties.dateTime.between(startRangeDate.getTime(), endRangeDate.getTime()));
List<StructSamePage> list = qb.list();
Try swapping dates you pass.
Date startRangeDate = new Date();
Date endRangeDate = dateBefore30Days;
QueryBuilder<StructSamePage> qb = UserDao.queryBuilder();
qb.where(UserDao.Properties.dateTime.between(endRangeDate.getTime(),startRangeDate.getTime() ));
List<StructSamePage> list = qb.list();
Generally between works if left hand side value is smaller than right hand side
The WhereCondition between in GreenDao uses this:
/** Creates an "BETWEEN ... AND ..." condition for this property. */
public WhereCondition between(Object value1, Object value2) {
Object[] values = { value1, value2 };
return new PropertyCondition(this, " BETWEEN ? AND ?", values);
}
So you should just have to change your dates accordingly. Because you are using NOW first and the day 30 days before later your code would do this:
Value >= NOW AND Value <= 30 DAYS BEFORE
If you use actual dates wich greenDAO does not use! Your code would look like this:
today = 2016-03-04
30DaysAgo = 2016-02-03
WHERE dateTime >= 2016-03-04 AND dateTime <= 2016-02-03
So you should be fine if you just change your order.
If you want to know more about how BETWEEN works you can read this
A word of advice: greenDao uses timestamps as INTEGERS in the database so if you use java Dates you get a Date that also has a time (when it was created) if you just remove 30 days from it you will not include the whole day 30 days ago but only the day from the time the current date object was created in time. So maybe you want to create the Date from a Calendar without a time.

Categories

Resources