linux cal命令

提示:cal命令用于在终端中显示日历,支持显示特定月份、年份以及多种格式的日历。

命令简介

cal 是Linux系统中用于显示日历的命令行工具。它可以显示当前月份的日历,也可以显示指定月份或年份的日历。cal命令简单实用,特别适合在服务器环境下快速查看日期信息,无需离开终端界面。

命令语法

cal [选项] [[月份] 年份]

常用选项

选项 说明
-1, --one 显示单月日历(默认)
-3, --three 显示前一个月、当前月、下一个月的日历
-s, --sunday 以周日作为一周的第一天
-m, --monday 以周一作为一周的第一天
-j, --julian 显示儒略历(从1月1日开始的天数)
-y, --year 显示整年的日历
-Y, --twelve 显示未来12个月的日历
-w, --week 显示周数(ISO 8601标准)
-n 月数 显示指定月数的日历
-A 月数 在当前日历后显示指定月数的日历
-B 月数 在当前日历前显示指定月数的日历
-h, --help 显示帮助信息
-V, --version 显示版本信息

使用示例

示例1:基本使用

显示当前月份的日历:

# 显示当前月份日历(默认)
cal

# 显示当前月份(显式使用-1选项)
cal -1

# 示例输出:
#      December 2024
# Su Mo Tu We Th Fr Sa
#  1  2  3  4  5  6  7
#  8  9 10 11 12 13 14
# 15 16 17 18 19 20 21
# 22 23 24 25 26 27 28
# 29 30 31

示例2:显示三个月日历

显示前一个月、当前月和下一个月的日历:

# 显示三个月的日历
cal -3

# 使用长选项
cal --three

# 示例输出:
#    November 2024         December 2024          January 2025
# Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa  Su Mo Tu We Th Fr Sa
#                 1  2   1  2  3  4  5  6  7            1  2  3  4
#  3  4  5  6  7  8  9   8  9 10 11 12 13 14   5  6  7  8  9 10 11
# 10 11 12 13 14 15 16  15 16 17 18 19 20 21  12 13 14 15 16 17 18
# 17 18 19 20 21 22 23  22 23 24 25 26 27 28  19 20 21 22 23 24 25
# 24 25 26 27 28 29 30  29 30 31              26 27 28 29 30 31

示例3:显示特定月份和年份

显示指定月份和年份的日历:

# 显示2024年12月的日历
cal 12 2024

# 显示当前年份的7月日历
cal 7

# 显示历史上的重要日期
cal 7 1969    # 阿波罗11号登月
cal 1 2000    # 新千年
cal 9 2001    # 9/11事件

示例4:显示整年日历

显示指定年份的全部月份日历:

# 显示当前年份的完整日历
cal -y

# 显示指定年份的完整日历
cal -y 2025
cal 2025

# 示例输出(部分):
#                              2025
#
#       January               February               March
# Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa   Su Mo Tu We Th Fr Sa
#           1  2  3  4                      1                      1
#  5  6  7  8  9 10 11    2  3  4  5  6  7  8    2  3  4  5  6  7  8
# 12 13 14 15 16 17 18    9 10 11 12 13 14 15    9 10 11 12 13 14 15
# 19 20 21 22 23 24 25   16 17 18 19 20 21 22   16 17 18 19 20 21 22
# 26 27 28 29 30 31      23 24 25 26 27 28      23 24 25 26 27 28 29
#                                               30 31

示例5:周起始日设置

设置一周的第一天为周日或周一:

# 以周日作为一周的第一天(默认)
cal -s
cal --sunday

# 以周一作为一周的第一天
cal -m
cal --monday

# 示例输出(周一作为第一天):
#     December 2024
# Mo Tu We Th Fr Sa Su
#                    1
#  2  3  4  5  6  7  8
#  9 10 11 12 13 14 15
# 16 17 18 19 20 21 22
# 23 24 25 26 27 28 29
# 30 31

示例6:儒略历显示

显示儒略历(从1月1日开始计数的天数):

# 显示当前月份的儒略历
cal -j

# 显示2024年12月的儒略历
cal -j 12 2024

# 示例输出:
#        December 2024
#  Su  Mo  Tu  We  Th  Fr  Sa
# 336 337 338 339 340 341 342
# 343 344 345 346 347 348 349
# 350 351 352 353 354 355 356
# 357 358 359 360 361 362 363
# 364 365 366

示例7:显示周数和多个月份

# 显示周数(ISO 8601标准)
cal -w
# 或
cal --week

# 显示未来12个月的日历
cal -Y
cal --twelve

# 显示指定数量的月份
cal -n 6        # 显示6个月
cal -A 2        # 显示当前月和后2个月
cal -B 1 -A 2   # 显示前1个月、当前月和后2个月

# 显示包含周数的三个月日历
cal -3 -w

示例8:高级用法和组合选项

# 组合选项:显示以周一为起始的三个月日历
cal -m -3

# 显示当前年份的儒略历
cal -j -y

# 显示2025年以周日为起始的日历
cal -s 2025

# 显示特定月份范围
seq 1 12 | xargs -I {} cal {} 2024  # 显示2024年所有月份

# 在脚本中获取特定日期是星期几
cal 12 2024 | awk 'NR>2{print $1}' | grep -n "25" | head -1

月份名称和缩写

cal命令支持多种语言环境下的月份名称:

# 查看当前语言环境
echo $LANG

# 设置不同语言环境查看日历
LANG=zh_CN.UTF-8 cal    # 中文
LANG=ja_JP.UTF-8 cal    # 日文
LANG=fr_FR.UTF-8 cal    # 法语
LANG=de_DE.UTF-8 cal    # 德语
LANG=es_ES.UTF-8 cal    # 西班牙语

# 临时设置英文环境
LANG=C cal

支持的年份范围

cal命令支持显示公元1年到9999年的日历:

# 显示最早年份的日历
cal 1
# 输出:公元1年1月

# 显示最晚年份的日历
cal 9999
# 输出:公元9999年12月

# 显示历史重要年份
cal 1066   # 诺曼征服英格兰
cal 1492   # 哥伦布发现新大陆
cal 1776   # 美国独立宣言
cal 1914   # 第一次世界大战开始
cal 1945   # 第二次世界大战结束

在脚本中使用cal命令

#!/bin/bash

# 脚本1:检查今天是否是周五
TODAY=$(date +%d)
if cal | grep -E "(^| )$TODAY( |$)" | grep -q "Fr"; then
    echo "今天是周五!🎉"
else
    echo "今天不是周五。"
fi

# 脚本2:计算某个月有多少天
get_month_days() {
    local month=$1
    local year=$2
    cal "$month" "$year" | awk 'NF {DAYS=$NF} END {print DAYS}'
}

# 使用示例
days_in_dec=$(get_month_days 12 2024)
echo "2024年12月有 $days_in_dec 天"

# 脚本3:生成月历报告
generate_calendar_report() {
    echo "=== 月历报告 ==="
    echo "生成时间: $(date)"
    echo ""
    cal -3
    echo ""
    echo "当前日期: $(date '+%Y年%m月%d日 %A')"
}

# 保存报告到文件
generate_calendar_report > /tmp/calendar_report.txt

# 脚本4:查找特定日期的星期几
find_weekday() {
    local day=$1
    local month=$2
    local year=$3
    cal "$month" "$year" | awk -v day="$day" '
        NR>2 {
            for(i=1;i<=NF;i++) {
                if($i == day) {
                    # 获取列索引对应的星期
                    if(NR==3) {print "星期" (i==1?"日":i==2?"一":i==3?"二":i==4?"三":i==5?"四":i==6?"五":"六")}
                    exit
                }
            }
        }
    '
}

# 使用示例
weekday=$(find_weekday 25 12 2024)
echo "2024年圣诞节是: $weekday"

与date命令结合使用

# 显示今天在日历中的位置
today=$(date +%d)
cal | sed "s/\(^\|[[:space:]]\)\($today\)\([[:space:]]\|$\)/\1**\2**\3/"

# 显示当前月份并高亮今天
cal | awk -v today="$(date +%d)" '{
    for(i=1;i<=NF;i++) {
        if($i == today && NR>2) {
            $i = "\033[1;31m" $i "\033[0m"
        }
    }
    print
}'

# 使用日期计算
echo "30天后的日期:"
date -d "+30 days" "+%Y-%m-%d"
cal $(date -d "+30 days" "+%m %Y")

特殊日期显示

# 显示带有节假日标记的日历(需要自定义)
mark_holiday() {
    cal | sed -e 's/ 25 /🎄/' -e 's/ 1 /🎆/' -e 's/ 14 /💝/'
}

# 显示当月的工作日数量
count_weekdays() {
    cal | awk '
    NR>2 {
        for(i=1;i<=NF;i++) {
            if($i ~ /^[0-9]+$/) {
                # 假设周一至周五是工作日(周一为第一天时)
                if(i>=2 && i<=6) count++
            }
        }
    }
    END {print "本月工作日天数:", count}'
}

# 显示当月的周末日期
get_weekends() {
    echo "本月周末日期:"
    cal | awk '
    NR>2 {
        for(i=1;i<=NF;i++) {
            if($i ~ /^[0-9]+$/) {
                # 假设周六和周日是周末
                if(i==1 || i==7) printf "%s ", $i
            }
        }
        if(NR>2) print ""
    }'
}

注意事项

  1. cal命令的参数顺序是cal [月份] [年份],如果只提供一个数字参数,cal会将其解释为年份
  2. 月份参数可以是1-12的数字,也可以使用月份名称的缩写(如jan、feb等)
  3. 年份参数可以是1-9999之间的数字,公元前的日期不支持
  4. 周起始日的设置(-s/-m)会影响周数的计算
  5. 儒略历显示(-j)从1月1日开始计数,1月1日是第1天
  6. 不同Linux发行版的cal命令可能有一些细微差异,某些选项可能不可用
  7. cal命令的输出格式可能受终端宽度影响,如果终端太窄,年历可能会显示为多行
  8. cal命令支持旧式语法cal [年份] [月份],但建议使用标准语法

历史趣闻

cal命令的历史可以追溯到UNIX系统的早期版本。一些有趣的日历事实:

  • 1752年9月,英国及其殖民地(包括美国)从儒略历切换到格里历,导致9月2日之后直接跳到9月14日,跳过了11天
  • 1900年不是闰年,但2000年是闰年(能被400整除的世纪年是闰年)
  • 1582年10月4日星期四的第二天是1582年10月15日星期五(格里历改革)
  • 一年中的第13个星期五可能有多达3个

故障排查

# 1. cal命令不存在
# 检查是否安装
which cal
# 安装(如果需要)
# Ubuntu/Debian: sudo apt-get install bsdmainutils
# RHEL/CentOS: sudo yum install util-linux

# 2. 显示乱码
# 检查语言环境
locale
# 设置UTF-8编码
export LANG=en_US.UTF-8

# 3. 月份或年份参数无效
# 检查参数范围
cal 13 2024    # 错误:月份无效
cal 12 10000   # 错误:年份超出范围

# 4. 输出格式问题
# 使用col命令处理格式
cal | col -b    # 去除退格和特殊字符

# 5. 获取特定版本的cal
cal --version
# 或
whatis cal

相关命令

  • date - 显示或设置系统日期和时间
  • timedatectl - systemd系统的时间日期控制工具
  • ntpdate - 通过NTP设置系统时间
  • hwclock - 硬件时钟管理工具
  • tzselect - 时区选择工具
  • calendar - 提醒服务,显示即将到来的事件
  • gcal - GNU日历工具,功能更强大