How to Get the Current Time in Seconds Since the Epoch in Bash on Linux
You need a timestamp for logging, calculating time differences, or working with APIs that expect Unix time. How do you get the current time in seconds since the epoch in Bash?
TL;DR
Use date +%s to get the current Unix timestamp (seconds since January 1, 1970 00:00:00 UTC). For milliseconds, use date +%s%3N. To convert a specific date to epoch seconds, use date -d "2024-01-15" +%s. To convert epoch seconds back to a human-readable date, use date -d @1704067200.
The Unix epoch is midnight UTC on January 1, 1970. The Unix timestamp counts seconds since that moment, making it useful for time calculations and comparisons.
Get the current timestamp:
date +%s
Output (current time):
1711892400
This number represents seconds elapsed since the epoch.
Why Use Unix Timestamps?
Unix timestamps are useful because:
- They're timezone-independent (always UTC)
- Easy to compare and calculate differences
- Widely used in programming and APIs
- Compact representation of time
- No ambiguity about format
Getting Milliseconds
Some applications need millisecond precision:
# Seconds with milliseconds (13 digits)
date +%s%3N
Output:
1711892400123
The %3N adds milliseconds (3 digits of nanoseconds).
For microseconds:
date +%s%6N
For nanoseconds:
date +%s%N
Converting Specific Dates to Epoch
Convert a date string to Unix timestamp:
# Specific date
date -d "2024-01-15" +%s
# Date with time
date -d "2024-01-15 14:30:00" +%s
# Relative dates
date -d "yesterday" +%s
date -d "next week" +%s
date -d "3 days ago" +%s
The -d flag parses date strings in various formats.
Converting Epoch Back to Human-Readable Date
Convert a Unix timestamp to readable format:
# Using @ prefix
date -d @1704067200
# With custom format
date -d @1704067200 +"%Y-%m-%d %H:%M:%S"
Output:
2024-01-01 00:00:00
Calculating Time Differences
Measure how long something takes:
#!/bin/bash
# Record start time
START=$(date +%s)
# Do something that takes time
sleep 5
# Your actual work here
# Record end time
END=$(date +%s)
# Calculate difference
ELAPSED=$((END - START))
echo "Operation took $ELAPSED seconds"
Output:
Operation took 5 seconds
Practical Example: Timestamped Logging
Add timestamps to log entries:
#!/bin/bash
LOG_FILE="app.log"
log() {
TIMESTAMP=$(date +%s)
DATETIME=$(date +"%Y-%m-%d %H:%M:%S")
echo "[$TIMESTAMP] [$DATETIME] $*" >> "$LOG_FILE"
}
# Usage
log "Application started"
log "User logged in"
log "Processing complete"
Log file output:
[1711892400] [2024-03-31 15:00:00] Application started
[1711892405] [2024-03-31 15:00:05] User logged in
[1711892412] [2024-03-31 15:00:12] Processing complete
Practical Example: Benchmarking
Compare performance of different approaches:
#!/bin/bash
benchmark() {
local description="$1"
local command="$2"
local start=$(date +%s%3N)
eval "$command"
local end=$(date +%s%3N)
local elapsed=$((end - start))
echo "$description: ${elapsed}ms"
}
# Usage
benchmark "Method 1" "for i in {1..1000}; do echo $i > /dev/null; done"
benchmark "Method 2" "seq 1 1000 > /dev/null"
Output:
Method 1: 245ms
Method 2: 12ms
Creating Unique Filenames with Timestamps
Use timestamps for unique file names:
# Backup with timestamp
TIMESTAMP=$(date +%s)
cp important.txt "important-$TIMESTAMP.txt.bak"
# Log file with timestamp
LOG_FILE="app-$TIMESTAMP.log"
touch "$LOG_FILE"
# More readable format
READABLE=$(date +"%Y%m%d-%H%M%S")
mkdir "backup-$READABLE"
Checking File Age
Determine how old a file is:
#!/bin/bash
FILE="$1"
if [ ! -f "$FILE" ]; then
echo "File not found"
exit 1
fi
# Get file modification time in epoch seconds
FILE_TIME=$(stat -c %Y "$FILE")
# Get current time
CURRENT_TIME=$(date +%s)
# Calculate age in seconds
AGE=$((CURRENT_TIME - FILE_TIME))
# Convert to days
AGE_DAYS=$((AGE / 86400))
echo "File is $AGE seconds old ($AGE_DAYS days)"
Setting Timeout Conditions
Implement timeouts in scripts:
#!/bin/bash
TIMEOUT=60 # seconds
START=$(date +%s)
while true; do
# Your condition
if some_check; then
echo "Success!"
break
fi
# Check timeout
CURRENT=$(date +%s)
ELAPSED=$((CURRENT - START))
if [ $ELAPSED -gt $TIMEOUT ]; then
echo "Timeout after $TIMEOUT seconds"
exit 1
fi
sleep 1
done
Comparing Timestamps
Check if one timestamp is older than another:
TIMESTAMP1=1704067200 # 2024-01-01
TIMESTAMP2=1711892400 # 2024-03-31
if [ $TIMESTAMP1 -lt $TIMESTAMP2 ]; then
echo "Timestamp 1 is older"
else
echo "Timestamp 2 is older"
fi
# Calculate difference
DIFF=$((TIMESTAMP2 - TIMESTAMP1))
DIFF_DAYS=$((DIFF / 86400))
echo "Difference: $DIFF_DAYS days"
Time Zones and Epoch
Epoch time is always UTC. To get a timestamp for a specific timezone:
# Current time in New York
TZ="America/New_York" date +%s
# Current time in Tokyo
TZ="Asia/Tokyo" date +%s
But since epoch is UTC-based, these return the same value - the current UTC time. To get the timestamp for "midnight in New York":
TZ="America/New_York" date -d "today 00:00:00" +%s
Practical Example: Session Timeout
Track user sessions with expiry:
#!/bin/bash
SESSION_FILE=".session"
TIMEOUT=3600 # 1 hour
start_session() {
date +%s > "$SESSION_FILE"
echo "Session started"
}
check_session() {
if [ ! -f "$SESSION_FILE" ]; then
echo "No active session"
return 1
fi
SESSION_START=$(cat "$SESSION_FILE")
CURRENT=$(date +%s)
ELAPSED=$((CURRENT - SESSION_START))
if [ $ELAPSED -gt $TIMEOUT ]; then
echo "Session expired"
rm "$SESSION_FILE"
return 1
fi
REMAINING=$((TIMEOUT - ELAPSED))
echo "Session active ($REMAINING seconds remaining)"
return 0
}
# Usage
start_session
sleep 5
check_session
Practical Example: Rate Limiting
Implement simple rate limiting:
#!/bin/bash
RATE_FILE=".last_run"
MIN_INTERVAL=300 # 5 minutes between runs
can_run() {
if [ ! -f "$RATE_FILE" ]; then
return 0 # No previous run, allowed
fi
LAST_RUN=$(cat "$RATE_FILE")
CURRENT=$(date +%s)
ELAPSED=$((CURRENT - LAST_RUN))
if [ $ELAPSED -lt $MIN_INTERVAL ]; then
WAIT=$((MIN_INTERVAL - ELAPSED))
echo "Please wait $WAIT seconds before running again"
return 1
fi
return 0
}
record_run() {
date +%s > "$RATE_FILE"
}
# Usage
if can_run; then
echo "Running task..."
# Do your task
record_run
fi
Using bc for Precise Calculations
For more complex time calculations:
#!/bin/bash
START=$(date +%s)
sleep 2
END=$(date +%s)
# Calculate with decimals
ELAPSED=$(echo "$END - $START" | bc)
echo "Elapsed: ${ELAPSED}s"
# Convert seconds to hours
HOURS=$(echo "scale=2; $ELAPSED / 3600" | bc)
echo "That's $HOURS hours"
Common Time Constants
Useful constants for time calculations:
# Time constants in seconds
SECOND=1
MINUTE=60
HOUR=3600
DAY=86400
WEEK=604800
MONTH=2592000 # 30 days
YEAR=31536000 # 365 days
# Calculate timestamps
ONE_HOUR_AGO=$(($(date +%s) - HOUR))
TOMORROW=$(($(date +%s) + DAY))
NEXT_WEEK=$(($(date +%s) + WEEK))
Epoch Time Limitations
The Unix timestamp has limitations:
- 32-bit systems face the "Year 2038 problem" (max timestamp: 2147483647)
- 64-bit systems are fine until year 292 billion+
- Doesn't include leap seconds
- Always UTC, requires conversion for local time display
For Y2038-safe code on 32-bit systems, consider using 64-bit integers or alternative time representations.
Converting Between Formats
Quick reference for conversions:
# Now to epoch
date +%s
# Epoch to human-readable
date -d @1711892400
# Specific date to epoch
date -d "2024-03-31 15:00:00" +%s
# With milliseconds
date +%s%3N
# File modification time to epoch
stat -c %Y filename
Getting the Unix timestamp in Bash is simple with date +%s. Whether you're logging events, measuring performance, implementing timeouts, or working with time-based logic, epoch seconds provide a reliable, timezone-independent way to work with time.
Found an issue?