How to manipulate the time part of a date column?

本秂侑毒 提交于 2019-12-12 06:49:06

问题


How do I write this code (hour is from lubridate package)?

Objective: if hour part of PICK_DATE is later than 16:00, the ADJ_PICK_DATE should be next day 03:00. If the hour part of PICK_DATE is earlier than 03:00, then ADJ_PICK_DATE is to be same day 03:00. Problem is, when there is no change needed, the code still adds 3 hours to the PICK_DATE i.e. when the hour part of PICK_DATE is within 03:00 and 16:00.

x$PICK_TIME <- cut(hour(x$PICK_DATE), c(-1, 2, 15, 24), c("EARLY", "OKAY", "LATE"))    
x$ADJ_PICK_DATE <- ifelse(x$PICK_TIME=="EARLY",
                          as.POSIXct(paste(format(x$PICK_DATE, "%d-%b-%Y"), "03:00"),
                                 format="%d-%b-%Y %H:%M"), x$PICK_DATE)
x$ADJ_PICK_DATE <- ifelse(x$PICK_TIME=="LATE",
                          as.POSIXct(paste(format(x$PICK_DATE+86400, "%d-%b-%Y"),
                                           "03:00"), format="%d-%b-%Y %H:%M"),
                          x$ADJ_PICK_DATE)
x$ADJ_PICK_DATE <- as.POSIXct(x$ADJ_PICK_DATE, origin = "1970-01-01")

Help please.

Sample data:

PICK_DATE   SHIP_DATE
01-APR-2017 00:51   02-APR-2017 06:55 AM
01-APR-2017 00:51   02-APR-2017 12:11 PM
01-APR-2017 00:51   02-APR-2017 12:11 PM
01-APR-2017 00:51   02-APR-2017 09:39 AM

回答1:


Here is a simple, reproducible example. I had to make up some sample data, based on an earlier question you asked. I suggest reading into dplyr and lubridate as they will help you with your work on manipulating dates.

EDIT: Updated to work with end-of-month dates.

library(lubridate)
library(dplyr)

df <- data.frame(pick_date = c("01-APR-2017 00:51", "02-APR-2017 08:53", "15-APR-2017 16:12", "23-APR-2017 02:04", "30-APR-2017 20:08"), ship_date = c("05-APR-2017 06:55", "09-APR-2017 12:11", "30-APR-2017 13:11", "02-MAY-2017 15:16", "05-MAY-2017 09:57"))

df %>% 
    mutate(pick_date = dmy_hm(pick_date)) %>% 
    mutate(ship_date = dmy_hm(ship_date)) %>% 
    mutate(pick_time = case_when(
        hour(pick_date) <= 3 ~ "early",
        hour(pick_date) >= 16 ~ "late",
        TRUE ~ "okay")
    ) %>% 
    mutate(new_pick_time = case_when(
        pick_time == "early" ~ hms(hours(3)),
        pick_time == "late" ~ hms(hours(3)),
        TRUE ~ hms(paste0(hour(pick_date), "H ", minute(pick_date), "M ", second(pick_date), "S")))
    ) %>% 
    mutate(temp_pick_date = case_when(
        pick_time == "early" ~ pick_date,
        pick_time == "late" ~ pick_date + days(1),
        TRUE ~ pick_date)
    ) %>% 
    mutate(new_pick_date = make_datetime(year(temp_pick_date), month(temp_pick_date), day(temp_pick_date), hour(new_pick_time), minute(new_pick_time), second(new_pick_time))) %>%
    select(-new_pick_time, -temp_pick_date)

This returns

            pick_date           ship_date pick_time       new_pick_date
1 2017-04-01 00:51:00 2017-04-05 06:55:00     early 2017-04-01 03:00:00
2 2017-04-02 08:53:00 2017-04-09 12:11:00      okay 2017-04-02 08:53:00
3 2017-04-15 16:12:00 2017-04-30 13:11:00      late 2017-04-16 03:00:00
4 2017-04-23 02:04:00 2017-05-02 15:16:00     early 2017-04-23 03:00:00
5 2017-04-30 20:08:00 2017-05-05 09:57:00      late 2017-05-01 03:00:00



回答2:


So it sounds like you just need to do two different arithmetic operations, conditional on the hour of a date time?

The simplest way I can think to access the hour component is to store the time in a POSIXlt. I believe the "l" stands or "list", and this lets you treat a timestamp like a list with the different time measurements being accessible attributes accordingly.

Like this:

> time <- as.POSIXlt('2017-07-29 15:12:01')
> time
[1] "2017-07-29 15:12:01 EDT"
> time$hour
[1] 15

So you could write a function that does the operation you desire, and feed it your date column. Hard for me to take it further because I don't quite understand the question, but here's a skeleton:

ComputeDifference <- function(time) {

     if (time$hour < 3) {
       # code to count orders between 0 and 3 "from same day 3:00"

    }
    if (time$hour > 16) {
      # code to consider late orders

    }

}

If you throw in sample data and refine the question, maybe I can take a more thorough crack at this.



来源:https://stackoverflow.com/questions/45390184/how-to-manipulate-the-time-part-of-a-date-column

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!