简体   繁体   English

四舍五入脚本可以基于时间最近的15分钟后,如何由负这个阈移30秒小数小时

[英]Rounding script works to the nearest 15 minutes based on duration, how to shift this threshold by negative 30 seconds for decimal hours

I have a script which rounds a time length to the nearest 15 minutes.我有一个脚本,可以将时间长度四舍五入到最接近的 15 分钟。 So for example 00:23:00 minutes to 00:37:59 duration will return 0.5 (decimal 30 minutes) etc continuous around the clock.因此,例如 00:23:00 分钟到 00:37:59 持续时间将返回 0.5(十进制 30 分钟)等全天候连续。 I am trying to now get the script to work in half minutes so I need to shift this by 30 second offset for the rounding, so 00:22:29 seconds will go to 0.25 and 00:22:30 will round to 0.5.我现在试图让脚本在半分钟内工作,所以我需要将它移动 30 秒偏移量以进行舍入,因此 00:22:29 秒将变为 0.25,00:22:30 将变为 0.5。 Here is the original script.这是原始脚本。 So this needs to return 0.5 not 0.25.所以这需要返回 0.5 而不是 0.25。 If you change the @finish to 08:22:29 it needs to then return 0.25.如果您将 @finish 更改为 08:22:29,则需要返回 0.25。 Thank you谢谢

declare @start datetime = '2020-03-01 08:00:00:000'
declare @finish datetime = '2020-03-01 08:22:30:000'

select
(CAST(DATEPART(hh, (DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( second, ( 15 * 60 ) / 2, (convert(varchar(5),(@finish - @start),108)) ) ) / 15 ) * 15, 0 ))) AS float) +
    CAST(DATEPART(mi, (DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( second, ( 15 * 60 ) / 2, (convert(varchar(5),(@finish - @start),108)) ) ) / 15 ) * 15, 0 ))) AS float) / 60 +
        CAST(DATEPART(ss, (DATEADD( minute, ( DATEDIFF( minute, 0, DATEADD( second, ( 15 * 60 ) / 2, (convert(varchar(5),(@finish - @start),108)) ) ) / 15 ) * 15, 0 ))) AS float) / 3600)

Here's another possible solution, using CASE to classify the modulo seconds over an hour:这是另一种可能的解决方案,使用CASE对一个小时内的模秒进行分类:

SELECT DATEDIFF(second,@start,@finish) / 3600 +
CASE WHEN DATEDIFF(second,@start,@finish) % 3600 <  450 THEN 0.0
     WHEN DATEDIFF(second,@start,@finish) % 3600 < 1350 THEN 0.25
     WHEN DATEDIFF(second,@start,@finish) % 3600 < 2250 THEN 0.5
     WHEN DATEDIFF(second,@start,@finish) % 3600 < 3150 THEN 0.75
     ELSE 1
END

Solution is to add a dateadd(second, 30, @finish) I believe.解决方案是添加一个 dateadd(second, 30, @finish) 我相信。 Not the start time, this will then either push the result to over 00:23 if 00:22:30 and above or keep the length below 00:23.不是开始时间,如果 00:22:30 及以上,这会将结果推送到 00:23 以上,或者将长度保持在 00:23 以下。 This should do the trick这应该可以解决问题

In your solution, the problem is starting from the division of two integer numbers that would result to an integer.在您的解决方案中,问题是从将导致整数的两个整数相除开始。 You can check for a solution .您可以检查解决方案

Since you are dealing with time, it might be appropriate to use the CEILING function.由于您正在处理时间,因此使用CEILING函数可能是合适的。 If you think that this way is more appropriate, you could use:如果您认为这种方式更合适,您可以使用:

declare @start datetime = '2020-03-01 08:00:00:000'
declare @finish datetime = '2020-03-01 08:22:30:000'

SELECT CEILING( DATEDIFF( ss, @start, @finish)/ (60*60.00) * 4) / 4

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM