date 是一个功能强大的Linux命令,用于显示和设置系统的日期和时间。它不仅可以显示当前时间,还可以格式化输出、计算日期、转换时间戳,是系统管理和脚本编程中不可或缺的工具。
date [选项]... [+格式]
date [选项] [MMDDhhmm[[CC]YY][.ss]]
| 选项 | 说明 |
|---|---|
-d, --date=STRING |
显示指定字符串描述的时间,而不是当前时间 |
-s, --set=STRING |
设置系统时间为指定时间 |
-u, --utc, --universal |
显示或设置UTC(协调世界时)时间 |
-r, --reference=FILE |
显示指定文件的最后修改时间 |
-R, --rfc-email |
以RFC 5322格式输出日期 |
--rfc-3339=FMT |
以RFC 3339格式输出日期 |
-I, --iso-8601[=FMT] |
以ISO 8601格式输出日期 |
--help |
显示帮助信息 |
--version |
显示版本信息 |
date命令支持丰富的格式控制符,可以自定义输出格式:
| 控制符 | 说明 | 示例输出 |
|---|---|---|
%Y |
四位数的年份 | 2024 |
%y |
两位数的年份 | 24 |
%m |
月份(01-12) | 12 |
%d |
日(01-31) | 15 |
%H |
小时(00-23) | 14 |
%I |
小时(01-12) | 02 |
%M |
分钟(00-59) | 30 |
%S |
秒(00-60) | 45 |
%A |
完整的星期名 | Monday |
%a |
缩写的星期名 | Mon |
%B |
完整的月份名 | December |
%b |
缩写的月份名 | Dec |
%p |
AM 或 PM | PM |
%Z |
时区缩写 | CST |
%z |
时区偏移(+hhmm) | +0800 |
%j |
一年中的第几天(001-366) | 350 |
%U |
一年中的第几周(周日为一周的开始) | 50 |
%W |
一年中的第几周(周一为一周的开始) | 50 |
%w |
星期几(0=周日,6=周六) | 1 |
%s |
自1970-01-01 00:00:00 UTC以来的秒数(时间戳) | 1702607400 |
%n |
换行符 | |
%t |
制表符 | |
%% |
百分号字符 | % |
# 显示当前日期和时间
date
# 显示UTC时间
date -u
# 显示当前时间戳
date +%s
# 显示年月日
date +"%Y-%m-%d"
# 显示完整日期时间
date +"%Y-%m-%d %H:%M:%S"
# 显示星期几
date +"%A"
# 显示一年中的第几天
date +"%j"
# 显示时区
date +"%Z"
# 组合多个格式
date +"当前时间: %Y年%m月%d日 %H时%M分%S秒"
# 显示明天的日期
date -d "tomorrow"
# 显示昨天的日期
date -d "yesterday"
# 显示下周的日期
date -d "next week"
# 显示上个月的日期
date -d "last month"
# 显示指定天数的日期
date -d "3 days"
date -d "2 weeks"
date -d "1 month"
date -d "1 year"
# 设置系统日期和时间(需要root权限)
sudo date -s "2024-12-15 14:30:00"
# 设置系统时间
sudo date -s "14:30:00"
# 设置系统日期
sudo date -s "2024-12-15"
# 通过指定字符串设置
sudo date --set="next Friday"
# 3天后的日期
date -d "+3 days"
# 2周前的日期
date -d "-2 weeks"
# 1个月后的日期
date -d "+1 month"
# 1年后的日期
date -d "+1 year"
# 复杂的日期计算
date -d "+1 year 2 months 3 days"
date -d "next Monday + 2 weeks"
# 显示本月最后一天
date -d "$(date +%Y-%m-01) +1 month -1 day"
# 显示本月第一天
date -d "$(date +%Y-%m-01)"
# 显示下周一
date -d "next Monday"
# 显示本月最后一个星期五
date -d "last Friday"
# 获取当前时间戳
timestamp=$(date +%s)
echo "当前时间戳: $timestamp"
# 将时间戳转换为日期
date -d @1702607400
date -d @1702607400 +"%Y-%m-%d %H:%M:%S"
# 将日期转换为时间戳
date -d "2024-12-15 14:30:00" +%s
# 将时间戳转换为指定格式
date -d @1702607400 +"北京时间: %Y年%m月%d日 %H:%M:%S"
# 计算24小时前的时间戳
timestamp_24h_ago=$(date -d "24 hours ago" +%s)
echo "24小时前的时间戳: $timestamp_24h_ago"
# 计算7天后的时间戳
timestamp_7d_later=$(date -d "+7 days" +%s)
echo "7天后的时间戳: $timestamp_7d_later"
# 计算两个时间戳的差值
start_timestamp=1702607400
end_timestamp=1702693800
difference=$((end_timestamp - start_timestamp))
echo "时间差: $difference 秒"
echo "时间差: $((difference / 3600)) 小时"
# 显示文件的最后修改时间
date -r /etc/passwd
# 显示文件的最后修改时间(自定义格式)
date -r /etc/passwd +"%Y-%m-%d %H:%M:%S"
# 显示目录的修改时间
date -r /home
# 检查文件是否在今天修改过
file_mod_time=$(date -r /var/log/syslog +%s)
today_start=$(date -d "today 00:00:00" +%s)
if [ $file_mod_time -gt $today_start ]; then
echo "syslog文件今天被修改过"
fi
# 创建一个以当前时间戳命名的文件
timestamp=$(date +%s)
touch "backup_${timestamp}.tar.gz"
# 创建以日期格式命名的文件
date_str=$(date +"%Y%m%d_%H%M%S")
touch "log_${date_str}.txt"
# 备份文件,保持原时间戳
cp -p source_file "backup_$(date +%Y%m%d).txt"
# RFC 5322格式(电子邮件标准)
date -R
# RFC 3339格式
date --rfc-3339=seconds
date --rfc-3339=date
date --rfc-3339=ns
# ISO 8601格式
date -I
date -Iseconds
date -Iminutes
date -Idate
date -Ihours
# 完整ISO 8601格式
date +"%Y-%m-%dT%H:%M:%S%:z"
#!/bin/bash
# log_with_timestamp.sh - 带时间戳的日志
LOG_FILE="/var/log/myapp_$(date +%Y%m%d).log"
log_message() {
local message="$1"
local timestamp=$(date +"%Y-%m-%d %H:%M:%S")
echo "[$timestamp] $message" >> "$LOG_FILE"
}
# 使用示例
log_message "应用程序启动"
log_message "连接到数据库"
log_message "处理用户请求"
log_message "应用程序关闭"
echo "日志已写入: $LOG_FILE"
tail -5 "$LOG_FILE"
#!/bin/bash
# backup_with_date.sh - 按日期备份
BACKUP_DIR="/backup"
DATE_PREFIX=$(date +"%Y%m%d_%H%M%S")
SOURCE_DIR="/var/www/html"
BACKUP_FILE="${BACKUP_DIR}/backup_${DATE_PREFIX}.tar.gz"
echo "开始备份..."
echo "源目录: $SOURCE_DIR"
echo "备份文件: $BACKUP_FILE"
# 创建备份
tar -czf "$BACKUP_FILE" "$SOURCE_DIR"
if [ $? -eq 0 ]; then
BACKUP_SIZE=$(du -h "$BACKUP_FILE" | cut -f1)
echo "备份成功"
echo "文件大小: $BACKUP_SIZE"
echo "备份时间: $(date)"
# 记录备份日志
echo "$(date) - 备份完成: $BACKUP_FILE ($BACKUP_SIZE)" >> "${BACKUP_DIR}/backup.log"
else
echo "备份失败"
exit 1
fi
# 清理7天前的备份
find "$BACKUP_DIR" -name "backup_*.tar.gz" -mtime +7 -delete
echo "已清理7天前的旧备份"
#!/bin/bash
# monitor_execution_time.sh - 监控脚本执行时间
# 记录开始时间
start_time=$(date +%s)
echo "脚本开始执行: $(date)"
# 模拟耗时操作
echo "执行任务..."
sleep 3
echo "任务1完成"
sleep 2
echo "任务2完成"
# 记录结束时间
end_time=$(date +%s)
execution_time=$((end_time - start_time))
echo "脚本结束执行: $(date)"
echo "总执行时间: ${execution_time}秒"
echo "总执行时间: $((execution_time / 60))分$((execution_time % 60))秒"
#!/bin/bash
# scheduler_check.sh - 检查是否在特定时间运行
CURRENT_HOUR=$(date +%H)
CURRENT_MINUTE=$(date +%M)
CURRENT_DAY=$(date +%u) # 1=周一, 7=周日
echo "当前时间: $(date +"%Y-%m-%d %H:%M:%S")"
echo "当前小时: $CURRENT_HOUR"
echo "当前分钟: $CURRENT_MINUTE"
echo "当前星期: $CURRENT_DAY"
# 检查是否在工作时间(9:00-18:00)
if [ $CURRENT_HOUR -ge 9 ] && [ $CURRENT_HOUR -lt 18 ]; then
echo "工作时间,执行任务..."
# 执行工作时间的任务
else
echo "非工作时间,跳过任务..."
fi
# 检查是否在周末
if [ $CURRENT_DAY -eq 6 ] || [ $CURRENT_DAY -eq 7 ]; then
echo "周末,执行备份..."
# 执行周末备份任务
fi
# 特定时间执行
if [ "$CURRENT_HOUR:$CURRENT_MINUTE" = "02:00" ]; then
echo "凌晨2点,执行数据库清理..."
# 执行夜间维护任务
fi
#!/bin/bash
# generate_time_html.sh - 生成带时间的HTML页面
HTML_FILE="/var/www/html/time.html"
CURRENT_TIME=$(date +"%Y年%m月%d日 %H时%M分%S秒")
WEEKDAYS=("星期日" "星期一" "星期二" "星期三" "星期四" "星期五" "星期六")
WEEKDAY=${WEEKDAYS[$(date +%w)]}
cat > "$HTML_FILE" << EOF
当前时间
服务器当前时间
$CURRENT_TIME
$WEEKDAY
页面生成时间: $(date +"%Y-%m-%d %H:%M:%S")
EOF
echo "HTML页面已生成: $HTML_FILE"
#!/bin/bash
# check_cert_expiry.sh - 检查SSL证书过期时间
DOMAIN="example.com"
CERT_FILE="/etc/ssl/certs/${DOMAIN}.crt"
if [ ! -f "$CERT_FILE" ]; then
echo "证书文件不存在: $CERT_FILE"
exit 1
fi
# 获取证书过期时间
EXPIRY_DATE=$(openssl x509 -enddate -noout -in "$CERT_FILE" | cut -d= -f2)
EXPIRY_TIMESTAMP=$(date -d "$EXPIRY_DATE" +%s)
CURRENT_TIMESTAMP=$(date +%s)
# 计算剩余天数
DAYS_LEFT=$(( (EXPIRY_TIMESTAMP - CURRENT_TIMESTAMP) / 86400 ))
echo "域名: $DOMAIN"
echo "证书过期时间: $EXPIRY_DATE"
echo "当前时间: $(date)"
echo "剩余天数: $DAYS_LEFT 天"
# 警告检查
if [ $DAYS_LEFT -le 30 ]; then
echo "警告: 证书即将在 $DAYS_LEFT 天后过期!"
# 发送告警通知
elif [ $DAYS_LEFT -le 0 ]; then
echo "紧急: 证书已过期!"
# 发送紧急通知
fi
#!/bin/bash
# birthday_reminder.sh - 生日提醒
BIRTHDAY_FILE="/home/user/birthdays.txt"
TODAY_MD=$(date +"%m-%d")
echo "=== 生日提醒检查 ==="
echo "检查日期: $(date +"%Y-%m-%d")"
echo ""
while IFS=, read -r name birthday; do
# 清理空格
name=$(echo "$name" | xargs)
birthday=$(echo "$birthday" | xargs)
# 提取生日月份和日
birthday_md=$(date -d "$birthday" +"%m-%d" 2>/dev/null)
if [ "$birthday_md" = "$TODAY_MD" ]; then
# 计算年龄
birth_year=$(date -d "$birthday" +%Y)
current_year=$(date +%Y)
age=$((current_year - birth_year))
echo "🎂 今天 ($(date +"%m月%d日")) 是 $name 的生日!"
echo " 生日: $birthday"
echo " 年龄: $age 岁"
echo ""
# 发送祝福(示例:发送邮件)
# echo "生日快乐,$name!" | mail -s "生日祝福" user@example.com
fi
done < "$BIRTHDAY_FILE"
if [ -z "$found" ]; then
echo "今天没有生日提醒"
fi
# 显示系统当前时区
timedatectl
# 显示所有可用时区
timedatectl list-timezones
# 转换时区
TZ='America/New_York' date
TZ='Asia/Tokyo' date
TZ='Europe/London' date
# 比较不同时区时间
echo "本地时间: $(date)"
echo "纽约时间: $(TZ='America/New_York' date)"
echo "东京时间: $(TZ='Asia/Tokyo' date)"
echo "伦敦时间: $(TZ='Europe/London' date)"
date: cannot set date: Operation not permitted
解决方案:
# 使用sudo设置时间
sudo date -s "2024-12-15 14:30:00"
# 或使用timedatectl(推荐)
sudo timedatectl set-time "2024-12-15 14:30:00"
date: invalid date '错误的日期'
解决方案:
# 使用标准格式
date -d "2024-12-15 14:30:00"
# 或使用自然语言
date -d "next Monday"
date -d "tomorrow 14:30"
# 查看支持的日期格式
man date
# 显示的时间时区不正确
解决方案:
# 查看当前时区
timedatectl
# 设置时区
sudo timedatectl set-timezone Asia/Shanghai
# 临时使用时区
TZ='Asia/Shanghai' date
# 夏令时转换导致的时间问题
解决方案:
# 使用UTC时间避免夏令时问题
date -u
# 或使用时区数据库
TZ='America/New_York' date
# 确保系统时区数据库是最新的
sudo apt-get install tzdata # Debian/Ubuntu
sudo yum install tzdata # RHEL/CentOS
| 命令 | 说明 |
|---|---|
timedatectl |
systemd的时间日期管理工具 |
hwclock |
硬件时钟管理工具 |
cal |
显示日历 |
touch |
修改文件时间戳 |
stat |
显示文件状态,包括时间戳 |
sleep |
暂停指定时间 |
at |
定时执行任务 |
crontab |
定时任务管理 |
tzselect |
时区选择工具 |
ntpdate |
从NTP服务器同步时间 |
#!/bin/bash
# performance_test.sh - 使用date进行性能测试
echo "开始性能测试..."
echo "======================"
# 记录开始时间
start_time=$(date +%s.%N)
# 执行要测试的命令
for i in {1..1000}; do
echo "Test $i" > /dev/null
done
# 记录结束时间
end_time=$(date +%s.%N)
# 计算执行时间
execution_time=$(echo "$end_time - $start_time" | bc)
echo "执行时间: ${execution_time}秒"
echo "平均每次: $(echo "$execution_time / 1000" | bc -l)秒"
# 基于时间戳的唯一ID
unique_id=$(date +"%Y%m%d%H%M%S%N")
echo "唯一ID: $unique_id"
# 基于时间和随机数的ID
timestamp=$(date +%s)
random=$RANDOM
unique_id="${timestamp}_${random}"
echo "唯一ID: $unique_id"
# 用于临时文件的唯一名称
temp_file="/tmp/temp_$(date +%s%N).tmp"
echo "临时文件: $temp_file"
#!/bin/bash
# calculate_time_diff.sh - 计算时间间隔
# 记录开始时间
start_time=$(date +"%Y-%m-%d %H:%M:%S")
start_timestamp=$(date -d "$start_time" +%s)
echo "任务开始: $start_time"
# 模拟任务执行
sleep 3
# 记录结束时间
end_time=$(date +"%Y-%m-%d %H:%M:%S")
end_timestamp=$(date -d "$end_time" +%s)
echo "任务结束: $end_time"
# 计算时间差
time_diff=$((end_timestamp - start_timestamp))
# 转换为可读格式
days=$((time_diff / 86400))
hours=$(( (time_diff % 86400) / 3600 ))
minutes=$(( (time_diff % 3600) / 60 ))
seconds=$((time_diff % 60))
echo "执行时间: ${time_diff}秒"
echo "执行时间: ${days}天 ${hours}小时 ${minutes}分 ${seconds}秒"
| 用途 | 命令示例 |
|---|---|
| 显示当前时间 | date |
| 显示当前时间戳 | date +%s |
| 显示年月日 | date +"%Y-%m-%d" |
| 显示完整时间 | date +"%Y-%m-%d %H:%M:%S" |
| 显示明天日期 | date -d "tomorrow" |
| 显示昨天日期 | date -d "yesterday" |
| 显示下周日期 | date -d "next week" |
| 显示UTC时间 | date -u |
| 显示文件修改时间 | date -r filename |
| 设置系统时间 | sudo date -s "2024-12-15 14:30:00" |
| 时间戳转日期 | date -d @1702607400 |
| 日期转时间戳 | date -d "2024-12-15" +%s |
| RFC 5322格式 | date -R |
| ISO 8601格式 | date -I |