处理日期和时间数据--日期和时间函数

时间:2022-09-22 17:47:32

  本节介绍一些对日期和时间数据类型进行操作的函数,包括GETDATE、CURRENT_TIMESTAP、GETUTCDATE、SYSDATETIME、SYSUTCDATETIME、SYSDATETIMEOFFSET、CAST、CONVERT、SWITCHOFFSET、TODATETIMEOFFSET、DATEADD、DATEDIFF、DATEPART、YEAR、MONTH、DAY,以及DATENAME。注意,SYSDATETIME、SYSUTCDATETIME、SYSDATETIMEOFFSET、SWITCHOFFSET,以及TODATETIMEOFFSET是SQL Server 2008中新增的,其他几个函数在SQL Server 2008之前的版本中也可以使用。不过,SQL Server 2008对原有的几个函数进行了改进,以支持新的日期和时间数据类型,以及新的日期和时间组成部分。

日期和时间函数

  以下几个不带参数的函数可以返回SQL Server实例所在系统的当前日期和时间:GETDATE、CURRENT_TIMESTAMP、GETUTCDATE、SYSDATETIME、SYSUTCDATETIME,以及SYSDATETIMEOFFSET。下表列举了这些函数的一些信息。

函数

返回类型

描述

是否是SQL Server 2008新加的

GETDATE

DATETIME

当前日期和时间

CURRENT_TIMESTAMP

DATETIME

与GETDATE相同,而且是ANSI SQL

GETUTCDATE

DATETIME

以UTC格式表示的当前日期和时间

SYSDATETIME

DATETIME2

当前日期和时间

SYSUTCDATETIME

DATETIME2

以UTC格式表示的当前日期和时间

SYSDATETIMEOFFSET

DATETIMEOFFSET

当前日期和时间,包含时区偏移量

注意,除了ANSI函数CURRENT_TIMESTAMP以外,对于不需要参数的函数,在调用它们时都必须多加一对空的圆括号。此外,因为CURRENT_TIMESTAMP和GETDATE返回的内容相同,但前者是标准SQL,所以推荐优先选用CURRENT_TIMESTAMP。我们应该尽量遵循一条实践原则:当完成同样的事情有多种选择,而且它们之间在功能和性能上都没有区别,但只有一个是标准SQL,其他都不是时,我们应该偏向选择使用标准SQL。

  以下代码演示了取得当前日期和时间函数的用法:

  
  
  
1 SELECT
2 GETDATE () AS [ GETDATE ] ,
3 CURRENT_TIMESTAMP AS [ CURRENT_TIMESTAMP ] ,
4 GETUTCDATE() AS [ GETUTCDATE ] ,
5 SYSDATETIME() AS [ SYSDATETIME ] ,
6 SYSUTCDATETIME() AS [ SYSUTCDATETIME ] ,
7 SYSDATETIMEOFFSET() AS [ SYSDATETIMEOFFSET ] ;

  或许你会发现,SQL Server 2008中的函数都不是只返回当前系统日期或只返回当前系统时间。不过,通过把CURRENT_TIMESTAMP或SYSDATETIME转换为DATE或TIME,可以容易地做到这一点,如下所示:

  
  
  
1 SELECT
2 CAST (SYSDATETIME() AS DATE) AS [ Current_date ] ,
3 CAST (SYSDATETIME() AS TIME) AS [ Current_time ] ;

CAST和CONVERT函数

  CAST和CONVERT函数用于转换值的数据类型。

语法

CAST(value AS datatype)

CONVERT(datatype,value [,style_number])

  这两个函数都可以将输入的值转换为指定的数据类型。在一些情况下,还能用CONVERT提供的第三个参数来指定转换的样式。例如,当把字符串转换成日期和时间数据类型(或者进行反向转换)时,style样式值可以指定字符串的格式。例如,样式值101表示'MM/DD/YYYY',而103则表示'DD/MM/YYYY'。有关样式值和它们各自含义的完整列表,可以在SQL Server联机丛书的“CAST和CONVERT”一节中找到相关的内容。当把字符串转换成某些日期和时间数据类型时,一些字符串格式是依赖于语言的。这里推荐要么使用一种独立于语言的格式,要么使用CONVERT函数,显示地指定要用的样式值。这样,无论登录时用的语言是什么,SQL Server对代码的解释方式都是一样的。

  注意,CAST是ANSI标准SQL,而CONVERT不是;所以,除非需要使用样式值,否则推荐优先使用CAST函数,以保证代码尽可能与标准兼容。

  以下代码把字符串文字'20090212'转换成一个DATE数据类型的值,其实只能提取其当前的系统日期:

  
  
  
1 SELECT CAST ( ' 20090212 ' AS DATE);

  以下代码把当前系统日期和时间值转换成一个TIME数据类型的值,其实只能提取其当前的系统时间:

  
  
  
1 SELECT CAST (SYSDATETIME() AS TIME);

  还记得DATE和TIME是SQL Server 2008新引入的数据类型吧。前面介绍过,如果在SQL Server 2008之前的版本中只想用日期或时间,就必须把DATETIME或SMALLDATETIME值中不相关的部分设置为“0”。换句话说,要只使用日期,就得把时间部分设置为午夜;要只使用时间,就得把日期设置为基础日期1900年1月1日。稍后将会介绍把给定的日期和时间值(比如CURRENT_TIMESTAMP)中不相关的部分设置为0的技巧。

  以下代码用样式值112('YYYYMMDD'),把当前日期和时间值转换为CHAR(8):

  
  
  
1 SELECT CONVERT ( CHAR ( 8 ), CURRENT_TIMESTAMP , 112 );

  例如,如果当前日期是2009年2月12日,这一代码将返回'20090212'。记住该样式是语言无关的,所以当用代码把结果再转换回DATETIME类型时,得到的当前日期的时间部分将是午夜:

  
  
  
1 SELECT CAST ( CONVERT ( CHAR ( 8 ), CURRENT_TIMESTAMP , 112 ) AS DATETIME );

  类似地,要把日期部分设置为基础日期,可以先用样式114值('hh:mm:ss.nnn')把当前日期和时间值转换为CHAR(12):

  
  
  
1 SELECT CONVERT ( CHAR ( 12 ), CURRENT_TIMESTAMP , 114 );

  当用代码把结果再转换回DATETIME时,得到的当前的日期部分将是基础日期:

  
  
  
1 SELECT CAST ( CONVERT ( CHAR ( 12 ), CURRENT_TIMESTAMP , 114 ) AS DATETIME );

SWITCHOFFSET函数

  SWITCHOFFSET函数可以按指定的时区对输入的DATETIMEOFFSET值进行调整。

语法

SWITCHOFFSET(datetimeoffset_value,time_zone)

  例如,以下代码将当前系统时间的datetimeoffset值按时区-05:00进行调整:

  
  
  
1 SELECT SWITCHOFFSET(SYSDATETIMEOFFSET(), ' -05:00 ' );

  如果当前系统的datetimeoffset值是February 12,2009 10:00:00.0000000 -08:00,这段代码将返回以下值:February 12,2009 13:00:00.0000000 -05:00。

  而以下代码则将当前的datetimeoffset值调整为UTC时间:

  
  
  
1 SELECT SWITCHOFFSET(SYSDATETIMEOFFSET(), ' +00:00 ' );

  假设当前的datetimeoffset值为前面提到的那个值,该代码将返回以下值:

February 12,2009 18:00:00.0000000 +00:00。

TODATETIMEOFFSET函数

语法

TODATETIMEOFFSET(date_and_time_value,time_zone)

  这个函数与SWITCHOFFSET函数的区别有两点。首先,它可以接受的输入不限于datetimeoffset值,而是支持任何日期和时间数据类型。其次,它不是根据输入值的原始值和指定的时区之间的差值来调整时间,而只是简单地用指定的时区将输入的日期和时间值作为datetimeoffset值返回。例如,如果当前系统的datetimeoffset值是February 12,2009 10:00:00.0000000 -08:00,运行以下代码:

  
  
  
1 SELECT TODATETIMEOFFSET(SYSDATETIMEOFFSET(), ' -05:00 ' );

会得到以下值:February 12,2009 10:00:00.0000000 -05:00。还记得前面的SWITCHOFFSET函数返回值是February 12,2009 13:00:00.0000000 -05:00吧,因为它是根据输入的时区(-08:00)和指定的时区(-05:00)之间的时区差来调整时间的。

  如前所述,TODATETIMEOFFSET函数可以支持任何日期和时间数据类型作为输入。例如,以下代码以当前系统日期和时间值作为输入,将其更改为时区是-05:00的datetimeoffset值:

  
  
  
1 SELECT TODATETIMEOFFSET(SYSDATETIME(), ' -05:00 ' );

DATEADD函数

  DATEADD函数可以将指定日期的部分作为单位,为输入的日期和时间值增加指定的数量。

语法

DATEADD(part,n,dt_val)

  日期部分的有效值包括year、quarter、month、dayofyear、day、week、weekday、hour、minute、second、millisecond、microsecond,以及nanosecond。最后两个是SQL Server 2008新增加的。也可以按缩写格式来指定这些时间部分,例如用yy代替year。要了解相关的细节,请参考SQL Server联机丛书。

  该函数返回值的类型与输入的日期和时间值的类型相同。如果输入的是一个字符串文字,输出的则是DATETIME。

例如,以下代码为“2009年2月12日”增加1年:

  
  
  
1 SELECT DATEADD ( year , 1 , ' 20090212 ' );

DATEDIFF函数

  DATEDIFF返回两个日期和时间值之间相差的指定部分的计数。

语法

DATEDIFF(part,dt_val1,dt_val2)

  例如,以下代码返回两个值之间相差的天数:

  
  
  
1 SELECT DATEADD ( day , DATEDIFF ( day , ' 20010101 ' , CURRENT_TIMESTAMP ), ' 20010101 ' );

  在SQL Server 2008之前的版本中,可以用以下代码将当前系统日期和时间值中的时间部分设置为午夜:

  
  
  
1 SELECT DATEADD ( month , DATEDIFF ( month , ' 20010101 ' , CURRENT_TIMESTAMP ), ' 20010101 ' );

  这段代码首先用DATEDIFF函数计算一个锚点(anchor)日期的午夜值(在这个例子中是'20010101')与当前日期和时间之间相差的总天数(也称为不同的diff值)。接着,再用DATEADD函数为锚点日期增加上一步得到的diff天。这样就可以得到当前系统日期在午夜的时间值。

  有趣的是,如果在这个表达式中用month(月)取代day(天)来作为计数单位,并确保使用的锚点日期是某个月的第1天(如我们这个例子所示),最后得到的结果将是当前月份的第1天:

  
  
  
1 SELECT DATEADD ( month , DATEDIFF ( month , ' 20010101 ' , CURRENT_TIMESTAMP ), ' 20010101 ' );

  类似地,用year(年)作为计数单位,并用某年的第1天作为锚点日期,最后得到的将是当前年的第1天。

  如果想要得到当前月或当前年的最后一天,只要简单地把锚点日期修改为月或年的最后1天。例如,以下表达式返回当前月份的最后1天:

  
  
  
1 SELECT DATEADD ( MONTH , DATEDIFF ( month , ' 19991231 ' , CURRENT_TIMESTAMP ), ' 19991231 ' );

DATEPART函数

  DATEPART函数返回一个表示给定日期和时间值的指定部分的整数。

语法

DATEPART(part,dt_val)

  part参数的有效值包括year、quarter、month、dayofyear、day、week、weekday、hour、minute、second、millisecond、microsecond、nanosecond、TZoffset,以及ISO_WEEK。最后4个part参数值是SQL Server 2008中新增的。如前所述,日期和时间部分的名称也可以使用缩写格式,如用yy代替year、用mm代替month、用dd代替day,等等。作为例子,以下代码返回输入值的月份部分:

  
  
  
1 SELECT DATEPART ( month , ' 20090212 ' );

  这一代码将返回整数2.

YEAR、MONTH和DAY函数

  YEAR、MONTH,以及DAY函数是DATEPART函数的简略版本,它们分别返回一个代表输入日期和时间值中年、月、日部分的整数。

语法

YEAR(dt_val)

MONTH(dt_val)

DAY(dt_val)

例如,以下代码提取出输入值的日、月、年部分:

  
  
  
1 SELECT DAY ( ' 20090212 ' ) AS theday,
2 MONTH ( ' 20090212 ' ) AS themonth,
3 YEAR ( ' 20090212 ' ) AS theyear;

DATENAME函数

  DATENAME函数返回一个表示给定日期和时间值的指定部分的字符串。

语法

DATENAME(part,dt_val)

  这个函数与DATEPART类似,它们的part输入参数的有效值都是相同的。不过,DATENAME返回的是代表请求部分的名字,而不是数字。例如,以下代码返回给定输入值的月份的名称:

  
  
  
1 SELECT DATENAME ( month , ' 20090212 ' );

  回想一下,对于同样的输入,前面的DATEPART返回的是整数2。而DATENAME返回的是月份的名称,该名称是依赖于语言的。如果当前会话的语言是某种英语,函数调用的返回值将是'February'。如果请求的部分没有名称,只是一个数字值(比如年份),则DATENAME函数将它的数字值作为字符串而返回。例如,以下代码返回'2009':

  
  
  
1 SELECT DATENAME ( year , ' 20090212 ' );

ISDATE函数

  ISDATE接受一个字符串作为输入,如果能把这个字符串转换为日期和时间数据类型的值,则返回值1;如果不能,则返回值0。

语法

ISDATE(string)

例如,以下代码返回1:

  
  
  
1 SELECT ISDATE ( ' 20090212 ' );

而以下代码则返回0:

  
  
  
1 SELECT ISDATE ( ' 20090230 ' );