提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


一、时间戳函数

1、unix_timestamp()

  • unix_timestamp() 无参数调用,获取当前系统时间戳为10位的bigint类型数值,该数值只精确到秒。
select unix_timestamp();
> 1680227307 
  • unix_timestamp(string timestamp) 输入格式默认为“yyyy-MM-dd HH:mm:ss”,如不符合则返回null。
select unix_timestamp('2023-03-31 01:48:27') ; 
> 1680227307

select unix_timestamp('2023-03-31');
> NULL
  • unix_timestamp(string date,string pattern) 将指定时间格式的字符串转化成时间戳,如不符合则返回null。
--固定日期转换成时间戳
select unix_timestamp('2023-03-31','yyyy-MM-dd');
> 1680220800 

select unix_timestamp('2023-03-31 01:48:27','yyyy-MM-dd HH:mm:ss');  
> 1680227307

select unix_timestamp('2023-03-31T10:02:41Z', "yyyy-MM-dd'T'HH:mm:ss'Z'");
> 1680256961

select unix_timestamp('2023-03-31','yyyy-MM-dd HH:mm:ss')   
> NULL
  • unix_timestamp() - unix_timestamp()是两个时间转换为timestamp之后相减,timestamp单位是秒,相减之后是两个时间之间相差的秒数。

cast((unix_timestamp() - unix_timestamp()) % 60 as int) --是相差的秒数。
cast((unix_timestamp() - unix_timestamp()) / 60 as int) % 60 --是相差的分钟数。
cast((unix_timestamp() - unix_timestamp()) / (60 * 60) as int) % 24 --是相差的小时数。
concat(cast((unix_timestamp() - unix_timestamp()) / (60 * 60 * 24) as int) --是相差的天数。

--是相差的秒数
select unix_timestamp('20230329185800','yyyyMMddHHmmss')- unix_timestamp('20230329185604','yyyyMMddHHmmss');
> 56
select cast((unix_timestamp('20230329185800','yyyyMMddHHmmss')- unix_timestamp('20230329185604','yyyyMMddHHmmss'))%60 AS int);
> 56

--是相差的分钟数
select cast((unix_timestamp('20230329185800','yyyyMMddHHmmss')- unix_timestamp('20230329185604','yyyyMMddHHmmss'))/60 AS int);
> 1

--是相差的小时数
select cast((unix_timestamp('20230329215800','yyyyMMddHHmmss')- unix_timestamp('20230329185604','yyyyMMddHHmmss'))/(60 * 60) AS int) % 24;
> 3

--是相差的天数
select cast((unix_timestamp('20230331185800','yyyyMMddHHmmss')- unix_timestamp('20230329185604','yyyyMMddHHmmss'))/(60 * 60 * 24) AS int)  ;
> 2

注意:unix_timestamp 类第一个参数只接受 string 类型

2、from_unixtime()

  • from_unixtime(bigint unixtime,string format) 将时间戳秒数转化成UTC时间,并用字符串表示,可通过format规定时间格式,指定输出的时间格式。其中unixtime是10位的时间戳值,而13位的所谓毫秒是不可以的。
-- 时间戳转换成固定日期
select from_unixtime(1680257881,'yyyy-MM-dd HH:mm:ss');
> 2023-03-31 10:18:01

select from_unixtime(1680257881,'yyyy-MM-dd');
> 2023-03-31

select from_unixtime(unix_timestamp('31/Mar/2023:10:18:01 +0800', 'dd/MMM/yyy:HH:mm:ss Z'))
> 2023-03-31 02:18:01

select from_unixtime(1680257881);
> 2023-03-31 10:18:01 

-- 取当前系统时间
select from_unixtime(unix_timestamp(),'yyyy-MM-dd HH:mm:ss');
> 2023-03-31 02:37:17

注意:from_unixtime 类 第一个参数只接受 bigint 类型。

3、unix_timestamp()与from_unixtime()结合使用

举例:已知通话开始时间为 “20230329185604”,通话时长为56秒,计算通话结束的时刻。

select from_unixtime((unix_timestamp(concat(substr('20230329185604',0,4),'-',substr('20230329185604',5,2),'-',substr('20230329185604',7,2),' ',substr('20230329185604',9,2),':',substr('20230329185604',11,2),':',substr('20230329185604',13,2)))+56),'yyyy-MM-dd HH:mm:ss');
> 2023-03-29 18:57:00 

select from_unixtime((unix_timestamp('20230329185604','yyyyMMddHHmmss')+56),'yyyy-MM-dd HH:mm:ss');
> 2023-03-29 18:57:00 

总结

1.Hive中获取时间戳的方式为unix_timestamp()函数,该函数只能够精确到秒级别的时间,对于时间精确到要求高的应用则该函数并不适合。

2.Hive获取当前时间毫秒级别的时间戳时需要使用cast函数将current_timestamp()转为double类型并乘以1000,则得到毫秒级别的时间戳。

3.对于Hive库中存储的毫秒精度的时间戳,为了确保时间精度不损失则需要使用to_utc_timestamp()函数,该函数支持毫秒级别的时间错,但需要指定当前时区。

-- 1.Hive中使用current_timestamp()函数获取当前时间,精确到毫秒。
select current_timestamp();
> 2023-03-31 11:18:48.184 


--2.Hive中获取当前时间戳为10位的bigint类型数值,该数值只精确到秒级别。
select unix_timestamp(current_timestamp());   
> 1680261703

--3.Hive中将时间戳转换为日期类型,结果可以看到时间的毫秒是无法正常获取到,因为时间戳只是精确到秒级别的,from_unixtime()函数也只支持秒级别的时间戳转换。
select from_unixtime(1680261703,'yyyy-MM-dd HH:mm:ss:SSS');
> 2023-03-31 11:21:43:000

-4.Hive中获取毫秒级别的时间戳,获取到了一个13位的数值,该数值精确到毫秒即为当前的时间的时间戳。
select current_timestamp(), cast(current_timestamp() as double) ;

+--------------------------+-------------------+
|           _c0            |        _c1        |
+--------------------------+-------------------+
| 2023-03-31 11:25:26.802  | 1.680261926802E9  |
+--------------------------+-------------------+

--5.Hive中处理毫秒级别的时间戳,使用Hive提供的to_utc_timestamp()函数将毫秒级别的时间戳转换为相应的时间并且精确到了毫秒,与上一步获取时间戳的时间一致。
select to_utc_timestamp(1.680261926802E9, 'GMT');
> 2023-03-31 11:25:26.802  

4.Hive中将十三位时间戳转换成日期,需要将“十三位时间戳” 除以1000并转为bigint类型,使用from_unixtime()转成想要的日期格式。

--十三位时间戳转换成日期,将十位时间戳/1000,转为bigint类型
select from_unixtime(cast(1679206709158/1000 as bigint),'yyyy-MM-dd HH:mm:ss');
> 2023-03-19 06:18:29

二、日期处理函数

1、date_format()

  • date_format(expr, fmt) 将时间戳转换为 fmt 格式的字符串
    expr:DATE、TIMESTAMP(“YYYY-MM-DD:HH-MM-SS”) 或有效日期/时间格式的 STRING。
    fmt:描述所需格式的 STRING 表达式。
select date_format('2023-03-31','yyyy-MM');
> 2023-03

select date_format('2023-03-31','yyyyMMdd');
> 20230331

select date_format('2023/03/31', 'y'); --识别不了/ 这种分隔符
> NULL

2、date_sub()

  • date_sub(startDate,numDays) 对当前日期减少天数,返回日期。
    startDate:日期表达式。
    numDays:一个整数表达式。

date_sub(‘yyyy-MM-dd’,n/-m) ,返回初始日期 n 天前,m 天后的日期。

select date_sub('2023-03-31',5); --2023-03-31 5天前
> 2023-03-26

select date_sub('2023-03-31',-2); --2023-03-31 2天后
> 2023-04-02

3、date_add()

  • date_add(startDate,numDays) 对当前日期增加的天数,返回日期。
    startDate:日期表达式。
    numDays:一个整数表达式。

date_sub(‘yyyy-MM-dd’,n/-m) ,返回初始日期 n 天后,m 天前的日期。

select date_add('2023-03-31',5); --2023-03-31 5天后
> 2023-04-05

select date_add('2023-03-31',-2); --2023-03-31 2天前
> 2023-03-29

4、datediff()

  • datediff(‘endDate’,‘startDate’) 返回前后日期之间的天数差,int类型。
    endDate:日期表达式。
    startDate:日期表达式。
select datediff('2023-03-31','2023-03-21');
> 10

select datediff('2023-03-31','2023-04-05');
> -5

--"yyyy/MM/dd"转换成"yyyy-MM-dd"
select datediff(regexp_replace('2023/03/31', "/", "-"), regexp_replace('2023/03/12', "/", "-"));
> 19

-- 求时间差
select datediff(from_unixtime(unix_timestamp('20221001','yyyyMMdd'),'yyyy-MM-dd'),from_unixtime(unix_timestamp(substr('2022-09-09',1,10),'yyyy-MM-dd'),'yyyy-MM-dd'));
> 22

5、last_day()

  • last_day(expr) 求当月最后一天
    expr:一个 DATE 表达式。
select last_day('2023-03-21');
> 2023-03-31
select last_day('2023-03-21 10:18:01');
> 2023-03-31

6、next_day()

  • next_day(expr, dayOfWeek),返回一个DATE。
    expr:一个 DATE 表达式。
    dayOfWeek:标识一周中某一天的 STRING 表达式。

dayOfWeek 必须是以下之一(不区分大小写):
‘SU’, ‘SUN’, ‘SUNDAY’
‘MO’, ‘MON’, ‘MONDAY’
‘TU’, ‘TUE’, ‘TUESDAY’
‘WE’, ‘WED’, ‘WEDNESDAY’
‘TH’, ‘THU’, ‘THURSDAY’
‘FR’, ‘FRI’, ‘FRIDAY’
‘SA’, ‘SAT’, ‘SATURDAY’

--取当前天的下一个周一
select next_day('2023-03-31','MO');
> 2023-04-03

--取当前周的周一
select date_sub(next_day('2023-03-31','MO'),7);
> 2023-03-27

7、add_months()

  • add_months(startDate, numMonths)
    startDate:一个 DATE 表达式。
    numMonths:整数。

add_months(‘yyyy-MM-dd’,n/-m) ,返回初始日期 n 月后,m 月前的日期。

select add_months('2023-03-01',1); --1个月后
> 2023-04-01

select add_months('2023-03-01',-6); --6个月前
> 2022-09-01

8、其他相关函数

#1、返回当天的三种方式
select current_date;
> 2023-03-31
select current_timestamp;
> 2023-03-31 15:20:11.566  
select from_unixtime(unix_timestamp());
> 2023-03-31 07:20:30

#2、返回日期中的年
select year('2023-03-31 01:48:27');
> 2023 

#3、返回日期中的月份
select month('2023-03-31 01:48:27');
> 3

#4、返回日期中的日
select day('2023-03-31 01:48:27');
> 31

#5、返回日期中的时
select hour('2023-03-31 01:48:27');
> 1

#6、返回日期中的分
select minute('2023-03-31 01:48:27');
> 48

#7、返回日期中的秒
select second('2023-03-31 01:48:27');
> 27

#8、返回日期中的当前月份的第几天
select dayofmonth('2023-03-31 01:48:27');
> 31

#9、返回日期中的当前的周数(今年第几周)
select weekofyear('2023-03-31 01:48:27');
> 13

#10、返回当月第一天
select date_sub(current_date,dayofmonth(current_date)-1);
> 2023-03-01 
select trunc('2023-03-31','MM');
> 2023-03-01 
select from_unixtime(unix_timestamp(date_format(from_unixtime(unix_timestamp('20230331','yyyymmdd'),'yyyy-mm-dd'),'yyyy-MM-01'),'yyyy-MM-dd'),'yyyyMMdd')
> 20230301 

#11、返回当年的第一天
select trunc('2023-03-31','YEAR');
> 2023-01-01

总结

1.date_format()/date_sub()/date_add()/datediff()/last_day()/next_day()/add_months 函数日期只能为’yyyy-MM-dd’格式 & 'yyyy-MM-dd HH:mm:ss’格式

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐