How do I convert date and seconds fields to a timestamp field in PostgreSQL? - postgresql

I have a date field, which is just text, and a field showing seconds since midnight.
CREATE TABLE t ("s" text, "d" text, "ts" timestamp)
;
INSERT INTO t ("s", "d")
VALUES
(24855, 20130604),
(24937.7, 20130604)
;
How can I convert these fields into a timestamp, so I can run time-based queries?
See a demo with SQL Fiddle:
http://sqlfiddle.com/#!15/67018/2

Since your data includes fractional seconds, you need to adjust for those:
UPDATE t
SET ts = to_timestamp(d||s, 'YYYYMMDDSSSS.MS');
Assuming milliseconds as the maximum precision. Else employ US for microseconds.
Consider the fine print in the manual:
In a conversion from string to timestamp, millisecond (MS) or
microsecond (US) values are used as the seconds digits after the
decimal point. For example to_timestamp('12:3', 'SS:MS') is not 3
milliseconds, but 300, because the conversion counts it as 12 + 0.3
seconds. This means for the format SS:MS, the input values 12:3,
12:30, and 12:300 specify the same number of milliseconds. To get
three milliseconds, one must use 12:003, which the conversion counts
as 12 + 0.003 = 12.003 seconds.
Also note that to_timestamp() returns timestamp with time zone, which is coerced to timestamp in the context of the update, which turns out all right. For other contexts, you may want to cast explicitly or use this alternative, yielding timestamp:
SELECT d::date + interval '1s' * s::numeric AS ts FROM t;
The plain cast to date (d::date) works because your dates are in standard ISO 8601 format - or so I assume.

Concatenate the two fields together and then use to_timestamp()
UPDATE t SET ts = to_timestamp(d||s, 'YYYYMMDDSSSS');
For a discussion of the formatting string used in to_timestamp, see Table 9-21: Template Patterns for Date/Time Formatting in the PostgreSQL documentation.

Related

how to keep datatype when substracting day from date/time column in SAS

My question is really simple, hope someone deigns to answer!.
Being very to new SAS, the date and its formats really is confusing me.
I have timestamp column from which I need to substract 2 days while keeping its datatype
The value of the column is "2022-04-20-19.37.57.714699"
What I need is "2022-04-18-19.37.57.714699"
When I try this I get number datatype:
PROC SQL;
CREATE TABLE my_table AS
SELECT
cust_id,query_date, (query_date)-2 as calc_date
FROM other_table
;quit;
I try format,datetime function, but ended up with "Statement is not valid or it is used out of proper order"
Thanks
Assuming that the QUERY_DATE variable is numeric and has datetime values in it (the number of seconds since 1960) then you can use the INTNX() function with the DTDAY interval to adjust the value by two days. To keep the same time of day use SAME for the alignment parameter.
intnx('dtday',query_date,-2,'same')
Alternatively you could just subtract 48 hours worth of seconds from the value.
query_date -2*'24:00:00't
If you want the values to display in a human readable way then attach any of the many datetime formats, such as DATETIME to the new variable.
CREATE TABLE my_table AS
SELECT cust_id,query_date
, intnx('dtday',query_date,2,'same') as calc_date format=datetime20.
FROM other_table
;
If the variable is just a string then you cannot subtract from strings. You will have to convert the strings into numbers to perform arithmetic. You probably have too many decimal places for SAS datetime informats/formats to replicate (and perhaps to be uniquely stored in a floating point value) so just convert the date part and then append back the rest to keep the same time of day. Since dates are stored as number of days you can just subtract the 2 days using normal subtraction.
put(input(query_date,yymmdd10.)-2,yymmdd10.)||substr(query_date,11)
This should solve your problem. The first issue to tackle is converting the date string into a sas datetime. The input() function with the anydtdtm. informat accomplishes that with a small caveat as seen in the output.
data test;
date_txt = '2022-04-20-19.37.57.714699';
query_date = input(date_txt, anydtdtm.); * convert string into sas datetime;
calc_date = intnx('dtday', query_date, -2, 's'); * backup 2 days preserving the time;
format query_date calc_date e8601dt26.6;
run;
date_txt
query_date
calc_date
2022-04-20-19.37.57.714699
2022-04-20T19:37:57.000000
2022-04-18T19:37:57.000000
The default width of the informat is 19 characters which excludes the fractional seconds, but the informat correctly converted the string into a datetime.
To attempt to capture the full width of the date string, I modified the informat to anydtdtm26.. However, that change resulted in an error and missing values for query_date and calc_date. Although the anydtdtm informat is robust with converting a wide variety of date and time formats, I suspected that the problem lies with the periods used to delimit the hours and minutes.
To correct that problem I used prxchange() function to replace the periods after hours and minutes with colons which are standard time componenent delimiters. That change allows the anydtdtm informat to properly convert the fractional seconds.
data test2;
date_txt = '2022-04-20-19.37.57.714699';
date_mod = prxchange('s/\./:/', 2, date_txt); * replace first 2 periods w/ colons;
query_date = input(date_mod, anydtdtm26.); * convert string into sas datetime;
calc_date = intnx('dtday', query_date, -2, 's'); * backup 2 days preserving the time;
format query_date calc_date e8601dt26.6;
run;
date_txt
date_mod
query_date
calc_date
2022-04-20-19.37.57.714699
2022-04-20-19:37:57.714699
2022-04-20T19:37:57.714699
2022-04-18T19:37:57.714699
Although I used a data step to illustrate the solution the functions can also be used in a SQL statement.

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.

Converting DateTime to Epoch milliseconds using Cypher in Neo4J

I'm running a query using Cypher in Neo4J where I have to compare a createdAt property of a node against a given time unit in Epoch milliseconds. This createdAt property is a string in the DateTime format, which is defined as -
DateTime
date with a precision of miliseconds, encoded as a string with the following format: yyyy-mm-ddTHH:MM:ss.sss+0000, where yyyy is
a four-digit integer representing the year, the year, mm is a
two-digit integer representing the month and dd is a two-digit integer
representing the day, HH is a two-digit integer representing the hour,
MM is a two digit integer representing the minute and ss.sss is a five
digit fixed point real number representing the seconds up to
milisecond precision. Finally, the +0000 of the end represents the
timezone, which in this case is always GMT.
Here are a couple of values of this property - 2011-03-21T19:32:38.295+0000, 2012-03-09T17:59:05.367+0000.
I came across the Temporal Values documentation on Neo4j, but couldn't find a way to perform the conversion.
When I execute some of the given examples, like this -
RETURN datetime('2015-06-24T12:50:35.556+0100') AS theDateTime
I get the error -
Neo.ClientError.Statement.SyntaxError: Unknown function 'datetime' (line 1, column 16 (offset: 15))
Would appreciate any help!
The temporal functions were added in neo4j version 3.4.0, and I have verified that your query works in that version.
Make sure you are using an appropriately recent version of neo4j.

Converting string timestamp into date

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.

Converting dates and timestamps when inserting data into Teradata

I am block-inserting data from Stata (a statistics package) into a Teradata database. I am having trouble converting dates and timestamps from Stata's native format to Teradata's.
Stata stores dates as days since 01/01/1960, so that 01jan1960 is 0 and 02jan1960 is 1. Timestamps are stored as milliseconds since 01jan1960 00:00:00.000, so that 1000 is 01jan1960 00:00:01. Here are some examples:
timestamp Stata's tstamp date Stata's date
2015-04-13 03:07:08 1744513628000 2015-04-13 20191
2015-04-14 19:55:43 1744660543000 2015-04-14 20192
2015-04-08 11:41:39 1744112499000 2015-04-08 20186
2015-04-15 06:53:34 1744700014000 2015-04-15 20193
I tried 2 approaches. The first involves converting the dates/timestamps to strings in Stata before inserting and then doing something like this once the data is inserted:
ALTER TABLE mytable ALTER date_variable DATETIME
However, I cannot figure out how to do the second part from the documentation I have and after searching the various fora.
The second approach is leaving the dates and timestamps as integers, and then doing some of conversion once the integers are inserted. Perhaps I can also pre-convert dates in Stata to TD's internal format with:
gen td_date = ((year(stata_dt)-1900)*10000 + month(stata_dt)*100 + day(stata_dt))
However, I am not sure what the formula for timestamps would be. I am also not sure how to do the second part (making the integers into dates/timestamps).
You can't change the datatype of a column in Teradata from string to date/timestamp.
But when you insert a string into a date/timestamp column there will be an automatic typecast. So simply convert to a string with 'yyyy-mm-dd' or 'yyyy-mm-dd hh:mi:ss' format.
You could also do the conversion during load on Teradata using calculations, but IMHO the 1st solution is preferable:
-- add the number of days to the start date
DATE '1960-01-01' + stata_dt
-- I use a similar approach for Unix Timestamps starting 1970 :-)
-- split into days and seconds
CAST(DATE '1960-01-01' + (stata_ts / 86400000) AS TIMESTAMP(0))
+ ((stata_ts MOD 86400000 / 1000) * INTERVAL '00:00:01' HOUR TO SECOND)