【问题标题】:Rounding time to specific hour even if it is the day before将时间四舍五入到特定时间,即使是前一天
【发布时间】:2021-07-09 23:38:23
【问题描述】:

我有时间数据,我想从暮光中减去,我还有其他代码。为此,我首先需要根据最近的暮光来标准化时间。我遇到的麻烦是在午夜后四舍五入,回到前一天的黄昏(参见:Df$time[2])

我已经在同一天成功地使用了带有 period() 的 lubridate 函数 round_date,但是对于清晨的时间,它只是恢复到当天的午夜。帮助菜单中的“change_on_boundary”参数似乎不再起作用。有人有其他方法吗?

*注意:我知道 tz 改变了,我并不担心。这是这个问题的虚拟数据集。

Df<-data.frame(time = as.POSIXct(c("2020-12-29 21:02:23 UTC", "2020-12-15 00:48:21 UTC", "2020-12-09 21:55:52 UTC" ,"2020-12-09 18:40:06 UTC",
 "2020-12-08 18:25:27 UTC" ,"2020-12-14 20:08:51 UTC", "2020-12-14 17:55:21 UTC","2020-12-05 23:53:36 UTC",
 "2020-12-05 21:21:21 UTC", "2020-12-06 19:11:11 UTC", "2020-12-05 21:09:31 UTC", "2020-12-05 18:13:53 UTC",
 "2020-12-15 20:36:56 UTC", "2020-12-26 06:00:00 UTC", "2020-12-16 00:40:46 UTC" ,"2020-12-26 05:34:42 UTC")))

Df$time
 [1] "2020-12-29 21:02:23 EST" "2020-12-15 00:48:21 EST" "2020-12-09 21:55:52 EST" "2020-12-09 18:40:06 EST" "2020-12-08 18:25:27 EST"
 [6] "2020-12-14 20:08:51 EST" "2020-12-14 17:55:21 EST" "2020-12-05 23:53:36 EST" "2020-12-05 21:21:21 EST" "2020-12-06 19:11:11 EST"
[11] "2020-12-05 21:09:31 EST" "2020-12-05 18:13:53 EST" "2020-12-15 20:36:56 EST" "2020-12-26 06:00:00 EST" "2020-12-16 00:40:46 EST"
[16] "2020-12-26 05:34:42 EST"

round_date(Df$time, unit = period(16, units = "hour"))
 [1] "2020-12-29 16:00:00 EST" "2020-12-15 00:00:00 EST" "2020-12-09 16:00:00 EST" "2020-12-09 16:00:00 EST" "2020-12-08 16:00:00 EST"
 [6] "2020-12-14 16:00:00 EST" "2020-12-14 16:00:00 EST" "2020-12-05 16:00:00 EST" "2020-12-05 16:00:00 EST" "2020-12-06 16:00:00 EST"
[11] "2020-12-05 16:00:00 EST" "2020-12-05 16:00:00 EST" "2020-12-15 16:00:00 EST" "2020-12-26 00:00:00 EST" "2020-12-16 00:00:00 EST"
[16] "2020-12-26 00:00:00 EST"

【问题讨论】:

    标签: r time lubridate


    【解决方案1】:

    如果我对问题的理解正确,您希望每次四舍五入到最接近的 16:00(下午 4 点)。正如您所发现的,lubridate::round_date() 在时间倒流时似乎会在午夜停止。

    对于您的示例,您可以找到哪些四舍五入的日期时间已达到午夜的最低点,并减去 8 小时以到达前一天的 16:00。

    library(tidyverse)
    library(lubridate)
    
    Df %>% 
      tibble %>% 
      force_tz('UTC') %>% 
      mutate(
        time_round = round_date(time, unit = period(16, units = 'hour')),
        time_round_final = as_datetime(ifelse(hour(time_round) == 0,       # if the hour is 0 (midnight), then...
                                         time_round - hours(24 - 16),      # we subtract 8 (24 - 16) hours, otherwise...
                                         time_round))                      # we keep the original rounded time
      )
    
    # A tibble: 16 x 3
    #    time                time_round          time_round_final   
    #    <dttm>              <dttm>              <dttm>             
    #  1 2020-12-29 21:02:23 2020-12-29 16:00:00 2020-12-29 16:00:00
    #  2 2020-12-15 00:48:21 2020-12-15 00:00:00 2020-12-14 16:00:00
    #  3 2020-12-09 21:55:52 2020-12-09 16:00:00 2020-12-09 16:00:00
    #  4 2020-12-09 18:40:06 2020-12-09 16:00:00 2020-12-09 16:00:00
    #  5 2020-12-08 18:25:27 2020-12-08 16:00:00 2020-12-08 16:00:00
    #  6 2020-12-14 20:08:51 2020-12-14 16:00:00 2020-12-14 16:00:00
    #  7 2020-12-14 17:55:21 2020-12-14 16:00:00 2020-12-14 16:00:00
    #  8 2020-12-05 23:53:36 2020-12-05 16:00:00 2020-12-05 16:00:00
    #  9 2020-12-05 21:21:21 2020-12-05 16:00:00 2020-12-05 16:00:00
    # 10 2020-12-06 19:11:11 2020-12-06 16:00:00 2020-12-06 16:00:00
    # 11 2020-12-05 21:09:31 2020-12-05 16:00:00 2020-12-05 16:00:00
    # 12 2020-12-05 18:13:53 2020-12-05 16:00:00 2020-12-05 16:00:00
    # 13 2020-12-15 20:36:56 2020-12-15 16:00:00 2020-12-15 16:00:00
    # 14 2020-12-26 06:00:00 2020-12-26 00:00:00 2020-12-25 16:00:00
    # 15 2020-12-16 00:40:46 2020-12-16 00:00:00 2020-12-15 16:00:00
    # 16 2020-12-26 05:34:42 2020-12-26 00:00:00 2020-12-25 16:00:00
    

    我使用lubridate::force_tz() 将时区应用于时间(为空),否则as_datetime() 似乎默认为 UTC(它必须假定无时区时间是您的本地时区?)并返回意外时间,通过静默更改(应用)时区。这可能是导致错误的常见原因。

    我们可以在不强制时区时观察到这一点(我在 GMT+11):

    Df %>% 
      tibble %>% 
      # force_tz('UTC') %>%
      mutate(
        time_round = round_date(time, unit = period(16, units = 'hour')),
        time_round_final = as_datetime(ifelse(hour(time_round) == 0,       # if the hour is 0 (midnight), then...
                                              time_round - hours(24 - 16),      # we subtract 8 (24 - 16) hours, otherwise...
                                              time_round)),                      # we keep the original rounded time
        tz_1 = tz(time), 
        tz_2 = tz(time_round),
        tz_3 = tz(time_round_final),
      )
    
    # # A tibble: 16 x 6
    #    time                time_round          time_round_final    tz_1  tz_2  tz_3 
    #    <dttm>              <dttm>              <dttm>              <chr> <chr> <chr>
    #  1 2020-12-29 21:02:23 2020-12-29 16:00:00 2020-12-29 05:00:00 ""    ""    UTC  
    #  2 2020-12-15 00:48:21 2020-12-15 00:00:00 2020-12-14 05:00:00 ""    ""    UTC  
    #  3 2020-12-09 21:55:52 2020-12-09 16:00:00 2020-12-09 05:00:00 ""    ""    UTC  
    #  4 2020-12-09 18:40:06 2020-12-09 16:00:00 2020-12-09 05:00:00 ""    ""    UTC  
    #  5 2020-12-08 18:25:27 2020-12-08 16:00:00 2020-12-08 05:00:00 ""    ""    UTC  
    #  6 2020-12-14 20:08:51 2020-12-14 16:00:00 2020-12-14 05:00:00 ""    ""    UTC  
    #  7 2020-12-14 17:55:21 2020-12-14 16:00:00 2020-12-14 05:00:00 ""    ""    UTC  
    #  8 2020-12-05 23:53:36 2020-12-05 16:00:00 2020-12-05 05:00:00 ""    ""    UTC  
    #  9 2020-12-05 21:21:21 2020-12-05 16:00:00 2020-12-05 05:00:00 ""    ""    UTC  
    # 10 2020-12-06 19:11:11 2020-12-06 16:00:00 2020-12-06 05:00:00 ""    ""    UTC  
    # 11 2020-12-05 21:09:31 2020-12-05 16:00:00 2020-12-05 05:00:00 ""    ""    UTC  
    # 12 2020-12-05 18:13:53 2020-12-05 16:00:00 2020-12-05 05:00:00 ""    ""    UTC  
    # 13 2020-12-15 20:36:56 2020-12-15 16:00:00 2020-12-15 05:00:00 ""    ""    UTC  
    # 14 2020-12-26 06:00:00 2020-12-26 00:00:00 2020-12-25 05:00:00 ""    ""    UTC  
    # 15 2020-12-16 00:40:46 2020-12-16 00:00:00 2020-12-15 05:00:00 ""    ""    UTC  
    # 16 2020-12-26 05:34:42 2020-12-26 00:00:00 2020-12-25 05:00:00 ""    ""    UTC 
    

    【讨论】:

      猜你喜欢
      • 2017-12-26
      • 1970-01-01
      • 2015-01-17
      • 1970-01-01
      • 2021-12-16
      • 1970-01-01
      • 2021-09-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多