Find DATETIME by unixtimestamp - sqlite

Hi i'm trying to find rows where the unixtimestamp is 0:
WHERE datetimeField = datetime(0,'unixepoch','localtime') -> does not work
WHERE datetimeField = datetime(0,'unixepoch','utc') -> does not work
WHERE datetimeField = '1970-01-01T01:00:00' -> works
any ideas why no datetime-format works?

Because you're doing a string comparison [sqlite's "=" is not timestamp-aware, it's comparing two things for equality]. Your datetimeField is presumably being stored as the String '1970-01-01T01:00:00', which sqlite's datetime functions can gracefully deal with, but is still eventually a string because sqlite doesn't have an intrinsic datetime type
Note that all three of these are different strings, and thus won't return true for the equality check:
sqlite> select datetime(0,'unixepoch','localtime');
1969-12-31 16:00:00
sqlite> select datetime(0,'unixepoch','utc');
1970-01-01 08:00:00
sqlite> select '1970-01-01T01:00:00';
1970-01-01T01:00:00
sqlite>
To clarify, a simple solution to this problem is to convert everything to another format that you're confident it can be converted to, and is easy to compare. Since you've already brought it up, I quite like epoch seconds. Given your date of one hour after midnight, on the first of January 1970:
sqlite> select strftime('%s', '1970-01-01T01:00:00');
3600
sqlite>
So from your code:
{stuff} WHERE 0 = strftime('%s', datetimeField)

Related

Is there a way to edit a database datetime table to remove the seconds in each row?

I have a database that currently saves the datetime data like this:
1|1|2022-01-02 06:00:00
2|1|2022-01-03 06:00:00
I want to remove the seconds from the data to look like this:
1|1|2022-01-02 06:00
2|1|2022-01-03 06:00
Is there a way to do this in sqlite3? As I write this I'm thinking about how I can do it using python which I do not think will be hard but I wanted to see if this could be done in sqlite3 first.
I found this in my research but I'm not using mySQL. https://www.tutorialspoint.com/remove-seconds-from-time-field-in-mysql
The dates you have in your table are actually strings and you can use the function SUBSTR() to strip off the last 3 chars:
UPDATE tablename
SET col = SUBSTR(col, 1, LENGTH(col) - 3);
Or, use the function strftime() function to get a string without seconds:
UPDATE tablename
SET col = strftime('%Y-%m-%d %H:%M', col);
Change col to the column's name.

Sqlite SELECT * for Last 30 days

I have a SQLite DB with the following columns:
File, Date_created, Owner
How do I get the list of files created in the last 30 days?
I tried the following, but it didn't limit the result. The list came back with files created 2 years ago!
SELECT * FROM Table1 WHERE Date_created > (SELECT DATETIME('now', '-30 day'))
Also, not sure if it matters, but my Created_date column is in the following date format: dd/mm/yyyy hh:mm:ss
SQLite doesn't have a native datetime data type, so that comparison's going to be on text. If your records are in DD/MM/YYYY format, you'll end up with comparisons like "07/03/2020" > "2020-06-07" which make little sense.
If you opt to store your datetimes as text, you must use a format that's lexicographically orderable. A great standard format that exhibits this property (if every piece of data has the same timezone, anyway) is ISO 8601, e.g. 2020-07-07 15:04:14+0300 at the time of writing in my timezone. As an aside, even xkcd recommends ISO 8601.
If you opt to store your datetimes as numbers, you can store them as either UNIX time, or maybe, if you're feeling adventurous, as e.g. the number 20200707150414. Do remember neither of these numeric options store timezone information, if that's important to your application.
As an aside,
SELECT * FROM Table1 WHERE Date_created > DATETIME('now', '-30 day')
is enough :)
Something like this might be what you are looking for, it's something that's come up in my head, haven't tested it.
Basically you're going 30 days backwards by Date_created.
SELECT * FROM Table1
WHERE DATEDIFF(DAY, DATEADD(DAY, -30, GETDATE()), Date_created) > 0

Why does SQLite consider larger number < smaller number to be true?

Querying the SQLite database of my Android app, I'm running into a curious problem. I've got a query that checks one epoch time (stored in the database in an integer field) against the current epoch time. To simplify debugging, I wrote a little test query to see how SQLite handles my epoch integer versus the strftime function. Here's my query:
select 1615759200 < strftime('%s', 'now');
The result is:
1
For reference: the value 1615759200 is the date March 14, 2021. The current date at time of writing is April 28, 2020 which is roughly 1588033692 in epoch time. For obvious reasons, I'm expecting the above query to result 0: false, as the date in 2021 is NOT smaller than the date in 2020. And yet, it returns 1: true! It's infuriating! Can anyone tell me what I'm missing here?
The data type that is returned by strftime() is text and you must cast it to an integer so that the comparison will work the way that you expect:
select 1615759200 < cast(strftime('%s', 'now') as int)
or:
select 1615759200 < strftime('%s', 'now') + 0
You can find more about data types and affinities of SQLite: Datatypes In SQLite Version 3

update or convert a date time value in a sqlite database

I have a SQLite database with a TEXT column that stores a DateTime value formated like this: '11/08/2019 00:00:00'. I would like to convert the entire column contents to UTC Epoch timestamp local timezone.
Is there an Update SQL string with a DateTime function that I could run using supported SQL syntax to perform this task or should I perhaps just write a quick C# console application to do it?
I have not found any example online or in SO that would do what I need to do in this situation.
An UPDATE SQL such as :-
UPDATE mytable SET mycolumn =
CASE WHEN substr(mycolumn,3,1) = '/'
THEN
strftime('%s',substr(mycolumn,7,4)||'-'||substr(mycolumn,4,2)||'-'||substr(mycolumn,1,2)||' '||substr(mycolumn,12,8))
ELSE
mycolumn
END
;
could be used.
Example
Perhaps consider the following which will convert the column (or not if it has already been converted (or not if it does not match the dd/mm/yyyy format))
Note the below just checks the 3rd character for /, a more rigorous check could be used if desired.
:-
DROP TABLE IF EXISTS mytable;
CREATE TABLE IF NOT EXISTS mytable (mycolumn TEXT);
/* Load the testing data */
INSERT INTO mytable VALUES
('11/08/2019 00:00:00'),
('01/08/2019 00:00:00'),
('31/01/2019 00:00:00'),
('31/01/2019 13:25:33.004') /* test for micro seconds (dropped by utc)*/;
/* display data before conversion */
SELECT * FROM mytable;
/* Convert the data to unix */
UPDATE mytable SET mycolumn =
CASE WHEN substr(mycolumn,3,1) = '/'
THEN
strftime('%s',substr(mycolumn,7,4)||'-'||substr(mycolumn,4,2)||'-'||substr(mycolumn,1,2)||' '||substr(mycolumn,12,8))
ELSE
mycolumn
END
;
/* Display data as is, as formatted localised and as formatted UTC */
SELECT *, datetime(mycolumn,'unixepoch','localtime') AS local, datetime(mycolumn,'unixepoch') AS utc FROM mytable;
Note the above would NOT cater for dates such as 1/1/2019, such dates would need a more complex CASE clause.
Note that UTC is worldwide coordinated time i.e one value is stored you adjust from UTC according to the time zone
Results
Note testing in timezone that is +10 hours
When first run the results are :-
Pre-conversion :-
Post-convserion
Rerun (DROP commented out)
Pre-conversion (mixed data) :-
circled data is already converted
Post-conversion :-

JulianDay() and Strftime() returning null when calculating difference between two dates

I have problem in retrieving difference between two date columns from a table in SQLite Database . When i execute the query using CocoaMySQL MesaSQLite 3.0.9 I am getting 'NULL' as result. I have records with values for that columns.
My query is
SELECT
cast ( ( strftime('%s',t.timestamp2)-strftime('%s',t.timestamp1 ) ) AS real
)/60/60 AS elapsed
FROM timestamps AS t;
SELECT (STRFTIME('%s',timestamp1) - STRFTIME('%s',timestamp2)) / -3600 from timestamps where objid= 3939
Result : Null
select timestamp1,timestamp2 from timestamps where objid = 3939.
Result :2014-01-29 02:55:00 AM 2014-01-29 03:00:00 AM ( means i have data in timestamps table)
SELECT julianday('now') - julianday('1776-07-04');
Result: 87287.5314
SELECT julianday(timestamp1) - julianday(timestamp2) from timestamps where objid =3939
Result: NULL value
'timestamp1' & 'timestamp2' are columns in 'timestamps' table .which have records with values.
Please give a solution to fix this issue ASAP.
I am not able to add screen shots.
Datestamps such as 2014-01-29 02:55:00 AM are not in a format understood by SQLite. Only 24h time is supported, you need to remove the AM/PM.
Other than that, if you plan on doing math on your datetimes, consider storing them in the first place in a format that makes computations easy, fast and reliable such as unixepoch seconds.

Resources