insertar funciones fechas fecha comparar actual android sql database sqlite date

android - funciones - sqlite time format



La mejor manera de trabajar con fechas en Android SQLite (9)

  1. Como se presume en este comentario , siempre usaría números enteros para almacenar fechas.
  2. Para el almacenamiento, puede utilizar un método de utilidad

    public static Long persistDate(Date date) { if (date != null) { return date.getTime(); } return null; }

    al igual que:

    ContentValues values = new ContentValues(); values.put(COLUMN_NAME, persistDate(entity.getDate())); long id = db.insertOrThrow(TABLE_NAME, null, values);

  3. Otro método de utilidad se encarga de la carga.

    public static Date loadDate(Cursor cursor, int index) { if (cursor.isNull(index)) { return null; } return new Date(cursor.getLong(index)); }

    se puede utilizar de esta manera:

    entity.setDate(loadDate(cursor, INDEX));

  4. Ordenar por fecha es una simple cláusula ORDEN SQL (porque tenemos una columna numérica). Lo siguiente ordenará descendente (la fecha más reciente va primero):

    public static final String QUERY = "SELECT table._id, table.dateCol FROM table ORDER BY table.dateCol DESC"; //... Cursor cursor = rawQuery(QUERY, null); cursor.moveToFirst(); while (!cursor.isAfterLast()) { // Process results }

Siempre asegúrese de almacenar la hora UTC / GMT , especialmente cuando trabaje con java.util.Calendar y java.text.SimpleDateFormat que usan la zona horaria predeterminada (es decir, la de su dispositivo). java.util.Date.Date() es seguro de usar ya que crea un valor UTC.

Tengo algunos problemas para trabajar con fechas en mi aplicación de Android que usa SQLite. Tengo un par de preguntas:

  1. ¿Qué tipo debo usar para almacenar fechas en SQLite (texto, entero, ...)?
  2. Dada la mejor manera de almacenar fechas, ¿cómo lo almaceno correctamente usando ContentValues?
  3. ¿Cuál es la mejor manera de recuperar la fecha de la base de datos SQLite?
  4. ¿Cómo hacer una selección sql en SQLite, ordenando los resultados por fecha?


La mejor manera de almacenar la date en SQlite DB es almacenar los DateTimeMilliseconds actuales. A continuación se muestra el fragmento de código para hacerlo

  1. Obtener el DateTimeMilliseconds

public static long getTimeMillis(String dateString, String dateFormat) throws ParseException { /*Use date format as according to your need! Ex. - yyyy/MM/dd HH:mm:ss */ String myDate = dateString;//"2017/12/20 18:10:45"; SimpleDateFormat sdf = new SimpleDateFormat(dateFormat/*"yyyy/MM/dd HH:mm:ss"*/); Date date = sdf.parse(myDate); long millis = date.getTime(); return millis; }

  1. Inserte los datos en su DB

public void insert(Context mContext, long dateTimeMillis, String msg) { //Your DB Helper MyDatabaseHelper dbHelper = new MyDatabaseHelper(mContext); database = dbHelper.getWritableDatabase(); ContentValues contentValue = new ContentValues(); contentValue.put(MyDatabaseHelper.DATE_MILLIS, dateTimeMillis); contentValue.put(MyDatabaseHelper.MESSAGE, msg); //insert data in DB database.insert("your_table_name", null, contentValue); //Close the DB connection. dbHelper.close(); }

Now, your data (date is in currentTimeMilliseconds) is get inserted in DB .

El siguiente paso es, cuando desea recuperar datos de la base de datos, debe convertir los respectivos milisegundos de la fecha y la fecha correspondientes. A continuación se muestra el fragmento de código de ejemplo para hacer lo mismo_

  1. Convertir los milisegundos de fecha en una cadena de fecha.

public static String getDate(long milliSeconds, String dateFormat) { // Create a DateFormatter object for displaying date in specified format. SimpleDateFormat formatter = new SimpleDateFormat(dateFormat/*"yyyy/MM/dd HH:mm:ss"*/); // Create a calendar object that will convert the date and time value in milliseconds to date. Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(milliSeconds); return formatter.format(calendar.getTime()); }

  1. Ahora, por fin recoger los datos y ver su funcionamiento ...

public ArrayList<String> fetchData() { ArrayList<String> listOfAllDates = new ArrayList<String>(); String cDate = null; MyDatabaseHelper dbHelper = new MyDatabaseHelper("your_app_context"); database = dbHelper.getWritableDatabase(); String[] columns = new String[] {MyDatabaseHelper.DATE_MILLIS, MyDatabaseHelper.MESSAGE}; Cursor cursor = database.query("your_table_name", columns, null, null, null, null, null); if (cursor != null) { if (cursor.moveToFirst()){ do{ //iterate the cursor to get data. cDate = getDate(cursor.getLong(cursor.getColumnIndex(MyDatabaseHelper.DATE_MILLIS)), "yyyy/MM/dd HH:mm:ss"); listOfAllDates.add(cDate); }while(cursor.moveToNext()); } cursor.close(); //Close the DB connection. dbHelper.close(); return listOfAllDates; }

Espero que esto ayude a todos! :)


La mejor manera es almacenar las fechas como un número, recibido mediante el comando Calendario.

//Building the table includes: StringBuilder query=new StringBuilder(); query.append("CREATE TABLE "+TABLE_NAME+ " ("); query.append(COLUMN_ID+"int primary key autoincrement,"); query.append(COLUMN_DATETIME+" int)"); //And inserting the data includes this: values.put(COLUMN_DATETIME, System.currentTimeMillis());

¿Por qué hacer esto? En primer lugar, obtener valores de un rango de fechas es fácil. Simplemente convierta su fecha en milisegundos, y luego consulte adecuadamente. Ordenar por fecha es igualmente fácil. Las llamadas a convertir entre varios formatos también son fáciles, como he incluido. La conclusión es que, con este método, puede hacer cualquier cosa que necesite hacer, sin problemas. Será un poco difícil leer un valor en bruto, pero más que compensa esa pequeña desventaja con la facilidad de lectura y uso de la máquina. Y, de hecho, es relativamente fácil construir un lector (y sé que hay algunos por ahí) que convertirá automáticamente la etiqueta de tiempo en fecha como tal para facilitar la lectura.

Vale la pena mencionar que los valores que surgen de esto deben ser largos, no int. Integer en sqlite puede significar muchas cosas, cualquier cosa desde 1-8 bytes, pero para casi todas las fechas, 64 bits, o una larga, es lo que funciona.

EDITAR: Como se ha señalado en los comentarios, debe usar el cursor.getLong() para obtener la marca de tiempo correctamente si hace esto.


Por lo general (igual que yo en mysql / postgres), almaceno las fechas en int (mysql / post) o en texto (sqlite) para almacenarlas en el formato de la marca de hora.

Luego los convertiré en objetos de fecha y realizaré acciones basadas en el usuario TimeZone


Prefiero esto. Esta no es la mejor manera, sino una solución rápida.

//Building the table includes: StringBuilder query= new StringBuilder(); query.append("CREATE TABLE "+TABLE_NAME+ " ("); query.append(COLUMN_ID+"int primary key autoincrement,"); query.append(COLUMN_CREATION_DATE+" DATE)"); //Inserting the data includes this: SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); values.put(COLUMN_CREATION_DATE,dateFormat.format(reactionGame.getCreationDate())); // Fetching the data includes this: try { java.util.Date creationDate = dateFormat.parse(cursor.getString(0); YourObject.setCreationDate(creationDate)); } catch (Exception e) { YourObject.setCreationDate(null); }


SQLite puede usar tipos de datos de texto, reales o enteros para almacenar fechas. Aún más, cada vez que realiza una consulta, los resultados se muestran con el formato %Y-%m-%d %H:%M:%S

Ahora, si inserta / actualiza los valores de fecha / hora utilizando las funciones de fecha / hora de SQLite, también puede almacenar milisegundos. Si ese es el caso, los resultados se muestran utilizando el formato %Y-%m-%d %H:%M:%f . Por ejemplo:

sqlite> create table test_table(col1 text, col2 real, col3 integer); sqlite> insert into test_table values ( strftime(''%Y-%m-%d %H:%M:%f'', ''2014-03-01 13:01:01.123''), strftime(''%Y-%m-%d %H:%M:%f'', ''2014-03-01 13:01:01.123''), strftime(''%Y-%m-%d %H:%M:%f'', ''2014-03-01 13:01:01.123'') ); sqlite> insert into test_table values ( strftime(''%Y-%m-%d %H:%M:%f'', ''2014-03-01 13:01:01.126''), strftime(''%Y-%m-%d %H:%M:%f'', ''2014-03-01 13:01:01.126''), strftime(''%Y-%m-%d %H:%M:%f'', ''2014-03-01 13:01:01.126'') ); sqlite> select * from test_table; 2014-03-01 13:01:01.123|2014-03-01 13:01:01.123|2014-03-01 13:01:01.123 2014-03-01 13:01:01.126|2014-03-01 13:01:01.126|2014-03-01 13:01:01.126

Ahora, haciendo algunas consultas para verificar si realmente podemos comparar los tiempos:

sqlite> select * from test_table /* using col1 */ where col1 between strftime(''%Y-%m-%d %H:%M:%f'', ''2014-03-01 13:01:01.121'') and strftime(''%Y-%m-%d %H:%M:%f'', ''2014-03-01 13:01:01.125''); 2014-03-01 13:01:01.123|2014-03-01 13:01:01.123|2014-03-01 13:01:01.123

Puede marcar el mismo SELECT utilizando col2 y col2 y obtendrá los mismos resultados. Como puede ver, la segunda fila (126 milisegundos) no se devuelve.

Tenga en cuenta que BETWEEN es inclusivo, por lo tanto ...

sqlite> select * from test_table where col1 between /* Note that we are using 123 milliseconds down _here_ */ strftime(''%Y-%m-%d %H:%M:%f'', ''2014-03-01 13:01:01.123'') and strftime(''%Y-%m-%d %H:%M:%f'', ''2014-03-01 13:01:01.125'');

... volverá el mismo conjunto.

Intente jugar con diferentes rangos de fecha / hora y todo se comportará como se espera.

¿Qué pasa sin la función de tiempo de strftime ?

sqlite> select * from test_table /* using col1 */ where col1 between ''2014-03-01 13:01:01.121'' and ''2014-03-01 13:01:01.125''; 2014-03-01 13:01:01.123|2014-03-01 13:01:01.123|2014-03-01 13:01:01.123

¿Qué pasa sin la función strftime y sin milisegundos?

sqlite> select * from test_table /* using col1 */ where col1 between ''2014-03-01 13:01:01'' and ''2014-03-01 13:01:02''; 2014-03-01 13:01:01.123|2014-03-01 13:01:01.123|2014-03-01 13:01:01.123 2014-03-01 13:01:01.126|2014-03-01 13:01:01.126|2014-03-01 13:01:01.126

¿Qué hay de ORDER BY ?

sqlite> select * from test_table order by 1 desc; 2014-03-01 13:01:01.126|2014-03-01 13:01:01.126|2014-03-01 13:01:01.126 2014-03-01 13:01:01.123|2014-03-01 13:01:01.123|2014-03-01 13:01:01.123 sqlite> select * from test_table order by 1 asc; 2014-03-01 13:01:01.123|2014-03-01 13:01:01.123|2014-03-01 13:01:01.123 2014-03-01 13:01:01.126|2014-03-01 13:01:01.126|2014-03-01 13:01:01.126

Funciona bien

Finalmente, cuando se trata de operaciones reales dentro de un programa (sin usar el ejecutable sqlite ...)

Por cierto: estoy usando JDBC (no estoy seguro acerca de otros idiomas) ... el controlador sqlite-jdbc v3.7.2 de xerial - quizás las revisiones más nuevas cambien el comportamiento que se explica a continuación ... Si está desarrollando en Android, no necesita un controlador jdbc. Todas las operaciones de SQL se pueden enviar utilizando el SQLiteOpenHelper .

JDBC tiene diferentes métodos para obtener valores de fecha / hora reales de una base de datos: java.sql.Date , java.sql.Time y java.sql.Timestamp .

Los métodos relacionados en java.sql.ResultSet son (obviamente) getDate(..) , getTime(..) y getTimestamp() respectivamente.

Por ejemplo:

Statement stmt = ... // Get statement from connection ResultSet rs = stmt.executeQuery("SELECT * FROM TEST_TABLE"); while (rs.next()) { System.out.println("COL1 : "+rs.getDate("COL1")); System.out.println("COL1 : "+rs.getTime("COL1")); System.out.println("COL1 : "+rs.getTimestamp("COL1")); System.out.println("COL2 : "+rs.getDate("COL2")); System.out.println("COL2 : "+rs.getTime("COL2")); System.out.println("COL2 : "+rs.getTimestamp("COL2")); System.out.println("COL3 : "+rs.getDate("COL3")); System.out.println("COL3 : "+rs.getTime("COL3")); System.out.println("COL3 : "+rs.getTimestamp("COL3")); } // close rs and stmt.

Como SQLite no tiene un tipo de datos DATE / TIME / TIMESTAMP real, todos estos 3 métodos devuelven valores como si los objetos se hubieran inicializado con 0:

new java.sql.Date(0) new java.sql.Time(0) new java.sql.Timestamp(0)

Entonces, la pregunta es: ¿cómo podemos realmente seleccionar, insertar o actualizar objetos de fecha / hora / marca de tiempo? No hay una respuesta fácil. Puedes probar diferentes combinaciones, pero te obligarán a incrustar funciones de SQLite en todas las sentencias de SQL. Es mucho más fácil definir una clase de utilidad para transformar texto en objetos de fecha dentro de su programa Java. Pero siempre recuerde que SQLite transforma cualquier valor de fecha a UTC + 0000.

En resumen, a pesar de la regla general de usar siempre el tipo de datos correcto, o incluso los enteros que denotan el tiempo Unix (milisegundos desde la época), me parece mucho más fácil usar el formato SQLite predeterminado ( ''%Y-%m-%d %H:%M:%f'' o en Java ''yyyy-MM-dd HH:mm:ss.SSS'' ) en lugar de complicar todas sus declaraciones SQL con funciones SQLite. El primer enfoque es mucho más fácil de mantener.

TODO: Revisaré los resultados cuando use getDate / getTime / getTimestamp dentro de Android (API15 o superior) ... tal vez el controlador interno sea diferente de sqlite-jdbc ...


Puede utilizar un campo de texto para almacenar fechas dentro de SQLite .

El almacenamiento de fechas en formato UTC, el valor predeterminado si usa datetime(''now'') (yyyy-MM-dd HH:mm:ss) , permitirá la clasificación por la columna de fecha.

Al recuperar las fechas como cadenas de SQLite , puede formatearlas o convertirlas según sea necesario a formatos regionalizados locales utilizando el Calendario o el método android.text.format.DateUtils.formatDateTime .

Aquí hay un método de formateador regionalizado que utilizo;

public static String formatDateTime(Context context, String timeToFormat) { String finalDateTime = ""; SimpleDateFormat iso8601Format = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss"); Date date = null; if (timeToFormat != null) { try { date = iso8601Format.parse(timeToFormat); } catch (ParseException e) { date = null; } if (date != null) { long when = date.getTime(); int flags = 0; flags |= android.text.format.DateUtils.FORMAT_SHOW_TIME; flags |= android.text.format.DateUtils.FORMAT_SHOW_DATE; flags |= android.text.format.DateUtils.FORMAT_ABBREV_MONTH; flags |= android.text.format.DateUtils.FORMAT_SHOW_YEAR; finalDateTime = android.text.format.DateUtils.formatDateTime(context, when + TimeZone.getDefault().getOffset(when), flags); } } return finalDateTime; }


"SELECT "+_ID+" , "+_DESCRIPTION +","+_CREATED_DATE +","+_DATE_TIME+" FROM "+TBL_NOTIFICATION+" ORDER BY "+"strftime(%s,"+_DATE_TIME+") DESC";