R语言日期和时间序列
一、日期和时间函数
1. 返回系统当前日期和时间
主要函数:
Sys.Date():返回当前日期Sys.time():返回当前日期和时间date():返回当前日期和时间(字符串格式)
案例代码:
r
# 获取当前日期(Date对象)
current_date <- Sys.Date()
print(current_date) # 输出类似 "2026-04-29"
# 获取当前日期和时间(POSIXct对象)
current_datetime <- Sys.time()
print(current_datetime) # 输出类似 "2026-04-29 14:30:25"
# 获取当前日期和时间(字符串格式)
current_datetime_str <- date()
print(current_datetime_str) # 输出类似 "Wed Apr 29 14:30:25 2026"
2. 时间函数 as.POSIXlt() 和 as.POSIXct()
说明:
POSIXct:从1970年1月1日开始的秒数,适合存储和计算POSIXlt:列表形式,包含年、月、日、时、分、秒等独立成分
案例代码:
r
# 创建一个时间字符串
time_str <- "2026-04-29 15:30:00"
# 转换为POSIXct格式(连续时间)
time_ct <- as.POSIXct(time_str)
print(time_ct) # 输出 "2026-04-29 15:30:00"
class(time_ct) # 查看类型:"POSIXct" "POSIXt"
# 转换为POSIXlt格式(列表时间)
time_lt <- as.POSIXlt(time_str)
print(time_lt) # 输出 "2026-04-29 15:30:00"
class(time_lt) # 查看类型:"POSIXlt" "POSIXt"
# 从POSIXlt中提取各个成分
print(paste("年:", time_lt$year + 1900)) # 年份需要加1900
print(paste("月:", time_lt$mon + 1)) # 月份从0开始,需要加1
print(paste("日:", time_lt$mday))
print(paste("时:", time_lt$hour))
print(paste("分:", time_lt$min))
print(paste("秒:", round(time_lt$sec)))
print(paste("星期几(0-6,0=周日):", time_lt$wday))
print(paste("一年中的第几天:", time_lt$yday))
二、日期格式转换
1. as.Date() 函数
语法:
r
as.Date(x, format = "输入格式")
常见格式代码:
%Y:4位数年份(2026)%y:2位数年份(26)%m:月份(01-12)%d:日期(01-31)%B:完整月份名(January)%b:缩写月份名(Jan)
案例代码:
r
# 不同格式的日期字符串
date1 <- "2026-04-29"
date2 <- "04/29/2026"
date3 <- "29Apr2026"
date4 <- "2026年4月29日"
# 转换为Date对象(需要指定输入格式)
d1 <- as.Date(date1) # 标准格式,无需指定
d2 <- as.Date(date2, format = "%m/%d/%Y")
d3 <- as.Date(date3, format = "%d%b%Y")
d4 <- as.Date(date4, format = "%Y年%m月%d日")
print(d1); print(d2); print(d3); print(d4)
print(class(d1)) # 输出 "Date"
2. format() 函数
语法:
r
format(日期对象, format = "输出格式")
案例代码:
r
# 创建一个日期对象
my_date <- as.Date("2026-04-29")
# 以不同格式输出
print(format(my_date, format = "%Y年%m月%d日")) # 2026年04月29日
print(format(my_date, format = "%B %d, %Y")) # April 29, 2026
print(format(my_date, format = "%a %b %d")) # Wed Apr 29
print(format(my_date, format = "%Y-%m-%d")) # 2026-04-29
print(format(my_date, format = "%y/%m/%d")) # 26/04/29
print(format(my_date, format = "%j")) # 一年中的第119天
print(format(my_date, format = "%A")) # 星期三(完整星期名)
三、其他函数
常用函数:
weekdays():返回星期几months():返回月份名称quarters():返回季度julian():返回从原点开始的天数
案例代码:
r
# 创建日期对象
dt <- as.Date("2026-04-29")
# 提取信息
print(weekdays(dt)) # 输出 "星期三"
print(months(dt)) # 输出 "四月"
print(quarters(dt)) # 输出 "Q2"(第二季度)
# 计算儒略日(从1970-01-01开始的天数)
julian_days <- julian(dt)
print(julian_days) # 输出类似 "20578"
# 从数字创建日期(从1970-01-01开始的天数)
origin_date <- as.Date(0, origin = "1970-01-01")
print(origin_date) # 输出 "1970-01-01"
四、生成日期时间
1. 生成日期序列
使用 seq() 函数:
r
# 生成连续日期序列
start_date <- as.Date("2026-01-01")
end_date <- as.Date("2026-01-10")
# 按天生成
daily_seq <- seq(start_date, end_date, by = "day")
print(daily_seq)
# 按周生成
weekly_seq <- seq(start_date, end_date, by = "week")
print(weekly_seq)
# 按月生成
monthly_seq <- seq(start_date, as.Date("2026-12-01"), by = "month")
print(monthly_seq)
# 指定长度生成
len_seq <- seq(start_date, by = "2 days", length.out = 10)
print(len_seq)
2. 生成时间序列
案例代码:
r
# 生成时间点序列(精确到小时)
start_time <- as.POSIXct("2026-04-29 08:00:00")
end_time <- as.POSIXct("2026-04-29 18:00:00")
# 按小时生成
hourly_seq <- seq(start_time, end_time, by = "hour")
print(hourly_seq)
# 按30分钟生成
min30_seq <- seq(start_time, end_time, by = "30 min")
print(min30_seq)
# 按指定数量生成
time_seq <- seq(start_time, by = "3 hours", length.out = 8)
print(time_seq)
3. 创建时间序列对象
使用 ts() 函数:
r
# 创建时间序列对象
# 参数:数据,起始时间,频率(12=月度,4=季度,1=年度)
data <- c(100, 120, 115, 130, 145, 140)
# 年度数据(从2020年开始)
ts_yearly <- ts(data, start = 2020, frequency = 1)
print(ts_yearly)
# 季度数据(从2020年第1季度开始)
ts_quarterly <- ts(data, start = c(2020, 1), frequency = 4)
print(ts_quarterly)
# 月度数据(从2020年1月开始)
ts_monthly <- ts(data, start = c(2020, 1), frequency = 12)
print(ts_monthly)
# 查看时间序列属性
print(start(ts_monthly)) # 起始时间
print(end(ts_monthly)) # 结束时间
print(frequency(ts_monthly)) # 频率
五、日期时间运算
1. 日期直接相减
案例代码:
r
# 创建两个日期
date_start <- as.Date("2026-04-29")
date_end <- as.Date("2026-05-20")
# 直接相减计算天数差
date_diff <- date_end - date_start
print(date_diff) # 输出 Time difference of 21 days
print(as.numeric(date_diff)) # 输出 21(纯数字)
# 计算年龄示例
birthday <- as.Date("1990-05-15")
today <- Sys.Date()
age_days <- today - birthday
age_years <- as.numeric(age_days) / 365.25
print(paste("年龄:", round(age_years, 1), "岁"))
2. 使用 difftime() 函数
语法:
r
difftime(time1, time2, units = "单位")
单位选项 :"auto", "secs", "mins", "hours", "days", "weeks"
案例代码:
r
# 创建时间点
time1 <- as.POSIXct("2026-04-29 14:00:00")
time2 <- as.POSIXct("2026-04-30 16:30:00")
# 计算不同单位的时间差
diff_days <- difftime(time2, time1, units = "days")
diff_hours <- difftime(time2, time1, units = "hours")
diff_mins <- difftime(time2, time1, units = "mins")
diff_secs <- difftime(time2, time1, units = "secs")
print(paste("天数差:", diff_days))
print(paste("小时差:", diff_hours))
print(paste("分钟差:", diff_mins))
print(paste("秒数差:", diff_secs))
# 时间差计算的实际应用
start_work <- as.POSIXct("2026-04-29 09:00:00")
end_work <- as.POSIXct("2026-04-29 17:30:00")
work_hours <- difftime(end_work, start_work, units = "hours")
print(paste("今天工作时间:", work_hours, "小时"))
六、lubridate 包(推荐使用)
安装和加载
r
# 安装包(如未安装)
# install.packages("lubridate")
# 加载包
library(lubridate)
1. 提取日期和时间
案例代码:
r
# 创建日期时间对象
now_time <- now() # 当前时间
print(now_time)
# 提取各个成分
print(paste("年:", year(now_time)))
print(paste("月:", month(now_time)))
print(paste("月(中文):", month(now_time, label = TRUE, abbr = FALSE)))
print(paste("日:", day(now_time)))
print(paste("时:", hour(now_time)))
print(paste("分:", minute(now_time)))
print(paste("秒:", second(now_time)))
print(paste("星期几:", wday(now_time, label = TRUE)))
print(paste("一年中的第几天:", yday(now_time)))
print(paste("季度:", quarter(now_time)))
2. 解析日期和时间
案例代码:
r
# 自动解析多种格式
d1 <- ymd("2026-04-29") # 年月日
d2 <- mdy("04/29/2026") # 月日年
d3 <- dmy("29-04-2026") # 日月年
d4 <- ymd_hms("2026-04-29 15:30:45") # 年月日时分秒
d5 <- mdy_hm("04/29/2026 03:45 PM") # 带上下午
print(d1); print(d2); print(d3)
print(d4); print(d5)
# 解析不规范的日期字符串
date_str <- c("20260429", "2026/04/29", "29-Apr-2026")
parsed_dates <- ymd(date_str) # 自动识别常见格式
print(parsed_dates)
3. 时间日期计算
案例代码:
r
# 创建基准日期
base_date <- ymd("2026-04-29")
# 日期加减运算
print(base_date + days(10)) # 加10天
print(base_date + weeks(2)) # 加2周
print(base_date + months(3)) # 加3个月
print(base_date + years(1)) # 加1年
print(base_date - days(5)) # 减5天
# 滚动到指定日期
print(floor_date(base_date, "month")) # 当月第一天
print(ceiling_date(base_date, "month")) # 下月第一天
print(floor_date(base_date, "year")) # 当年第一天
# 计算两个日期之间的跨度
date1 <- ymd("2026-01-15")
date2 <- ymd("2026-12-31")
# 计算间隔
interval_days <- date2 - date1
print(paste("相差天数:", interval_days))
# 使用interval和time_length
time_span <- interval(date1, date2)
print(paste("相差天数:", time_length(time_span, "days")))
print(paste("相差周数:", time_length(time_span, "weeks")))
print(paste("相差月数:", time_length(time_span, "months")))
print(paste("相差年数:", time_length(time_span, "years")))
4. 时间间隔
案例代码:
r
# 创建间隔
start <- ymd_hms("2026-04-29 09:00:00")
end <- ymd_hms("2026-04-29 17:00:00")
# 创建间隔对象
work_interval <- interval(start, end)
print(work_interval)
# 检查某个时间是否在间隔内
check_time <- ymd_hms("2026-04-29 12:30:00")
is_within <- check_time %within% work_interval
print(paste("12:30是否在工作时间内:", is_within))
# 合并间隔
int1 <- interval(ymd("2026-01-01"), ymd("2026-01-31"))
int2 <- interval(ymd("2026-02-01"), ymd("2026-02-28"))
int_union <- union(int1, int2)
print(int_union)
# 判断间隔是否重叠
int3 <- interval(ymd("2026-01-15"), ymd("2026-02-15"))
int_overlap <- intersect(int1, int3)
print(int_overlap)
5. 时区的操作
案例代码:
r
# 查看当前时区
current_tz <- Sys.timezone()
print(paste("当前时区:", current_tz))
# 创建带时区的时间
time_utc <- now(tzone = "UTC")
time_shanghai <- now(tzone = "Asia/Shanghai")
time_newyork <- now(tzone = "America/New_York")
print(paste("UTC时间:", time_utc))
print(paste("上海时间:", time_shanghai))
print(paste("纽约时间:", time_newyork))
# 时区转换
original_time <- ymd_hms("2026-04-29 14:00:00", tz = "Asia/Shanghai")
converted_time <- with_tz(original_time, tzone = "America/New_York")
print(paste("上海时间(14:00)等于纽约时间:", converted_time))
# 强制修改时区(不改变时间数值)
forced_time <- force_tz(original_time, tzone = "UTC")
print(paste("强制设为UTC:", forced_time))
七、zoo 包(时间序列基础包)
安装和加载
r
# install.packages("zoo")
library(zoo)
1. 创建时间序列
案例代码:
r
# 准备数据
data_values <- c(10, 15, 13, 18, 20, 22)
dates <- as.Date(c("2026-01-01", "2026-01-02", "2026-01-03",
"2026-01-04", "2026-01-05", "2026-01-06"))
# 创建zoo对象
zoo_ts <- zoo(data_values, order.by = dates)
print(zoo_ts)
# 查看属性和结构
print(class(zoo_ts))
print(index(zoo_ts)) # 查看时间索引
print(coredata(zoo_ts)) # 查看核心数据
# 创建不规则时间序列
irregular_dates <- as.Date(c("2026-01-01", "2026-01-03", "2026-01-10", "2026-02-01"))
irregular_data <- c(100, 150, 200, 180)
zoo_irregular <- zoo(irregular_data, order.by = irregular_dates)
print(zoo_irregular)
2. 类型转换
案例代码:
r
# 创建示例zoo对象
dates <- seq(as.Date("2026-01-01"), as.Date("2026-01-10"), by = "day")
values <- rnorm(10, mean = 100, sd = 10)
zoo_obj <- zoo(values, order.by = dates)
# zoo转数据框
df <- data.frame(date = index(zoo_obj), value = coredata(zoo_obj))
print(head(df))
# zoo转ts(需要规则时间序列)
# 先合并成规则序列
regular_zoo <- merge(zoo_obj, zoo(, seq(start(zoo_obj), end(zoo_obj), by = "day")))
ts_obj <- as.ts(regular_zoo)
print(ts_obj)
# zoo转xts(需要xts包)
# library(xts)
# xts_obj <- as.xts(zoo_obj)
3. 数据操作
案例代码:
r
# 创建示例数据
dates <- seq(as.Date("2026-01-01"), as.Date("2026-01-10"), by = "day")
values <- c(10, 15, NA, 18, 20, NA, 23, 25, 27, 30)
zoo_obj <- zoo(values, dates)
# 处理缺失值 - 线性插值
zoo_na_interp <- na.approx(zoo_obj)
print("插值后的数据:")
print(zoo_na_interp)
# 向前填充缺失值
zoo_na_locf <- na.locf(zoo_obj)
print("向前填充后的数据:")
print(zoo_na_locf)
# 删除缺失值
zoo_na_omit <- na.omit(zoo_obj)
print("删除缺失值后的数据:")
print(zoo_na_omit)
# 滚动计算(移动平均)
zoo_ma <- rollmean(zoo_obj, k = 3, fill = NA)
print("3期移动平均:")
print(zoo_ma)
# 滚动求和
zoo_sum <- rollsum(zoo_obj, k = 3, fill = NA)
print("3期滚动求和:")
print(zoo_sum)
# 差分运算
zoo_diff <- diff(zoo_obj)
print("一阶差分:")
print(zoo_diff)
# 滞后
zoo_lag <- lag(zoo_obj, k = 1)
print("滞后一期:")
print(zoo_lag)
八、xts 包(时间序列扩展包)
安装和加载
r
# install.packages("xts")
library(xts)
1. 创建时间序列
案例代码:
r
# 准备数据
dates <- seq(as.Date("2026-01-01"), as.Date("2026-01-10"), by = "day")
data_matrix <- matrix(1:20, ncol = 2)
# 创建xts对象
xts_obj <- xts(data_matrix, order.by = dates)
print(xts_obj)
# 命名列
colnames(xts_obj) <- c("Value1", "Value2")
print(xts_obj)
# 使用日期时间(精确到分钟)
minute_dates <- seq(as.POSIXct("2026-04-29 09:00:00"),
as.POSIXct("2026-04-29 17:00:00"),
by = "30 min")
minute_data <- rnorm(length(minute_dates), mean = 100, sd = 5)
xts_minute <- xts(minute_data, order.by = minute_dates)
print(head(xts_minute))
2. xts 包的基本操作
案例代码:
r
# 创建示例xts对象
dates <- seq(as.Date("2026-01-01"), as.Date("2026-01-10"), by = "day")
data <- data.frame(
price = round(runif(10, 100, 200), 2),
volume = round(runif(10, 1000, 5000))
)
xts_obj <- xts(data, order.by = dates)
# 查看数据
print(first(xts_obj)) # 查看前6行
print(last(xts_obj)) # 查看后6行
print(head(xts_obj, 3)) # 查看前3行
print(tail(xts_obj, 3)) # 查看后3行
# 索引操作
print(index(xts_obj)) # 提取时间索引
print(coredata(xts_obj)) # 提取核心数据
# 按时间范围子集
print(xts_obj["2026-01-03/2026-01-06"]) # 日期范围子集
print(xts_obj["2026-01-05"]) # 单个日期
# 使用逻辑索引
print(xts_obj[xts_obj$price > 150]) # 价格大于150的行
3. 按时间统计数据
案例代码:
r
# 创建完整月度数据
dates_monthly <- seq(as.Date("2026-01-01"), as.Date("2026-12-31"), by = "day")
monthly_data <- xts(runif(length(dates_monthly), 50, 150), order.by = dates_monthly)
# 按月汇总
monthly_avg <- apply.monthly(monthly_data, mean) # 每月平均值
monthly_sum <- apply.monthly(monthly_data, sum) # 每月总和
monthly_max <- apply.monthly(monthly_data, max) # 每月最大值
print(head(monthly_avg))
print(head(monthly_sum))
# 按季度汇总
quarterly_avg <- apply.quarterly(monthly_data, mean)
print(quarterly_avg)
# 按年汇总
yearly_avg <- apply.yearly(monthly_data, mean)
print(yearly_avg)
# 按周汇总
weekly_avg <- apply.weekly(monthly_data, mean)
print(head(weekly_avg))
# 自定义周期(每3天)
period.apply(monthly_data, endpoints(monthly_data, on = "days", k = 3), mean)
4. 更改时间周期
案例代码:
r
# 创建高频时间序列(小时级)
hours <- seq(as.POSIXct("2026-04-29 00:00:00"),
as.POSIXct("2026-04-29 23:00:00"),
by = "hour")
high_freq_data <- xts(rnorm(length(hours), 100, 10), order.by = hours)
# 转换为日数据(降采样)
daily_data <- to.daily(high_freq_data)
print(daily_data)
# 转换为周期性数据
period.apply(high_freq_data, endpoints(high_freq_data, on = "hours", k = 6), mean)
# 升采样(从日数据到小时数据)
daily_dates <- seq(as.Date("2026-04-01"), as.Date("2026-04-05"), by = "day")
daily_values <- xts(1:5, order.by = daily_dates)
# 创建小时级别的时间索引
hourly_index <- seq(as.POSIXct("2026-04-01 00:00:00"),
as.POSIXct("2026-04-05 23:00:00"),
by = "hour")
# 合并并向前填充
hourly_values <- merge(daily_values, xts(, hourly_index))
hourly_filled <- na.locf(hourly_values)
print(head(hourly_filled, 10))
# 使用align.time对齐时间
aligned <- align.time(high_freq_data, n = 60*60) # 对齐到整点
print(head(aligned))
九、综合案例
案例1:股票数据分析(完整流程)
r
# 加载所需包
library(lubridate)
library(xts)
# 创建模拟股票数据
set.seed(123)
dates <- seq(as.Date("2026-01-01"), as.Date("2026-03-31"), by = "day")
n <- length(dates)
# 生成模拟数据
stock_data <- data.frame(
date = dates,
open = round(runif(n, 100, 110), 2),
high = round(runif(n, 105, 115), 2),
low = round(runif(n, 95, 105), 2),
close = round(runif(n, 100, 112), 2),
volume = round(runif(n, 100000, 500000))
)
# 转换为xts对象
stock_xts <- xts(stock_data[, -1], order.by = stock_data$date)
# 1. 计算收益率
stock_xts$returns <- diff(log(stock_xts$close))
print(head(stock_xts))
# 2. 按月统计平均收益率
monthly_returns <- apply.monthly(stock_xts$returns, mean, na.rm = TRUE)
print("月平均收益率:")
print(monthly_returns)
# 3. 计算移动平均线(5日、20日)
stock_xts$ma5 <- rollmean(stock_xts$close, k = 5, fill = NA)
stock_xts$ma20 <- rollmean(stock_xts$close, k = 20, fill = NA)
# 4. 查找金叉信号(5日均线上穿20日均线)
stock_xts$signal <- ifelse(!is.na(stock_xts$ma5) & !is.na(stock_xts$ma20),
ifelse(stock_xts$ma5 > stock_xts$ma20 &
lag(stock_xts$ma5) <= lag(stock_xts$ma20), 1, 0), 0)
# 5. 统计信号数量
signal_count <- sum(stock_xts$signal, na.rm = TRUE)
print(paste("金叉信号出现次数:", signal_count))
# 6. 提取金叉日期的数据
signal_dates <- stock_xts[stock_xts$signal == 1]
print("金叉信号日期的数据:")
print(signal_dates)
案例2:时间区间计算(工作日统计)
r
library(lubridate)
# 定义项目起止时间
project_start <- ymd("2026-04-01")
project_end <- ymd("2026-06-30")
# 生成所有日期序列
all_dates <- seq(project_start, project_end, by = "day")
# 提取工作日(周一到周五)
workdays <- all_dates[!wday(all_dates) %in% c(1, 7)] # 去除周六(7)周日(1)
print(paste("工作日总数:", length(workdays)))
print(paste("休息日总数:", length(all_dates) - length(workdays)))
# 计算每月工作日
workdays_by_month <- table(month(workdays, label = TRUE))
print("每月工作日分布:")
print(workdays_by_month)
# 排除节假日示例
holidays <- ymd(c("2026-05-01", "2026-06-01")) # 五一、六一劳动节
# 实际工作日(排除节假日)
actual_workdays <- setdiff(workdays, holidays)
print(paste("排除节假日后工作日:", length(actual_workdays)))
# 显示节假日
print("法定节假日:")
print(holidays)
十、要点回顾
| 知识点 | 功能 | 主要函数/包 |
|---|---|---|
| 基本日期函数 | 获取当前日期时间 | Sys.Date(), Sys.time(), date() |
| 时间类转换 | 转换为POSIX格式 | as.POSIXct(), as.POSIXlt() |
| 日期格式转换 | 字符串与日期互转 | as.Date(), format() |
| 日期运算 | 日期加减、时间差 | difftime(), 直接 - |
| lubridate包 | 处理日期时间 | ymd(), month(), %within%, 时区转换 |
| zoo包 | 不规则时间序列 | zoo(), na.approx(), rollmean() |
| xts包 | 高性能时间序列 | xts(), apply.monthly(), to.daily() |
| 序列生成 | 生成规则时间序列 | seq(, by="days"), seq(, by="hour") |
| 时间聚合 | 按周期统计 | apply.monthly(), period.apply() |
| 缺失值处理 | 插值、填充 | na.locf(), na.approx() |
注意事项:
- 日期计算要注意时区问题(使用
lubridate的with_tz()) - 时间序列降采样时注意选择合适的聚合函数(均值、总和等)
- 缺失值处理前应先确认数据结构(regular vs irregular)
ts()和xts/zoo适用场景不同(规则周期 vs 任意时间点)