Julia 教程 / Julia 日期、时间与周期
17. 日期、时间与周期
Dates 模块是 Julia 标准库中处理日期和时间的完整工具包,提供类型安全的日期运算和丰富的格式化能力。
17.1 Date/DateTime/Time 类型
三种核心类型
using Dates
# Date — 仅日期(无时间)
d = Date(2026, 5, 11)
println(d) # 2026-05-11
# DateTime — 日期+时间
dt = DateTime(2026, 5, 11, 14, 30, 0)
println(dt) # 2026-05-11T14:30:00
# Time — 仅时间(无日期)
t = Time(14, 30, 0)
println(t) # 14:30:00
# 当前时间
println(now()) # DateTime
println(today()) # Date
println(now(Time)) # Time
类型层次
# AbstractDateTime
# ├── TimeType
# │ ├── Date — 日期
# │ └── DateTime — 日期时间
# └── Time — 时间(独立)
| 类型 | 精度 | 示例 |
|---|
Date | 天 | Date(2026, 5, 11) |
DateTime | 毫秒 | DateTime(2026, 5, 11, 14, 30) |
Time | 纳秒 | Time(14, 30, 0) |
构造方式
# 从字符串构造
d1 = Date("2026-05-11")
dt1 = DateTime("2026-05-11T14:30:00")
t1 = Time("14:30:00")
# 使用关键字参数
d2 = Date(2026, 5)
dt2 = DateTime(2026, 5, 11, 14)
# 从 Unix 时间戳
epoch = DateTime(1970, 1, 1)
dt_from_ts = epoch + Second(1715428200)
17.2 日期解析与格式化
格式化符号
| 符号 | 含义 | 示例 |
|---|
yyyy | 四位年 | 2026 |
mm | 两位月 | 05 |
dd | 两位日 | 11 |
HH | 24小时 | 14 |
MM | 分钟 | 30 |
SS | 秒 | 00 |
EEEE | 星期全名 | Sunday |
E | 星期缩写 | Sun |
解析日期
# 自定义格式解析
d = Date("11/05/2026", dateformat"dd/mm/yyyy")
println(d) # 2026-05-11
dt = DateTime("2026年05月11日 14:30", dateformat"yyyy年mm月dd日 HH:MM")
println(dt)
# 中文日期解析
d2 = Date("2026年5月11日", dateformat"yyyy年m月d日")
格式化输出
d = Date(2026, 5, 11)
# 使用 format 函数
println(Dates.format(d, dateformat"yyyy-mm-dd")) # 2026-05-11
println(Dates.format(d, dateformat"dd/mm/yyyy")) # 11/05/2026
println(Dates.format(d, dateformat"yyyy年mm月dd日")) # 2026年05月11日
dt = DateTime(2026, 5, 11, 14, 30, 45)
println(Dates.format(dt, dateformat"yyyy-mm-dd HH:MM:SS"))
# 2026-05-11 14:30:45
# dayname / dayofweek
println(Dates.dayname(d)) # Sunday (或中文系统下的星期日)
println(Dates.dayofweek(d)) # 7
17.3 日期运算
周期类型
using Dates
d = Date(2026, 1, 15)
# Period 类型
d + Day(1) # +1天
d + Week(2) # +2周
d + Month(3) # +3月
d + Year(1) # +1年
# 减法
d - Day(10)
# 组合运算
d + Month(1) + Day(15) # 2026-03-02
日期差值
d1 = Date(2026, 1, 1)
d2 = Date(2026, 12, 31)
# 日期差
diff = d2 - d1
println(typeof(diff)) # Day
println(value(diff)) # 364
# 转换为不同单位
diff_days = Dates.value(Day(d2 - d1))
diff_weeks = diff_days ÷ 7
# DateTime 差值
dt1 = DateTime(2026, 1, 1, 0, 0, 0)
dt2 = DateTime(2026, 1, 1, 12, 30, 0)
diff = dt2 - dt1
println(typeof(diff)) # Millisecond
比较运算
d1 = Date(2026, 1, 1)
d2 = Date(2026, 6, 15)
println(d1 < d2) # true
println(d1 == d2) # false
println(d1 > d2) # false
# min / max
println(min(d1, d2)) # 2026-01-01
println(max(d1, d2)) # 2026-06-15
⚠️ 注意:Month(1) 和 Day(30) 不总相等(不同月份天数不同)。Julia 会自动处理月末溢出。
17.4 时区处理 (TimeZones.jl)
using TimeZones
# 创建带时区的时间
utc = ZonedDateTime(DateTime(2026, 5, 11, 14, 0), tz"UTC")
shanghai = astimezone(utc, tz"Asia/Shanghai")
println(shanghai) # 2026-05-11T22:00:00+08:00
# 时区转换
nyc = astimezone(utc, tz"America/New_York")
tokyo = astimezone(utc, tz"Asia/Tokyo")
println("UTC: $utc")
println("上海: $shanghai")
println("纽约: $nyc")
println("东京: $tokyo")
# 获取当前时区时间
now_shanghai = now(tz"Asia/Shanghai")
println("上海现在: $now_shanghai")
时区列表
# 常用时区标识
# tz"UTC" 协调世界时
# tz"Asia/Shanghai" 中国标准时间 (UTC+8)
# tz"Asia/Tokyo" 日本标准时间 (UTC+9)
# tz"America/New_York" 美国东部时间
# tz"Europe/London" 英国时间
# 列出所有时区
# TimeZone[] # 所有可用时区
17.5 日期范围与序列
创建日期范围
# 等间隔日期序列
dates = Date(2026, 1, 1):Day(1):Date(2026, 1, 10)
for d in dates
println(d)
end
# 2026-01-01
# 2026-01-02
# ...
# 2026-01-10
# 月度序列
months = Date(2026, 1, 1):Month(1):Date(2026, 12, 1)
println(collect(months)) # 12个月的第一天
# 年度序列
years = Date(2020, 1, 1):Year(1):Date(2026, 1, 1)
生成日期列表
# 所有工作日
function workdays(start::Date, stop::Date)
return filter(d -> Dates.dayofweek(d) <= 5, start:Day(1):stop)
end
wdays = workdays(Date(2026, 5, 1), Date(2026, 5, 31))
println("5月工作日: $(length(wdays)) 天")
# 月末日期
function month_ends(year)
return [Dates.lastdayofmonth(Date(year, m, 1)) for m in 1:12]
end
println(month_ends(2026))
日期提取组件
d = DateTime(2026, 5, 11, 14, 30, 45)
println(year(d)) # 2026
println(month(d)) # 5
println(day(d)) # 11
println(hour(d)) # 14
println(minute(d)) # 30
println(second(d)) # 45
println(dayofweek(d)) # 1 (Monday=1)
println(dayofyear(d)) # 131
println(week(d)) # 19
println(daysinmonth(d)) # 31
println(isleapyear(d)) # false
17.6 性能计时
@elapsed
# @elapsed 返回执行时间(秒)
t = @elapsed sum(1:1_000_000)
println("耗时: $(round(t*1000, digits=2)) ms")
@timev
# @timev 提供详细计时信息
@timev begin
data = rand(1000, 1000)
result = data * data'
s = sum(result)
end
# 输出:
# 0.123456 seconds (15 allocations: 15.259 MiB)
# elapsed time (ns): 123456789
# gc time (ns): 1234567
# bytes allocated: 16000000
# pool allocs: 15
@time
# @time 基本计时
@time result = sum(sin(x) for x in 1:10_000_000)
# 0.345678 seconds (4 allocations: 160 bytes)
using BenchmarkTools
# @btime 自动多次运行取最优
@btime sum(1:1_000_000)
# 1.234 ms (0 allocations)
# @benchmark 详细统计
@benchmark sin(1.0)
# 输出最小、中位数、平均、最大时间
# 精确比较两种实现
@btime [sin(x) for x in 1:1000] # 分配内存
@btime collect(sin(x) for x in 1:1000) # 生成器
17.7 Dates 模块常用函数速查
创建函数
| 函数 | 用途 | 示例 |
|---|
Date(y,m,d) | 创建日期 | Date(2026,5,11) |
DateTime(y,m,d,H,M,S) | 创建日期时间 | DateTime(2026,5,11,14,30) |
Time(H,M,S) | 创建时间 | Time(14,30,0) |
now() | 当前日期时间 | now() |
today() | 当前日期 | today() |
提取函数
| 函数 | 用途 | 示例 |
|---|
year(d) | 年份 | year(Date(2026,5,11)) → 2026 |
month(d) | 月份 | month(d) → 5 |
day(d) | 日 | day(d) → 11 |
hour(dt) | 小时 | hour(now()) |
minute(dt) | 分钟 | minute(now()) |
second(dt) | 秒 | second(now()) |
dayofweek(d) | 星期几(1=Mon) | dayofweek(d) |
dayofyear(d) | 年内第几天 | dayofyear(d) |
week(d) | 周数 | week(d) |
查询函数
| 函数 | 用途 | 示例 |
|---|
isleapyear(d) | 是否闰年 | isleapyear(Date(2024,1,1)) |
daysinmonth(d) | 当月天数 | daysinmonth(d) |
daysinyear(d) | 当年天数 | daysinyear(d) |
isfinite(d) | 是否有限 | isfinite(d) |
调整函数
| 函数 | 用途 | 示例 |
|---|
firstdayofmonth(d) | 月初 | firstdayofmonth(d) |
lastdayofmonth(d) | 月末 | lastdayofmonth(d) |
firstdayofyear(d) | 年初 | firstdayofyear(d) |
lastdayofyear(d) | 年末 | lastdayofyear(d) |
firstdayofweek(d) | 周一 | firstdayofweek(d) |
lastdayofweek(d) | 周日 | lastdayofweek(d) |
周期类型
| 类型 | 含义 | 示例 |
|---|
Year(n) | n年 | d + Year(1) |
Month(n) | n月 | d + Month(6) |
Week(n) | n周 | d + Week(2) |
Day(n) | n天 | d + Day(7) |
Hour(n) | n小时 | dt + Hour(3) |
Minute(n) | n分钟 | dt + Minute(30) |
Second(n) | n秒 | dt + Second(45) |
Millisecond(n) | n毫秒 | dt + Millisecond(100) |
17.8 实际应用:时间序列分析
生成时间序列
using Dates
# 每日数据
dates = Date(2026, 1, 1):Day(1):Date(2026, 12, 31)
values = cumsum(randn(length(dates))) # 随机游走
# 每周聚合
function weekly_average(dates, values)
weeks = Dict{Date, Vector{Float64}}()
for (d, v) in zip(dates, values)
week_start = d - Day(Dates.dayofweek(d) - 1)
push!(get!(weeks, week_start, Float64[]), v)
end
sorted_weeks = sort(collect(weeks))
return ([w for (w, _) in sorted_weeks],
[mean(vs) for (_, vs) in sorted_weeks])
end
using Statistics
weekly_dates, weekly_vals = weekly_average(dates, values)
println("周平均值数量: $(length(weekly_dates))")
交易日历
# 工作日判断
is_workday(d::Date) = Dates.dayofweek(d) <= 5
# 计算交易日
function trading_days(start::Date, stop::Date)
return filter(is_workday, start:Day(1):stop)
end
# N个交易日后
function add_trading_days(d::Date, n::Int)
current = d
added = 0
while added < n
current += Day(1)
if is_workday(current)
added += 1
end
end
return current
end
start = Date(2026, 1, 1)
result = add_trading_days(start, 20)
println("20个交易日后: $result")
日期区间统计
function monthly_stats(dates, values)
monthly = Dict{Tuple{Int,Int}, Vector{Float64}}()
for (d, v) in zip(dates, values)
key = (year(d), month(d))
push!(get!(monthly, key, Float64[]), v)
end
for (ym, vals) in sort(collect(monthly))
println("$(ym[1])-$(lpad(ym[2], 2, '0')): " *
"均值=$(round(mean(vals), digits=2)), " *
"标准差=$(round(std(vals), digits=2))")
end
end
17.9 扩展阅读
17.10 本章小结
| 主题 | 要点 |
|---|
| 三种类型 | Date(日)、DateTime(毫秒)、Time(纳秒) |
| 解析格式化 | dateformat"yyyy-mm-dd" 自定义格式 |
| 日期运算 | Day/Month/Year 类型安全 |
| 时区 | TimeZones.jl 的 ZonedDateTime |
| 日期范围 | start:step:stop 生成序列 |
| 组件提取 | year/month/day/hour 等 |
| 性能计时 | @time/@elapsed/BenchmarkTools |