2011-05-10 17 views
11

Tengo una base de datos SQLite donde almaceno las fechas como tics. No estoy usando el formato predeterminado ISO8601. Digamos que tengo una tabla definida de la siguiente manera:¿Cómo puedo almacenar la marca de tiempo actual en SQLite como ticks?

CREATE TABLE TestDate (LastModifiedTime DATETIME) 

Utilizando SQL, deseo insertar la fecha y la hora actuales. Si ejecuto alguno de los enunciados siguientes, termino almacenando la fecha y la hora como una cadena y no como ticks.

INSERT INTO TestDate (LastModifiedTime) VALUES(CURRENT_TIMESTAMP) 
INSERT INTO TestDate (LastModifiedTime) VALUES(DateTime('now')) 

He mirado el SQLite documenation, pero no parecen encontrar ninguna opción para obtener la fecha y hora actual en las garrapatas.

Por supuesto, puedo definir un parámetro en C# y almacenar el valor como System.DateTime. Esto hace que la fecha y hora se guarde en la base de datos en tics.

Lo que me gustaría hacer es poder insertar y actualizar la marca de tiempo actual directamente desde dentro de la declaración SQL. ¿Cómo haría esto?

Editar:

La razón por la que desea que los datos almacenados como garrapatas en la base de datos, es que las fechas se almacenan en el mismo formato que se almacena por el proveedor de datos ADO.Net, y de modo que cuando el los datos también se consultan utilizando el proveedor ADO.Net, se recupera correctamente como tipo System.DataTime .Net.

+0

THX, para insertar la marca de tiempo actual en la base de datos solo agregue ---> DateTime ('ahora') – user956584

Respuesta

2

Tras un nuevo estudio de la SQLite documentation y otra información que se encuentra en las conversiones numéricas fecha, me han llegado con la siguiente fórmula, que parece producir resultados correctos:

INSERT INTO TestDate(LastModifiedTime) 
    VALUES(CAST((((JulianDay('now', 'localtime') - 2440587.5)*86400.0) + 62135596800) * 10000000 AS BIGINT)) 

Parece una manera dolorosa de producir algo que esperaría estar disponible como un formato de fecha y hora incorporado, especialmente porque la base de datos admite el almacenamiento de valores de fecha y hora en tics. Con suerte, esto se vuelve útil para otros también.

Actualización:

La fórmula anterior no es perfecto cuando se trata de ahorro de luz diurna. Consulte la sección Caveats And Bugs en documentos de SQLite sobre el cálculo del tiempo local.

+1

Su fórmula es incorrecta porque no tiene en cuenta los cambios de horario de verano. Los metadatos de LastModifiedTime en NTFS se almacenan como UTC, por lo tanto, su conversión tiene un error. – JasDev

+0

Eso es verdad. Agregué una nota con respecto a los cálculos de tiempo local. ¿Tiene alguna sugerencia para mejorar la fórmula? – Elan

21

Esta rareza particular de SQLite me causó mucha angustia.

Una forma sencilla - guardar y recuperar como marca de tiempo regulares

create table TestDate (
     LastModifiedTime datetime 
); 
insert into TestDate (LastModifiedTime) values (datetime('now')); 
select datetime(LastModifiedTime), strftime('%s.%f', LastModifiedTime) from TestDate; 

de salida: 2011-05-10 21: 34: 46 | 1305063286.46.000

dolorosa manera - guardar y recuperar como una marca de tiempo UNIX

Puede usar strftime para recuperar el valor en tics. Además, para almacenar una marca de tiempo UNIX (más o menos equivalente a tics), puede rodear el número de segundos en comillas simples.

insert into TestDate (LastModifiedTime) values ('1305061354'); 

SQLite almacenará esto internamente como algún otro valor que no sea una marca de tiempo UNIX. En la recuperación, debe indicar explícitamente a SQLite que la recupere como una marca de tiempo UNIX.

select datetime(LastModifiedTime, 'unixepoch') FROM TestDate; 

para almacenar la fecha y hora actuales, el uso strftime ('% s', 'ahora').

insert into TestDate (LastModifiedTime) VALUES (strftime('%s', 'now')); 

ejemplo completo:

create table TestDate (
     LastModifiedTime datetime 
);  
insert into TestDate (LastModifiedTime) values (strftime('%s', 'now')); 
select datetime(LastModifiedTime, 'unixepoch') from TestDate; 

Cuando ejecutado por sqlite3, esta secuencia de comandos con la impresión:

2011-05-10 21:02:34 (or your current time) 
+0

La salida de la marca de tiempo de The Easy Way no parece válida por un par de razones: tiene un punto decimal adicional y tiene los segundos del reloj intercalados entre los segundos de época y los milisegundos. Para mis propósitos, necesito comparar 'ahora' con marcas de tiempo que ya están almacenadas en la base de datos en milisegundos, no en segundos decimales. Pero la precisión en milisegundos no es realmente importante, así que terminé usando 'strftime ('% s000', 'now')' en su lugar. – spaaarky21

1

El siguiente devolverá el número de milisegundos desde el UNIX Epoch:

SELECT (strftime('%s', 'now') - strftime('%S', 'now') + strftime('%f', 'now')) * 1000 AS ticks 

Funciona agarrando el número de segundos desde el Epoch Unix (% s), restando el número de segundos en el hora actual (% S), agregando el número de segundos con decimales (% f), y multiplicando el resultado por 1000 para convertir de segundos a milisegundos.

La resta y la suma son para agregar precisión al valor sin sesgar el resultado. Como se indica en la documentación de SQLite, todos los usos de 'ahora' dentro del mismo paso devolverán el mismo valor.

Cuestiones relacionadas