KDB:How to parse a millisecond timestamp in kdb - kdb

I'm trying to parse the following utc timestamps in kdb
t:1605083972601 1605083972853 1605083972854 1605083972860 1605083972865
such that it resolves at least to the millisecond. I have tried to do the following:
`datetime$("P"$10$string[`long$t])
`datetime$("P"$10$string[`long$(t*1000)])
which both return:
2020.11.11T08:39:32.000 2020.11.11T08:39:32.000 2020.11.11T08:39:32.000 2020.11.11T08:39:32.000
Obviously having it round to the second is inadequate.
How does one effectively achieve this in kdb?
Thanks

Following function converts unix to Kdb timestamp:
{`timestamp$(1000000*x)+`long$1970.01.01D0-2000.01.01D0}
Kdb timestamp starts from 1st Jan 2000. That is why unix timestamp has to be adjusted by 1970.01.01 and 2000.01.01 difference

Another approach which makes it explicit that what you have are number of milliseconds since unix epoch:
q)f:1970.01.01+0D00:00:00.001*
q)f 1605083972601 1605083972853 1605083972854 1605083972860 1605083972865
2020.11.11D08:39:32.601000000 2020.11.11D08:39:32.853000000 2020.11.11D08:39:..

Related

Db2: How to convert Unix / epoch time to timestamp?

I have a BIGINT value which represents a UNIX timestamp (epoch). How can I convert it to the built-in TIMESTAMP type?
As example, I want to turn 1611140400 into the related date and time. TIMESTAMP_FORMAT does not work.
You can use datetime arithmetics in Db2 and Db2 on Cloud. For Db2 on Cloud (which is running in UTC):
VALUES (TIMESTAMP('1970-01-01') + 1611140400 seconds)
Epoch is seconds since January 1st, 1970 GMT / UTC. Thus, adding your number as seconds to that date will give:
2021-01-20 11:00:00.0
If you are running in a different timezone, you need to take care of it, e.g.:
VALUES (TIMESTAMP(‘1970-01-01-00.00.00.000000’) + 1611140400 seconds + current timezone)

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)

PostgreSQL epoch time conversion

I am using the postgresSQL function to_timestamp(double precision) to convert from epoch time to normal timestamp but I am facing a problem where the timestamp is incorrect
SELECT to_timestamp(1428058548491);
produces "47223-05-17 12:08:11.000064+02"
while it should be 4/3/2015, 12:55:48 PM GMT+2:00 DST
SELCT to_timestamp(1428058557697);
produces "47223-05-17 14:41:36.999936+02"
while it should be 4/3/2015, 12:55:57
as can be seen the dates have been converted totally incorrect
As was explained from people In the comments for people who get the same problem. The function to_timestamp() expects it in seconds not milliseconds therefore that is the solution.
Quote from the manual:
it accepts a double precision argument and converts from Unix epoch (seconds since 1970-01-01 00:00:00+00) to timestamp with time zone

DB2 convert long value to timestamp

Is there a scalar function in DB2 to convert a long number to TIMESTAMP?
As #Dan1111 points out; no, there's nothing built in.
However, if you've got a 'long' number (I'm assuming BIGINT), I'm guessing you have a count of seconds (or similar) from the Unix Epoch (1970-01-01 00:00:00.000 UTC). If so, it's easy to 'cheat', and you can use this logic to write your own:
SELECT TIMESTAMP('1970-01-01', '00:00:00') + <your_column> SECONDS
FROM <your_table>
This of course presumes that the count is actually from UTC (and that you plan to interpret the results as such), as daylight savings time (and timezones, to a lesser extent) screws things up royally.
A quick example:
SELECT TIMESTAMP('1970-01-01', '00:00:00') + 1348241581 SECONDS
FROM sysibm/sysdummy1
Yields the expected:
2012-09-21-15.33.01.000000
(GMT, obviously)

converting db2 datestamp to Unix timestamp

How can i convert 2012-04-12 00:00:00 to a unix timestamp in DB2. is there any inbuild function available in sql s
Thank you.
Using the DAYS and MIDNIGHT_SECONDS is much more precise than TIMESTAMPDIFF:
SELECT
86400*(DAYS(CURRENT TIMESTAMP - CURRENT TIMEZONE)-DAYS('1970-01-01'))
+ MIDNIGHT_SECONDS(CURRENT TIMESTAMP - CURRENT TIMEZONE)
"UNIX_TIMESTAMP"
FROM SYSIBM.SYSDUMMY1
By Unix timestamp I assume you mean the number of seconds (or whatever) since 1970-01-01 00:00:00 UTC.
There is no built in functionality for this in DB2 (as of V6R1).
You're also up against the following issues:
All timestamps in DB2 are 'local time' - they contain no timezone information, and all CURRENT_TIMESTAMP writes are based on what time the requesting system thinks it is, not the host.
Daylight savings time changes frequently. You would need to add overhead to manage this for your conversion.
The TIMESTAMPDIFF function returns an estimate, not an exact value. You could probably survive for the years/months durations, over sufficient differences, but days aren't likely to cut it.
Timestamp arithmetic is imprecise (among other things, months are assumed to be always 30 days in length...)
Your best bet will be to start using DAYS (which returns the number of days since 0001-01-01). Keep in mind you better do everything in UTC, because it will not take DST into account.