2010-12-13 251 views
27

我有日期作爲字符串存儲在像「28/11/2010」一樣的sqlite數據庫中。 我想將字符串轉換爲日期。Sqlite將字符串轉換爲日期

具體來說,我必須在兩個日期之間轉換大量的字符串日期。

在postgresql中,我使用to_date('30/11/2010','dd/MM/yyyy'),我如何用sqlite做同樣的事情?

事情是這樣的:

SELECT * FROM table 
    WHERE to_date(column,'dd/MM/yyyy') 
    BETWEEN to_date('01/11/2010','dd/MM/yyyy') 
    AND  to_date('30/11/2010','dd/MM/yyyy') 

回答

46

由於sqlite的doesn't have a date type你需要做字符串比較來實現這一目標。對於工作,你需要扭轉的順序 - 例如從DD/MM/YYYY至年月日,使用類似

where substr(column,7)||substr(column,4,2)||substr(column,1,2) 
     between '20101101' and '20101130' 
+1

+1:如果日期已被格式化爲SQLite的日期處理函數所理解的事情,那麼可以做一些更智能的事情。 (或者如果日期在存入數據庫之前已被轉換爲朱利安日)。但事實並非如此,「日期」需要修補。當然,他也可以嘗試添加他自己的'to_date'函數,但是如何做到這一點取決於嵌入的SQLite(我們不知道)。 – 2010-12-13 13:25:48

+1

@Donal重新創建了自己的'to_date'函數,那麼該字段中的所有字符串都不是有效日期的賭注是什麼:-) – 2010-12-13 14:13:01

8

有一件事你應該看看是SQLite date and time functions,特別是如果你將不得不操縱很多日期。以更改內部格式(必須是ISO,即yyyy-MM-dd)爲代價才能使用日期。

+3

本文檔被全部引用...但是,IMO需要重新編寫快速找到信息。所有有意義的細節都被埋沒例如,是否有可能在不到10秒的時間內首先確定strftime函數的返回類型...?不!在任何體面的javadoc中都是可行的。 – Stephan 2015-10-11 10:45:40

+0

它被引用過,因爲它更經常被忽略,但被授予它可以做返工。 – MPelletier 2015-10-11 14:23:59

16

保存日期爲TEXT(20/10/2013 03:26) 要進行查詢並選擇日期之間的記錄嗎?

更好的版本是:

SELECT TIMSTARTTIMEDATE 
FROM TIMER 
WHERE DATE(substr(TIMSTARTTIMEDATE,7,4) 
||substr(TIMSTARTTIMEDATE,4,2) 
||substr(TIMSTARTTIMEDATE,1,2)) 
BETWEEN DATE(20131020) AND DATE(20131021); 

的SUBSTR從20/10/2013給人20131020 日期格式(20131021) - 這使得SQL使用日期和使用日期和時間函數。

OR

SELECT TIMSTARTTIMEDATE 
FROM TIMER 
WHERE DATE(substr(TIMSTARTTIMEDATE,7,4) 
||'-' 
||substr(TIMSTARTTIMEDATE,4,2) 
||'-' 
||substr(TIMSTARTTIMEDATE,1,2)) 
BETWEEN DATE('2013-10-20') AND DATE('2013-10-21'); 

這裏是一個線

SELECT TIMSTARTTIMEDATE FROM TIMER WHERE DATE(substr(TIMSTARTTIMEDATE,7,4)||'-'||substr(TIMSTARTTIMEDATE,4,2)||'-'||substr(TIMSTARTTIMEDATE,1,2)) BETWEEN DATE('2013-10-20') AND DATE('2013-10-21'); 
0

這是出生日期(文本)格式的日期YYYY-MM-DD HH:MM:SS比如我希望所有的(2014年1月5日)烯05-2014的記錄:

SELECT 
fecha 
FROM 
Mytable 
WHERE 
DATE(substr(fecha ,1,4) ||substr(fecha ,6,2)||substr(fecha ,9,2)) 
BETWEEN 
DATE(20140105) 
AND 
DATE(20140105); 
3

的UDF方法是我的喜好比較脆substr VAL UE的。

#!/usr/bin/env python3 
import sqlite3 
from dateutil import parser 
from pprint import pprint 


def date_parse(s): 
    ''' Converts a string to a date ''' 
    try: 
     t = parser.parse(s, parser.parserinfo(dayfirst=True)) 
     return t.strftime('%Y-%m-%d') 
    except: 
     return None 


def dict_factory(cursor, row): 
    ''' Helper for dict row results ''' 
    d = {} 
    for idx, col in enumerate(cursor.description): 
     d[col[0]] = row[idx] 
    return d 


def main(): 
    ''' Demonstrate UDF ''' 
    with sqlite3.connect(":memory:") as conn: 
     conn.row_factory = dict_factory 
     setup(conn) 

     ################################################## 
     # This is the code that matters. The rest is setup noise. 
     conn.create_function("date_parse", 1, date_parse) 
     cur = conn.cursor() 
     cur.execute(''' select "date", date_parse("date") as parsed from _test order by 2; ''') 
     pprint(cur.fetchall()) 
     ################################################## 

def setup(conn): 
    ''' Setup some values to parse ''' 
    cur = conn.cursor() 

    # Make a table 
    sql = ''' 
    create table _test (
     "id" integer primary key, 
     "date" text 
    ); 
    ''' 
    cur.execute(sql) 

    # Fill the table 
    dates = [ 
     '2/1/03', '03/2/04', '4/03/05', '05/04/06', 
     '6/5/2007', '07/6/2008', '8/07/2009', '09/08/2010', 
     '2-1-03', '03-2-04', '4-03-05', '05-04-06', 
     '6-5-2007', '07-6-2008', '8-07-2009', '09-08-2010', 
     '31/12/20', '31-12-2020', 
     'BOMB!', 
    ] 
    params = [(x,) for x in dates] 
    cur.executemany(''' insert into _test ("date") values(?); ''', params) 


if __name__ == "__main__": 
    main() 

這會給你的結果:

[{'date': 'BOMB!', 'parsed': None}, 
{'date': '2/1/03', 'parsed': '2003-01-02'}, 
{'date': '2-1-03', 'parsed': '2003-01-02'}, 
{'date': '03/2/04', 'parsed': '2004-02-03'}, 
{'date': '03-2-04', 'parsed': '2004-02-03'}, 
{'date': '4/03/05', 'parsed': '2005-03-04'}, 
{'date': '4-03-05', 'parsed': '2005-03-04'}, 
{'date': '05/04/06', 'parsed': '2006-04-05'}, 
{'date': '05-04-06', 'parsed': '2006-04-05'}, 
{'date': '6/5/2007', 'parsed': '2007-05-06'}, 
{'date': '6-5-2007', 'parsed': '2007-05-06'}, 
{'date': '07/6/2008', 'parsed': '2008-06-07'}, 
{'date': '07-6-2008', 'parsed': '2008-06-07'}, 
{'date': '8/07/2009', 'parsed': '2009-07-08'}, 
{'date': '8-07-2009', 'parsed': '2009-07-08'}, 
{'date': '09/08/2010', 'parsed': '2010-08-09'}, 
{'date': '09-08-2010', 'parsed': '2010-08-09'}, 
{'date': '31/12/20', 'parsed': '2020-12-31'}, 
{'date': '31-12-2020', 'parsed': '2020-12-31'}] 

SQLite的等價的東西這個健壯的substrinstr電話,你應該避免糾結的編織。

0

我將日期存儲爲'DD-MON-YYYY格式(2016年6月10日),下面的查詢適用於我在兩個日期之間搜索記錄。

select date, substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), case 
substr(date, 4,3) 
when 'Jan' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Jan' , '01')) 
when 'Feb' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Feb' , '02')) 
when 'Mar' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Mar' , '03')) 
when 'Apr' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Apr' , '04')) 
when 'May' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'May' , '05')) 
when 'Jun' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Jun' , '06')) 
when 'Jul' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Jul' , '07')) 
when 'Aug' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Aug' , '08')) 
when 'Sep' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Sep' , '09')) 
when 'Oct' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Oct' , '10')) 
when 'Nov' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Nov' , '11')) 
when 'Dec' then strftime('%s', replace(substr(date,8,11) || '-' || substr(date,4,4) || substr(date, 1,2), 'Dec' , '12')) 
else '0' end as srcDate from payment where srcDate >= strftime('%s', '2016-07-06') and srcDate <= strftime('%s', '2016-09-06'); 
1

如果來源日期格式不一致有一些問題 與substr功能,例如:

2017年1月1日2017年1月11日2017年11月11日17年1月1日

所以我使用臨時表跟蹤了一個不同的應用程序。如果存在,此片段輸出'YYYY-MM-DD'+時間。

請注意,此版本接受日/月/年格式。如果您希望月/日/年 交換前兩個變量DayPartMonthPart。另外,兩年的日期'44 -99假定1944-1999,而'00 -43假設2000-2043。

BEGIN; 

    CREATE TEMP TABLE [DateconvertionTable] (Id TEXT PRIMARY KEY, OriginalDate TEXT , SepA INTEGER, DayPart TEXT,Rest1 TEXT, SepB INTEGER, MonthPart TEXT, Rest2 TEXT, SepC INTEGER, YearPart TEXT, Rest3 TEXT, NewDate TEXT); 
    INSERT INTO [DateconvertionTable] (Id,OriginalDate) SELECT SourceIdColumn, SourceDateColumn From [SourceTable]; 

    --day Part (If day is first) 

    UPDATE [DateconvertionTable] SET SepA=instr(OriginalDate ,'/'); 
    UPDATE [DateconvertionTable] SET DayPart=substr(OriginalDate,1,SepA-1) ; 
    UPDATE [DateconvertionTable] SET Rest1=substr(OriginalDate,SepA+1); 

    --Month Part (If Month is second) 

    UPDATE [DateconvertionTable] SET SepB=instr(Rest1,'/'); 
    UPDATE [DateconvertionTable] SET MonthPart=substr(Rest1, 1,SepB-1); 
    UPDATE [DateconvertionTable] SET Rest2=substr(Rest1,SepB+1); 

    --Year Part (3d) 

    UPDATE [DateconvertionTable] SET SepC=instr(Rest2,' '); 

      --Use Cases In case of time string included 
    UPDATE [DateconvertionTable] SET YearPart= CASE WHEN SepC=0 THEN Rest2 ELSE substr(Rest2,1,SepC-1) END; 

      --The Rest considered time 
    UPDATE [DateconvertionTable] SET Rest3= CASE WHEN SepC=0 THEN '' ELSE substr(Rest2,SepC+1) END; 

      -- Convert 1 digit day and month to 2 digit 
    UPDATE [DateconvertionTable] SET DayPart=0||DayPart WHERE CAST(DayPart AS INTEGER)<10; 
    UPDATE [DateconvertionTable] SET MonthPart=0||MonthPart WHERE CAST(MonthPart AS INTEGER)<10; 

      --If there is a need to convert 2 digit year to 4 digit year, make some assumptions... 
    UPDATE [DateconvertionTable] SET YearPart=19||YearPart WHERE CAST(YearPart AS INTEGER)>=44 AND CAST(YearPart AS INTEGER)<100; 
    UPDATE [DateconvertionTable] SET YearPart=20||YearPart WHERE CAST(YearPart AS INTEGER)<44 AND CAST(YearPart AS INTEGER)<100; 

    UPDATE [DateconvertionTable] SET NewDate = YearPart || '-' || MonthPart || '-' || DayPart || ' ' || Rest3; 

    UPDATE [SourceTable] SET SourceDateColumn=(Select NewDate FROM DateconvertionTable WHERE [DateconvertionTable].id=SourceIdColumn); 
    END;