【问题标题】:Rounding timestamp to the nearest 30 seconds将时间戳四舍五入到最接近的 30 秒
【发布时间】:2021-12-11 10:31:15
【问题描述】:

我的表如下:

t: ([]dt: 2021.10.25T09:30:28 2021.10.25T09:30:32;price:9.99 10.00)

我希望将时间戳四舍五入到最接近的 30 秒标记。 我尝试像这样使用 xbar:

update roundedDt: 30 xbar dt.second from t

然而,它似乎已经降低了结果。 两行所需的结果应该是 09:30:30。

如何一轮到最接近的 30 秒标记?

【问题讨论】:

    标签: kdb


    【解决方案1】:

    Jonathon 的答案是最灵活的修改舍入的方法,而不仅仅是几秒钟,而另一种简单的解决方案是只修改几秒钟,那就是偏移 15:

    q)update roundedDt:30 xbar 15+dt.second from t
    dt                      price roundedDt
    ---------------------------------------
    2021.10.25T09:30:28.000 9.99  09:30:30
    2021.10.25T09:30:32.000 10    09:30:30
    

    编辑:如果您希望完整的 dateTime 舍入,我会将其转换为时间戳,以便于使用并调整我的偏移量/xbar 以匹配。

    q)update roundedDt:30000000000 xbar 15000000000 + `timestamp$dt from t
    dt                      price roundedDt
    -----------------------------------------------------------
    2021.10.25T09:30:28.000 9.99  2021.10.25D09:30:30.000000000
    2021.10.25T09:30:32.000 10    2021.10.25D09:30:30.000000000
    2020.10.25T23:59:59.000 9.99  2020.10.26D00:00:00.000000000
    2020.10.26T00:00:01.000 10    2020.10.26D00:00:00.000000000
    

    【讨论】:

      【解决方案2】:

      你可以试试这样的:

      update roundedDt:?[(`ss$dt)within(0;14);`time$(`int$`time$dt)-1000*`ss$dt;
          ?[(`ss$dt)within(15;44);`time$30000+(`int$`time$dt)-1000*`ss$dt;`time$60000+(`int$`time$dt)-1000*`ss$dt]] from t
      

      【讨论】:

        【解决方案3】:

        您可以使用 xbar 的修改版本,它会舍入到最接近的 int 而不是 floor:

        q)xbar2:{type[y]$x*"j"$y%x:$[16h=abs type x;"j"$x;x]}
        q)update roundedDt:xbar2[30;dt.second] from t
        dt                      price roundedDt
        ---------------------------------------
        2021.10.25T09:30:28.000 9.99  09:30:30
        2021.10.25T09:30:32.000 10    09:30:30
        

        请注意,由于此函数是在根命名空间中定义的,因此您必须使用括号表示法 (xbar2[30;dt.second])。如果您希望使用中缀表示法 (30 xbar2 dt.second),则需要在 .q 命名空间中定义函数,即 .q.xbar2:{type[y]$x*"j"$y%x:$[16h=abs type x;"j"$x;x]}

        xbar2 是基于原来的xbar,但是xbar 使用div 具有地板结果的效果,这里使用% 将产生一个浮点输出,然后将其转换到一个 long int,它将四舍五入到最接近的整数。

        【讨论】:

          【解决方案4】:

          这个解决方案怎么样:

          / x is your timestamp
          / y is the timebucket (in seconds)
          .time.round:{
              :"z"$+[`date$x;`time$1e3*y*`int$%[`time$x;y*1e3]];
           };
          

          例如,如果要在最近的 30 秒处舍入,则需要按如下方式使用:

          ts1:2020.10.30T10:32:35
          .time.round[ts1;30]
          

          在您的情况下,只需键入:

          t[`round_time]:{.time.round[x;30]} each t[`dt]
          

          附带说明一下,一些建议的解决方案会将时间戳(例如 2020.10.25T23:59:59 和 2020.10.26T00:00:01)分别舍入到 24:00:00 和 00:00:00,这不是什么我想我们会喜欢的。

          【讨论】:

          • 有效点,也许我错过了 delita 试图实现的目标。我将使用时间戳替代方案更新我的解决方案。
          • @MattMoore 我喜欢你的解决方案——它非常干净
          猜你喜欢
          • 1970-01-01
          • 2018-06-03
          • 2018-10-25
          • 1970-01-01
          • 2018-05-27
          • 2014-12-12
          • 2017-12-02
          • 2011-01-22
          • 2015-02-04
          相关资源
          最近更新 更多