Do I need to convert TIMESTAMP to DATE before doing a comparison? EX:
AND SORD.CREATED >= TO_DATE(FROM_TZ(CAST(TO_DATE('','DD-MON-YYYY HH24:MI:SS') AS TIMESTAMP), 'Asia/Kuala_Lumpur') AT TIME ZONE 'UTC','DD-MON-YYYY HH24:MI:SS')
AND SORD.CREATED < TO_DATE(FROM_TZ(CAST(TO_DATE('','DD-MON-YYYY HH24:MI:SS') AS TIMESTAMP), 'Asia/Kuala_Lumpur') AT TIME ZONE 'UTC','DD-MON-YYYY HH24:MI:SS')
Just looking for an opinion, since I'm still new and learning about databases.
It's hard to tell exactly what you database you are using. From the functions in the code you provided, I am guessing Oracle? Please confirm.
In general, I can tell you the following:
You aren't passing any values. The first parameter to TO_DATE is empty, and that would contain the string to convert to a date.
You need to know what the values in your database are. Is SORD.CREATED a DATE or TIMESTAMP datatype? Does it keep UTC values? If so, then yes, you should convert local times to UTC before querying. If possible, you should do this outside of the query itself.
If the values in your database are of type TIMESTAMP WITH TIME ZONE, then you can use a DATE or TIMESTAMP with the AT TIME ZONE function, like you showed in your question.
Don't cast to/from a string unnecessarily. If your source data is already in a DATE or TIMESTAMP datatype, there's no need to convert to a string. Once a date is a date, you should keep it a date. Introducing string formatting can sometimes introduce errors.
Related
I have a Oracle SQL statement where I have to get the current timestamp as one of the columns. But I dont require the Timezone which CURRENT_TIMESTAMP gives or the AM/PM given by LOCALTIMESTAMP.
I require the current timestamp in 24hr format without the timezone.
Is it possible to get that in Oracle SQL?
It seems you're mixing 2 concepts here: "datatype" and "date format mask".
data type: LOCALTIMESTAMP returns datatype TIMESTAMP and CURRENT_TIMESTAMP returns datatype TIMESTAMP WITH TIME ZONE. TIMESTAMP is similar to DATE but has a higher precision. As usual... checking the docs is worth it.
date format mask: determines how you display the date information. Americans can't read 24 hour format, the rest of the world is confused by AM/PM. Fortunately, you can decide how you want to display the date as explained in the oracle docs.
If you just want to return the current date in 24 hour format you could do something like:
SELECT
TO_CHAR(SYSDATE,'DD-MON-YYYY HH24:MI:SS') as mydate,
<other columns>
FROM
<table_name>
If you need the date to be more precise and you require fractional seconds then you can use SYSTIMESTAMP instead of DATE with a format mask 'DD-MON-YYYY HH24:MI:SS.FF9'
I have a String in this format: 2018-11-01T00:00:00-07:00 and I would like to convert it to a TIMESTAMP and insert it into a TIMESTAMP column. However, when I insert it, it drops the -07:00 without first converting it to -00:00. How do I ensure that it is converted and stored in Redshift properly?
Here is an example:
select ORIGINAL_DATE, TO_TIMESTAMP(ORIGINAL_DATE,'YYYY-MM-DD HH24:MI:SS') FROM CDW_LANDING.X where id = XXXXXX;
=> 2018-11-01T00:00:00-07:00 2018-10-31 17:00:00
The TO_TIMESTAMP converts it to 2018-10-31 17:00:00 which is what I want. However, when I insert it, it becomes 2018-11-01 00:00:00 and simply drops the -07:00.
Here is the example:
insert into cdw_stage.X (ORIG_DT)
select TO_TIMESTAMP(ORIGINAL_DATE,'YYYY-MM-DD HH24:MI:SS')
from CDW_LANDING.INVOICE where id = XXXXXX;
But when I query it with select ORIG_DT from cdw_landing.X;, it displays 2018-11-01 00:00:00. What I would like to see is 2018-10-31 17:00:00 which is what the TO_TIMESTAMP function should do.
The ORIG_DT in Redshift is in TIMESTAMP format. The input date is in VARCHAR.
How do I get Redshift to save this correctly? I also added postgres tag because Redshift is based off of postgres. Thank you so much!!!
2018-11-01T00:00:00-07:00 is not a timestamp (timestamp without time zone) literal, strictly speaking. It is a timestamptz (timestamp with time zone) literal. This is the root of all pain in your question. The wrong cast to timestamp ignores the offset. The Postgres manual:
In a literal that has been determined to be timestamp without time zone, PostgreSQL will silently ignore any time zone indication. That
is, the resulting value is derived from the date/time fields in the
input value, and is not adjusted for time zone.
Bold emphasis mine.
The use of TO_TIMESTAMP() can't save you. The Redshift manual:
Formats that include a time zone (TZ, tz, or OF) are not supported as input.
(The same is true in Postgres.)
Solution
Cast to timestamptz (or use a column of that type to begin with), the rest should fall in place:
SELECT cast('2018-11-01T00:00:00-07:00' AS timestamptz);
Or:
SELECT '2018-11-01T00:00:00-07:00'::timestamptz;
The manual about casting in Redshift.
When an actual timestamptz is assigned to a timestamp column it is converted according to the current timezone setting of the session automatically. If you want a different target timezone, use the AT TIME ZONE construct. Details:
Ignoring time zones altogether in Rails and PostgreSQL
The related answer is for Postgres, but timestamp handling in Redshift (while differing in many other aspects!) is the same. The Redshift manual:
When converting DATE or TIMESTAMP to TIMESTAMPTZ, DATE or TIMESTAMP
are assumed to use the current session time zone. The session time
zone is UTC by default. For more information about setting the session
time zone, see timezone.
I uploaded a table using fastload and want to convert the event_time column to a timestamp or just get the dates since I don't need the time component.
The text format is 'MM/DD/YYYY HH:MM:SS AM/PM', for example, '05/24/2013 08:12:00 AM'
I have tried
CAST(event_time AS TIMESTAMP(0))
and
CAST(SUBSTRING (event_time,1,10) AS date)
but they don't work for me. The error I get is invalid timestamp/date.
As a bonus question,
I don't think there are any outliers in the data (i.e. every row is in format as described above), but if there were, how do I account for those errors? or will Teradata automatically pass on those rows?
The CASTs don't work because this is not the default timestamp/date format.
The easiest way utilizes the TO_DATE function which is supported since TD14:
TO_DATE(event_time, 'MM/DD/YYYY HH:MM:SS AM')
Before TD14 it's:
CAST(CAST(event_time AS TIMESTAMP FORMAT 'MM/DD/YYYYbHH:MI:SSbT') AS DATE)
Regarding outliers, they will result in an "invalid date/timestamp" error. When you cast them during FastLoad to a Timestamp those rows will fail to load and will be inserted into the ET-error table. But you can't use the newer CAST-syntax in FL, must be the old Teradata-style cast:
:event_time (TIMESTAMP, FORMAT 'MM/DD/YYYYbHH:MI:SSbT')
I have a SQL Builder library that direcltly uses ADO.NET. I have a means of creating a select query with a greater-than-or-equal operator, like:
select *
from book
where book.date_created >= {some date}
My issue is that {some date} is going to always be in the UTC time zone, but it's being compared to the book.date_created column which is a TIMESTAMP(6) WITH TIME ZONE column, which will not be in the UTC timezone.
I can execute the query, but my results are off becuaes of timezone comparisons. My query is for all books where the date_created >= x, but some of the results returned are not greater than x because after subtracting 5 hours for the time zone, they are now less than x. The IDataRecord DateTime fields returned are converted to UTC using DateTime.SpecifyKind()
Can I form my query such that it interprets book.date_created in the UTC timezone?
Note: While I'd love to change my Oracle DB columns to not specify timezones, changing table structures is not something I can do.
Edit:
Currently, {some date} is a SQL Parameter. It's backing datatype is a DateTime with UTC as the timezone. As a parameter, it is a TimestampWithTZ. The Value of the parameter is a DateTime with the kind specified as UTC as well.
Update:
The issue seems to be related to my results set from the IDataRecord. When I pull DateTimes off, I use DateTime.SpecifyKind() to put them in UTC mode. The problem is, the date times come out as DateTimeKind.Unspecified. When converting from Unspecified to UTC, it just drops the timezone and declares it is UTC without changing the underlying value. I'm not sure how to have the IDataRecord pull in the TimeZone value.
You need to use the FROM_TZ function that transforms a TIMESTAMP into a TIMESTAMP WITH TIME ZONE. For example, if you know that your variable is in UTC time (+0:00):
SELECT *
FROM book
WHERE date_created >= from_tz(<timestamp>, '+0:00');
Here's a sample script that shows the behaviour you describe (your local time zone should be set to +1:00):
CREATE TABLE t (tz TIMESTAMP(6) WITH TIME ZONE);
INSERT INTO t VALUES
(to_timestamp_tz('20000101 00:00:00 +1:00','yyyymmdd hh24:mi:ss tzh:tzm'));
INSERT INTO t VALUES
(to_timestamp_tz('20000101 00:00:00 -1:00','yyyymmdd hh24:mi:ss tzh:tzm'));
-- This will return two values instead of one
SELECT *
FROM t
WHERE tz >= to_timestamp('20000101 00:00:00', 'yyyymmdd hh24:mi:ss');
-- This query will return only one row
SELECT *
FROM t
WHERE tz >= from_tz (to_timestamp('20000101 00:00:00',
'yyyymmdd hh24:mi:ss'), '+0:00');
below links will help you.
Datetime Datatypes and Time Zone Support
TIMESTAMP WITH TIME ZONE Data Type
Write Time Zone Aware Code in Oracle
ORACLE timezone summary
Oracle Date and Time data types
I have a database field of type time with time zone. How can I query this field in EST5EDT time zone with the output format hh:mm:ss?
All I can find is using multiple calls to EXTRACT:
SELECT EXTRACT(HOUR FROM TIME WITH TIME ZONE '20:38:40-07' AT TIME ZONE 'EST5EDT');
[Edit:]
To be clear, this query:
SELECT TIME WITH TIME ZONE '20:38:40.001-07' AT TIME ZONE 'EST5EDT';
Returns "22:38:40.001" but I just want "22:38:40" as the output.
Use the TO_CHAR() function:
SELECT TO_CHAR(date '2001-09-28' +time, 'HH24:MI:SS')
Seeing that TO_CHAR only accepts the timestamp datatype, you need to concatentate an arbitrary date value to your time value.
"time with time zone" is basically a bogus datatype, and as such isn't really supported in a lot of cases.
How do you define "time with time zone"? Time zones are dependent on dates, which aren't included in the datatype, and thus it's not fully defined. (yes, it's mandatory by the SQL standard, but that doesn't make it sane)
You're probably best off first fixing what datatype you're using. Either use timestamp with time zone, or use time (without time zone).
You can simply use CAST and CAST to the time type:
SELECT CAST(now() AS TIME)
(Of course, the result will have a different data type)