Converting string timestamp into date - postgresql

I have dates in a postgres database. The problem is they are stored in a string field and have values similar to: "1187222400000" (which would correspond to 07.08.2007).
I would like to convert them into readable dates usind some SQL to_date() expression or something similar but can't come up with the correct syntax to make it work.

There really isn't enough information here for a conclusion, so I propose this 'scientific-wild-ass-guess' to resolve your puzzle. :)
It appears this number is UNIX 'epoch time' in milliseconds. I'll show this example as if your string field had the arbitrary name, 'epoch_milli'. In postgresql you can convert it to a time stamp using this statement:
SELECT TIMESTAMP WITH TIME ZONE 'epoch' + epoch_milli * INTERVAL '1 millisecond';
or using this built-in postgresql function:
SELECT to_timestamp(epoch_milli / 1000)
either of which, for the example '1187222400000', produces the result
"2007-08-15 17:00:00-07"
You can do some of your own sleuthing with quite a few values selected similarly to this:
SELECT to_timestamp(epoch_milli/1000)::DATE
FROM (VALUES (1187222400000),(1194122400000)) AS val(epoch_milli);
"Well, bollocks, man. I just want the date." Point taken.
Simply cast the timestamp to a date to discard the excess bits:
SELECT to_timestamp(epoch_milli / 1000)::DATE
Of course its possible that this value is a conversion or is relative to some other value, hence the request for a second example data point.

Related

Pull data between 2 dates in redshift

I am trying to pull data from Redshift but cannot seem to make the date range work and I am constantly getting an error.
The column where the data is located is called "impression_time" in the impression_db table.
The date is in UNIX
Here is the query I am trying to pull:
SELECT
split_part((timestamp '1970-01-01'::date + impression_time * interval '1 second'), ' ',1) AS impression_time ,
FROM impression_db
WHERE impression_time >= '2021-09-01'
AND impression_time < '2021-10-01'
It would really be helpful if you posted the error message but here's what I postulate is happening.
I assume that the impression_time data type is a date or a timestamp based on the WHERE clause (could be string but I don't think so). Your are comparing impression_time to a string that looks like a date and relying on implicit casting to convert these for you.
With that assumption I see that you are multiplying impression_time by the time interval '1 second'. This multiplication only makes sense if impression_time is a numeric value. I expect that an implicit cast is again needed to convert impression_time to an epoch representation so that this multiplication can be done. Then you are taking this epoch time interval and adding it to the Unix base time, casting that to a timestamp, and then implicitly casting that to a string. Lastly you perform split_part on this string to get the date portion. All of this could be replaced by
impression_time::date::text AS impression_time
or am I misreading what you are doing?
Now as for what your error likely is - I suspect one of the many implicit castings is not happening or happening in a way that doesn't make sense to the rest of the query. The exact error message should point to where the issue is occurring.

How to truncate date in postgres?

I am using below condition to truncate date in postgres
to_date(to_char(trunc(appointment_date),'YYYYMMDD')||appointment_end_time,''YYYYMMDDHH24:MI:SS')AS tq
How I can use this in postgres ?
Strange data typing, sometimes requires strange, looking at least, queries. Try (see fiddle)
date_trunc('day',appointment_date)
+ substr(appoinment_end,12)::interval
As your to_char() call uses the format 'HH24:MI:SS' for the "time" column, you can cast that column directly to a time value, e.g. using the :: operator: appointment_end_time::time.
To build a new timestamp from the date part of the appointment_date and the time value, just add them:
appointment_date::date + appointment_end_time::time
So first the timestamp is converted to a date (that does not have a time), and then the time value is added to that, which yields a timestamp.
Note that to_date() returns a date so your code would remove the just added time part again. You would need to use to_timestamp() if you really want a timestamp as the result.
To answer the question's title "how to truncate date in Postgres?" (which in reality refers to a timestamp not a date): you can either cast it to a date (see above) or you can use date_trunc() (not trunc()) with a unit to which it should be truncated. However, date_trunc returns a timestamp not a date value, so you couldn't add a time to the result.

postgreSQL increment number in output

I am extracting three values (server, region, max(date)) from my postgresql> But I want to extract an additional 4th field which should be the numerical addition of 1 to 3rd field. I am unable to use date add function as in the database date field is defined as an integer.
date type in DB
date|integer|not null
tried using cast and date add function
MAX(s.date)::date + cast('1 day' as interval)
Error Received
ERROR: cannot cast type integer to date
Required output
select server, region, max(alarm_date), next date from table .....
testserver, europe, 20190901, 20190902
testserver2, europe, 20191001, 20191002
next date value should be the addition to alarm_date
To convert an integer like 20190901 to a date, use something like
to_date(CAST(s.date AS text), 'YYYYMMDD')
It is a bad idea to store dates as integers like that. Using the date data type will prevent corrupted data from entering the database, and it will make all operations natural.
First solution that came to my mind:
select (20190901::varchar)::date + 1
Which output 2019-09-02 as type date.
Other solutions can be found here.

Is ISO8601 the best date-format for PostgreSQL jsonb when i want to filter by the date?

I'm new to PostgreSQL and I have the following question:
I have a table with just an id-column and a data-column, which uses the jsonb-type. Inside the jsonb-object I have a datetime field. I read in various posts, that I should use the ISO-8601 dateformat to store in the DB.
I want to filter my table by date like this:
SELECT * FROM table WHERE data->'date' > '2016-01-01T00:00'
Is this really the best date-format for this purpose?
Thanks in advance :)
IMHO Your query should produce
ERROR: operator does not exist: jsonb > timestamp with time zone
If I get it right. In case you change -> to ->> it should get a text value instead of jsonb field (which is also not comparable to timestamp).
It should be smth like
SELECT * FROM table WHERE (data->>'date')::timestamptz > '2016-01-01T00:00' to work
The big advantage of that format is that string order corresponds to date order, so a comparison like the one you quote in your question would actually work as intended.
A second advantage is that a timestamp in that format can easily be converted to a PostgreSQL timestamp with time zone value, because the type input function understands this format.
I hope you are not dealing with dates “before Christ”, because it wouldn't work so easily with those.

Selecting records between two timestamps

I am converting an Unix script with a SQL transact command to a PostgreSQL command.
I have a table with records that have a field last_update_time(xtime) and I want to select every record in the table that has been updated within a selected period.
Say, the current time it 05/01/2012 10:00:00 and the selected time is 04/01/2012 23:55:00. How do I select all the records from a table that have been updated between these dates. I have converted the 2 times to seconds in the Unix script prior to issuing the psql command, and have calculated the interval in seconds between the 2 periods.
I thought something like
SELECT A,B,C FROM table
WHERE xtime BETWEEN now() - interval '$selectedtimeParm(in secs)' AND now();
I am having trouble evaluating the Parm for the selectedtimeParm - it doesn't resolve properly.
Editor's note: I did not change the inaccurate use of the terms period, time frame, time and date for the datetime type timestamp because I discuss that in my answer.
What's wrong with:
SELECT a,b,c
FROM table
WHERE xtime BETWEEN '2012-04-01 23:55:00'::timestamp
AND now()::timestamp;
If you want to operate with a count of seconds as interval:
...
WHERE xtime BETWEEN now()::timestamp - (interval '1s') * $selectedtimeParm
AND now()::timestamp;
Note the standard ISO 8601 date format YYYY-MM-DD h24:mi:ss which is unambiguous with any locale or DateStyle setting.
The first value for the BETWEEN construct must be the smaller one. If you don't know which value is smaller use BETWEEN SYMMETRIC instead.
In your question you refer to the datetime type timestamp as "date", "time" and "period". In the title you used the term "time frames", which I changed to "timestamps". All of these terms are wrong. Freely interchanging them makes the question even harder to understand.
That, and the fact that you only tagged the question psql (the problem hardly concerns the command line terminal) might help to explain why nobody answered for days. Normally, it's a matter of minutes around here. I had a hard time understanding your question.
Understand the data types date, interval, time and timestamp - with or without time zone. Start by reading the chapter "Date/Time Types" in the manual.
Error message would have gone a long way, too.
For anyone who is looking for the fix to this. You need to remove timestamp from the where clause and use BETWEEN!
TABLENAME.COL-NAME-FOR-TIMESTAMP BETWEEN '2020-01-29 04:18:00-06' AND CURRENT_TIMESTAMP