Been stuck trying to make this work for a while: I am using sugar ORM for sqlite in my android app and I am trying to write a query with a condition on a date field. The where clause format for sqlite dates does not seem to be working.
eg:
MySugarRecordClass.find(MySugarRecordClass.class, "some_date_field>?", "2015-01-01")
or
MySugarRecordClass.find(MySugarRecordClass.class, "date(some_date_field)>date(?)", "2015-01-01")
I have tried using several date formats but I still can't get it.
Unfortunetly SQLite (the DB behind Sugar) does not have a date type: http://www.sqlite.org/datatype3.html. I personally store and compare my dates as integers after converting them to the UNIXTIMESTAMP.
You can also store the date as a string to do a comparison on, but I suggest sticking with the 'YYYY-mm-dd hh:mm:ss' format in 24 hour format, like so: '2015-08-11 13:13:00' (time for 1:13pm exactly).
Whatever way you do it, you need to be consistent and save/compare your dates that exact way every time.
Related
..and later retrieve and show them as Strings?
I'm asking the user some input and I want to store both the date (i.e., day, month and year) and the time (i.e., the hour of the day) this input was submitted. Each submission is then saved in my SQlite database, and later retrieved from a RecyclerView.
I'm facing two problems at least. Right now I set up two TEXT fields in the database, FIELD_DATE and FIELD_TIME, where I'd like to store the string representation of date & time, in a format depending on the Android user locale.
From what I've read, the android.text.format.DateFormat should help me. So I set:
java.text.DateFormat dateFormat = DateFormat.getMediumDateFormat(getActivity());
java.text.DateFormat timeFormat = DateFormat.getTimeFormat(getActivity());
Now I think I should call format(Date d) on both objects to get my string, but I don't know where do I get this Date object - don't even know if my two lines are correct. So:
How to get a string representation of current date & time, based on the user defined (at OS level) locale?
That said (asked), I wonder if two fields for date & time are really what I'm looking for. As said, at the end I would like to show a RecyclerView reading the database. In that I will also need to filter out entries based on date, i.e.
Entries referring to last week // last month // All
entries
So I'm also asking:
Is a two-text-fields pattern the right choice to store date & time, given the need to easily filter out entries belonging to, say, last week? Should I better have separate columns for day, month and year?
How to query the database to have only last week rows, given the FIELD_DATE / FIELD_TIME structure (or any other better structure you can suggest)?
I'm quite stuck on these three questions.
Edit: finally came up with how to get the strings I wanted at first, it was as simple as instantiating a new Date object:
Date d = new Date();
String date = DateFormat.getMediumDateFormat(getActivity()).format(d);
String time = DateFormat.getTimeFormat(getActivity()).format(d);
Now I have both the needs to display these strings (which is quite simple, as they are already formatted) and to apply some filter to the db, like entries belonging to last week (which, in turn, would be quite simple with current time in millis since 1970). What to do?
If you want to be able to run complex queries such as find all records from last week, I would recommend storing a timestamp in an integer instead. A timestamp is expressed as the number of milliseconds since the Epoch (Jan 1, 1970). It makes it easy to make queries on exact date and time ranges.
The timestamp is easily found from e.g. System.currentTimeMillis().
The other approach would be to use sqlite's built in date type, but I would personally choose the timestamp approach.
Is there any reason you would want to store it in the current locale's format in the first place? If you are displaying the date to the user you're likely better of formatting the timestamp into a date when displayed, using one of the many date features of Java and android such as java.util.Calendar, java.util.Date, android.text.SimpleDateFormat etc.
As an example, you could run this code to get the timestamp of the start of this month:
Calendar now = Calendar.getInstance();
now.set(Calendar.DAY_OF_MONTH, 1);
now.set(Calendar.HOUR_OF_DAY, 0);
now.set(Calendar.MINUTE, 0);
now.set(Calendar.SECOND, 0);
long startOfThisMonth = now.getTimeInMillis();
In my project i stored the dates in the dateadded filed like below.
01-07-14 12:00
02-07-14 12:00
25-06-14 13.00
When i fire query for minimum date:
Select dateadded from dgadata order by dateadded asc limit 1
That is return 01-07-14 12:00 and even if i write Select min(dateadded) from dgadata the output is same. But here the minimum date is 26-06-14 13.00
And in the max date i write like
Select dateadded from dgadata order by dateadded desc limit 1
Here the result is 25-06-14 13.00 but here the max date is 02-07-14 12:00
I think my query is fine i don't know why i am getting wrong result.
SQLite doesn't have dedicated datetime types, but does have a few datetime functions. Follow the string representation formats (actually only formats 1-10) understood by those functions (storing the value as a string) and then you can use them, plus lexicographical comparison on the strings will match datetime comparison (as long as you don't try to compare dates to times or datetimes to times, which doesn't make a whole lot of sense anyway).
Depending on which language you use, you can even get automatic conversion. (Which doesn't apply to comparisons in SQL statements like the example, but will make your life easier.)
The reason is because the comparison is performed in the stored string. I think that this may help.
For what I can see, it seems that you have defined your dateadded field as TEXT, you should store a timestamp (integer) value instead of a text value, this way it will be easy to order them.
SQLite does not have a storage class set aside for storing dates and/or times. Instead,
the built-in Date And Time Functions of SQLite are capable of storing dates and times
as TEXT, REAL, or INTEGER values:
TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS").
REAL as Julian day numbers, the number of days since noon in Greenwich on November 24,
4714 B.C. according to the proleptic Gregorian calendar.
INTEGER as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.
Applications can chose to store dates and times in any of these formats and freely
convert between formats using the built-in date and time functions.`
Another possible solution is to store your dates as YYYMMMDDHHMMSS, this way your order by will work aswell.
My date is in text format, as SQLite has no data type for date and time, so now I want to sort my data by date.
So when I query the database like
SELECT jobno, ondate FROM Reports ORDER BY DATE(ondate)
this will return the data sort alphabetically not by data. How would I sort by date?
Either use Unix-epoch format, which is basically an INTEGER type, or time string (YYYY-MM-DD stuff).
A list of time string formats you can use can be found here.
Sort unix-epoch as you would sort an INTEGER type, and a time string as you would sort a TEXT type.
When SQLite compares/sorts strings of the form dd/mm/YYYY, it handles them like any other string, i.e., the first characters in the string have priority, e.g., 01/10/2013 is sorted before 22/01/2000.
If you ever compare or sort dates, or use any of SQLite's built-in date functions, you must use one of the supported date formats, like YYYY-MM-DD.
(In you particular query, you are calling the DATE function, which returns NULL if it does not recognize the format of its parameter. This means that your records were not sorted at all.)
I would suggest 2 things, to put your dates in milliseconds or use a text with the format YYYYMMDD.
Convert them every time you want to display them or you want to store them.
It's not complicated, and it will save you a lot of trouble.
Storing the date as a timestamp i.e in millisecond is a better option.
From how to store 6:00pm in sqlite database in android, I know that for SQLite, there is no data type "TIME".
So, if I want to store time(year,month,day,hour,min,sec), how can I create that column? I should use "TEXT"?? But, how can I parse them for Android and
if I want to sort by time, how can I do it?
Thank for all your help!
You can define for yourself a date format (link) and you can create let's say a DateManager class to convert a date to a string (to store it in the SQLite database) and to convert a string into a date, both based on that date format specified by you.
The easiest solution would be to store the Date as miliseconds (long).
You can get the miliseconds from a date using date.getTime() when you store them, and when you re-create your Date object you could use Date d=new Date(milliseconds).
I'm writing an application where users enter some details into an SQLite Database. I need to write code whereby the last 31 days of stored data in the database is outputted.
The code to save the date string is:
currentDateString = DateFormat.getDateInstance().format(new Date());
This gives the date in the format (for todays date) as 30 Mar 2012.
Is there anyway to change this data format into DD/MM/YYYY? (30/03/2012)
This string is saved into the SQL Database as follows:
ContentValues dbcv = new ContentValues();
dbcv.put(KEY_DATE, date);
(currentDateTime String = Date in previous class)
I wish to output every row of the database that comes within the last 31 days.
How can I do this?
Thanks!
First of all, you are doing two questions instead on just one, I will try to give you an answer to both.
To change the date format in java take a look at the documentation for the SimpleDateFormat, you can pass a pattern to the constructor of that class to make it format your dates the way you really want. In your specific case the pattern you are looking for is dd/MM/yyyy
If you are storing dates in your database as strings you lose some of the benefits that storing dates as they are have. For example, your second question will be easily performed if you were storing dates instead of strings in your tables since the only thing you need to achieve what you want is to do a select operation to your table using the date functions provided by SQLLite. Take a look a this webpage as it will give you an idea of what you can do with those functions: SQLLite Date Functions
Note: Of course, if you still want to store them as strings the only solution you will have is read all the records, parse all the strings back to dates and use the java.util.Calendar class to check which record is older than 31 days and which one is not. I'd rather do the SQL query instead of that as it has too much better performance (specially on a mobile device).
EDIT:
SQLLite and Android are not specifically my strengths, I did a small research and I found several posts in which people were actually storing them as strings as you initially started to do. If SQLLite on Android doesn't support storing dates as they are (as other databases do) then maybe the best option in your scenario is using a long value as the date. Look at the Date definition class, it has a method getTime that returns the date value as long value, you can use that value later to create a new instance of a date (using its constructor).
To format that date (the Date object, of course) in something readable by the user, DateFormat (or any of its implementations) is still the answer.
To do the query you want to do having dates stored as longs I suggest you to take a look to the DateUtils class from the Apache Commons Lang library. In that class you will find several functions that work on dates, so, before creating the query you need to fetch the rows in last 31 dates, you could use something like:
Date now = new Date();
Date before = DateUtils.addDays(now, -31);
long beforeAsLong = before.getTime();
String query = "select * from TABLE_NAME where DATE_FIELD >= " + beforeAsLong;
Hope this helps.