I have an application that logs the time an action occurred in milliseconds since midnight and stores it in a Db2 10.5 database table. I need to convert that figure to a human-readable timestamp output.
SELECT ACTION_NAME,
ACTION_TIME
FROM ACT.ACTIONS
ALARM1 1818000
ALARM2 76500000
I want to be able to run a SELECT but have the value returned like
ALARM1 05:03
ALARM2 21:15
Any guidance would be appreciated.
You can add the number of seconds to "midnight":
SELECT action_name, time '00:00' + (action_time/1000) second as action_time
FROM actions;
Online example (based on DB2 11.1)
There is the TIME type in Db2:
The TIME function returns a time from a value.
so we could use that.
We still need DATE, TIME or TIMESTAMP as the input, not INT. So let's try with TIMESTAMP. We can get the timestap of current day like this;
db2 "values timestamp(current date)"
1
-------------------
2019-08-23-00.00.00
1 record(s) selected.
Now we can simply add the offset in either seconds or microseconds. E.g. with 76500000:
db2 "values timestamp(current date) + (76500000/1000) seconds"
1
-------------------
2019-08-23-21.15.00
1 record(s) selected.
and with time:
db2 "values time(timestamp(current date) + (76500000/1000) seconds)"
1
--------
21:15:00
With our data:
db2 "create table ACT.ACTIONS(action_name varchar(10), action_time int)"
db2 "insert into ACT.ACTIONS values ('ALARM1',1818000)"
db2 "insert into ACT.ACTIONS values ('ALARM2',76500000)"
db2 "select action_name, time( timestamp(current date) + (action_time/1000) seconds) as time from act.actions"
ACTION_NAME TIME
----------- --------
ALARM1 00:30:18
ALARM2 21:15:00
2 record(s) selected.
(note that you likely have an error in your example)
Edit:
As noted, there is no need for CURRENT TIMESTAMP, I didn't notice that we can use STRING representation of the time, i.e. '00:00' as #a_horse_with_no_name shown:
db2 "select action_name, time('00:00') + (action_time/1000) seconds as action_time_fmt from act.actions"
ACTION_NAME ACTION_TIME_FMT
----------- ---------------
ALARM1 00:30:18
ALARM2 21:15:00
2 record(s) selected.
If you need the milli-second part, you can do e.g.
values timestamp('0001-01-01') + (1818005 / 1000) seconds + (mod(1818005,1000)*1000) microseconds"
1
--------------------------
0001-01-01-00.30.18.005000
1 record(s) selected.
Related
I have a simple database
id name value date time
1 box 34 2020-06-08 14:45:00
2 box 35 2020-06-08 15:00:00
3 box 4 2020-06-08 15:15:00
4 box 44 2020-06-08 15:30:00
5 box 42 2020-06-08 15:45:00
6 box 41 2020-06-08 16:00:00
7 box 0 2020-06-08 16:15:00
8 box 0 2020-06-08 16:30:00
9 box 0 2020-06-08 16:45:00
...
I am trying to retrieve the latest past 1 hour data from a Postgresql database. The objective is to run this query every hour to get the past one hour data for further processing in another software.
The records in the database already contain all the timestamps for the day (15 minutes interval).
Therefore, from the example, assuming my local time is 16:00:00, I will want to take the past 1 hour data from my local time.
I have tried the following:
SELECT id, name, value, date, time
FROM boxbox
WHERE time >= (NOW() - INTERVAL '1 hour')
ORDER BY time desc
But I am getting this SQL error
SQL Error [42883]: ERROR: operator does not exist: time without time zone >=
timestamp with time zone
The table datatype is as follow:
id - int4
name - varchar
value - int
date - date
time - time
Thank you.
Well, now() returns a timestamp with time zone, not a time value. And you can't compare a time value with a timestamp with time zone value.
You need to use localtime:
SELECT id, name, value, "date", "time"
FROM boxbox
WHERE "time" >= localtime - INTERVAL '1 hour'
ORDER BY "time" desc
However the above won't work properly if the time crossed midnight. If you also need to take care of that, you need to combine your date and time columns to a single timestamp column:
SELECT id, name, value, "date", "time"
FROM boxbox
WHERE "date" + "time" >= now () - INTERVAL '1 hour'
ORDER BY "time" desc
Given the following sqlfiddle: http://www.sqlfiddle.com/#!17/f483a/2/0
create table test (
start_date date
);
insert into test values ('2019/01/01');
select
start_date,
age(now()::date,start_date) as date_diff
from test;
Which generates the following output:
date_diff | 0 years 7 mons 27 days 0 hours 0 mins 0.00 secs
How could I instead generate the correct number of calendar days
239 days
without using a custom function?
Don't use the age function. Subtracting a date from a date yields an integer. now() returns a timestamp so you need to use current_date instead.
select start_date,
current_date - start_date as date_diff
from test;
I have a table full of "Julian Dates", that is the number of days and seconds away from 1/1/2035. I need to convert these to normal postgres timestamps. Can anyone help?
--Converts '2000-06-20 12:30:15' into an Epoch time base which gives a result of -12612.478993055556
select (EXTRACT(epoch FROM ('2000-06-20 12:30:15'::timestamp - '2035-01-01 00:00:00'))/86400.00) as run_ts
--Question, how to convert -12612.478993055556 back into '2000-06-20 12:30:15'
select -12612.478993055556 ??? as run_ts
You can use to_timestamp() to convert an epoch to a timestamp.
The epoch you posted does not correspond to 2000-06-20, as you have removed another date 2035-01-01 from it.
select (EXTRACT(epoch FROM ('2000-06-20 12:30:15'::timestamp )));
date_part
-----------
961504215
(1 row)
select to_timestamp(961504215);
to_timestamp
------------------------
2000-06-20 08:30:15-04
(1 row)
select to_timestamp(-12612.478993055556);
to_timestamp
-------------------------------
1969-12-31 15:29:47.521007-05
(1 row)
EDIT
Since you are not considering a true epoch but really a difference between two dates, you can simply add this difference to the reference date. You can use the day interval to remove the need to multiply by 86400 (seconds/day)
select '2035-01-01 00:00:00'::timestamp + interval '1' day * -12612.478993055556;
?column?
---------------------
2000-06-20 12:30:15
Hi i have to add 24 hours on a timestamp converted from a string in postgres db.
here my code:
select to_timestamp(timestamp_start, 'YYYY-MM-DD HH24:MI:SS.US') + interval '24 hour' as tstamp from tablename
the query works but it adds two 0 at the end of the timestamp: "2017-05-23 17:35:13.105867+00"
why and how to solve it?
+00 meant it is timestamp with timezone and your client timezone is UTC.
If you dont want those +00 on the screen, cast it to timestamp without timezone, eg:
t=# select now();
now
-------------------------------
2017-05-23 09:04:46.105322+00
(1 row)
Time: 0.690 ms
t=# select now()::timestamp;
now
----------------------------
2017-05-23 09:04:51.849522
(1 row)
Time: 0.537 ms
So for query in original post it would be:
select (to_timestamp(timestamp_start, 'YYYY-MM-DD HH24:MI:SS.US') + interval '24 hour')::timestamp as tstamp
from tablename
I have a PostgreSQL table with a field named effective_date and data type is integer(epoch date). What I want to do is to select only the entries that have an effective_date of my choice (I only want to query by the month). My query is below and the problem is, it is not returning anything although the table do have many entries that match the selection criteria.
$query = "select *
from ". $this->getTable() ."
where pay_stub_entry_name_id = 43
AND to_char(effective_date, 'Mon') = 'Jul'
AND deleted = 0";
Use extract(month from the_date) instead of to_char. See datetime functions in the Pg docs.
With to_char you'll suffer from all sorts of issues with case, localisation, and more.
Assuming you meant that the data type of effective_date was timestamp or date, you'd write:
$query = "select *
from ". $this->getTable() ."
where pay_stub_entry_name_id = 43
AND extract(month from effective_date) = 7
AND deleted = 0";
If it's integer then - assuming it's an epoch date - you have to convert it to a timestamp with to_timestamp, then use extract on it. See the epoch section in the documentation linked to above, eg:
$query = "select *
from ". $this->getTable() ."
where pay_stub_entry_name_id = 43
AND extract(month from to_timestamp(effective_date)) = 7
AND deleted = 0";
The immediate cause of your problem was that you were calling to_char(integer,text) with an integer epoch date. Only the timestamp versions of to_char do date formatting; Mon isn't special for the others, so it was simply output as a literal string Mon. Compare:
regress=# SELECT to_char(current_timestamp, 'Mon');
to_char
---------
Aug
(1 row)
regress=# select to_char( extract(epoch from current_timestamp), 'Mon');
to_char
---------
Mon
(1 row)
Remember to parameterise your real-world versions of these queries to help avoid SQL injection.