强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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)

BenchmarkTools.jl(推荐)

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 扩展阅读

资源 链接
Julia 官方文档 - Dates https://docs.julialang.org/en/v1/stdlib/Dates/
TimeZones.jl https://github.com/JuliaTime/TimeZones.jl
BusinessDays.jl https://github.com/JuliaFinance/BusinessDays.jl
Dates 速查表 https://docs.julialang.org/en/v1/stdlib/Dates/#Dates.format

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