SQL Server 2008 introduces four new date and time data types:
Two of the most welcome of these new types are the new date and time data types. These new data types allow you to store date-only and time-only values. In previous versions of SQL Server, the datetime and smalldatetime
data types were the only available types for storing date or time
values, and they always store both the date and time. This made
date-only or time-only comparisons tricky at times because you always
had to account for the other component. In addition, the datetime stored date values range only from 1/1/1753 to 12/31/9999, with accuracy only to 3.33 milliseconds. The smalldatetime stored date values range only from 1/1/1900 to 6/6/2079, with accuracy of only 1 minute.
The new date
data type stores only the date component without the time component,
and stores date values ranging from 1/1/0001 to 12/31/9999.
The new time data
type stores only the time component with accuracy that can be specified
down to seven decimal places (100 nanoseconds). The default is seven
decimal places.
The datetime2 data type stores both date and time components, similar to datetime,
increases the range of allowed values to 1/1/0001 to 12/31/9999, also
with accuracy down to seven decimal places (100 ns). The default
precision is seven decimal places.
The datetimeoffset data type also stores both date and time components just like datetime2, but includes the time zone offset from Universal Time Coordinates (UTC). The time zone offset ranges from -14:00 to +14:00.
Along with the new date and time
data types, SQL Server 2008 also introduces some new date and time
functions for returning the current system date and time in different
formats:
SYSDATETIME()— Returns the current system datetime as a DATETIME2(7) value
SYSDATETIMEOFFSET()— Returns the current system datetime as a DATETIMEOFFSET(7) value
SYSUTCDATETIME— Returns the current system datetime as a DATETIME2(7) value representing the current UTC time
SWITCHOFFSET (DATETIMEOFFSET,time_zone)— Changes the DATETIMEOFFSET value from the stored time zone offset to the specified time zone
TODATETIMEOFFSET (datetime, time_zone)— Applies the specified time zone to the datetime value that does not reflect time zone difference from UTC
Listing 1
demonstrates the use of some of the new data types and functions.
Notice the difference in the specified decimal precision returned for
the time values.
Listing 1. Using the new date and time Data Types and Functions
declare @date date, @time time, @time3 time(3), @datetime2 datetime2(7), @datetimeoffset datetimeoffset, @datetime datetime, @utcdatetime datetime2(7)
select @datetime = getdate(), @date = getdate(), @time = sysdatetime(), @time3 = sysdatetime(), @datetime2 = SYSDATETIME(), @datetimeoffset = SYSDATETIMEOFFSET(), @utcdatetime = SYSUTCDATETIME()
select @datetime as 'datetime', @date as 'date', @time as 'time', @time3 as 'time3' select @datetime2 as 'datetime2', @datetimeoffset as 'datetimeoffset', @utcdatetime as 'utcdatetime'
select SYSDATETIMEOFFSET() as sysdatetimeoffset, SYSDATETIME() as sysdatetime go
datetime date time time3 ----------------------- ---------- ---------------- ----------------- 2010-03-28 23:18:30.490 2010-03-28 23:18:30.4904294 23:18:30.492
datetime2 datetimeoffset utcdatetime ---------------------- ---------------------------------- ---------------------- 2010-03-28 23:18:30.49 2010-03-28 23:18:30.4924295 -04:00 2010-03-29 03:18:30.49
sysdatetimeoffset sysdatetime ---------------------------------- ---------------------- 2010-03-28 23:24:10.7485902 -04:00 2010-03-28 23:24:10.74
|
Be aware that retrieving the value from getdate() or sysdatetime() into a datetimeoffset
variable or column does not capture the offset from UTC, even if you
store the returned value in a column or variable defined with the datetimeoffset data type. To do so, you need to use the SYSDATETIMEOFFSET() function:
declare @datetimeoffset1 datetimeoffset,
@datetimeoffset2 datetimeoffset
select
@datetimeoffset1 = SYSDATETIME(),
@datetimeoffset2 = SYSDATETIMEOFFSET()
select @datetimeoffset1, @datetimeoffset2
go
---------------------------------- ----------------------------------
2010-03-28 23:36:39.7271831 +00:00 2010-03-28 23:36:39.7271831 -04:00
Note that in the output, SQL
Server Management Studio (SSMS) trims the time values down to two
decimal places when it displays the results in the Text Results tab.
However, this is just for display purposes (and applies only with text
results; grid results display the full decimal precision). The actual
value does store the precision down to the specified number of decimal
places, which can be seen if you convert the datetime2 value to a string format that displays all the decimal places:
select SYSDATETIME() as datetime2_trim,
convert(varchar(30), SYSDATETIME(), 121) as datetime2_full
go
datetime2_trim datetime2_full
---------------------- ------------------------------
2010-03-30 23:52:30.68 2010-03-30 23:52:30.6851262
The SWITCHOFFSET() function can be used to convert a datetimeoffset value into a different time zone offset value:
select SYSDATETIMEOFFSET(), SWITCHOFFSET ( SYSDATETIMEOFFSET(), '-07:00' )
go
---------------------------------- ----------------------------------
2010-03-29 00:07:21.1335738 -04:00 2010-03-28 21:07:21.1335738 -07:00
When you are specifying a time zone value for the SWITCHOFFSET or TODATETIMEOFFSET
offset functions, the value can be specified as an integer value
representing the number of minutes of offset or as a time value in hh:mm format. The range of allowed values is +14 hours to -13 hours.
select TODATETIMEOFFSET ( SYSDATETIME(), -300 )
select TODATETIMEOFFSET ( SYSDATETIME(), '-05:00' )
go
----------------------------------
2010-03-29 00:23:05.5773288 -05:00
----------------------------------
2010-03-29 00:23:05.5773288 -05:00
Date and Time Conversions
If an existing CONVERT style includes the time part, and the conversion is from datetimeoffset
to a string, the time zone offset (except for style 127) is included.
If you do not want the time zone offset, you need to use cast or convert
the datetimeoffset value to datetime2 first and then to a string:
select convert(varchar(35), SYSDATETIMEOFFSET(), 121) as datetime_offset,
CONVERT(varchar(30), cast(SYSDATETIMEOFFSET() as datetime2),121) as datetime2
go
datetime_offset datetime2
----------------------------------- ------------------------------
2010-03-30 23:57:36.1015950 -04:00 2010-03-30 23:57:36.1015950
When you convert from datetime2 or datetimeoffset to date, there is no rounding and the date part is extracted explicitly. For any implicit conversion from datetimeoffset to date, time, datetime2, datetime, or smalldatetime, conversion is based on the local date and time value (to the persistent time zone offset). For example, when the datetimeoffset(3) value, 2006-10-21 12:20:20.999 -8:00, is converted to time(3), the result is 12:20:20.999, not 20:20:20.999(UTC).
If you convert from a
higher-precision time value to a lower-precision value, the conversion
is permitted, and the higher-precision values are truncated to fit the
lower precision type.
If you are converting a time(n), datetime2(n), or datetimeoffset(n)
value to a string, the number of digits depends on the type
specification. If you want a specific precision in the resulting string,
convert to a data type with the appropriate precision first and then to
a string, as follows:
select
convert(varchar(35), sysdatetime(), 121) as datetime_offset,
CONVERT(varchar(30), cast(sysdatetime() as datetime2(3)), 121) as datetime2
go
datetime_offset datetime2
----------------------------------- ------------------------------
2010-03-31 00:04:37.3306880 2010-03-31 00:04:37.331
If you attempt to cast a string literal with a fractional seconds precision that is more than that allowed for smalldatetime or datetime, Error 241 is raised:
declare @datetime datetime
select @datetime = '2010-03-31 00:04:37.3306880'
go
Msg 241, Level 16, State 1, Line 2
Conversion failed when converting date and/or time from character string.