Comprehensive Reference Guide β Formatting, parsing, arithmetic, timezones, and practical date operations
The date command is the primary tool for displaying and manipulating dates and times in Bash. It supports extensive formatting options, date arithmetic, parsing, and timezone conversionsβessential for log rotation, backup scheduling, report generation, and system administration tasks.
Display: Format current date/time with date +FORMAT
Parse: Convert strings to dates with date -d "STRING"
Arithmetic: Add/subtract time with date -d "+1 day"
Timezone: Convert between zones with TZ=zone date
| Specifier | Description | Example |
|---|---|---|
%Y | 4-digit year | 2025 |
%y | 2-digit year | 25 |
%m | Month (01-12) | 11 |
%d | Day of month (01-31) | 18 |
%e | Day of month (1-31, space pad) | 18 |
%B | Full month name | November |
%b | Abbreviated month | Nov |
%A | Full weekday name | Tuesday |
%a | Abbreviated weekday | Tue |
%u | Day of week (1-7, Monday=1) | 2 |
%w | Day of week (0-6, Sunday=0) | 2 |
%j | Day of year (001-366) | 322 |
%U | Week number (Sunday start) | 46 |
%W | Week number (Monday start) | 46 |
%V | ISO week number | 47 |
| Specifier | Description | Example |
|---|---|---|
%H | Hour (00-23) | 14 |
%I | Hour (01-12) | 02 |
%M | Minute (00-59) | 30 |
%S | Second (00-59) | 45 |
%N | Nanoseconds (000000000-999999999) | 123456789 |
%p | AM/PM (uppercase) | PM |
%P | am/pm (lowercase) | pm |
%s | Unix epoch (seconds since 1970) | 1731958245 |
%Z | Timezone abbreviation | EST |
%z | Timezone offset | -0500 |
%:z | Timezone offset with colon | -05:00 |
| Specifier | Equivalent | Example |
|---|---|---|
%F | %Y-%m-%d | 2025-11-18 |
%T | %H:%M:%S | 14:30:45 |
%D | %m/%d/%y | 11/18/25 |
%R | %H:%M | 14:30 |
%r | %I:%M:%S %p | 02:30:45 PM |
%c | Locale date/time | Tue Nov 18 14:30:45 2025 |
%x | Locale date | 11/18/2025 |
%X | Locale time | 14:30:45 |
date +%Y-%m-%d β 2025-11-18
date +%H:%M:%S β 14:30:45
date +%s β 1731958245 (epoch)
date -d "tomorrow" β Tomorrow's date
date -d @1731958245 β From epoch
Essential date formats for system administrationβlogs, backups, and reports.
#!/bin/bash
# Date formatting for various purposes
echo "=== Standard Formats ==="
echo "Default: $(date)"
echo "ISO 8601: $(date +%Y-%m-%dT%H:%M:%S%z)"
echo "ISO Date: $(date +%Y-%m-%d)"
echo "ISO Time: $(date +%H:%M:%S)"
echo "RFC 2822: $(date -R)"
echo "UTC: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
echo ""
echo "=== Regional Formats ==="
echo "US Date: $(date +%m/%d/%Y)"
echo "US Long: $(date '+%B %d, %Y')"
echo "EU Date: $(date +%d/%m/%Y)"
echo "EU Long: $(date '+%d %B %Y')"
echo ""
echo "=== Filename-Safe Formats ==="
echo "Daily backup: backup-$(date +%Y-%m-%d).tar.gz"
echo "Timestamped: log-$(date +%Y%m%d_%H%M%S).txt"
echo "Hourly: data-$(date +%Y-%m-%d_%H).csv"
echo "Weekly: report-$(date +%Y-W%W).pdf"
echo "Monthly: archive-$(date +%Y-%m).zip"
echo ""
echo "=== Log Entry Formats ==="
# Syslog style
echo "$(date '+%b %d %H:%M:%S') $(hostname) myapp[$$]: Message"
# ISO style (recommended)
echo "[$(date '+%Y-%m-%d %H:%M:%S')] INFO: Application started"
# With milliseconds
echo "[$(date '+%Y-%m-%d %H:%M:%S.%3N')] DEBUG: Detailed message"
echo ""
echo "=== Report Headers ==="
echo "Generated: $(date '+%A, %B %e, %Y at %I:%M %p %Z')"
echo "Timestamp: $(date '+%Y-%m-%d %H:%M:%S %Z')"
echo ""
echo "=== Special Values ==="
echo "Epoch: $(date +%s)"
echo "Nanoseconds: $(date +%N)"
echo "Day of year: $(date +%j) / 365"
echo "Week number: $(date +%W) / 52"
echo "Quarter: Q$(( ($(date +%-m) - 1) / 3 + 1 ))"
Calculating future and past dates for scheduling, retention, and planning.
#!/bin/bash
# Date arithmetic with -d flag
echo "=== Reference Point ==="
echo "Today: $(date '+%Y-%m-%d %A')"
echo ""
echo "=== Adding Time ==="
echo "Tomorrow: $(date -d 'tomorrow' '+%Y-%m-%d %A')"
echo "+1 day: $(date -d '+1 day' '+%Y-%m-%d')"
echo "+3 days: $(date -d '+3 days' '+%Y-%m-%d')"
echo "+1 week: $(date -d '+1 week' '+%Y-%m-%d')"
echo "+2 weeks: $(date -d '+2 weeks' '+%Y-%m-%d')"
echo "+1 month: $(date -d '+1 month' '+%Y-%m-%d')"
echo "+3 months: $(date -d '+3 months' '+%Y-%m-%d')"
echo "+1 year: $(date -d '+1 year' '+%Y-%m-%d')"
echo ""
echo "=== Subtracting Time ==="
echo "Yesterday: $(date -d 'yesterday' '+%Y-%m-%d %A')"
echo "-1 day: $(date -d '-1 day' '+%Y-%m-%d')"
echo "-7 days: $(date -d '-7 days' '+%Y-%m-%d')"
echo "-30 days: $(date -d '-30 days' '+%Y-%m-%d')"
echo "-3 months: $(date -d '-3 months' '+%Y-%m-%d')"
echo "-1 year: $(date -d '-1 year' '+%Y-%m-%d')"
echo ""
echo "=== Time Arithmetic ==="
echo "Now: $(date '+%H:%M:%S')"
echo "+2 hours: $(date -d '+2 hours' '+%H:%M:%S')"
echo "-30 minutes: $(date -d '-30 minutes' '+%H:%M:%S')"
echo "+90 seconds: $(date -d '+90 seconds' '+%H:%M:%S')"
echo ""
echo "=== Combined Arithmetic ==="
echo "+1 day 3 hours: $(date -d '+1 day +3 hours' '+%Y-%m-%d %H:%M')"
echo "tomorrow noon: $(date -d 'tomorrow 12:00' '+%Y-%m-%d %H:%M')"
echo "next monday 9am: $(date -d 'next monday 09:00' '+%Y-%m-%d %H:%M')"
echo ""
echo "=== From Specific Date ==="
base_date="2025-01-15"
echo "Base: $base_date"
echo "+30 days: $(date -d "$base_date +30 days" '+%Y-%m-%d')"
echo "+6 months: $(date -d "$base_date +6 months" '+%Y-%m-%d')"
echo "End of month: $(date -d "$base_date +1 month -1 day" '+%Y-%m-%d')"
echo ""
echo "=== Practical: Retention Dates ==="
echo "Delete files older than:"
echo " 7 days: $(date -d '-7 days' '+%Y-%m-%d')"
echo " 30 days: $(date -d '-30 days' '+%Y-%m-%d')"
echo " 90 days: $(date -d '-90 days' '+%Y-%m-%d')"
echo " 1 year: $(date -d '-1 year' '+%Y-%m-%d')"
Converting between date formats and parsing various input strings.
#!/bin/bash
# Date parsing and format conversion
echo "=== Parse Various Input Formats ==="
inputs=(
"November 18, 2025"
"Nov 18, 2025"
"18 Nov 2025"
"11/18/2025"
"2025-11-18"
"2025/11/18"
"18-Nov-2025"
)
for input in "${inputs[@]}"; do
parsed=$(date -d "$input" '+%Y-%m-%d' 2>/dev/null)
if [[ $? -eq 0 ]]; then
printf "%-20s β %s\n" "$input" "$parsed"
else
printf "%-20s β FAILED\n" "$input"
fi
done
echo ""
echo "=== Parse with Time ==="
echo "'2025-11-18 14:30': $(date -d '2025-11-18 14:30' '+%Y-%m-%d %H:%M:%S')"
echo "'Nov 18 2:30 PM': $(date -d 'Nov 18 2:30 PM' '+%Y-%m-%d %H:%M:%S')"
echo "'2025-11-18T14:30:00': $(date -d '2025-11-18T14:30:00' '+%Y-%m-%d %H:%M:%S')"
echo ""
echo "=== Convert Between Formats ==="
# US to ISO
us_date="11/18/2025"
iso=$(date -d "$us_date" '+%Y-%m-%d')
echo "US to ISO: $us_date β $iso"
# ISO to verbose
iso_date="2025-11-18"
verbose=$(date -d "$iso_date" '+%A, %B %d, %Y')
echo "ISO to verbose: $iso_date β $verbose"
# Short to long
short="Nov 18"
long=$(date -d "$short" '+%B %d, %Y')
echo "Short to long: $short β $long"
echo ""
echo "=== Epoch Conversions ==="
# Current to epoch
now_epoch=$(date +%s)
echo "Now to epoch: $(date '+%Y-%m-%d %H:%M:%S') β $now_epoch"
# Epoch to human
echo "Epoch to human: 1731958245 β $(date -d @1731958245 '+%Y-%m-%d %H:%M:%S')"
# String to epoch
date_str="2025-12-25 00:00:00"
epoch=$(date -d "$date_str" +%s)
echo "String to epoch: $date_str β $epoch"
echo ""
echo "=== Parse Log Timestamps ==="
# Syslog format
syslog="Nov 18 14:30:45"
parsed=$(date -d "$syslog" '+%Y-%m-%d %H:%M:%S')
echo "Syslog: $syslog β $parsed"
# Apache format (need to adjust)
apache="18/Nov/2025:14:30:45"
adjusted=$(echo "$apache" | sed 's/\// /g; s/:/ /')
parsed=$(date -d "$adjusted" '+%Y-%m-%d %H:%M:%S')
echo "Apache: $apache β $parsed"
echo ""
echo "=== Validate Date Input ==="
validate_date() {
date -d "$1" '+%Y-%m-%d' &>/dev/null
}
test_dates=("2025-11-18" "2025-02-30" "invalid" "13/45/2025")
for d in "${test_dates[@]}"; do
if validate_date "$d"; then
echo "'$d' is VALID"
else
echo "'$d' is INVALID"
fi
done
@ prefix to parse Unix epoch: date -d @1731958245
Computing elapsed time, age, and duration between two dates.
#!/bin/bash
# Calculating time differences
echo "=== Days Between Two Dates ==="
date1="2025-01-01"
date2="2025-11-18"
epoch1=$(date -d "$date1" +%s)
epoch2=$(date -d "$date2" +%s)
diff_secs=$((epoch2 - epoch1))
diff_days=$((diff_secs / 86400))
echo "From: $date1"
echo "To: $date2"
echo "Days: $diff_days"
echo "Weeks: $((diff_days / 7))"
echo "Months (approx): $((diff_days / 30))"
echo ""
echo "=== Time Until Future Date ==="
future="2025-12-25"
now=$(date +%s)
future_epoch=$(date -d "$future" +%s)
until_secs=$((future_epoch - now))
until_days=$((until_secs / 86400))
echo "Days until $future: $until_days"
echo ""
echo "=== Age Calculation ==="
birth_date="1982-06-25"
today=$(date +%s)
birth_epoch=$(date -d "$birth_date" +%s)
age_secs=$((today - birth_epoch))
age_days=$((age_secs / 86400))
age_years=$((age_days / 365))
echo "Birth: $birth_date"
echo "Age: ~$age_years years ($age_days days)"
echo ""
echo "=== Format Duration ==="
format_duration() {
local secs=$1
local days=$((secs / 86400))
local hours=$(( (secs % 86400) / 3600 ))
local mins=$(( (secs % 3600) / 60 ))
local s=$((secs % 60))
if ((days > 0)); then
printf "%dd %dh %dm %ds" $days $hours $mins $s
elif ((hours > 0)); then
printf "%dh %dm %ds" $hours $mins $s
elif ((mins > 0)); then
printf "%dm %ds" $mins $s
else
printf "%ds" $s
fi
}
echo "Duration examples:"
for secs in 45 3661 86400 90061 604800; do
printf "%8d seconds = %s\n" $secs "$(format_duration $secs)"
done
echo ""
echo "=== Working Days Between Dates ==="
count_workdays() {
local start=$1
local end=$2
local count=0
local current=$start
while [[ "$current" < "$end" ]]; do
local dow=$(date -d "$current" +%u)
if ((dow < 6)); then # Mon-Fri
((count++))
fi
current=$(date -d "$current +1 day" +%Y-%m-%d)
done
echo $count
}
start="2025-11-01"
end="2025-11-18"
workdays=$(count_workdays "$start" "$end")
echo "Working days from $start to $end: $workdays"
echo ""
echo "=== Practical: SLA Calculation ==="
ticket_opened="2025-11-18 09:00:00"
ticket_closed="2025-11-18 14:30:45"
open_epoch=$(date -d "$ticket_opened" +%s)
close_epoch=$(date -d "$ticket_closed" +%s)
resolution_secs=$((close_epoch - open_epoch))
resolution_mins=$((resolution_secs / 60))
resolution_hours=$(echo "scale=2; $resolution_secs / 3600" | bc)
echo "Opened: $ticket_opened"
echo "Closed: $ticket_closed"
echo "Resolution time: ${resolution_mins} minutes (${resolution_hours} hours)"
Converting between timezones and displaying times for global teams.
#!/bin/bash
# Timezone operations
echo "=== Current Time in Various Zones ==="
echo "Local: $(date '+%Y-%m-%d %H:%M:%S %Z')"
echo "UTC: $(TZ=UTC date '+%Y-%m-%d %H:%M:%S %Z')"
echo ""
echo "US Timezones:"
echo " Eastern: $(TZ=America/New_York date '+%H:%M %Z')"
echo " Central: $(TZ=America/Chicago date '+%H:%M %Z')"
echo " Mountain: $(TZ=America/Denver date '+%H:%M %Z')"
echo " Pacific: $(TZ=America/Los_Angeles date '+%H:%M %Z')"
echo ""
echo "International:"
echo " London: $(TZ=Europe/London date '+%H:%M %Z')"
echo " Paris: $(TZ=Europe/Paris date '+%H:%M %Z')"
echo " Tokyo: $(TZ=Asia/Tokyo date '+%H:%M %Z')"
echo " Sydney: $(TZ=Australia/Sydney date '+%H:%M %Z')"
echo ""
echo "=== Convert Specific Time Between Zones ==="
# Meeting at 2 PM Eastern - what time elsewhere?
meeting_time="2025-11-18 14:00:00"
meeting_epoch=$(TZ=America/New_York date -d "$meeting_time" +%s)
echo "Meeting: $meeting_time Eastern"
echo ""
echo "Equivalent times:"
for tz in "America/Los_Angeles:Pacific" "America/Chicago:Central" \
"UTC:UTC" "Europe/London:London" "Asia/Tokyo:Tokyo"; do
IFS=':' read -r zone label <<< "$tz"
converted=$(TZ=$zone date -d @$meeting_epoch '+%H:%M %Z (%Y-%m-%d)')
printf " %-10s %s\n" "$label:" "$converted"
done
echo ""
echo "=== Parse Time with Timezone ==="
# Input time is in Pacific, convert to local
pacific_time="2025-11-18 09:00:00"
pacific_epoch=$(TZ=America/Los_Angeles date -d "$pacific_time" +%s)
echo "Source: $pacific_time Pacific"
echo "Local: $(date -d @$pacific_epoch '+%Y-%m-%d %H:%M:%S %Z')"
echo "UTC: $(TZ=UTC date -d @$pacific_epoch '+%Y-%m-%d %H:%M:%S %Z')"
echo ""
echo "=== Timezone Offset Information ==="
echo "Current timezone: $(date +%Z)"
echo "UTC offset: $(date +%z)"
echo "Offset with colon: $(date +%:z)"
echo ""
echo "=== Store in UTC, Display Local ==="
# Best practice: store timestamps in UTC
stored_utc="2025-11-18T19:30:45Z"
# Display in various local times
echo "Stored (UTC): $stored_utc"
for tz in "America/New_York" "America/Los_Angeles" "Europe/London"; do
local_time=$(TZ=$tz date -d "$stored_utc" '+%Y-%m-%d %H:%M:%S %Z')
printf " %-20s %s\n" "$tz:" "$local_time"
done
echo ""
echo "=== Practical: Global Team Meeting Planner ==="
echo ""
echo "Finding a good meeting time (9 AM - 5 PM for all):"
# Check 14:00 UTC
utc_hour=14
echo "Testing ${utc_hour}:00 UTC:"
zones=("America/New_York" "America/Los_Angeles" "Europe/London" "Asia/Tokyo")
all_good=true
for tz in "${zones[@]}"; do
local_hour=$(TZ=$tz date -d "2025-11-18 ${utc_hour}:00 UTC" '+%H')
local_time=$(TZ=$tz date -d "2025-11-18 ${utc_hour}:00 UTC" '+%H:%M %Z')
if ((10#$local_hour >= 9 && 10#$local_hour < 17)); then
status="β"
else
status="β"
all_good=false
fi
printf " %s %-20s %s\n" "$status" "$tz" "$local_time"
done
America/New_York not EST. Abbreviations are ambiguous (EST = Eastern Standard Time or Eastern Summer Time in Australia).
Finding specific weekdays, first/last of month, and calendar calculations.
#!/bin/bash
# Weekday and calendar operations
echo "=== Current Day Information ==="
echo "Day name: $(date '+%A')"
echo "Day number (Mon=1): $(date '+%u')"
echo "Day number (Sun=0): $(date '+%w')"
echo "Day of month: $(date '+%d')"
echo "Day of year: $(date '+%j')"
echo ""
echo "=== Find Specific Weekdays ==="
echo "Next Monday: $(date -d 'next monday' '+%Y-%m-%d')"
echo "Next Friday: $(date -d 'next friday' '+%Y-%m-%d')"
echo "Last Sunday: $(date -d 'last sunday' '+%Y-%m-%d')"
echo "This Wednesday: $(date -d 'this wednesday' '+%Y-%m-%d')"
echo ""
echo "=== This Week's Days ==="
for day in monday tuesday wednesday thursday friday saturday sunday; do
echo " $(date -d "this $day" '+%Y-%m-%d %A')"
done
echo ""
echo "=== First and Last of Month ==="
year=$(date '+%Y')
month=$(date '+%m')
# First day
first=$(date -d "$year-$month-01" '+%Y-%m-%d (%A)')
echo "First of month: $first"
# Last day
last=$(date -d "$year-$month-01 +1 month -1 day" '+%Y-%m-%d (%A)')
echo "Last of month: $last"
# Days in month
days_in_month=$(date -d "$year-$month-01 +1 month -1 day" '+%d')
echo "Days in month: $days_in_month"
echo ""
echo "=== First Monday of Month ==="
first_of_month="$year-$month-01"
dow=$(date -d "$first_of_month" '+%u') # 1=Monday
if ((dow == 1)); then
first_monday="$first_of_month"
else
days_until=$((8 - dow))
first_monday=$(date -d "$first_of_month +$days_until days" '+%Y-%m-%d')
fi
echo "First Monday: $first_monday"
echo ""
echo "=== Check Weekend vs Weekday ==="
check_day() {
local d=$1
local dow=$(date -d "$d" '+%u')
local name=$(date -d "$d" '+%A')
if ((dow >= 6)); then
echo "$d ($name) is a WEEKEND"
else
echo "$d ($name) is a WEEKDAY"
fi
}
check_day "2025-11-18"
check_day "2025-11-22"
check_day "2025-11-23"
echo ""
echo "=== Practical: Next Occurrence ==="
# Find next occurrence of a specific day (e.g., 15th)
target_day=15
current_day=$(date '+%d')
current_month=$(date '+%Y-%m')
if ((10#$current_day < target_day)); then
next_occurrence="$current_month-$(printf '%02d' $target_day)"
else
next_occurrence=$(date -d "$current_month-01 +1 month" '+%Y-%m')-$(printf '%02d' $target_day)
fi
echo "Next ${target_day}th: $next_occurrence ($(date -d "$next_occurrence" '+%A'))"
echo ""
echo "=== Calendar for Current Month ==="
cal
Using natural language for intuitive date manipulation.
#!/bin/bash
# Relative and natural language dates
echo "=== Basic Relative Terms ==="
echo "now: $(date -d 'now' '+%Y-%m-%d %H:%M:%S')"
echo "today: $(date -d 'today' '+%Y-%m-%d')"
echo "yesterday: $(date -d 'yesterday' '+%Y-%m-%d')"
echo "tomorrow: $(date -d 'tomorrow' '+%Y-%m-%d')"
echo ""
echo "=== Time-of-Day Terms ==="
echo "midnight: $(date -d 'midnight' '+%H:%M:%S')"
echo "noon: $(date -d 'noon' '+%H:%M:%S')"
echo "teatime: $(date -d 'teatime' '+%H:%M:%S')" # 4:00 PM
echo ""
echo "=== Ago and Hence ==="
echo "3 days ago: $(date -d '3 days ago' '+%Y-%m-%d')"
echo "2 weeks ago: $(date -d '2 weeks ago' '+%Y-%m-%d')"
echo "1 month ago: $(date -d '1 month ago' '+%Y-%m-%d')"
echo "1 week hence: $(date -d '1 week hence' '+%Y-%m-%d')"
echo "fortnight: $(date -d 'fortnight' '+%Y-%m-%d')" # 2 weeks
echo ""
echo "=== Compound Expressions ==="
echo "yesterday noon: $(date -d 'yesterday noon' '+%Y-%m-%d %H:%M')"
echo "tomorrow midnight: $(date -d 'tomorrow midnight' '+%Y-%m-%d %H:%M')"
echo "next week monday: $(date -d 'next week monday' '+%Y-%m-%d')"
echo "2 days ago 3pm: $(date -d '2 days ago 15:00' '+%Y-%m-%d %H:%M')"
echo ""
echo "=== First/Last of Period ==="
# First of current month
echo "First of month: $(date -d "$(date '+%Y-%m-01')" '+%Y-%m-%d')"
# Last of current month
echo "Last of month: $(date -d "$(date '+%Y-%m-01') +1 month -1 day" '+%Y-%m-%d')"
# First of year
echo "First of year: $(date '+%Y-01-01')"
# Last of year
echo "Last of year: $(date '+%Y-12-31')"
echo ""
echo "=== Practical: Report Periods ==="
today=$(date '+%Y-%m-%d')
echo "Report periods as of $today:"
echo ""
echo "Today: $today"
echo "Yesterday: $(date -d 'yesterday' '+%Y-%m-%d')"
echo ""
echo "This week: $(date -d 'last monday' '+%Y-%m-%d') to $(date -d 'next sunday' '+%Y-%m-%d')"
echo "Last week: $(date -d 'last monday -7 days' '+%Y-%m-%d') to $(date -d 'last sunday' '+%Y-%m-%d')"
echo ""
echo "This month: $(date '+%Y-%m-01') to $(date -d "$(date '+%Y-%m-01') +1 month -1 day" '+%Y-%m-%d')"
echo "Last month: $(date -d 'last month' '+%Y-%m-01') to $(date -d "$(date '+%Y-%m-01') -1 day" '+%Y-%m-%d')"
echo ""
echo "Last 7 days: $(date -d '-6 days' '+%Y-%m-%d') to $today"
echo "Last 30 days: $(date -d '-29 days' '+%Y-%m-%d') to $today"
echo "Last 90 days: $(date -d '-89 days' '+%Y-%m-%d') to $today"
echo ""
echo "=== Quarter Calculation ==="
month=$(date '+%-m')
quarter=$(( (month - 1) / 3 + 1 ))
year=$(date '+%Y')
q_start_month=$(( (quarter - 1) * 3 + 1 ))
q_end_month=$((quarter * 3))
q_start=$(date -d "$year-$q_start_month-01" '+%Y-%m-%d')
q_end=$(date -d "$year-$q_end_month-01 +1 month -1 day" '+%Y-%m-%d')
echo "Current quarter: Q$quarter $year"
echo "Q$quarter: $q_start to $q_end"
Creating dated filenames and implementing rotation schemes.
#!/bin/bash
# Log rotation and file dating
echo "=== Filename Timestamp Patterns ==="
echo "Second: file-$(date '+%Y%m%d_%H%M%S').log"
echo "Minute: file-$(date '+%Y%m%d_%H%M').log"
echo "Hourly: file-$(date '+%Y-%m-%d_%H').log"
echo "Daily: file-$(date '+%Y-%m-%d').log"
echo "Weekly: file-$(date '+%Y-W%W').log"
echo "Monthly: file-$(date '+%Y-%m').log"
echo "Yearly: file-$(date '+%Y').log"
echo ""
echo "=== Rotation File Names ==="
base="application"
echo "Current: ${base}.log"
for i in {1..7}; do
rotated="${base}.log.$(date -d "-$i days" '+%Y-%m-%d')"
echo "Day -$i: $rotated"
done
echo ""
echo "=== Backup Naming Schemes ==="
prefix="backup"
echo "Daily: ${prefix}-daily-$(date '+%Y-%m-%d').tar.gz"
echo "Weekly: ${prefix}-weekly-$(date -d 'last sunday' '+%Y-%m-%d').tar.gz"
echo "Monthly: ${prefix}-monthly-$(date '+%Y-%m').tar.gz"
echo "Quarterly: ${prefix}-Q$(( ($(date '+%-m') - 1) / 3 + 1 ))-$(date '+%Y').tar.gz"
echo "Yearly: ${prefix}-$(date '+%Y').tar.gz"
echo ""
echo "=== Rotation Script Pattern ==="
cat << 'SCRIPT'
#!/bin/bash
LOG_DIR="/var/log/myapp"
LOG_FILE="$LOG_DIR/app.log"
KEEP_DAYS=7
# Rotate current log
if [[ -f "$LOG_FILE" ]]; then
mv "$LOG_FILE" "${LOG_FILE}.$(date '+%Y-%m-%d')"
touch "$LOG_FILE"
chmod 644 "$LOG_FILE"
fi
# Remove old rotated logs
find "$LOG_DIR" -name "app.log.*" -mtime +$KEEP_DAYS -delete
echo "Rotation complete: $(date)"
SCRIPT
echo ""
echo "=== Find Files by Date ==="
echo "Modified in last 24 hours:"
echo " find /var/log -mtime -1 -type f"
echo ""
echo "Modified more than 7 days ago:"
echo " find /var/log -mtime +7 -type f"
echo ""
echo "Modified today:"
echo " find /var/log -daystart -mtime 0 -type f"
echo ""
echo "Modified between dates:"
echo " find /var/log -newermt '2025-11-01' ! -newermt '2025-11-15'"
echo ""
echo "=== Cleanup Schedule ==="
echo "Retention policy cleanup dates:"
printf "%-20s %s\n" "Hourly logs:" "$(date -d '-24 hours' '+%Y-%m-%d %H:%M')"
printf "%-20s %s\n" "Daily backups:" "$(date -d '-7 days' '+%Y-%m-%d')"
printf "%-20s %s\n" "Weekly backups:" "$(date -d '-4 weeks' '+%Y-%m-%d')"
printf "%-20s %s\n" "Monthly backups:" "$(date -d '-12 months' '+%Y-%m-%d')"
printf "%-20s %s\n" "Yearly backups:" "$(date -d '-7 years' '+%Y-%m-%d')"
echo ""
echo "=== Date-Based Directory Structure ==="
# Create hierarchy: /logs/2025/11/18/
log_dir="/tmp/logs/$(date '+%Y/%m/%d')"
echo "Creating: $log_dir"
mkdir -p "$log_dir"
ls -la /tmp/logs/
Working with cron schedules and finding next run times.
#!/bin/bash
# Cron schedule helpers
echo "=== Current Time Context ==="
echo "Now: $(date '+%Y-%m-%d %H:%M:%S %A')"
echo "Hour: $(date '+%H')"
echo "Minute: $(date '+%M')"
echo "Day: $(date '+%d')"
echo "Month: $(date '+%m')"
echo "Weekday: $(date '+%u') ($(date '+%A'))"
echo ""
echo "=== Next Run Calculations ==="
# Daily at 2 AM
current_hour=$(date '+%H')
if ((10#$current_hour < 2)); then
next_daily=$(date -d 'today 02:00' '+%Y-%m-%d %H:%M')
else
next_daily=$(date -d 'tomorrow 02:00' '+%Y-%m-%d %H:%M')
fi
echo "Daily @2AM: $next_daily"
# Weekly on Sunday at 3 AM
current_dow=$(date '+%u')
if ((current_dow == 7 && 10#$current_hour < 3)); then
next_weekly=$(date -d 'today 03:00' '+%Y-%m-%d %H:%M')
else
next_weekly=$(date -d 'next sunday 03:00' '+%Y-%m-%d %H:%M')
fi
echo "Weekly Sun@3AM: $next_weekly"
# Monthly on 1st at midnight
current_day=$(date '+%d')
if ((10#$current_day == 1 && 10#$current_hour < 1)); then
next_monthly=$(date -d 'today 00:00' '+%Y-%m-%d %H:%M')
else
next_monthly=$(date -d "$(date -d '+1 month' '+%Y-%m-01') 00:00" '+%Y-%m-%d %H:%M')
fi
echo "Monthly 1st: $next_monthly"
# Every 15 minutes
current_min=$(date '+%M')
next_quarter=$((((10#$current_min / 15) + 1) * 15))
if ((next_quarter >= 60)); then
next_15min=$(date -d '+1 hour' '+%Y-%m-%d %H:00')
else
next_15min=$(date '+%Y-%m-%d %H:')$(printf '%02d' $next_quarter)
fi
echo "Every 15min: $next_15min"
echo ""
echo "=== Cron Expression Examples ==="
cat << 'EOF'
# ββββββββββββββ minute (0 - 59)
# β ββββββββββββββ hour (0 - 23)
# β β ββββββββββββββ day of month (1 - 31)
# β β β ββββββββββββββ month (1 - 12)
# β β β β ββββββββββββββ day of week (0 - 6, Sunday=0)
# β β β β β
# * * * * *
0 2 * * * # Daily at 2:00 AM
0 3 * * 0 # Weekly Sunday at 3:00 AM
0 0 1 * * # Monthly on 1st at midnight
*/15 * * * * # Every 15 minutes
0 9-17 * * 1-5 # Hourly 9-5, Mon-Fri
0 0 * * 1 # Weekly Monday at midnight
EOF
echo ""
echo "=== Time Until Next Run ==="
next_run=$(date -d 'tomorrow 02:00' '+%s')
now=$(date '+%s')
until_secs=$((next_run - now))
until_hours=$((until_secs / 3600))
until_mins=$(( (until_secs % 3600) / 60 ))
echo "Next daily backup (2 AM):"
echo " Runs at: $(date -d @$next_run '+%Y-%m-%d %H:%M')"
echo " In: ${until_hours}h ${until_mins}m"
echo ""
echo "=== Check if Should Run Now ==="
# Simulate cron check for "0 * * * *" (hourly on the hour)
should_run_hourly() {
local minute=$(date '+%M')
((10#$minute == 0))
}
# Simulate check for "0 2 * * *" (daily at 2 AM)
should_run_daily_2am() {
local hour=$(date '+%H')
local minute=$(date '+%M')
((10#$hour == 2 && 10#$minute == 0))
}
# Simulate check for weekday only
is_weekday() {
local dow=$(date '+%u')
((dow <= 5))
}
echo "Current minute: $(date '+%M')"
should_run_hourly && echo "Hourly job: SHOULD RUN" || echo "Hourly job: not yet"
echo "Current hour: $(date '+%H')"
should_run_daily_2am && echo "Daily 2AM job: SHOULD RUN" || echo "Daily 2AM job: not yet"
is_weekday && echo "Weekday check: YES" || echo "Weekday check: NO (weekend)"
A reusable library of date/time functions for scripts.
#!/bin/bash
# Complete date/time function library
#######################################
# Date Parsing and Formatting
#######################################
# Parse any date to epoch
to_epoch() {
date -d "$1" '+%s' 2>/dev/null
}
# Epoch to formatted date
from_epoch() {
local epoch=$1
local format=${2:-'%Y-%m-%d %H:%M:%S'}
date -d @$epoch "+$format"
}
# Format date
format_date() {
local input=$1
local format=$2
date -d "$input" "+$format"
}
#######################################
# Date Arithmetic
#######################################
# Add days to date
add_days() {
local d=$1 n=$2
date -d "$d +$n days" '+%Y-%m-%d'
}
# Subtract days
sub_days() {
local d=$1 n=$2
date -d "$d -$n days" '+%Y-%m-%d'
}
# Days between dates
days_between() {
local d1=$1 d2=$2
local e1=$(to_epoch "$d1")
local e2=$(to_epoch "$d2")
echo $(( (e2 - e1) / 86400 ))
}
# Add months
add_months() {
local d=$1 n=$2
date -d "$d +$n months" '+%Y-%m-%d'
}
#######################################
# Date Checks
#######################################
# Is valid date
is_valid_date() {
date -d "$1" &>/dev/null
}
# Is weekend
is_weekend() {
local dow=$(date -d "$1" '+%u')
((dow >= 6))
}
# Is in range
date_in_range() {
local d=$1 start=$2 end=$3
local de=$(to_epoch "$d")
local se=$(to_epoch "$start")
local ee=$(to_epoch "$end")
((de >= se && de <= ee))
}
#######################################
# Calendar Functions
#######################################
# First of month
first_of_month() {
local d=${1:-$(date '+%Y-%m-%d')}
date -d "$(date -d "$d" '+%Y-%m-01')" '+%Y-%m-%d'
}
# Last of month
last_of_month() {
local d=${1:-$(date '+%Y-%m-%d')}
date -d "$(date -d "$d" '+%Y-%m-01') +1 month -1 day" '+%Y-%m-%d'
}
# Days in month
days_in_month() {
local d=${1:-$(date '+%Y-%m-%d')}
date -d "$(date -d "$d" '+%Y-%m-01') +1 month -1 day" '+%d'
}
# Quarter of date
quarter_of() {
local d=${1:-$(date '+%Y-%m-%d')}
local month=$(date -d "$d" '+%-m')
echo $(( (month - 1) / 3 + 1 ))
}
#######################################
# Duration Formatting
#######################################
# Format seconds as readable
format_duration() {
local secs=$1
local d=$((secs / 86400))
local h=$(( (secs % 86400) / 3600 ))
local m=$(( (secs % 3600) / 60 ))
local s=$((secs % 60))
if ((d > 0)); then
printf "%dd %dh %dm" $d $h $m
elif ((h > 0)); then
printf "%dh %dm %ds" $h $m $s
elif ((m > 0)); then
printf "%dm %ds" $m $s
else
printf "%ds" $s
fi
}
#######################################
# Demo
#######################################
echo "========================================"
echo " Date/Time Library Demo"
echo "========================================"
echo ""
echo "=== Parsing and Formatting ==="
echo "to_epoch 'Nov 18, 2025': $(to_epoch 'Nov 18, 2025')"
echo "from_epoch 1731958245: $(from_epoch 1731958245)"
echo "format_date 'tomorrow' '%A %B %d': $(format_date 'tomorrow' '%A %B %d')"
echo ""
echo "=== Date Arithmetic ==="
echo "add_days '2025-11-18' 10: $(add_days '2025-11-18' 10)"
echo "sub_days '2025-11-18' 30: $(sub_days '2025-11-18' 30)"
echo "days_between '2025-01-01' '2025-11-18': $(days_between '2025-01-01' '2025-11-18')"
echo "add_months '2025-11-18' 3: $(add_months '2025-11-18' 3)"
echo ""
echo "=== Date Checks ==="
is_valid_date "2025-11-18" && echo "2025-11-18: valid" || echo "2025-11-18: invalid"
is_valid_date "2025-02-30" && echo "2025-02-30: valid" || echo "2025-02-30: invalid"
is_weekend "2025-11-22" && echo "2025-11-22: weekend" || echo "2025-11-22: weekday"
echo ""
echo "=== Calendar Functions ==="
echo "first_of_month: $(first_of_month)"
echo "last_of_month: $(last_of_month)"
echo "days_in_month: $(days_in_month)"
echo "quarter_of: Q$(quarter_of)"
echo ""
echo "=== Duration Formatting ==="
echo "3661 seconds: $(format_duration 3661)"
echo "90061 seconds: $(format_duration 90061)"
echo ""
echo "========================================"
# Current date/time
date # Default format
date '+%Y-%m-%d' # ISO date
date '+%H:%M:%S' # Time
date '+%s' # Epoch
# Parse dates
date -d "Nov 18, 2025" # Parse string
date -d @1731958245 # From epoch
date -d "2025-11-18 14:30" # With time
# Arithmetic
date -d "tomorrow"
date -d "+3 days"
date -d "-1 week"
date -d "next monday"
date -d "last month"
# Timezone
TZ=UTC date
TZ=America/Los_Angeles date
| Task | Command |
|---|---|
| ISO timestamp | date +%Y-%m-%dT%H:%M:%S%z |
| Filename safe | date +%Y%m%d_%H%M%S |
| Days between | $(( ($(date -d "$d2" +%s) - $(date -d "$d1" +%s)) / 86400 )) |
| Is weekend | (($(date -d "$d" +%u) >= 6)) |
| Last of month | date -d "$(date +%Y-%m-01) +1 month -1 day" |
| Validate | date -d "$input" &>/dev/null |
%Y-%m-%dT%H:%M:%S%z)America/New_York)