I want to make a function call that hase efect in SQLite like TIMEDIFF in MySQL.
I made this:
select strftime('%s','2012-01-01 12:00:00') - strftime('%s','2004-01-01 02:34:56')
but this is just the number of seconds. So how can i make a str like %Y-%m-%d %H:%M:%S where %H:%M:%S is the hours, minutes and seconds difference, and when it is bigger then 24 hours then %d will show how much dais it is and so on with %Y and %m.
You cannot represent a time difference with %Y-%m-%d ..., at least not as a date format. How would you express less than a day of difference? (0000-00-00 ... is not a valid date). Also, what would a month be? 30 days? 31 days? 23423432 days?
I suggest you keep your difference in seconds, and when presenting it you adapt it as necessary.
On the other hand, if you really want to do as you asked, here's one way:
sqlite> select datetime(strftime('%s','2012-01-01 12:00:00')
- strftime('%s','2004-01-01 02:34:56') - 62167305600, 'unixepoch');
0007-12-31 09:25:04
Even if I feel the downvote by the OP wasn't justified, I can't stop myself from explaining why what I mentioned above as clearly not a very good option returns "incorrect" results when the time difference is less than 1 day: the reason is implied in what I wrote above: there is no such date as 0000-00-00 ... so instead the datetime returned goes in negative territory: -001-12-31 ...
Here's a way to obtain 438:53:45, but it's quite involved:
earlier date: d1
later date: d2
select
cast(
(strftime('%s', d2) - strftime('%s', d1)) / 86400 * 24
+ cast(strftime("%H", time(strftime('%s', d2)
- strftime('%s', d1), 'unixepoch'))
as int)
as text)
|| ":"
|| substr(time(strftime('%s', d2) - strftime('%s', d1), 'unixepoch'), 4);
Example:
d1 = '2004-01-01 02:34:56'
d2 = '2012-01-01 12:00:00'
sqlite> select cast((strftime('%s','2012-01-01 12:00:00') - strftime('%s','2004-01-01 02:34:56')) / 86400 *24 + cast(strftime("%H", time(strftime('%s','2012-01-01 12:00:00') - strftime('%s','2004-01-01 02:34:56'), 'unixepoch')) as int) as text)
|| ":"
|| substr(time(strftime('%s','2012-01-01 12:00:00') - strftime('%s','2004-01-01 02:34:56'), 'unixepoch'), 4);
70137:25:04
Related
I got two different datetimes: 2020-05-18 12:30:01 and 2020-05-17 13:00:00.
I want to show the time difference between them in the format HH:MM:SS, which is 23:30:01.
If the difference is higher than 24 hours, let's say 28 hours, 12 minutes and 45 seconds, it would show like 28:12:45.
How can I do that in SQLite?
SQLite supports a limited number of functions for datetime manipulation.
One of these functions is strftime(), and
strftime('%s', somedate)
returns the number of seconds from '1970-01-01' up to somedate.
With the use of this function, arithmetic calculations, string padding and concatenations you can get what you want like this:
CASE WHEN ((strftime('%s', date1) - strftime('%s', date2)) / 3600) < 10 THEN '0' ELSE '' END ||
((strftime('%s', date1) - strftime('%s', date2)) / 3600) || ':' ||
SUBSTR('0' || (((strftime('%s', date1) - strftime('%s', date2)) / 60) % 60), -2) || ':' ||
SUBSTR('0' || ((strftime('%s', date1) - strftime('%s', date2)) % 60), -2)
Replace date1 and date2 with your dates.
See a simplified demo.
SELECT time(
(
julianday('2020-05-18 12:30:01')-
julianday('2020-05-17 13:00:00')
)*60*60*24, 'unixepoch'
);
answsers the question when time difference is lower than 24h...
I have a Pythonic system that stores student absences data in a SQLite database. Each row includes the start and end time of the absence, represented by the number of seconds since Jan 01 1970. I was asked to add a feature which limits the number of hours of absence per week.
It sounds easy to pull out the amount of hours, using a statement like this:
SELECT (sum(ending-starting)/3600)
FROM requests
WHERE student_id = {x}
AND starting BETWEEN {y} AND ({y}+604800)
AND approved = 1
The problem is that the limit must only be the hours defined as "mandatory presence." For example, if a user has defined the hours 8:00 to 17:00 as a "mandatory presence," an absence that begins on Sunday at 14:00 and ends on Monday at the same time, will be calculated in the code above 24 hours, while in practice it is only 9 hours.
"Mandatory presence" is defined in the database as two numerical parameters: "morning" and "evening" (always a round hour). Is there a way to make the calculation above taking into account these two numbers?
If it can not be done in sql, I would love to hear how to select the data in sql and then perform the calculation in python.
I believe the following may do what you wish :-
SELECT
(
sum((
(ending - starting)
-(
CASE WHEN starting < strftime('%s',date(starting,'unixepoch')||' 08:00')
THEN strftime('%s',date(starting,'unixepoch')||' 08:00') - starting
ELSE 0
END
+
CASE WHEN ending > strftime('%s',date(starting,'unixepoch')||' 17:00')
THEN ending - strftime('%s',date(starting,'unixepoch')||' 17:00')
ELSE 0
END
)
) /3600)
) AS ha, *
FROM requests
WHERE student_id = {x}
AND starting BETWEEN {y} AND ({y}+604800)
AND approved = 1
;
MikeT's answer is not entirely working, but it certainly helped me reach the desired result. Here's the perfect statement:
SELECT
(
sum((
(ending - starting)
-(
CASE WHEN starting < strftime('%s',date(starting,'unixepoch')||printf(' %02d:00', morning))
THEN strftime('%s',date(starting,'unixepoch')||printf(' %02d:00', morning)) - starting
ELSE 0
END
+
CASE WHEN ending > strftime('%s',date(ending,'unixepoch')||printf(' %02d:00', evening))
THEN ending - strftime('%s',date(ending,'unixepoch')||printf(' %02d:00', evening))
ELSE 0
END
)
) /3600.0
-(
(24-evening+morning)
*
(round(julianday(ending, 'unixepoch'))-round(julianday(starting, 'unixepoch')))
)
)) AS ha
FROM requests
INNER JOIN students ON requests.student_id = students.ID
INNER JOIN institutes ON students.inst_id = institutes.ID
WHERE student_id = {x}
AND starting BETWEEN {y} AND ({y}+604800)
AND approved = 1;
Thank you very much for your help!
In my Teradata table, I have the epoch timestamps under the column dhTimestamp
dhTimestamp
1435308067705
1434965874565
1434763800794
1434775876034
1434765207057
How can I convert the epoch timestamp to Human Date/Time format on Teradata?
This is a SQL UDF for standard unixtime:
/**********
Converting Unix/POSIX time to a Timestamp
Unix time: Number of seconds since 1970-01-01 00:00:00 UTC not counting leap seconds (currently 24 in 2011)
Also working for negative numbers.
The maximum range of Timestamps is based on the range of INTEGERs:
1901-12-13 20:45:52 (-2147483648) to 2038-01-19 03:14:07 (2147483647)
Can be changed to use BIGINT instead of INTEGER
20101211 initial version - Dieter Noeth
**********/
REPLACE FUNCTION Epoch2Timestamp (UnixTime INT)
RETURNS TimeStamp(0)
LANGUAGE SQL
CONTAINS SQL
DETERMINISTIC
RETURNS NULL ON NULL INPUT
SQL SECURITY DEFINER
COLLATION INVOKER
INLINE TYPE 1
RETURN
CAST(DATE '1970-01-01' + (UnixTime / 86400) AS TIMESTAMP(0))
+ ((UnixTime MOD 86400) * INTERVAL '00:00:01' HOUR TO SECOND)
;
SELECT
Epoch2Timestamp(-2147483648)
,Epoch2Timestamp(0)
,Epoch2Timestamp(2147483647)
;
But your values seem to include milliseconds, this needs a modified calculation:
CAST(DATE '1970-01-01' + (UnixTime / 86400000) AS TIMESTAMP(3))
+ ((UnixTime / 1000.000 MOD 86400) * INTERVAL '00:00:01' HOUR TO SECOND)
Edit 2016-07-01:
There was an issue with dayight saving time (see this thread on Teradata's on DevEx), this should fix it:
-- Unix time to Timestamp WITH TIME ZONE (+00:00)
REPLACE FUNCTION UnixTime_to_TimeStamp_TZ (UnixTime INT)
RETURNS TIMESTAMP(0) WITH TIME ZONE
LANGUAGE SQL
CONTAINS SQL
DETERMINISTIC
SQL SECURITY DEFINER
COLLATION INVOKER
INLINE TYPE 1
RETURN
((CAST(DATE '1970-01-01' + (UnixTime / 86400) AS TIMESTAMP(0) AT 0)) AT 0)
+ ((UnixTime MOD 86400) * INTERVAL '00:00:01' HOUR TO SECOND);
-- Unixtime to Timestamp, implicit TIME ZONE of the local session
REPLACE FUNCTION UnixTime_to_TimeStamp (UnixTime INT)
RETURNS TIMESTAMP(0)
LANGUAGE SQL
CONTAINS SQL
DETERMINISTIC
SQL SECURITY DEFINER
COLLATION INVOKER
INLINE TYPE 1
RETURN
CAST(((CAST(DATE '1970-01-01' + (UnixTime / 86400) AS TIMESTAMP(0) AT 0)) AT 0)
+ ((UnixTime MOD 86400) * INTERVAL '00:00:01' HOUR TO SECOND) AS TIMESTAMP(0));
This is the most simplied way to convert EPOCH TO TERADATA LOCAL.
SELECT
dhTimestamp as unix_epoc_time ,
to_timestamp(unix_epoc_time) utc,
cast(cast(utc as char(19))||'+00:00' as timestamp(0) with time zone) AT LOCAL
If you have epoch with more than 10 digit , then chop the numbers after 10th digit, It will just work fine.
remember , Unix time is in UTC.
your system will treat this utc as local. So, let us make it understand that it is UTC by adding '+00:00' and then convert it to your LOCAL using AT LOCAL OR using either of these "America Central" , "America Eastern" , "America Mountain" etc..
I was able to convert epoch column to timestamp using below query..
SELECT CAST((date '1970-01-01' + CAST(epochtimecolumn/1000 AS INTEGER)/86400) AS TIMESTAMP(6)) + (CAST(epochtimecolumn/1000 AS INTEGER) MOD 86400) * INTERVAL '00:00:01' HOUR TO SECOND + (epcho_time_column_with_milliseconds MOD 1000) * INTERVAL '00:00:00.001' HOUR TO SECOND from table_name
Just replace epochtimecolumn with your column in the above query to run it in teradata.
Hope it helps!!
I want to return ISO standard week numbers (ie week 1-52/53) from a date.
I have tried using the built in function strftime, but with no success.
Can anyone suggest a way without having to write a custom C or other function.
I know this is an old question, but recently I was looking for an efficient solution for the same problem, and this is what I came up with:
SELECT
my_date,
(strftime('%j', date(my_date, '-3 days', 'weekday 4')) - 1) / 7 + 1 as iso_week
FROM my_table;
The basic idea is to calculate the ISO week number by simply performing integer division of the day of year of the Thursday of the date being looked up (my_date) by 7, giving a result between 0 and 52, and then adding 1 to it. And the subtraction by 1 just before the division is there just for the alignment of the division: Thursday of week 1, for example, can have a day of year between 1 and 7, and we want the result of the division to be 0 in all cases, so we need to subtract 1 from the day of year before dividing it by 7.
What specifically did you try?
This works for me (using built-in SQLite from Python REPL):
import sqlite3
c = sqlite3.connect(':memory:')
c.execute('''create table t (c);''')
c.execute('''insert into t values ('2012-01-01');''')
c.execute('''select c, strftime('%W',c) from t;''').fetchone()
# -> (u'2012-01-01', u'00')
OK, so I managed to answer my own question. For anyone who might need a similar solution, this is what I came up with. Please note, I do not have an IT background and my SQL is self taught.
General process
Get the Thursday of the week the date belongs too.
Get the 4th of January of the year of that Thursday.
Get the Thursday of the week the 4th January date belongs too.
Subtract Step 2 with Step 3, divide by 7 and add 1.
Translated into SQLite....
SELECT
date,
CASE CAST (strftime('%w', wknumjanfourth) AS INTEGER)
WHEN 0 THEN ((JULIANDAY(datesThur) - JULIANDAY(strftime("%s", wknumjanfourth) - 259200, 'unixepoch')) / 7) + 1
ELSE ((JULIANDAY(datesThur) - JULIANDAY(DATE(strftime("%s", wknumjanfourth) - (86400 * (strftime('%w', wknumjanfourth) - 1)), 'unixepoch'), '+3 day')) / 7) + 1
END AS weeknum
FROM
(
SELECT
date,
datesThur,
DATE(datesThur,'start of year','+3 day') AS wknumjanfourth
FROM
(SELECT
date,
CASE CAST (strftime('%w', date) AS INTEGER)
WHEN 0 THEN DATE(strftime("%s", date) - 259200, 'unixepoch')
ELSE DATE(DATE(strftime("%s", date) - (86400 * (strftime('%w', date) - 1)), 'unixepoch'), '+3 day')
END AS datesThur
FROM TEST
))
If anyone can improve this SQL, I would appreciate the feedback.
I am trying to express the difference of two given dates in days, hours, and minutes (like 1 day, 6 hours, 17 minutes.) as SQLite query output. I have entryin and entryout as datetime fields in a SQLitedatabase. I tried all combinations of julianday and strftime but still running into rough weather.
I tried strftime('%d %H:%M', julianday(entryout)-julianday(entryin)). For a row the values are 2011-11-10 11:46, and 2011-11-09 09:00. but the output is 25 14:46 instead of 01 02:46.
Can some one help me with this, or point me correct logic for this? Thanks in advance.
You can try something like this:
SELECT
CAST((strftime('%s', '2011-11-10 11:46') - strftime('%s', '2011-11-09 09:00')) / (60 * 60 * 24) AS TEXT) || ' ' ||
CAST(((strftime('%s', '2011-11-10 11:46') - strftime('%s', '2011-11-09 09:00')) % (60 * 60 * 24)) / (60 * 60) AS TEXT) || ':' ||
CAST((((strftime('%s', '2011-11-10 11:46') - strftime('%s', '2011-11-09 09:00')) % (60 * 60 * 24)) % (60 * 60)) / 60 AS TEXT);