How to convert a timestamp into seconds (and fractions) in PostgreSQL - postgresql

I'm trying to get some (application) performance data from a PostgreSQL database by looking at two dates in a record, subtracting them and getting the result as a number of seconds with fractions.
It seems I'm able to get a timestamp which includes hours, minutes, seconds, and milliseconds, or I can get just the seconds (and fractions) without e.g. the minutes or I can get a UNIX timestamp which is only seconds (without the milliseconds). Is there a convenient way to convert a timestamp to seconds+millis?
Example:
SELECT extract(SECOND FROM TIME '00:01:02.1234') as secs;
secs
--------
2.1234
I was hoping to get 62.1234 (that's 1 * 60 + 02.1234) as the return value for overall seconds, not just the "seconds component" from the time value.
Is there an existing function to do that, or do I have to EXTRACT each part, multiply, and add each component together?

Use EPOCH:
SELECT extract(EPOCH FROM TIME '00:01:02.1234') as secs; 62.1234

Related

TIMESTAMPDIFF alias in postgresql

I recently switched to using postgreSQL and I am having same difficulties finding an alternative for timestampiff
My original query was something like
select a.column_a, a.column_b, TIMESTAMPDIFF(SQL_TSI_MINUTE, a.TIME_START, now()) AS "Time_diff"
from table as a
where
...
I can do just ( now() - a.TIME_START) but i want to show the result in minutes. Is there any better alternatives in postgresql to do the subtraction from now and show the result just as minutes ?
now() - a.TIME_START returns an interval which can be converted to seconds using extract() and those can be converted to minutes:
extract(epoch from now() - a.time_start) / 60 as diff_minutes
If you don't need it as a number, another option is to simply format the interval to show minutes and seconds
to_char(now() - a.time_start, 'mi:ss')
Note that this will hide the information if the interval was bigger than 60 minutes (or bigger than a day). If that can happen as well, maybe you want to use 'dd hh24:mi:ss' as a format mask instead

Issue selecting timespan values in KDB

I am facing an issue while selecting the following following timespan :
t:([] date:2#.z.d ; time: 10D21:28:47.425287000 10D12:18:23.287989000 )
date time
--------------------------------
2018.03.15 10D21:28:47.425287000
2018.03.15 10D12:18:23.287989000
when i run the following query, i am not getting the second record back
select from t where time within (12:00;13:00)
I am expecting the 2nd record from the table :
date time
-------------------------------
2018.03.15 10D12:18:23.287989000
Is the 10 in the time value 10D12:18:23.287989000 intentional ?
The reason behind the data not coming back is the time (type timespan ) is actually not the nano seconds since midnight ; as per the table it is 10 days plus nanos since midnight
To select the data only on the basis of time :
q)select from t where (`time$(`date$0)+time) within (12:00;13:00)
date time
-------------------------------
2018.03.15 10D12:18:23.287989000
Try adding the date and time from the table , you would see the date forwarded by 10 days
q)select date+time from t
date
-----------------------------
2018.03.25D21:28:47.425287000
2018.03.25D12:18:23.287989000
The timespan is basically nDhh:mm:ss.sssssssss , where n is relative to midnight. If its 0 then it's current day otherwise its +/- n days (depending on whether n is positive or negative).
try running the following , it will return you the difference between the 2 timestamps as a timespan with n=10.
q)2018.03.25D10:12:00.000000000 - 2018.03.15D10:00:00.000000000
10D00:12:00.000000000
Although you should fix your timestamps (there shouldn't be a 10D) if you're in a situation where you can't fix the upstream data but you believe the timestamps to actually be correct, then you can strip away the 10D as follows:
q)update mod[;`long$10D]time from t
date time
-------------------------------
2018.03.16 0D21:28:47.425287000
2018.03.16 0D12:18:23.287989000

Returning 24+ hours in PostgreSQL query

Alright... I have here a query that calculates a server uptime and sometimes this uptime goes over 24 hours. I use basically
select start, end, start-end as real_uptime from uptime
start and end being timestamp with timezone fields
Also, I have a stored function that sums all the real_uptime for a period and returns them...
However, I dumped the values start and end and put them into a spreadsheet and, doing the calculations there, the results had gone differently from what the stored function processed (the stored function returned lower values). I think that he ignores results for real_uptime bigger than one day. Postgresql shows them as x days hh:mm:ss... And I want them as hh:mm:ss (representing the total uptime in hours, without the full days counting.
Any ideas?
In PostgreSQL you can extract the epoch from timestamps: the seconds elapsed since 1970-01-01 00:00:00. With those values you can easily construct your desired output:
SELECT "start", "end", format('%s:%s:%s',
(up_secs / 3600)::int::text, -- hours
lpad(((up_secs % 3600) / 60)::int::text, 2, '0'), -- minutes
lpad((up_secs % 60)::text, 2, '0')) AS uptime -- seconds
FROM (
SELECT "start", "end",
(extract(epoch from "end") - extract(epoch from "start")) AS up_secs
FROM uptime) sub;
The lpad() function makes the minutes and seconds always two characters wide.

Storing date as time in millis

I try to represent date objects in a data storage without the hassle of Date object in Java. So I thought of using just a time in milliseconds and store the UTC time zone as well. I thought about using simple shift routines to combine everything in a single long as time zone is just 5bits (+/-12).
Can someone see any problem with this? What other compact storage schemes (other than textual representation) of date exist and how do they compare to this?
I think you're under valuing granularity in your time zone and over valuing the need for bits in the timestamp.
A long has has 8 bytes for this purpose.
Lets say you allow yourself 2 bytes for the time zone. That leaves you with 6 for the timestamp. 6*8 = 48 bits for a timestamp.
The largest number a 48 bit unsigned integer can handle is 281474976710655.
Divide by 1000 to get from miliseconds to seconds 281474976710
Punch that number into an epoch converter: 10889-08-02T05:31:50+00:00
That's the year 10,889 when we're in 2,015.
Just use 2 bytes for the timezone. You've got the space. That will easily allow you to represent the timezone as minutes offset +-24 hours. And since it's whole bytes, the packing code will be simpler to comprehend.

After midnight times in postgresql

I have data from a text file I'm reading into a postgres 9.1 table, and the data looks like this:
451,22:30:00,22:30:00,San Jose,1
451,22:35:00,22:35:00,Santa Clara,2
451,22:40:00,22:40:00,Lawrence,3
451,22:44:00,22:44:00,Sunnyvale,4
451,22:49:00,22:49:00,Mountain View,5
451,22:53:00,22:53:00,San Antonio,6
451,22:57:00,22:57:00,California Ave,7
451,23:01:00,23:01:00,Palo Alto,8
451,23:04:00,23:04:00,Menlo Park,9
451,23:07:00,23:07:00,Atherton,10
451,23:11:00,23:11:00,Redwood City,11
451,23:15:00,23:15:00,San Carlos,12
451,23:18:00,23:18:00,Belmont,13
451,23:21:00,23:21:00,Hillsdale,14
451,23:24:00,23:24:00,Hayward Park,15
451,23:27:00,23:27:00,San Mateo,16
451,23:30:00,23:30:00,Burlingame,17
451,23:33:00,23:33:00,Broadway,18
451,23:38:00,23:38:00,Millbrae,19
451,23:42:00,23:42:00,San Bruno,20
451,23:47:00,23:47:00,So. San Francisco,21
451,23:53:00,23:53:00,Bayshore,22
451,23:58:00,23:58:00,22nd Street,23
451,24:06:00,24:06:00,San Francisco,24
It is from a timetable for a commuter rail line, Caltrain. I'm trying to query stations, to get train arrival and departure times. I did this several months ago in MySql, and I got
select * from trains as a, trains as b where a.trip_id=b.trip_id and a.st
op_id='San Antonio' and b.stop_id='San Carlos' and a.arrival_time < b.arrival_ti
me;
So far so good, pretty straightforward. However, when I tried copying the data into a postgres database, I got an error for the various columns that had times after midnight, either 24 or 25:00:00 something. However, if I change them to be 00:00:00 and 01:00:00 something, won't that mess with the query? A time after midnight will appear to be before the starting time? MySql apparently didn't have a problem with those times, and I'm not sure what to do. I'm thinking I should use the last column, or maybe convert the times to something that doesn't take into account PM/AM?
You should try using the interval type for the time columns. Those will keep track of the number of hours, minutes, and seconds instead of trying to record a time of day.
See the PostgreSQL documentation on dates and times.
An interval can have a time component greater than 24 hours, unlike the time datatype that is confined to 00:00 <= x <= 23:59.