如何让lubridate转换后的分钟部分固定为3位长度?
Great question! I’ve run into this exact issue before—lubridate’s hm() function doesn’t include a built-in setting to force leading zeros for single-digit minutes when rendering period objects. But with a little string manipulation (no extra packages required beyond base R and lubridate), we can get that clean, consistent format you’re after.
Here’s a step-by-step solution using your sample data:
Step 1: Load Packages and Data
First, let’s set up our environment and sample data frame:
library(lubridate) df <- data.frame(Time = c("13:04", "13:55", "8:00", "8:45"))
Step 2: Parse Time to Period Objects
Use hm() to convert the string times into lubridate period objects:
df$period <- hm(df$Time)
If you print df$period now, you’ll see the default formatting (e.g., 8H 0M 0S instead of 8H 00M 0S).
Step 3: Custom Formatting Function
We’ll write a simple function to extract the hours, minutes, and seconds from each period, format minutes to two digits with a leading zero if needed, then combine everything into your desired string format:
format_time_consistent <- function(period_obj) { # Extract components hrs <- hour(period_obj) mins <- sprintf("%02d", minute(period_obj)) # Forces two-digit minutes secs <- second(period_obj) # Combine into formatted string paste0(hrs, "H ", mins, "M ", secs, "S") }
The sprintf("%02d", ...) line is the magic here—it ensures any single-digit minute (0-9) gets a leading zero to make it two digits.
Step 4: Apply the Function to Your Data
Add the formatted time to your data frame:
df$formatted_time <- format_time_consistent(df$period)
Result
Your data frame will now have a formatted_time column with the clean, consistent format you want:
| Time | period | formatted_time |
|---|---|---|
| 13:04 | 13H 4M 0S | 13H 04M 0S |
| 13:55 | 13H 55M 0S | 13H 55M 0S |
| 8:00 | 8H 0M 0S | 8H 00M 0S |
| 8:45 | 8H 45M 0S | 8H 45M 0S |
Bonus: If You Want Two-Digit Seconds Too
If you later decide you want seconds to also be two digits (e.g., 00S instead of 0S), just adjust the secs line in the function to use sprintf as well:
secs <- sprintf("%02d", second(period_obj))
Bonus: Dplyr One-Liner
If you use dplyr, you can skip the separate function and do this all in a mutate call for conciseness:
library(dplyr) df <- df %>% mutate( period = hm(Time), formatted_time = paste0( hour(period), "H ", sprintf("%02d", minute(period)), "M ", second(period), "S" ) )
内容的提问来源于stack exchange,提问作者Matt.TW

