How to calculate time differences HH:MM in a table? - sqlite

Im working on a flight-logbook in sqlite.
The "flights"-table has the following structure:
CREATE TABLE flights (event_id INT PRIMARY KEY, date TEXT, offblock TEXT, onblock TEXT, duration TEXT;
My goal is to find a statement that i can insert into the "duration" column, so that I will have the flight duration there.
INSERT INTO flights VALUES (1, "2019-04-04", "12:00", "18:00", XXX);
The result of duration should be 06:00, like this:
SELECT duration from flights WHERE event_id = 1;
06:00
Can anyone give me a working hint how to do this in the easiest possible way?
Thanks a lot!

You can do it with strftime() and time() like this:
SELECT strftime('%H:%M', time(strftime('%s','18:00') - strftime('%s','12:00'), 'unixepoch'))
which results in:
06:00

What you want to do is pretty complex as you have a string which represents time, which there isn't an explicit type for in sqlite. It's quite complicated, but it is possible and you could do the following:
-First remove the colon from the string: how to remove characters from a string in sqlite3 database?
-Then convert this string to an int: Convert string to int inside WHERE clause of SQLITE statment
-You would need to do this for the hours and minutes separately, as ints are obviously 10 based and minutes are 60 based so you can't simply subtract them. You would do this via ths Substr(X,Y,Z) function: https://www.sqlite.org/lang_corefunc.html
-Then you would do arithmetic to subtract final - initial time for both the hours and minutes. https://www.w3resource.com/sqlite/arithmetic-operators.php
-Finally take the calculated hours, and minutes, and add a colon in between them (assuming you want the same format).
Like I said, it's kinda heavy.. but it is doable if this automation saves time in the long run. This should be enough to get you there.

Related

SQLite difference between dates in millisecond

How can I compute in SQLite the minimum interval of time in milliseconds ?
Ok to give some context,
Here is how my table look like:
link_budget table
So there is this time column, I would like to make a request that gives me the intervals between two consecutive rows in milliseconds.
I don't know how to make my requests.
Any suggestions ?
Since SQLite does not have a native datetime data type, instead forcing you to either store as a string or as a number, and you have picked a string, you need to convert it into something that can be calculated upon.
You can use the julianday function for this.
To calculate the difference between two values you would simply do this:
SELECT julianday('2006-07-01 12:08:15.310')-julianday('2006-07-01 12:08:14.141')
This, however, will give you the difference in days. One day contains 86400 seconds and thus 86400000 milliseconds, which gives you this:
SELECT (julianday('2006-07-01 12:08:15.310')-julianday('2006-07-01 12:08:14.141'))*86400000
Note that the precision of the floating point types used internally by SQLite does not have enough precision to get the above value accurate but it should likely be close enough to give you millisecond-precision.
For instance, this:
select (julianday('2006-07-01 12:08:14.141')-julianday('2006-07-01 12:08:14.140'))*(86400000)
Which should give 1 millisecond of difference gives this result:
1.00582838058472
try this:
SELECT (STRFTIME('%s', '2021-10-20 18:22:43') - STRFTIME('%s', '2021-10-20 18:22:42'))*1000;
for timestamps that contain milliseconds try this:
SELECT STRFTIME('%s', '2021-10-20 18:22:43.325')*1000 + SUBSTR(STRFTIME('%f', '2021-10-20 18:22:43.325'), 4) -
( STRFTIME('%s', '2021-10-20 18:22:42.921')*1000 + SUBSTR(STRFTIME('%f', '2021-10-20 18:22:42.921'), 4) );

In SQLite3, how do I use Datetime('Now') to find datetimes that are more than N days ago?

I have a table that includes a 'LastUpdated' column that is generated when the row is inserted using Sqlite's datetime('now') function.
How do I write a Select statement that finds all rows with 'LastUpdated' more than 100 days old?
I think it's a variant of:
SELECT * FROM Table WHERE (DATETIME('Now')-100 Days) > LastUpdated
But I'm unsure of:
a) How to specify the 100 Days?
b) Whether I can actually compare datetimes like this or if I first have to convert DATETIME('Now') to a string?
c) DATETIME('Now') results in UTC time, correct? I think so from my reading of the documentation, but it was a little confusing...
Figured it out--I didn't see all the handy modifiers at the bottom of the SQLite Datetime Documentation.
A bunch of helpful examples there demonstrating addition/subtraction of any datetime unit (years, months, hours, seconds, etc)
SELECT * FROM Table WHERE (DATETIME('Now','-100 Days') > LastUpdated

ORDER BY timestring as time instead of a string

I have a table with a column of times such as
| time|
|=====|
| 9:20|
|14:33|
| 7:35|
In my query, I have ORDER BY time, but it sorts the times as strings, so the result is ordered as
|14:33|
| 7:35|
| 9:20|
What do I have to do to my ORDER BY statement to get the result to be sorted as times so it would result in
| 7:35|
| 9:20|
|14:33|
One solution is to pad hours that do not include a leading 0 with one in the query itself and then perform the sort.
SELECT * FROM <table> ORDER BY SUBSTR('0' || time, -5, 5);
Here's the breakdown on what the SUBSTR method is doing.
|| is a string concatenation operation in SQLite. So '0' || '7:35' will give '07:35', and '0' || '14:23' will give '014:23'. Since we're only interested in a string like HH:MM, we only want the last 5 characters from this concatenated string.
If you store the original string with a leading 0 for hours and minutes, then you could simply order by the time column and get the desired results.
|14:33|
|07:35|
|09:20|
That will also make it easy to the use the time column as an actual time unit, and do computations on it easily. For example, if you wanted to add 20 minutes to all times, that can simply be achieved with:
SELECT TIME(time, '+20 minutes') FROM <table>;
The reason for this 0 padding is because SQLite as of now only understands 24 hour times such as 'HH:MM' but not 'H:MM'.
Here's a good reference page for SQLite documentation on Date and Time related functions.
The best way is to store the time as seconds. Either as a unix timestamp(recommended), or as number of seconds since midnight.
In the second case, 7:35 will 7*3600+35*60=27300 and the representation for 14:33 will be 52380 Store them as integers(timestamps). Similarly for unix timestamps, times are stored as no of seconds since 1970.
You can now sort them as integers
Use utility methods to easily handle the conversion

How to compare two dates in SQLite?

I kind of assumed it was a string, so I compared it as a string, but not surprisingly it failed. I believe thats how it works in Mysql. I could be wrong as I haven't worked on it in a while. In either case, how can I check if dates are equal in SQLite? I will be using it in a WHERE clause.
SELECT a._id, b._id, b.start_date,a.event_name, b.start_time,
b.end_date, b.end_time, b.location FROM events_info b INNER JOIN events a ON
a._id=b.event_id WHERE b.start_time = '6:00';
(added space to make it easier to look at)
SQLite doesn't have a dedicated DATETIME type. Normally what people do is make sure they store the date as a formatted string that is consistent; for example, YYYY-MM-DD hh:mm:ss. If you do so, as long as you're consistent, then you can compare dates directly:
SELECT * FROM a WHERE q_date < '2013-01-01 00:00:00';
This works because even though the comparison is technically an alphabetical comparison and not a numeric one, dates in a consistent format like this sort alphabetically as well as numerically.
For such a schema, I would suggest storing dates in 24-hour format (the above example is midnight). Pad months, days, and hours with zeros. If your dates will span multiple timezones, store them all in UTC and do whatever conversion you need client-side to convert them to the local time zone.
Normally dates and times are stored all in one column. If you have to have them separated for whatever reason, just make sure you dates are all consistent and your times are all consistent. For example, dates should all be YYYY-MM-DD and times should all be hh:mm:ss.
The reason that YYYY-MM-DD hh:mm:ss is the preferred format is because when you go from the largest date interval (years) to the smallest (seconds), you can index and sort them very easily and with high performance.
SELECT * FROM a WHERE q_date = '2012-06-04 05:06:00';
would use the index to hone in on the date/time instead of having to do a full table scan. Or if they're in two separate rows:
SELECT * FROM a WHERE q_date = '2012-06-04' AND q_time = '05:06:00';
The key is to make sure that the dates and times are in a consistent format going into the database. For user-friendly presentation, do all conversion client-side, not in the database. (For example, convert '2012-06-04 05:06:00' to "1:06am Eastern 6/4/2012".)
If this doesn't answer question, could you please post the exact format that you're using to store your dates and times, and two example dates that you're trying to compare that aren't working the way you expect them to?
Sqlite can not compare dates directly. we need to convert them in seconds as well as integer also.
Example
SELECT * FROM Table
WHERE
CAST(strftime('%s', date_field) AS integer) <=CAST(strftime('%s', '2015-01-01') AS integer) ;
From Datatypes In SQLite Version 3:
1.2 Date and Time Datatype
SQLite does not have a storage class set aside for storing dates and/or times. Instead, the built-in Date And Time Functions of SQLite are capable of storing dates and times as TEXT, REAL, or INTEGER values:
TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS").
REAL as Julian day numbers, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic Gregorian calendar.
INTEGER as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.
Applications can chose to store dates and times in any of these formats and freely convert between formats using the built-in date and time functions.
If you look at the examples in Date And Time Functions, something like this should get you close to what you want (which, I'm assuming, is 6:00 of the current day):
WHERE b.start_time = date('now', 'start of day', '+6 hours')

Formatting time in SQL as day.hour

I'm creating a report from a stored procedure that pulls two date/times (CreatedDate and ClosedDate). I need a column on the report that shows the difference (i.e. time it took to go from open to close). First, I just subtracted CreatedDate from ClosedDate (in the report [SQL Server Reporting Services], not in the stored procedure) and got a time that looks like this: 72.20:34:18.6230000 (day.hour:minute:second). I need to shrink this down, if possible, to just day.hour...
I was experimenting with some of the functions found on MSDN (http://msdn.microsoft.com/en-us/library/ms186724.aspx). DATEDIFF almost gives me what I need, but I can only specify days or hours, and ideally (as I said), I need it to show the 'time to close' as both (day.hour).
Is this possible?
In SSRS, you can apply a custom format to that column to show only days.hours. Right click the column in design mode -->text box properties-->Number(on left hand side). If you don't see one of the formats for date, time or number that fits what you need, create a custom one at the bottom.
Convert to minutes
divide by 1440 gives whole days
modulo 1440 gives remaining minutes, divide by 60 for hours
Something like (not tested):
SELECT
CAST(DATEDIFF(minute, CreatedDate, ClosedDate) / 1440 AS varchar(20)) + '.'
CAST((DATEDIFF(minute, CreatedDate, ClosedDate) % 1440) / 60 AS varchar(20))
FROM
MyTable
You may need to fiddle with the hours representation in cade I've misunderstood
DATEDIFF for day and hour go by boundaries: that is if there are just 3 minutes between the 2 values spanning midnight, there will be one hour/day difference. So I used minutes
Edit:
To overflow the int from DATEDIFF requires a difference of 4000+ years
Thoughts:
Using datetime2 and have CreatedDate of lowest 0001-01-01
ClosedDate is a sentinel value like 9999-12-31 say for "open" items
CreatedDate and ClosedDate are varchar and conversion to datetime is faulty
Your example shows 72 days difference which would be around 104k minutes.
I would try this to see where you have more than 1000 year differences which would be a mere half billion or so minutes:
SELECT * FROM mytables
WHERE DATEDIFF(year, CreatedDate, ClosedDate) > 1000

Resources