2010-12-13 6 views
27

J'ai la date stockée en tant que chaîne dans une base de données sqlite comme "28/11/2010". Je veux convertir la chaîne à ce jour.Sqlite convertir la chaîne à ce jour

Plus précisément, je dois convertir beaucoup de dates de chaînes entre deux dates.

Dans postgresql, j'utilise to_date('30/11/2010','dd/MM/yyyy'), comment puis-je faire la même chose avec sqlite?

Quelque chose comme ceci:

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') 

Répondre

46

SQLite doesn't have a date type vous aurez besoin de faire la comparaison de chaînes pour y parvenir. Pour cela vous devez travailler pour inverser l'ordre - par exemple du jj/mm/aaaa à aaaaMMjj, en utilisant quelque chose comme

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

+1: Si la date avait été formatée dans quelque chose que les fonctions de gestion des dates de SQLite comprennent, il aurait été possible de faire quelque chose de plus intelligent. (Ou si la date avait été convertie en jours juliens avant d'être stockée dans la base de données.) Mais ce n'était pas le cas, et la "date" doit être réparée. Bien sûr, il pourrait aussi essayer d'ajouter sa propre fonction 'to_date', mais la façon de le faire dépend de ce que SQLite incorpore (que nous ne connaissons pas). –

+1

@Donal re créer sa propre fonction 'to_date', ce qui est le pari que toutes les chaînes dans ce champ ne sont pas des dates valides :-) –

8

Une chose que vous devriez regarder dans est le SQLite date and time functions, surtout si vous allez devoir manipuler beaucoup de dates. C'est la bonne façon d'utiliser les dates, au prix de changer le format interne (doit être ISO, c'est-à-dire aaaa-MM-jj).

+3

Cette documentation est encore et encore citée ... Cependant, IMO il doit être retravaillé à trouver l'information rapidement. Tous les détails significatifs sont enterrés. Par exemple, est-il possible de déterminer le type de retour de la fonction strftime à première vue en moins de 10 secondes? Non ! Dans tout javadoc décent, c'est faisable. – Stephan

+0

C'est sur cités parce que c'est encore plus souvent ignoré, mais accordé il pourrait faire avec un retravailler. – MPelletier

16

Date enregistrée comme texte (20/10/2013 03:26) Pour faire une requête et sélectionner des enregistrements entre les dates?

meilleure version est:

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

le substr du 20/10/2013 donne le format de date 20.131.020 DATE (20131021) - qui rend le travail SQL avec des dates et en utilisant les fonctions de date et d'heure.

OU

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'); 

et voici dans une ligne

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

Ceci est pour fecha (TEXTE) Date de format AAAA-MM-JJ HH: mm: ss, par exemple, je veux tous les dossiers de Ene-05-2014 (2014-01-05):

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

L'approche UDF est ma préférence par rapport à cassants substr val ues.

#!/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() 

Cela vous donnera ces résultats:

[{'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'}] 

L'équivalent SQLite de tout ce robuste est une armure emmêlés de substr et instr appels que vous devriez éviter.

0

Je stocke la date en format 'DD-MON-YYYY (10-juin-2016) et la requête ci-dessous fonctionne pour moi de rechercher des enregistrements entre 2 dates.

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

Si le format Source Date ne correspond pas il y a un problème avec substr fonction, par exemple:

1/1/2017ou1/11/2017ou11/11/2017ou1/1/17 etc.

Alors J'ai suivi une approche différente en utilisant une table temporaire. Cet extrait génère "YYYY-MM-DD" + heure s'il existe.

Notez que cette version accepte le format Jour/Mois/Année. Si vous voulez mois/jour/année échanger les deux premières variables DayPart et MonthPart. En outre, les dates de deux ans '44 -'99 supposent 1944-1999 alors que '00 -'43 suppose 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; 
Questions connexes