0

I have been searching and i still can not understand how this works.

I know that SQLite doesn't store Date type values and we have to format them to TEXT. I already did that, but my question is how do i delete them by date?

Because if I do DELETE * FROM TABLE WHERE COLUMN_DATE >= '09-05-2017' , I will be comparing Strings and not Dates, so i guess the comparison won't be right.

I have seen people doing these type of comparisons even if it is TEXT type. I doesn't make sense to me.

Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
Steven Smith
  • 111
  • 1
  • 2
  • 11
  • 3
    Are you storing your dates in ISO8601 format (YYYY-MM-DD) as recommended? If you are then varro's answer is right, if you're not then you should rebuild your database to use the right format and then varro's answer will be correct. – mu is too short May 09 '17 at 02:50

3 Answers3

4

It will work if you use the canonical text format and use correct syntax, e.g.,

DELETE FROM TABLE WHERE COLUMN_DATE >= '2017-05-09'
varro
  • 2,382
  • 2
  • 16
  • 24
  • But at the end of the day aren't those just Strings ? – Steven Smith May 09 '17 at 09:51
  • Yes - just strings (or TEXT in SQLite terms). So when you make a comparison, you are comparing strings ,which means that '09-05-2017' < '10-01-2016', because the strings sort that way lexigraphically, but if you use the canonical ISO format, then '2017-05-09' > '2016-01-10', which is what you want for a time comparison. – varro May 09 '17 at 14:59
0

A much more efficient and simpler in terms of SQLite side date comparisons/arithmetic is to store dates as INTs in SQLite.

Date in Android is effectively just a container for milliseconds-since-the-Epoch (milliseconds since Jan 1st 1970 at midnight UTC) which is time zone independent.

INT in SQLite is 1, 2, 4, 8 byte data type automatically chosen depending on values in the column.

In order to convert a Java Date into a SQLite INT value when storing data in DB, use getTime() method:

Date javaDate = ...;
long sqlDate = date.getTime();

To retrieve a date from SQLite, use Cursor's getLong() method and pass it to Date(long) constructor:

SQLiteDatabase db = ...;
Cursor c = db.query(..);
long sqlDate = c.getLong(...);
Date javaDate = new Date(sqlDate);
Alexander Abakumov
  • 13,617
  • 16
  • 88
  • 129
  • FYI, the troublesome old date-time classes such as `java.util.Date`, `java.util.Calendar`, and `java.text.SimpleDateFormat` are now legacy, supplanted by the [*java.time*](https://docs.oracle.com/javase/9/docs/api/java/time/package-summary.html) classes. Much of the *java.time* functionality is back-ported to Java 6 & Java 7 in the [***ThreeTen-Backport***](http://www.threeten.org/threetenbp/) project. Further adapted for earlier Android in the [***ThreeTenABP***](https://github.com/JakeWharton/ThreeTenABP) project. See [*How to use ThreeTenABP…*](http://stackoverflow.com/q/38922754/642706). – Basil Bourque Mar 26 '18 at 21:37
  • @BasilBourque: `java.time` is [supported starting from API 26 only](https://developer.android.com/reference/java/time/package-summary.html), so it's still has an extremely limited adoption. Introducing a dependency on a 3rd party library like ThreeTenABP to promote backward compatibility with the older Android versions especially if `java.util.Date` is pretty sufficient to do its job in a specific project isn't something that everyone wants to do. But anyway thanks for pointing this out. – Alexander Abakumov Mar 27 '18 at 15:48
0

tl;dr

  • Store date-only values as strings in standard ISO 8601 fashion: YYYY-MM-DD
  • Query using ISO 8601 strings from the java.time classes, specifically LocalDate.

Example:

LocalDate ld = LocalDate.of( 2017 , Month.JANUARY , 23 ) ; // Or `LocalDate.parse`, or `LocalDate.now()`.
String sql = "DELETE * FROM tbl WHERE col >= '" + ld.toString() + "' ;" ;

Details

Keep in mind that SQLite was never meant to be a heavy-duty database, just a step up from writing text to a file. So if you need sophisticated date-time support, you should switch to a more sophisticated database.

SQLite lacks proper data types, as you alluded in the Question. For storing date-time types, the documentation suggests three routes: (a) ISO 8601 strings, (b) Real number representing Julian day numbers (I don't recommend this), and (c) Integer for storing number of seconds since the epoch reference of first moment of 1970 in UTC as shown in Answer by Abakumov (though you should NOT be using Date class shown there).

You seem to be tracking date-only values, without a time of day. So I would use the ISO 8601 for text: YYYY-MM-DD.

The java.time types in Java use the standard ISO 8601 formats by default when parsing/generating date-time values. The date-only class in Java is LocalDate, lacking a time-of-day and lacking a time zone.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate today = LocalDate.now( z ) ;

Specify a date.

LocalDate ld = LocalDate.parse( "2017-09-05" ) ;  // Standard ISO 8601 format for input: YYYY-MM-DD.

The advantage of standard ISO 8601 format is that alphabetical order happens to also be chronological order.

So you can do text-based comparison using greater-than/less-than logic.

String sql = "DELETE * FROM tbl WHERE col >= '" + ld.toString() + "' ;" ;

Another big advantage over the other two approaches:

  • Trying to represent date-time with a fractional real number is messy.
  • Storing a count-from-epoch makes debugging and troubleshooting difficult as a human cannot readily read the meaning of the data.

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.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • It would be nice if you expand on your statement `though you should NOT be using Date class`. Adding a 3rd party 'compatibility' library to your project if you do just simple dates operations (like in the OP's question), which `java.util.Date` is pretty sufficient for, doesn't seem right. It's not clear from your answer why `java.time` should be a one-solution-for-all-situations and what are the benefits you get for the simple tasks with `java.time` vs `java.util.Date`. – Alexander Abakumov Mar 27 '18 at 16:00
  • And regarding your proposal to store dates as strings. This is not only bad advice from the performance and app DB size perspective (which is important in mobile world), but significantly complicates your life when it comes to queries involving dates arithmetic. Sacrificing all the above just for human readability during debugging (which should be compensated by a good column values formatting SQLite client) makes this option very questionable. – Alexander Abakumov Mar 27 '18 at 16:32