如果我对问题的理解正确,您希望每次四舍五入到最接近的 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