Truncating timestamps
Let's suppos开发者_JAVA百科e I have a timestamp variable:
select timestamp '2011-02-24 08:30:42 +06:00' from dual;
Is there any way to "truncate" it to something like
'2011-02-24 08:00:00 +06:00'
(I've cut minutes and seconds, but left the timezone)
The target oracle version is 11g r2
SQL> select to_timestamp_tz(to_char(timestamp '2011-02-24 08:30:42 +06:00', 'YYYY-MM-DD HH24 TZH:TZM'), 'YYYY-MM-DD HH24 TZH:TZM') from dual;
TO_TIMESTAMP_TZ(TO_CHAR(TIMESTAMP'2011-02-2408:30:42+06:00','YYYY-MM-DDTZH:
---------------------------------------------------------------------------
24.02.2011 8:00:00,000000000 +06:00
I got it to work using:
SELECT TO_TIMESTAMP_TZ(TO_CHAR(timestamp '2011-02-24 08:30:42 +06:00', 'YYYY-MM-DD HH24') || ':00:00 '|| TO_CHAR(timestamp '2011-02-24 08:30:42 +06:00', 'TZH:TZM'), 'YYYY-MM-DD HH24:MI:SS TZH:TZM')
FROM DUAL
TRUNC supports timestamps 9.2.0.3+, but in my testing on 10g Express Edition this
SELECT TRUNC(timestamp '2011-02-24 08:30:42 +06:00', 'HH')
FROM DUAL
...totally screwed the hours and AM/PM. Didn't matter for a literal, or if supplied inside of TO_TIMESTAMP_TZ for me. The documentation for TRUNC(date) for 10gR2 says "The value returned is always of datatype DATE, even if you specify a different datetime datatype for date.".
Your NLS_DATE_FORMAT is probably set to display only the date portion. This works for me:
SELECT
to_char( TRUNC(timestamp'2011-02-24 08:30:42 +06:00', 'HH'), 'YYYY-MM-DD HH24:MI:SS' )
FROM DUAL;
Keep in mind that the result returned is a DATE, so you lose any localization info. You can return a GMT-normalized timestamp by casting the result to a timestamp:
SELECT
to_char( from_tz( cast( TRUNC(timestamp'2011-02-24 08:30:42 +06:00' at time zone 'GMT', 'HH' ) as timestamp ), 'GMT' ), 'YYYY-MM-DD HH24:MI:SS TZR' )
FROM DUAL;
To preserve the timezone info you have to do something pretty convoluted. It might be easier to use a stored function to perform the conversion at that point. This works much like the Oracle built-in TRUNC() function:
create or replace function trunc_timestamp(
ts in timestamp_tz_unconstrained,
fmt in varchar2
)
return timestamp_tz_unconstrained
is
tzone varchar2(20);
begin
tzone := extract( timezone_region from ts );
if tzone = 'UNKNOWN' then
tzone := to_char( extract( timezone_hour from ts ), 'fm09' )
|| ':'
|| to_char( extract( timezone_minute from ts ), 'fm09' );
end if;
return from_tz( cast( TRUNC( ts at time zone tzone, fmt ) as timestamp ), tzone );
end;
/
I created a sqlfiddle for a demo.
Try select cast(timestamp as date) from dual
精彩评论