Answers:
您可以使用文本字段将日期存储在中SQLite
。
以UTC格式存储日期,如果使用默认格式,datetime('now')
(yyyy-MM-dd HH:mm:ss)
则将允许按日期列进行排序。
SQLite
然后,您可以使用“日历”或android.text.format.DateUtils.formatDateTime
方法将日期作为字符串检索,然后根据需要将其格式化/转换为本地区域化格式。
这是我使用的区域化格式化程序方法;
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;
}
最好的方法是使用“日历”命令将日期存储为数字。
//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());
为什么这样 首先,从日期范围获取值很容易。只需将日期转换为毫秒,然后进行适当的查询即可。按日期排序同样很容易。正如我提到的,在各种格式之间进行转换的调用也同样容易。最重要的是,使用这种方法,您可以做任何需要做的事情,没有问题。读取原始值会稍有困难,但由于容易机读和使用,因此弥补了这一轻微缺点。实际上,构建一个可以自动将时间标签转换为日期的阅读器(我知道那里有一些阅读器)相对容易,以便于阅读。
值得一提的是,由此产生的值应该是长整数,而不是整数。sqlite中的整数可以表示很多东西,从1到8个字节不等,但是对于几乎所有日期,64位或一个长整数才有效。
编辑:正如评论中指出的那样,cursor.getLong()
如果您执行此操作,则必须使用来正确获取时间戳。
对于存储,您可以使用实用程序方法
public static Long persistDate(Date date) {
if (date != null) {
return date.getTime();
}
return null;
}
像这样:
ContentValues values = new ContentValues();
values.put(COLUMN_NAME, persistDate(entity.getDate()));
long id = db.insertOrThrow(TABLE_NAME, null, values);
另一种实用程序方法负责加载
public static Date loadDate(Cursor cursor, int index) {
if (cursor.isNull(index)) {
return null;
}
return new Date(cursor.getLong(index));
}
可以这样使用:
entity.setDate(loadDate(cursor, INDEX));
按日期排序是简单的SQL ORDER子句(因为我们有一个数字列)。以下将按降序排列(即最新日期在前):
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
}
始终确保存储UTC / GMT时间,尤其是在使用UTC / GMT时,java.util.Calendar
并且java.text.SimpleDateFormat
使用默认(即设备的)时区。
java.util.Date.Date()
可以安全使用,因为它可以创建UTC值。
SQLite可以使用文本,实数或整数数据类型来存储日期。而且,无论何时执行查询,结果都将使用format来显示%Y-%m-%d %H:%M:%S
。
现在,如果您使用SQLite日期/时间函数插入/更新日期/时间值,则实际上也可以存储毫秒。如果是这样,结果将使用format显示%Y-%m-%d %H:%M:%f
。例如:
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
现在,进行一些查询以验证我们是否真正能够比较时间:
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
您可以SELECT
使用col2
和进行相同的检查col3
,您将获得相同的结果。如您所见,第二行(126毫秒)未返回。
请注意,BETWEEN
包括在内,因此...
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');
...将返回相同的集合。
尝试使用不同的日期/时间范围,一切都会按预期进行。
没有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
没有strftime
功能又没有毫秒怎么办?
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
那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
效果很好。
最后,在处理程序中的实际操作时(不使用sqlite可执行文件...)
顺便说一句:我正在使用JDBC(不确定其他语言)...来自xerial的sqlite-jdbc驱动程序v3.7.2- 也许较新的版本会更改下面说明的行为...如果您使用Android开发,则不要需要一个jdbc驱动程序。可以使用提交所有SQL操作SQLiteOpenHelper
。
JDBC有不同的方法来从数据库中获取实际的日期/时间值:java.sql.Date
,java.sql.Time
,和java.sql.Timestamp
。
相关的方法java.sql.ResultSet
是(明显)getDate(..)
,getTime(..)
和getTimestamp()
分别。
例如:
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.
由于SQLite没有实际的DATE / TIME / TIMESTAMP数据类型,所有这三种方法都返回值,就好像对象是用0初始化的:
new java.sql.Date(0)
new java.sql.Time(0)
new java.sql.Timestamp(0)
因此,问题是:我们如何才能真正选择,插入或更新日期/时间/时间戳对象?没有简单的答案。您可以尝试不同的组合,但是它们将迫使您将SQLite函数嵌入所有SQL语句中。定义实用程序类以将文本转换为Java程序内的Date对象要容易得多。但请始终记住,SQLite会将任何日期值转换为UTC + 0000。
总而言之,尽管总的规则是始终使用正确的数据类型,甚至是表示Unix时间的整数(自纪元以来的毫秒数),但我发现使用默认的SQLite格式('%Y-%m-%d %H:%M:%f'
或Java 格式)要容易得多,'yyyy-MM-dd HH:mm:ss.SSS'
而不是使所有SQL语句复杂化为SQLite函数。前一种方法更容易维护。
待办事项:在Android(API15或更高版本)中使用getDate / getTime / getTimestamp时,我将检查结果...内部驱动程序可能与sqlite-jdbc不同...
存储date
在SQlite DB中的最佳方法是存储当前文件DateTimeMilliseconds
。以下是这样做的代码段
- 得到
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;
}
- 将数据插入数据库
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 .
下一步是,当您要从数据库中检索数据时,需要将相应的日期时间毫秒转换为相应的日期。以下是执行相同代码的示例代码段
- 将日期毫秒转换为日期字符串。
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());
}
- 现在,最后获取数据并查看其工作...
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;
}
希望这对大家有帮助!:)
1-就像StErMi所说的一样。
2-请阅读以下内容:http : //www.vogella.de/articles/AndroidSQLite/article.html
3-
Cursor cursor = db.query(TABLE_NAME, new String[] {"_id", "title", "title_raw", "timestamp"},
"//** YOUR REQUEST**//", null, null, "timestamp", null);
看这里:
4-请参阅答案3
我喜欢这个。这不是最佳方法,而是快速解决方案。
//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);
}
"SELECT "+_ID+" , "+_DESCRIPTION +","+_CREATED_DATE +","+_DATE_TIME+" FROM "+TBL_NOTIFICATION+" ORDER BY "+"strftime(%s,"+_DATE_TIME+") DESC";