Truncate time from datetime in PRESTO - date

I've a requirement to truncate time from datetime in Presto.
I noticed that I cannot use Trunc() function which is used in Redshift to achieve the same.
date_trunc() returns a timestamp again resetting to the start.

Cast the datetime to date
CAST(x AS DATE)
date(x) -- This is an alias for CAST(x AS DATE).
IF the date/time values to be converted are held as strings then such a conversion might fail; in which using TRY_CAST() is recommended as this returns NULL if the conversion fails.

Related

How to convert char type to timestamp?

I am dealing with the table which has date information in CHar(20) type. This date is in dd.mm.yyyy HH.MM.SS format but my pgadmin has Month first format. I tried editing posgres config file to change the date format. I tried to use SET timezone and then tried to convert type to timestamp but nothing is working. How can I convert following column into timestamp format? I followed miost of the answers here on stackoverflow but getting out of range error even after using set function or editing config file.
Use to_timestamp:
to_timestamp(stringcol, 'DD/MM/YYYY HH24:MI')
To change the data type of the column, which is highly commendable:
ALTER TABLE mytable ALTER date1 TYPE timestamp
USING CAST (to_timestamp(date1, 'DD/MM/YYYY HH24:MI') AS timestamp);

How to parse a ZoneDateTime format?

I'm currently trying to parse a timestamp that looks like: 2020-08-03T11:37:42.529Z[UTC]
This timestamp was generated with Java's ZoneDateTime data type
What I have already tried was to parse it via:
SELECT '2020-08-03T11:37:42.529Z[UTC]'::timestamp with time zone;
But that would fail with an exception (unless I parse up until timezone Z).
Edit
For clarification, this is currently a String that is saved in a file, so this application has no direct interaction with Java.
As explained by Adrian, the below code (using at time zone) does not really work. The only other alternative I can think of is to replace the timezone abbreviation with a proper offset. To do that, a function is probably the easiest solution:
create or replace function replace_tz_abbrev(p_input text)
returns text
as
$$
declare
l_offset_hours text;
l_tz_abbrev text;
begin
l_tz_abbrev := substring(p_input from '\[([A-Z]+)\]');
select to_char(utc_offset, 'hh24:mi')
into l_offset_hours
from pg_catalog.pg_timezone_abbrevs
where abbrev = l_tz_abbrev;
return regexp_replace(p_input, '\[[A-Z]+\]', l_offset_hours);
end;
$$
language plpgsql;
This is a rough sketch, the function needs some error checking in case the abbreviation doesn't exist. Maybe checking pg_timezone_names as a fallback to deal with names like Europe/Berlin.
The result of replace_tz_abbrev() can be cast to a timestamptz (at least with the given example). This can either be done in the function itself (and changing it to returns timestamptz or when calling it.
The below is not correct
(I'll just leave it here for reference, so that the comments
One way I can think of is to extract the time zone from the string and use it together with the to_timestamp() function:
with data (input) as (
values ('2020-08-03T11:37:42.529Z[UTC]')
)
select to_timestamp(input, 'yyyy-mm-dd"T"hh24:mi:ss.ms') at time zone substring(input from '\[([A-Z]+)\]')
from data;
Assuming the timestamp string always ends with [timezone] then:
select regexp_replace('2020-08-03T11:37:42.529Z[UTC]', '\[[^\]]*\]', '')::timestamp with time zone;
regexp_replace
-----------------------------
08/03/2020 04:37:42.529 PDT
Where regexp_replace() replaces the [timezone] with an empty string and then you cast the 2020-08-03T11:37:42.529Z portion to a timestamp with time zone.
You can't directly convert this format to a timestamp with timezone. if you are allowed to manipulate the string to get the timedate separtly from the timezone you can do this:
select TIMESTAMP 'The date and time go here'AT TIME ZONE 'timezone name or abbreviation go here';
select TIMESTAMP '2020-08-03T11:37:42.529'AT TIME ZONE 'Africa/Dar_es_Salaam';
select TIMESTAMP '2020-08-03T11:37:42.529'AT TIME ZONE 'UTC';
The reason you have to split the string is that like you discovered a simple conversion does not work and the function TO_TIMESTAMP() that allows you to specify the format does not support specifiying in the format that the string will contain a timezone, only a time offset (example: -03 hours).
-- No way to include the timezone name in the format param.
-- if you insist to add 'TZ'or 'tz' you will get "ERROR: "TZ"/"tz"/"OF" format patterns are not supported in to_date"
select TO_TIMESTAMP('2020-08-03T11:37:42.529Z[UTC]','YYYY-MM-DD HH24:MI:SS.MS')
The difference between the a timezone and a time offset is also why you might not want to do what you are trying to do, postgres does not store timezones (or time offsets). Instead it converts to UTC, and later on reads the column as UTC if the column is 'timestamp without timezone', if the column is 'timestamp with timezone' it converts from UTC to what ever the current session is set to. if you care about the timezone you should store it in another column.

Postgres: SQL Error [42846]: ERROR: cannot cast type bigint to date [duplicate]

I am new to postgresql bot not to sql in general. I have a table that I need to read values from, on of the columns is a unix timestamp that I want to convert in to a more human readable format thus I found this:
SELECT lt,dw,up,to_char(uxts, 'YYYY-MM-DD HH24:MI:SS')
from products;
But that produces an error:
ERROR: multiple decimal points
I am lost here. I am sure someone can show me how to do it. The documentation isn't that clear to me. Postgresql 9.5 is the database.
to_char() converts a number, date or timestamp to a string, not the other way round.
You want to_timestamp()
Convert Unix epoch (seconds since 1970-01-01 00:00:00+00) to timestamp
So just apply that function on your column
SELECT lt,dw,up,to_timestamp(uxts) as uxts
from products;
This assumes that uxts is some kind of number data type (integer, bigint or double precision)

Casting String type to Unix Date Amazon Athena

I'm looking to get a result in Amazon Athena were I can count the quantity of users created by day (or maybe by month)
But previous that I have to convert the unix timestamp to another date format. And this is where i fail.
My last goal is to convert this type of timestamp:
1531888605109
In something like:
2018-07-18
According to Epoch Converter
But when I try to apply the solution i saw in this quiestion: Casting unix time to date in Presto
I got the error:
[Simba]AthenaJDBC An error has been thrown from the AWS Athena client. SYNTAX_ERROR: line 1:13: Unexpected parameters (varchar) for function from_unixtime. Expected: from_unixtime(double) , from_unixtime(double, bigint, bigint) , from_unixtime(double, varchar(x)) [SQL State=HY000, DB Errorcode=100071]
This is my query:
select cast(from_unixtime(created)as date) as date_creation,
count(created)
from datalake.test
group by date_creation
Maybe I've to cast over the sctring because the data type of the field is not a date.
My table description: Link to the table description
line 1:13: Unexpected parameters (varchar) for function from_unixtime. Expected: from_unixtime(double)
This means that your timestamps -- even though they appear numeric -- are varchars.
You need to add a CAST to cast(from_unixtime(created)as date), like:
CAST(from_unixtime(CAST(created AS bigint)) AS date)
Note: When dealing with time-related data, please have in mind that https://github.com/prestosql/presto/issues/37 is not resolved yet in Presto.

Create timestamp index from JSON on PostgreSQL

I have a table on PostgreSQL with a field named data that is jsonb with a lot of objects, I want to make an index to speed up the queries. I'm using few rows to test the data (just 15 rows) but I don't want to have problems with the queries in the future. I'm getting data from the Twitter API, so with a week I get around 10gb of data. If I make the normal index
CREATE INDEX ON tweet((data->>'created_at'));
I get a text index, if I make:
Create index on tweet((CAST(data->>'created_at' AS timestamp)));
I get
ERROR: functions in index expression must be marked IMMUTABLE
I've tried to make it "inmutable" setting the timezone with
date_trunc('seconds', CAST(data->>'created_at' AS timestamp) at time zone 'GMT')
but I'm still getting the "immutable" error. So, How can I accomplish a timestamp index from a JSON? I know that I could make a simple column with the date because probably it will remain constant in the time, but I want to learn how to do that.
This expression won't be allowed in the index either:
(CAST(data->>'created_at' AS timestamp) at time zone 'UTC')
It's not immutable, because the first cast depends on your DateStyle setting (among other things). Doesn't help to translate the result to UTC after the function call, uncertainty has already crept in ...
The solution is a function that makes the cast immutable by fixing the time zone (like #a_horse already hinted).
I suggest to use to_timestamp() (which is also only STABLE, not IMMUTABLE) instead of the cast to rule out some source of trouble - DateStyle being one.
CREATE OR REPLACE FUNCTION f_cast_isots(text)
RETURNS timestamptz AS
$$SELECT to_timestamp($1, 'YYYY-MM-DD HH24:MI')$$ -- adapt to your needs
LANGUAGE sql IMMUTABLE;
Note that this returns timestamptz. Then:
CREATE INDEX foo ON t (f_cast_isots(data->>'created_at'));
Detailed explanation for this technique in this related answer:
Does PostgreSQL support "accent insensitive" collations?
Related:
Query on a time range ignoring the date of timestamps