PL/SQL 如何处理两个timestamp类型的差值

今天遇到一个问题,前端返回请求时间和响应时间给我,而我将两个差值保存为以毫秒为单位的number类型存入数据库。本来以为很简单 燃鹅0.0..

请求时间和响应时间都是字符串表示时间戳类型,我需要将前端传入的字符串转为时间戳然后才能进行相应的相加减。

例如传入的请求时间
requestTime :='2017-11-23T11:16:01.960+08:00'
响应时间
responseTime := '2017-10-23T11:16:01.960+08:00'

刚开始我用的是oracle自带的cast函数,cast函数能够进行数据类型之间的转换,格式是CAST ( { expr | ( subquery ) | MULTISET ( subquery ) } AS type_name )
我这里用的代码是
SELECT CAST('2017-11-23T11:16:01.960+08:00' AS TIMESTAMP WITH TIME ZONE) FROM dual;

但是报错了。。。 提示ORA-01843:无效的月份

--后来试了半天查了资料发现貌似只能支持这种格式
SELECT CAST('23-11月-17 11:16:01.960上午+08:00' AS TIMESTAMP WITH TIME ZONE) FROM dual;

这个就有点坑了。。。PS:当然这个年月日和上下午格式可以通过修改v$nls_parameters表上的NLS_LANGUAGE字段

后来发现oracle还有一个to_timestamp函数和to_timestamp_tz函数能够将字符串转为时间戳类型,其中to_timestamp_tz函数是将字符串转为带时区的时间戳类型。
两种函数支持的语法分别是

TO_TIMESTAMP( string1 [, format_mask] ['nlsparam'] )
TO_TIMESTAMP_TZ( string1 [, format_mask] ['nlsparam'] )

格式的话
1. YYYY 四个数字代表年
2. MM 月范围从01-12
3. MON 代表月的缩写
4. MONTH 月份的全称
5. DD 日期
6. HH 小时
7. HH12 12小时制
8. HH24 24小时制
9. MI 分钟
10. SS
11. TZH 代表时区的小时
12. TZM 代表时区的分钟

那么我这里只需要根据传入时间的格式就可以转换为相应的时间戳了,代码如下。

requestTimestamp := to_timestamp_tz('2017-11-23T11:16:01.940+08:00', 'YYYY-MM-DDTHH:MI:SS.FF3TZH:TZM');

但是这里报错了提示ORA-01821日期格式无法识别

这里日期和时间之间多了一个字母’T’…查了一下找不到这个东西是什么意思0.0 我直接replace掉然后再转换就可以了。

然后cost := responsetTimestamp - requestTimestamp;
本来以为两个时间戳类型相减会是number类型的。。。额实际上是interval类型(例如 +000000000 00:00:00.000000)

oracle数据库中使用INTERVAL类型表示两个时间之间的差值,其中有两种类型的interval:一种为“年份-月份”,即保存年份和月份(YYYY-MM);一种为“天-时间”(DD HH:MM:SS),用来保存天数、小时、分钟和秒。

那么我要怎么才能通过这个interval类型拿到millis呢?
我写了一个函数,通过获取差值的天数、小时、分钟、秒、毫秒,然后 cost := 天数 * 24 * 60 * 60 * 1000 + 小时 * 60 * 60 * 60 + 秒 * 60 * 1000 + 毫秒, 具体代码如下

FUNCTION timestamp_difference(p_timestamp_1 timestamp,p_timestamp_2 timestamp) RETURN NUMBER IS
  v_difference VARCHAR2(100);
  v_date VARCHAR2(100);
  v_time VARCHAR2(100);
  v_hour VARCHAR2(10);
  v_minute  VARCHAR2(10);
  v_second  VARCHAR2(100);
  x_response VARCHAR2(1000);
    BEGIN
      IF p_timestamp_1 IS NOT NULL 
      AND p_timestamp_2 IS NOT NULL THEN
        v_difference := to_char(p_timestamp_2 - p_timestamp_1);
        v_date := regexp_substr(v_difference, '[^ ]+', 2, 1);
        v_time := regexp_substr(v_difference, '[^ ]+', 1, 2);
        v_hour := regexp_substr(v_time, '[^:]+', 1, 1);
        v_minute := regexp_substr(v_time, '[^:]+', 1, 2);
        v_second := regexp_substr(v_time, '[^:]+', 1, 3);
        x_response := to_number(v_date) * 24 * 60 * 60 * 1000 
        + to_number(v_hour) * 60 * 60 * 1000 
        + to_number(v_minute) * 60 * 1000 
        + to_number(v_second) * 1000;
      END IF;
      RETURN x_response;
      EXCEPTION WHEN OTHERS THEN
        dbms_output.put_line(SQLERRM);
        RETURN NULL;
    END timestamp_difference;

你可能感兴趣的:(PL/SQL 如何处理两个timestamp类型的差值)