Skip to content

Instantly share code, notes, and snippets.

@jonlachmann
Created June 7, 2023 15:13
Show Gist options
  • Save jonlachmann/5782aaa107a84eed6c84bb61ec6373d4 to your computer and use it in GitHub Desktop.
Save jonlachmann/5782aaa107a84eed6c84bb61ec6373d4 to your computer and use it in GitHub Desktop.
Calculate the number of days, weekdays or weeks in a month, quarter, half-year or year.
library(lubridate)
# Function to count days, weekdays and weeks in a given month
counts <- function (year, month) {
# Get the number of days in the month
num_days <- days_in_month(as.Date(paste(year, month, "01", sep = "-")))
# Initialize a counter
weekday_count <- 0
week_count <- 0
# Loop through each day of the month
for (day in 1:num_days) {
# Get the date
date <- as.Date(paste(year, month, day, sep = "-"))
# Check if the day is a weekday (Monday to Friday)
if (weekdays(date) %in% c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday")) {
weekday_count <- weekday_count + 1
}
if (weekdays(date) == "Wednesday") {
week_count <- week_count + 1
}
}
# Return the weekday count
return(c(num_days, weekday_count, week_count))
}
# Function to count days, weekdays and weeks per month within a given date range
counts_range <- function (start_date, end_date) {
# Convert start and end dates to date objects
start_date <- as.Date(start_date)
end_date <- as.Date(end_date)
# Get the start and end year and month
start_year <- as.numeric(format(start_date, "%Y"))
end_year <- as.numeric(format(end_date, "%Y"))
start_month <- as.numeric(format(start_date, "%m"))
end_month <- as.numeric(format(end_date, "%m"))
# Initialize a list to store the counts per month
counts_per_month <- list()
# Loop through each year and month
for (year in start_year:end_year) {
for (month in 1:12) {
# Check if the month is within the range
if ((year == start_year && month < start_month) ||
(year == end_year && month > end_month)) {
next # Skip the iteration if the month is outside the range
}
# Count weekdays for the month
weekday_count <- counts(year, month)
# Store the count in the list
counts_per_month[[paste(year, month, sep = "-")]] <- weekday_count
}
}
# Return the counts per month
return(counts_per_month)
}
# Function to convert counts per month to counts per month, quarter, halfyear and year
per_q_h_y <- function (x) {
per_quarter <- rowSums(matrix(x, length(x) / 3, byrow = T))
per_halfyear <- rowSums(matrix(x, length(x) / 6, byrow = T))
per_year <- rowSums(matrix(x, length(x) / 12, byrow = T))
return(list(m = x, q = per_quarter, h = per_halfyear, y = per_year))
}
# Example usage
start_date <- "1900-01-01"
end_date <- "2100-12-31"
counts_per_month <- counts_range(start_date, end_date)
days_per_month <- unlist(lapply(counts_per_month, function (x) x[1]))
weekdays_per_month <- unlist(lapply(counts_per_month, function (x) x[2]))
weeks_per_month <- unlist(lapply(counts_per_month, function (x) x[3]))
days_per <- per_q_h_y(days_per_month)
weekdays_per <- per_q_h_y(weekdays_per_month)
weeks_per <- per_q_h_y(weeks_per_month)
days_mat <- matrix(unlist(lapply(days_per, summary)), 4, byrow = TRUE)
weekdays_mat <- matrix(unlist(lapply(weekdays_per, summary)), 4, byrow = TRUE)
weeks_mat <- matrix(unlist(lapply(weeks_per, summary)), 4, byrow = TRUE)
full_mat <- rbind(days_mat, weekdays_mat, weeks_mat)[, c(1, 4, 6)]
colnames(full_mat) <- c("Min.", "Mean", "Max.")
periodicities <- c("month", "quarter", "half-year", "year")
rownames(full_mat) <- c(paste0("Days per ", periodicities), paste0("Weekdays per ", periodicities), paste0("Weeks per ", periodicities))
print(full_mat)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment