今天遇到一个问题,前端返回请求时间和响应时间给我,而我将两个差值保存为以毫秒为单位的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;