我知道这里已经有一些答案,但我想我会添加我想出的内容,因为(至少对我而言)它似乎很容易理解:
CREATE FUNCTION dbo.fn_DateDiff_YMDMHS
(
@Startdate as datetime2(0),
@Enddate as datetime2(0)
)
RETURNS TABLE
AS
RETURN
(
select
TotalYears [Years],
datediff(month, dateadd(Year, TotalYears, @Startdate), @Enddate) Months,
datediff(day, dateadd(month, TotalMonths, @Startdate), @Enddate) [Days],
datediff(hour, dateadd(day, TotalDays, @Startdate), @Enddate) [Hours],
datediff(minute, dateadd(hour, TotalHours, @Startdate), @Enddate) [Minutes],
datediff(second, dateadd(minute, TotalMinutes, @Startdate), @Enddate) [Seconds]
from (
select
datediff(SECOND, @Startdate, @Enddate) TotalSeconds,
datediff(minute, @Startdate, @Enddate) TotalMinutes,
datediff(hour, @Startdate, @Enddate) TotalHours,
datediff(day, @Startdate, @Enddate) TotalDays,
datediff(month, @Startdate, @Enddate) TotalMonths,
datediff(year, @Startdate, @Enddate) TotalYears) DateDiffs
)
然后当你打电话时:
select * from dbo.fn_DateDiff_YMDMHS('1900-01-01 00:00:00', '1910-10-05 03:01:02')
你会得到这个返回:
Years Months Days Hours Minutes Seconds
10 9 4 3 1 2
显然,您可以将其更改为格式化输出并使用标量变量,但我将把它留给您 :-)
编辑:
我最终还需要执行 time ago 函数来返回“5 年零 2 天前”之类的格式
CREATE FUNCTION fn_DateDiff_YMDMHS_String
(
@StartDate datetime2(0),
@EndDate datetime2(0),
@OutputYears bit = 1,
@OutputMonths bit = 1,
@OutputDays bit = 1,
@OutputHours bit = 0,
@OutputMinutes bit = 0,
@OutputSeconds bit = 0,
@OutputSuffix bit = 0
)
RETURNS varchar(256)
AS
BEGIN
DECLARE @Output varchar(256) = ''
declare @Years int, @Months int, @Days int, @Hours int, @Minutes int, @Seconds int
select
@Years = case when @OutputYears = 1 then Years else 0 end,
@Months = case when @OutputMonths = 1 then Months else 0 end,
@Days = case when @OutputDays = 1 then Days else 0 end,
@Hours = case when @OutputHours = 1 then Hours else 0 end,
@Minutes = case when @OutputMinutes = 1 then Minutes else 0 end,
@Seconds = case when @OutputSeconds = 1 then Seconds else 0 end
from dbo.fn_DateDiff_YMDMHS(@StartDate, @EndDate)
declare @and varchar(5) = ''
if @OutputYears = 1 and @Years > 0
begin
set @Output = @Output + cast(@Years as varchar(4)) + ' year'
if @Years > 1 set @Output = @Output + 's ' else set @Output = @Output + ' '
if @Months > 0 and @Days + @Hours + @Minutes + @Seconds = 0 set @and = 'and '
end
if @OutputMonths = 1 and @Months > 0
begin
set @Output = @Output + @and + cast(@Months as varchar(2)) + ' month'
if @Months > 1 set @Output = @Output + 's ' else set @Output = @Output + ' '
if @Days > 0 and @Hours + @Minutes + @Seconds = 0 set @and = 'and '
end
if @OutputDays = 1 and @Days > 0
begin
set @Output = @Output + @and + cast(@Days as varchar(2)) + ' day'
if @Days > 1 set @Output = @Output + 's ' else set @Output = @Output + ' '
if @Hours > 0 and @Minutes + @Seconds = 0 set @and = 'and '
end
if @OutputHours = 1 and @Hours > 0
begin
set @Output = @Output + @and + cast(@Hours as varchar(2)) + ' hour'
if @Hours > 1 set @Output = @Output + 's ' else set @Output = @Output + ' '
if @Minutes > 0 and @Seconds = 0 set @and = 'and '
end
if @OutputMinutes = 1 and @Minutes > 0
begin
set @Output = @Output + @and + cast(@Minutes as varchar(2)) + ' minute'
if @Minutes > 1 set @Output = @Output + 's ' else set @Output = @Output + ' '
if @Seconds > 0 set @and = 'and '
end
if @OutputSeconds = 1 and @Seconds > 0
begin
set @Output = @Output + @and + cast(@Seconds as varchar(2)) + ' second'
if @Seconds > 1 set @Output = @Output + 's ' else set @Output = @Output + ' '
end
if @OutputSuffix = 1
begin
if @StartDate < @EndDate
begin
set @Output = @Output + 'ago'
end
else
begin
set @Output = 'in ' + @Output
end
end
RETURN @Output
END
这里有 2 个例子
select dbo.fn_DateDiff_YMDMHS_String('2000-01-01 00:00:00', '2007-09-19 14:39:53', 1, 1, 1, 1,1,1, 1)
7 years 8 months 18 days 8 hours 39 minutes and 53 seconds ago
和
select dbo.fn_DateDiff_YMDMHS_String('2000-01-01 00:00:00', '2007-09-19 14:39:53', 1, 1, 1, 0,0,0, 1)
7 years 8 months and 18 days ago
无论如何,我希望这对将来的某个人有用,因为我在搜索时找不到很多类似的东西(尽管可能只是那些日子之一)我对改进持开放态度,因为我知道我是并不总是最紧凑或最快的代码程序员:-)
问候
利亚姆