#' Pad 2
#'
#' @param x string to pad
pad2 <- function(x) stringr::str_pad(x, 2, "left", "0")
#' Format durations
#'
#' @param duration_in vector of periods to transform
#' @param time_ind indicator - truncate times longer than 24 hours?
#' @export
format_duration <- function(duration_in, time_ind = FALSE){
# Return error if class isn't duration or numeric
if (class(duration_in) == "Duration")
duration_num <- as.numeric(duration_in)
else if (class(duration_in) == "numeric")
duration_num <- duration_in
else
stop("Argument class must be duration or numeric")
# Convert to numeric - seconds
duration_num <- as.numeric(duration_in)
# Extract hours - integer part of quotient with 3600 sec (1 hour)
hr <- duration_num %/% 3600
# Extract minutes - part left over from above, then integer quotient with
# 60 sec (1 min)
min <- (duration_num %% 3600) %/% 60
# Output string
# If time_ind, take off days and pad, otherwise, add colon.
if (time_ind)
stringr::str_c(pad2(hr %% 24), pad2(min))
else
stringr::str_c(hr, ":", pad2(min))
}
#' Split an interval at midnight
#'
#' @param start_in date to start
#' @param end_in date to end
#' @importFrom lubridate %--%
split_interval <- function(start_in, end_in){
# Create the vector
out_vec <- start_in
# Set up the while loop to populate the vector
midnight <- lubridate::floor_date(start_in - lubridate::minutes(), unit = "days") + lubridate::days()
while (midnight < end_in) {
out_vec <- c(out_vec, midnight)
midnight <- midnight + lubridate::days()
}
# Add the end
out_vec <- c(out_vec, end_in)
# Convert back to an interval
int_out <- lubridate::int_diff(out_vec)
# The following is a workaround, as tibbles don't take intervals and data.frames munge them
# Use base::rev to reverse order
data.frame(start_dttm_comp = lubridate::int_start(int_out),
end_dttm_comp = lubridate::int_end(int_out))
}
#' Transform TimetrackIO Report
#'
#' @param df_in time tracking data to transform
#' @importFrom magrittr %>%
#' @importFrom rlang .data
#' @importFrom dplyr n
#' @export
time_2transform <- function(df_in){
# Transform data
df_text <- df_in %>%
dplyr::mutate(
# Get the total duration
duration_total = lubridate::as.duration(.data$start_dttm %--% .data$end_dttm),
# Split the interval on midnight
interval_split = purrr::map2(.data$start_dttm, .data$end_dttm, split_interval)
) %>%
tidyr::unnest(cols = c(.data$interval_split)) %>%
dplyr::mutate(
# Create duration objects for plot text
duration_comp = lubridate::as.duration(.data$start_dttm_comp %--% .data$end_dttm_comp),
# Date to plot as datetime
date_to_plot_dttm = lubridate::floor_date(.data$start_dttm_comp, "days"),
# Date to plot
date_to_plot = lubridate::as_date(.data$date_to_plot_dttm),
# Create period objects for plotting
start_period_plot = lubridate::as.period(.data$date_to_plot_dttm %--% .data$start_dttm_comp),
end_period_plot = lubridate::as.period(.data$date_to_plot_dttm %--% .data$end_dttm_comp),
# Convert period objects to durations
start_duration_plot = lubridate::as.duration(.data$start_period_plot),
end_duration_plot = lubridate::as.duration(.data$end_period_plot),
mid_duration_plot = (.data$start_duration_plot + .data$end_duration_plot)/2,
# Create text to plot
plot_text = dplyr::if_else(
.data$duration_comp < lubridate::as.duration("8M"), "",
stringr::str_c(
.data$activity, ": ", format_duration(.data$duration_comp),
# If the activity was less than 15 minutes...
dplyr::if_else(
.data$duration_comp < lubridate::as.duration("15M"), "",
stringr::str_c(
# If the event straddles midnight, print the total
dplyr::if_else(
.data$duration_total == .data$duration_comp, "",
stringr::str_c("\n(Total: ", format_duration(.data$duration_total), ")")
),
dplyr::if_else(.data$notes == "", "", stringr::str_c("\n", .data$notes))
)
)
)
)
)
# Select only the appropriate variables
df_text %>%
dplyr::select(.data$date_to_plot, .data$start_duration_plot, .data$mid_duration_plot,
.data$end_duration_plot, .data$activity, .data$plot_text)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.