Android SQLite에서 날짜를 다루는 가장 좋은 방법

SQLite를 사용하는 Android 응용 프로그램에서 날짜를 사용하는 데 문제가 있습니다. 몇 가지 질문이 있습니다.

  1. SQLite에 날짜를 저장하려면 어떤 유형을 사용해야합니까 (텍스트, 정수, …)?
  2. 날짜를 저장하는 가장 좋은 방법이 주어지면 ContentValues를 사용하여 올바르게 저장하는 방법은 무엇입니까?
  3. SQLite 데이터베이스에서 날짜를 검색하는 가장 좋은 방법은 무엇입니까?
  4. SQLite에서 SQL을 선택하여 날짜별로 결과를 정렬하는 방법은 무엇입니까?


답변

텍스트 필드를 사용하여에 날짜를 저장할 수 있습니다 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;
}

답변

가장 좋은 방법은 Calendar 명령을 사용하여받은 날짜를 숫자로 저장하는 것입니다.

//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()); 

왜 이렇게합니까? 우선, 날짜 범위에서 값을 가져 오는 것이 쉽습니다. 날짜를 밀리 초로 변환 한 다음 적절하게 쿼리하십시오. 날짜별로 정렬하는 것도 비슷합니다. 다양한 형식으로 변환하는 호출도 마찬가지로 포함되어 있습니다. 결론은이 방법을 사용하면 문제없이 수행 할 수있는 모든 것을 할 수 있다는 것입니다. 원시 값을 읽는 것은 약간 어려울 수 있지만 쉽게 기계를 읽고 사용할 수 있다는 점에서 약간의 단점을 구성합니다. 실제로 실제로 읽기 쉬운 시간표를 날짜로 자동 변환하는 리더를 작성하는 것이 상대적으로 쉽습니다 (그리고 일부가 있다는 것을 알고 있습니다).

이것에서 나오는 값은 int가 아니라 길어야한다는 것을 언급 할 가치가 있습니다. sqlite의 정수는 1-8 바이트의 많은 것을 의미 할 수 있지만 거의 모든 날짜에 대해 64 비트 또는 긴 것이 작동합니다.

편집 : 의견에서 지적 했듯이이 cursor.getLong()작업을 수행하면 타임 스탬프를 올바르게 얻는 데 사용해야합니다 .


답변

  1. 이 주석에서 추정 것처럼 항상 정수를 사용하여 날짜를 저장합니다.
  2. 저장을 위해 유틸리티 방법을 사용할 수 있습니다

    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);
    
  3. 다른 유틸리티 방법은 로딩을 처리합니다

    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));
  4. 날짜순은 간단한 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 시간을 , 특히 작업을 할 때, 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 실행 파일을 사용하지 않고 …)

BTW : 나는 JDBC (하지 않도록 다른 언어에 대한)에서 … SQLite는-JDBC 드라이버 v3.7.2 사용하고 xerial을 – 어쩌면 새로운 버전에서는 안드로이드 개발하는 경우, 당신은하지 않습니다 … 동작은 아래에 설명 변경 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)

따라서 질문은 어떻게 날짜 / 시간 / 시간 소인 객체를 실제로 선택, 삽입 또는 업데이트 할 수 있습니까?입니다. 쉬운 대답이 없습니다. 다른 조합을 시도 할 수 있지만 모든 SQL 문에 SQLite 함수를 포함시켜야합니다. Java 프로그램 내에서 텍스트를 Date 객체로 변환하는 유틸리티 클래스를 정의하는 것이 훨씬 쉽습니다. 그러나 SQLite는 모든 날짜 값을 UTC + 0000으로 변환합니다.

요약하면, 항상 올바른 데이터 유형을 사용하는 일반적인 규칙이나 Unix 시간을 나타내는 정수 (epoch 이후 밀리 초)에도 불구하고 모든 SQL 문을 복잡하게하기보다는 기본 SQLite 형식 ( '%Y-%m-%d %H:%M:%f'또는 Java 'yyyy-MM-dd HH:mm:ss.SSS')을 사용하는 것이 훨씬 쉽습니다 . SQLite 함수. 전자의 접근 방식은 유지 관리가 훨씬 쉽습니다.

TODO : 안드로이드에서 getDate / getTime / getTimestamp를 사용할 때 결과를 확인할 것입니다 (API15 이상) … 어쩌면 내부 드라이버가 sqlite-jdbc와 다를 수 있습니다 …


답변

일반적으로 (mysql / postgres에서와 동일) 날짜를 int (mysql / post) 또는 text (sqlite)로 저장하여 타임 스탬프 형식으로 저장합니다.

그런 다음 Date 객체로 변환하고 사용자 TimeZone을 기반으로 작업을 수행합니다.


답변

가게에 가장 좋은 방법 dateSQLite는 DB는 전류를 저장하는 것입니다 DateTimeMilliseconds. 다음은 그렇게하는 코드 스 니펫입니다.

  1. 얻을 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. 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 .

다음 단계는 DB에서 데이터를 검색하려는 경우 각 날짜 시간 (밀리 초)을 해당 날짜로 변환해야합니다. 다음은 동일한 작업을 수행하는 샘플 코드 스 니펫입니다.

  1. 날짜 밀리 초를 날짜 문자열로 변환하십시오.
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. 이제 마지막으로 데이터를 가져 와서 작동하는지 확인하십시오.
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

삼 –

Cursor cursor = db.query(TABLE_NAME, new String[] {"_id", "title", "title_raw", "timestamp"},
                "//** YOUR REQUEST**//", null, null, "timestamp", null);

여기를 보아라:

SQLiteDatabase의 Query ()

4-답변 3 참조