2010-11-25 35 views
12

PythonとSQLiteを使用して日付の格納/取り出しに問題があります。SQLiteの日付の格納と変換

私は、SQLite日付列に日付をISO形式 (つまり、'2010-05-25')のテキストとして保存することを理解します。それが表に書き戻しデータに来るとき私は英国の日付(例えばウェブページ上)を表示するとき、私は

datetime.datetime.strptime(mydate,'%Y-%m-%d').strftime('%d/%m/%Y') 

を使用して日付を変換 しかし、SQLiteは非常に 寛容であるとされかなり日付フィールドに'25/06/2003'を保存する幸せが、私は、同じ 列の日付形式の混合物で

  • を残しすることができ

    • ので、この は理想的ではありません

      SQLiteの日付関数はISO形式でのみ機能します。

    は、したがって、私はコミット 前にバックISO形式に日付文字列を変換する必要があり、その後私は は、すべての日付フィールドで書かれており、必要に応じてISOに変換されようとしてデータをチェックし、一般的な機能が必要になります。それは のビットが私にとって面倒だと聞こえますが、おそらくそれは避けられません。

    より簡単なソリューションはありますか?日付フィールドを の10文字のフィールドに変更し、テーブル全体に'dd/mm/yyyy'を保存する方が簡単でしょうか?この方法では、テーブルからの読み込みまたは書き込み時には の変換は必要なく、日付計算を実行する必要がある場合は datetime()関数を使用できます。

    この問題を他の開発者がどのように克服していますか?どんな助けもありがとう。 私はPython 3.1でSQLite3を使用しています。

  • 答えて

    14

    あなたはsqlite3.connectdetect_types=sqlite3.PARSE_DECLTYPES、 を設定した場合、接続は、データベースからデータを引き出す際にPythonのデータ型 にsqliteのデータ型を変換しようとします。

    これは、非常に良くあなたが datetime.datetime.strptimedateutil.parser.parseで解析する必要が ランダム日付のような文字列よりも日時オブジェクトを操作するので、非常に良いことです。

    残念ながら、detect_typesを使用すると、それは以外のいくつかの形式で挿入された場合(データベースからデータを引き出すDATEデータとして受諾 文字列からのsqliteを停止しませんが、あなたは しようとするとエラーになりますYYYY-MM-DD) 接続がdatetime.dateオブジェクトに変換するために失敗するので:

    conn=sqlite3.connect(':memory:',detect_types=sqlite3.PARSE_DECLTYPES) 
    cur=conn.cursor() 
    cur.execute('CREATE TABLE foo(bar DATE)') 
    # Unfortunately, this is still accepted by sqlite 
    cur.execute("INSERT INTO foo(bar) VALUES (?)",('25/06/2003',)) 
    
    # But you won't be able to draw the data out later because parsing will fail 
    try: 
        cur.execute("SELECT * FROM foo") 
    except ValueError as err: 
        print(err) 
        # invalid literal for int() with base 10: '25/06/2003' 
        conn.rollback() 
    

    しかし、少なくともエラーはあなたが 文字列を挿入したという事実を警告しますDATEは本当にdatetimeを挿入する必要があります。日付オブジェクト:

    cur.execute("INSERT INTO foo(bar) VALUES (?)",(datetime.date(2003,6,25),)) 
    cur.execute("SELECT ALL * FROM foo") 
    data=cur.fetchall() 
    data=zip(*data)[0] 
    print(data) 
    # (datetime.date(2003, 6, 25),) 
    

    YYYY-MM-DD形式を使用する限り、DATEデータとして文字列を挿入することもできます。あなたは、文字列を挿入しますが、それはdatetime.dateオブジェクトとして出戻ってくることに注意してください:

    cur.execute("INSERT INTO foo(bar) VALUES (?)",('2003-06-25',)) 
    cur.execute("SELECT ALL * FROM foo") 
    data=cur.fetchall() 
    data=zip(*data)[0] 
    print(data) 
    # (datetime.date(2003, 6, 25), datetime.date(2003, 6, 25)) 
    

    ですから、DATEフィールドにのみdatetime.dateオブジェクトを挿入について規律ある場合に描画するとき、あなたは後で問題ありませんよデータを出力する。

    ユーザーがさまざまな形式の日付データを入力している場合は、dateutil.parser.parseをチェックしてください。これらのさまざまな文字列をdatetime.datetimeオブジェクトに変換するのに役立つ場合があります。

    +0

    ありがとうございます。日付オブジェクトのように見えます。よろしく。 –

    5

    SQLite自体にはネイティブの日付/時刻型がないことに注意してください。 @unutbuが答えたので、pysqlite/sqlite3モジュールは、どの列/値が日付/時刻であるかを推測しようとします(そして、それは本当に推測です)。 SQL式は簡単にそれを混乱させます。

    SQLiteにはさまざまな日付時刻関数があり、さまざまな文字列、unixepochとjulian形式の数字で動作し、変換を行うことができます。ドキュメントを参照してください:

    http://www.sqlite.org/lang_datefunc.html

    あなたはSQLiteのは、あなたは、Pythonに値をインポートし、それを行うにはPythonライブラリを使用するのではなく、必要な日付/時刻の仕事を得るためにそれがより便利かもしれません。たとえば、文字列値が存在すること、特定の長さなどが必要であるというSQLテーブル定義に制約を入れることができます。

    +0

    Rogerに返信してくれてありがとう。これらのSQLiteの日付関数をチェックアウトします。よろしく。 –