开发者

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜